linux/fs/nfs/nfs42proc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
   4 */
   5#include <linux/fs.h>
   6#include <linux/sunrpc/sched.h>
   7#include <linux/nfs.h>
   8#include <linux/nfs3.h>
   9#include <linux/nfs4.h>
  10#include <linux/nfs_xdr.h>
  11#include <linux/nfs_fs.h>
  12#include "nfs4_fs.h"
  13#include "nfs42.h"
  14#include "iostat.h"
  15#include "pnfs.h"
  16#include "nfs4session.h"
  17#include "internal.h"
  18
  19#define NFSDBG_FACILITY NFSDBG_PROC
  20
  21static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
  22                struct nfs_lock_context *lock, loff_t offset, loff_t len)
  23{
  24        struct inode *inode = file_inode(filep);
  25        struct nfs_server *server = NFS_SERVER(inode);
  26        struct nfs42_falloc_args args = {
  27                .falloc_fh      = NFS_FH(inode),
  28                .falloc_offset  = offset,
  29                .falloc_length  = len,
  30                .falloc_bitmask = server->cache_consistency_bitmask,
  31        };
  32        struct nfs42_falloc_res res = {
  33                .falloc_server  = server,
  34        };
  35        int status;
  36
  37        msg->rpc_argp = &args;
  38        msg->rpc_resp = &res;
  39
  40        status = nfs4_set_rw_stateid(&args.falloc_stateid, lock->open_context,
  41                        lock, FMODE_WRITE);
  42        if (status)
  43                return status;
  44
  45        res.falloc_fattr = nfs_alloc_fattr();
  46        if (!res.falloc_fattr)
  47                return -ENOMEM;
  48
  49        status = nfs4_call_sync(server->client, server, msg,
  50                                &args.seq_args, &res.seq_res, 0);
  51        if (status == 0)
  52                status = nfs_post_op_update_inode(inode, res.falloc_fattr);
  53
  54        kfree(res.falloc_fattr);
  55        return status;
  56}
  57
  58static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
  59                                loff_t offset, loff_t len)
  60{
  61        struct nfs_server *server = NFS_SERVER(file_inode(filep));
  62        struct nfs4_exception exception = { };
  63        struct nfs_lock_context *lock;
  64        int err;
  65
  66        lock = nfs_get_lock_context(nfs_file_open_context(filep));
  67        if (IS_ERR(lock))
  68                return PTR_ERR(lock);
  69
  70        exception.inode = file_inode(filep);
  71        exception.state = lock->open_context->state;
  72
  73        do {
  74                err = _nfs42_proc_fallocate(msg, filep, lock, offset, len);
  75                if (err == -ENOTSUPP) {
  76                        err = -EOPNOTSUPP;
  77                        break;
  78                }
  79                err = nfs4_handle_exception(server, err, &exception);
  80        } while (exception.retry);
  81
  82        nfs_put_lock_context(lock);
  83        return err;
  84}
  85
  86int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len)
  87{
  88        struct rpc_message msg = {
  89                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE],
  90        };
  91        struct inode *inode = file_inode(filep);
  92        int err;
  93
  94        if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE))
  95                return -EOPNOTSUPP;
  96
  97        inode_lock(inode);
  98
  99        err = nfs42_proc_fallocate(&msg, filep, offset, len);
 100        if (err == -EOPNOTSUPP)
 101                NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE;
 102
 103        inode_unlock(inode);
 104        return err;
 105}
 106
 107int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
 108{
 109        struct rpc_message msg = {
 110                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DEALLOCATE],
 111        };
 112        struct inode *inode = file_inode(filep);
 113        int err;
 114
 115        if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE))
 116                return -EOPNOTSUPP;
 117
 118        inode_lock(inode);
 119        err = nfs_sync_inode(inode);
 120        if (err)
 121                goto out_unlock;
 122
 123        err = nfs42_proc_fallocate(&msg, filep, offset, len);
 124        if (err == 0)
 125                truncate_pagecache_range(inode, offset, (offset + len) -1);
 126        if (err == -EOPNOTSUPP)
 127                NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE;
 128out_unlock:
 129        inode_unlock(inode);
 130        return err;
 131}
 132
 133static ssize_t _nfs42_proc_copy(struct file *src,
 134                                struct nfs_lock_context *src_lock,
 135                                struct file *dst,
 136                                struct nfs_lock_context *dst_lock,
 137                                struct nfs42_copy_args *args,
 138                                struct nfs42_copy_res *res)
 139{
 140        struct rpc_message msg = {
 141                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY],
 142                .rpc_argp = args,
 143                .rpc_resp = res,
 144        };
 145        struct inode *dst_inode = file_inode(dst);
 146        struct nfs_server *server = NFS_SERVER(dst_inode);
 147        loff_t pos_src = args->src_pos;
 148        loff_t pos_dst = args->dst_pos;
 149        size_t count = args->count;
 150        ssize_t status;
 151
 152        status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
 153                                     src_lock, FMODE_READ);
 154        if (status)
 155                return status;
 156
 157        status = nfs_filemap_write_and_wait_range(file_inode(src)->i_mapping,
 158                        pos_src, pos_src + (loff_t)count - 1);
 159        if (status)
 160                return status;
 161
 162        status = nfs4_set_rw_stateid(&args->dst_stateid, dst_lock->open_context,
 163                                     dst_lock, FMODE_WRITE);
 164        if (status)
 165                return status;
 166
 167        status = nfs_sync_inode(dst_inode);
 168        if (status)
 169                return status;
 170
 171        res->commit_res.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
 172        if (!res->commit_res.verf)
 173                return -ENOMEM;
 174        status = nfs4_call_sync(server->client, server, &msg,
 175                                &args->seq_args, &res->seq_res, 0);
 176        if (status == -ENOTSUPP)
 177                server->caps &= ~NFS_CAP_COPY;
 178        if (status)
 179                goto out;
 180
 181        if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
 182                                    &res->commit_res.verf->verifier)) {
 183                status = -EAGAIN;
 184                goto out;
 185        }
 186
 187        truncate_pagecache_range(dst_inode, pos_dst,
 188                                 pos_dst + res->write_res.count);
 189
 190        status = res->write_res.count;
 191out:
 192        kfree(res->commit_res.verf);
 193        return status;
 194}
 195
 196ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
 197                        struct file *dst, loff_t pos_dst,
 198                        size_t count)
 199{
 200        struct nfs_server *server = NFS_SERVER(file_inode(dst));
 201        struct nfs_lock_context *src_lock;
 202        struct nfs_lock_context *dst_lock;
 203        struct nfs42_copy_args args = {
 204                .src_fh         = NFS_FH(file_inode(src)),
 205                .src_pos        = pos_src,
 206                .dst_fh         = NFS_FH(file_inode(dst)),
 207                .dst_pos        = pos_dst,
 208                .count          = count,
 209        };
 210        struct nfs42_copy_res res;
 211        struct nfs4_exception src_exception = {
 212                .inode          = file_inode(src),
 213                .stateid        = &args.src_stateid,
 214        };
 215        struct nfs4_exception dst_exception = {
 216                .inode          = file_inode(dst),
 217                .stateid        = &args.dst_stateid,
 218        };
 219        ssize_t err, err2;
 220
 221        if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY))
 222                return -EOPNOTSUPP;
 223
 224        src_lock = nfs_get_lock_context(nfs_file_open_context(src));
 225        if (IS_ERR(src_lock))
 226                return PTR_ERR(src_lock);
 227
 228        src_exception.state = src_lock->open_context->state;
 229
 230        dst_lock = nfs_get_lock_context(nfs_file_open_context(dst));
 231        if (IS_ERR(dst_lock)) {
 232                err = PTR_ERR(dst_lock);
 233                goto out_put_src_lock;
 234        }
 235
 236        dst_exception.state = dst_lock->open_context->state;
 237
 238        do {
 239                inode_lock(file_inode(dst));
 240                err = _nfs42_proc_copy(src, src_lock,
 241                                dst, dst_lock,
 242                                &args, &res);
 243                inode_unlock(file_inode(dst));
 244
 245                if (err >= 0)
 246                        break;
 247                if (err == -ENOTSUPP) {
 248                        err = -EOPNOTSUPP;
 249                        break;
 250                } if (err == -EAGAIN) {
 251                        dst_exception.retry = 1;
 252                        continue;
 253                }
 254
 255                err2 = nfs4_handle_exception(server, err, &src_exception);
 256                err  = nfs4_handle_exception(server, err, &dst_exception);
 257                if (!err)
 258                        err = err2;
 259        } while (src_exception.retry || dst_exception.retry);
 260
 261        nfs_put_lock_context(dst_lock);
 262out_put_src_lock:
 263        nfs_put_lock_context(src_lock);
 264        return err;
 265}
 266
 267static loff_t _nfs42_proc_llseek(struct file *filep,
 268                struct nfs_lock_context *lock, loff_t offset, int whence)
 269{
 270        struct inode *inode = file_inode(filep);
 271        struct nfs42_seek_args args = {
 272                .sa_fh          = NFS_FH(inode),
 273                .sa_offset      = offset,
 274                .sa_what        = (whence == SEEK_HOLE) ?
 275                                        NFS4_CONTENT_HOLE : NFS4_CONTENT_DATA,
 276        };
 277        struct nfs42_seek_res res;
 278        struct rpc_message msg = {
 279                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEEK],
 280                .rpc_argp = &args,
 281                .rpc_resp = &res,
 282        };
 283        struct nfs_server *server = NFS_SERVER(inode);
 284        int status;
 285
 286        if (!nfs_server_capable(inode, NFS_CAP_SEEK))
 287                return -ENOTSUPP;
 288
 289        status = nfs4_set_rw_stateid(&args.sa_stateid, lock->open_context,
 290                        lock, FMODE_READ);
 291        if (status)
 292                return status;
 293
 294        status = nfs_filemap_write_and_wait_range(inode->i_mapping,
 295                        offset, LLONG_MAX);
 296        if (status)
 297                return status;
 298
 299        status = nfs4_call_sync(server->client, server, &msg,
 300                                &args.seq_args, &res.seq_res, 0);
 301        if (status == -ENOTSUPP)
 302                server->caps &= ~NFS_CAP_SEEK;
 303        if (status)
 304                return status;
 305
 306        return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
 307}
 308
 309loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 310{
 311        struct nfs_server *server = NFS_SERVER(file_inode(filep));
 312        struct nfs4_exception exception = { };
 313        struct nfs_lock_context *lock;
 314        loff_t err;
 315
 316        lock = nfs_get_lock_context(nfs_file_open_context(filep));
 317        if (IS_ERR(lock))
 318                return PTR_ERR(lock);
 319
 320        exception.inode = file_inode(filep);
 321        exception.state = lock->open_context->state;
 322
 323        do {
 324                err = _nfs42_proc_llseek(filep, lock, offset, whence);
 325                if (err >= 0)
 326                        break;
 327                if (err == -ENOTSUPP) {
 328                        err = -EOPNOTSUPP;
 329                        break;
 330                }
 331                err = nfs4_handle_exception(server, err, &exception);
 332        } while (exception.retry);
 333
 334        nfs_put_lock_context(lock);
 335        return err;
 336}
 337
 338
 339static void
 340nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata)
 341{
 342        struct nfs42_layoutstat_data *data = calldata;
 343        struct inode *inode = data->inode;
 344        struct nfs_server *server = NFS_SERVER(inode);
 345        struct pnfs_layout_hdr *lo;
 346
 347        spin_lock(&inode->i_lock);
 348        lo = NFS_I(inode)->layout;
 349        if (!pnfs_layout_is_valid(lo)) {
 350                spin_unlock(&inode->i_lock);
 351                rpc_exit(task, 0);
 352                return;
 353        }
 354        nfs4_stateid_copy(&data->args.stateid, &lo->plh_stateid);
 355        spin_unlock(&inode->i_lock);
 356        nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
 357                            &data->res.seq_res, task);
 358}
 359
 360static void
 361nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
 362{
 363        struct nfs42_layoutstat_data *data = calldata;
 364        struct inode *inode = data->inode;
 365        struct pnfs_layout_hdr *lo;
 366
 367        if (!nfs4_sequence_done(task, &data->res.seq_res))
 368                return;
 369
 370        switch (task->tk_status) {
 371        case 0:
 372                break;
 373        case -NFS4ERR_EXPIRED:
 374        case -NFS4ERR_ADMIN_REVOKED:
 375        case -NFS4ERR_DELEG_REVOKED:
 376        case -NFS4ERR_STALE_STATEID:
 377        case -NFS4ERR_BAD_STATEID:
 378                spin_lock(&inode->i_lock);
 379                lo = NFS_I(inode)->layout;
 380                if (pnfs_layout_is_valid(lo) &&
 381                    nfs4_stateid_match(&data->args.stateid,
 382                                             &lo->plh_stateid)) {
 383                        LIST_HEAD(head);
 384
 385                        /*
 386                         * Mark the bad layout state as invalid, then retry
 387                         * with the current stateid.
 388                         */
 389                        pnfs_mark_layout_stateid_invalid(lo, &head);
 390                        spin_unlock(&inode->i_lock);
 391                        pnfs_free_lseg_list(&head);
 392                        nfs_commit_inode(inode, 0);
 393                } else
 394                        spin_unlock(&inode->i_lock);
 395                break;
 396        case -NFS4ERR_OLD_STATEID:
 397                spin_lock(&inode->i_lock);
 398                lo = NFS_I(inode)->layout;
 399                if (pnfs_layout_is_valid(lo) &&
 400                    nfs4_stateid_match_other(&data->args.stateid,
 401                                        &lo->plh_stateid)) {
 402                        /* Do we need to delay before resending? */
 403                        if (!nfs4_stateid_is_newer(&lo->plh_stateid,
 404                                                &data->args.stateid))
 405                                rpc_delay(task, HZ);
 406                        rpc_restart_call_prepare(task);
 407                }
 408                spin_unlock(&inode->i_lock);
 409                break;
 410        case -ENOTSUPP:
 411        case -EOPNOTSUPP:
 412                NFS_SERVER(inode)->caps &= ~NFS_CAP_LAYOUTSTATS;
 413        }
 414}
 415
 416static void
 417nfs42_layoutstat_release(void *calldata)
 418{
 419        struct nfs42_layoutstat_data *data = calldata;
 420        struct nfs42_layoutstat_devinfo *devinfo = data->args.devinfo;
 421        int i;
 422
 423        for (i = 0; i < data->args.num_dev; i++) {
 424                if (devinfo[i].ld_private.ops && devinfo[i].ld_private.ops->free)
 425                        devinfo[i].ld_private.ops->free(&devinfo[i].ld_private);
 426        }
 427
 428        pnfs_put_layout_hdr(NFS_I(data->args.inode)->layout);
 429        smp_mb__before_atomic();
 430        clear_bit(NFS_INO_LAYOUTSTATS, &NFS_I(data->args.inode)->flags);
 431        smp_mb__after_atomic();
 432        nfs_iput_and_deactive(data->inode);
 433        kfree(data->args.devinfo);
 434        kfree(data);
 435}
 436
 437static const struct rpc_call_ops nfs42_layoutstat_ops = {
 438        .rpc_call_prepare = nfs42_layoutstat_prepare,
 439        .rpc_call_done = nfs42_layoutstat_done,
 440        .rpc_release = nfs42_layoutstat_release,
 441};
 442
 443int nfs42_proc_layoutstats_generic(struct nfs_server *server,
 444                                   struct nfs42_layoutstat_data *data)
 445{
 446        struct rpc_message msg = {
 447                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTSTATS],
 448                .rpc_argp = &data->args,
 449                .rpc_resp = &data->res,
 450        };
 451        struct rpc_task_setup task_setup = {
 452                .rpc_client = server->client,
 453                .rpc_message = &msg,
 454                .callback_ops = &nfs42_layoutstat_ops,
 455                .callback_data = data,
 456                .flags = RPC_TASK_ASYNC,
 457        };
 458        struct rpc_task *task;
 459
 460        data->inode = nfs_igrab_and_active(data->args.inode);
 461        if (!data->inode) {
 462                nfs42_layoutstat_release(data);
 463                return -EAGAIN;
 464        }
 465        nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
 466        task = rpc_run_task(&task_setup);
 467        if (IS_ERR(task))
 468                return PTR_ERR(task);
 469        rpc_put_task(task);
 470        return 0;
 471}
 472
 473static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
 474                struct file *dst_f, struct nfs_lock_context *src_lock,
 475                struct nfs_lock_context *dst_lock, loff_t src_offset,
 476                loff_t dst_offset, loff_t count)
 477{
 478        struct inode *src_inode = file_inode(src_f);
 479        struct inode *dst_inode = file_inode(dst_f);
 480        struct nfs_server *server = NFS_SERVER(dst_inode);
 481        struct nfs42_clone_args args = {
 482                .src_fh = NFS_FH(src_inode),
 483                .dst_fh = NFS_FH(dst_inode),
 484                .src_offset = src_offset,
 485                .dst_offset = dst_offset,
 486                .count = count,
 487                .dst_bitmask = server->cache_consistency_bitmask,
 488        };
 489        struct nfs42_clone_res res = {
 490                .server = server,
 491        };
 492        int status;
 493
 494        msg->rpc_argp = &args;
 495        msg->rpc_resp = &res;
 496
 497        status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context,
 498                        src_lock, FMODE_READ);
 499        if (status)
 500                return status;
 501
 502        status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context,
 503                        dst_lock, FMODE_WRITE);
 504        if (status)
 505                return status;
 506
 507        res.dst_fattr = nfs_alloc_fattr();
 508        if (!res.dst_fattr)
 509                return -ENOMEM;
 510
 511        status = nfs4_call_sync(server->client, server, msg,
 512                                &args.seq_args, &res.seq_res, 0);
 513        if (status == 0)
 514                status = nfs_post_op_update_inode(dst_inode, res.dst_fattr);
 515
 516        kfree(res.dst_fattr);
 517        return status;
 518}
 519
 520int nfs42_proc_clone(struct file *src_f, struct file *dst_f,
 521                     loff_t src_offset, loff_t dst_offset, loff_t count)
 522{
 523        struct rpc_message msg = {
 524                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLONE],
 525        };
 526        struct inode *inode = file_inode(src_f);
 527        struct nfs_server *server = NFS_SERVER(file_inode(src_f));
 528        struct nfs_lock_context *src_lock;
 529        struct nfs_lock_context *dst_lock;
 530        struct nfs4_exception src_exception = { };
 531        struct nfs4_exception dst_exception = { };
 532        int err, err2;
 533
 534        if (!nfs_server_capable(inode, NFS_CAP_CLONE))
 535                return -EOPNOTSUPP;
 536
 537        src_lock = nfs_get_lock_context(nfs_file_open_context(src_f));
 538        if (IS_ERR(src_lock))
 539                return PTR_ERR(src_lock);
 540
 541        src_exception.inode = file_inode(src_f);
 542        src_exception.state = src_lock->open_context->state;
 543
 544        dst_lock = nfs_get_lock_context(nfs_file_open_context(dst_f));
 545        if (IS_ERR(dst_lock)) {
 546                err = PTR_ERR(dst_lock);
 547                goto out_put_src_lock;
 548        }
 549
 550        dst_exception.inode = file_inode(dst_f);
 551        dst_exception.state = dst_lock->open_context->state;
 552
 553        do {
 554                err = _nfs42_proc_clone(&msg, src_f, dst_f, src_lock, dst_lock,
 555                                        src_offset, dst_offset, count);
 556                if (err == -ENOTSUPP || err == -EOPNOTSUPP) {
 557                        NFS_SERVER(inode)->caps &= ~NFS_CAP_CLONE;
 558                        err = -EOPNOTSUPP;
 559                        break;
 560                }
 561
 562                err2 = nfs4_handle_exception(server, err, &src_exception);
 563                err = nfs4_handle_exception(server, err, &dst_exception);
 564                if (!err)
 565                        err = err2;
 566        } while (src_exception.retry || dst_exception.retry);
 567
 568        nfs_put_lock_context(dst_lock);
 569out_put_src_lock:
 570        nfs_put_lock_context(src_lock);
 571        return err;
 572}
 573