Merge tag 'nfsd-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2024 21:27:37 +0000 (14:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2024 21:27:37 +0000 (14:27 -0700)
Pull nfsd updates from Chuck Lever:
 "The bulk of the patches for this release are optimizations, code
  clean-ups, and minor bug fixes.

  One new feature to mention is that NFSD administrators now have the
  ability to revoke NFSv4 open and lock state. NFSD's NFSv3 support has
  had this capability for some time.

  As always I am grateful to NFSD contributors, reviewers, and testers"

* tag 'nfsd-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (75 commits)
  NFSD: Clean up nfsd4_encode_replay()
  NFSD: send OP_CB_RECALL_ANY to clients when number of delegations reaches its limit
  NFSD: Document nfsd_setattr() fill-attributes behavior
  nfsd: Fix NFSv3 atomicity bugs in nfsd_setattr()
  nfsd: Fix a regression in nfsd_setattr()
  NFSD: OP_CB_RECALL_ANY should recall both read and write delegations
  NFSD: handle GETATTR conflict with write delegation
  NFSD: add support for CB_GETATTR callback
  NFSD: Document the phases of CREATE_SESSION
  NFSD: Fix the NFSv4.1 CREATE_SESSION operation
  nfsd: clean up comments over nfs4_client definition
  svcrdma: Add Write chunk WRs to the RPC's Send WR chain
  svcrdma: Post WRs for Write chunks in svc_rdma_sendto()
  svcrdma: Post the Reply chunk and Send WR together
  svcrdma: Move write_info for Reply chunks into struct svc_rdma_send_ctxt
  svcrdma: Post Send WR chain
  svcrdma: Fix retry loop in svc_rdma_send()
  svcrdma: Prevent a UAF in svc_rdma_send()
  svcrdma: Fix SQ wake-ups
  svcrdma: Increase the per-transport rw_ctx count
  ...

1  2 
MAINTAINERS
fs/nfsd/filecache.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4layouts.c
fs/nfsd/nfs4state.c

diff --cc MAINTAINERS
Simple merge
Simple merge
Simple merge
index 4c0d00bdfbb1f3bdc7c3affdeb45bf9e8d7a0b4b,b1e585c1d9a3aa149e7af4e48a206b2affb530e9..4f3072b5979a6e3cf0f6a90ca32d39fa790c8e9c
@@@ -152,6 -152,23 +152,23 @@@ void nfsd4_setup_layout_type(struct svc
  #endif
  }
  
 -                      vfs_setlease(fl->nf_file, F_UNLCK, NULL,
 -                                   (void **)&ls);
+ void nfsd4_close_layout(struct nfs4_layout_stateid *ls)
+ {
+       struct nfsd_file *fl;
+       spin_lock(&ls->ls_stid.sc_file->fi_lock);
+       fl = ls->ls_file;
+       ls->ls_file = NULL;
+       spin_unlock(&ls->ls_stid.sc_file->fi_lock);
+       if (fl) {
+               if (!nfsd4_layout_ops[ls->ls_layout_type]->disable_recalls)
++                      kernel_setlease(fl->nf_file, F_UNLCK, NULL,
++                                      (void **)&ls);
+               nfsd_file_put(fl);
+       }
+ }
  static void
  nfsd4_free_layout_stateid(struct nfs4_stid *stid)
  {
index 9257425cbd1a0d0e1dc87b9497e04409a23bd06a,ee9aa484344345380266cd37fa888b7ef3def751..1a93c7fcf76c55ee2a34a99ec72f48b2c167c0f8
@@@ -8447,13 -8796,18 +8796,18 @@@ nfsd4_get_writestateid(struct nfsd4_com
   * code is returned.
   */
  __be32
- nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode)
+ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
+                               bool *modified, u64 *size)
  {
        __be32 status;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
        struct file_lock_context *ctx;
 -      struct file_lock *fl;
 +      struct file_lease *fl;
        struct nfs4_delegation *dp;
+       struct iattr attrs;
+       struct nfs4_cb_fattr *ncf;
  
+       *modified = false;
        ctx = locks_inode_context(inode);
        if (!ctx)
                return 0;
                                return 0;
                        }
  break_lease:
 -                      dp = fl->fl_owner;
+                       nfsd_stats_wdeleg_getattr_inc(nn);
++                      dp = fl->c.flc_owner;
+                       ncf = &dp->dl_cb_fattr;
+                       nfs4_cb_getattr(&dp->dl_cb_fattr);
                        spin_unlock(&ctx->flc_lock);
-                       nfsd_stats_wdeleg_getattr_inc();
-                       status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
-                       if (status != nfserr_jukebox ||
-                                       !nfsd_wait_for_delegreturn(rqstp, inode))
-                               return status;
+                       wait_on_bit_timeout(&ncf->ncf_cb_flags, CB_GETATTR_BUSY,
+                                       TASK_INTERRUPTIBLE, NFSD_CB_GETATTR_TIMEOUT);
+                       if (ncf->ncf_cb_status) {
+                               /* Recall delegation only if client didn't respond */
+                               status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
+                               if (status != nfserr_jukebox ||
+                                               !nfsd_wait_for_delegreturn(rqstp, inode))
+                                       return status;
+                       }
+                       if (!ncf->ncf_file_modified &&
+                                       (ncf->ncf_initial_cinfo != ncf->ncf_cb_change ||
+                                       ncf->ncf_cur_fsize != ncf->ncf_cb_fsize))
+                               ncf->ncf_file_modified = true;
+                       if (ncf->ncf_file_modified) {
+                               /*
+                                * Per section 10.4.3 of RFC 8881, the server would
+                                * not update the file's metadata with the client's
+                                * modified size
+                                */
+                               attrs.ia_mtime = attrs.ia_ctime = current_time(inode);
+                               attrs.ia_valid = ATTR_MTIME | ATTR_CTIME;
+                               setattr_copy(&nop_mnt_idmap, inode, &attrs);
+                               mark_inode_dirty(inode);
+                               ncf->ncf_cur_fsize = ncf->ncf_cb_fsize;
+                               *size = ncf->ncf_cur_fsize;
+                               *modified = true;
+                       }
                        return 0;
                }
                break;