Merge tag 'nfs-for-6.6-4' of git://git.linux-nfs.org/projects/anna/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Oct 2023 21:04:53 +0000 (14:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Oct 2023 21:04:53 +0000 (14:04 -0700)
Pull NFS client fixes from Anna Schumaker:
 "Stable Fix:
   - Fix a pNFS hang in nfs4_evict_inode()

  Fixes:
   - Force update of suid/sgid bits after an NFS v4.2 ALLOCATE op
   - Fix a potential oops in nfs_inode_remove_request()
   - Check the validity of the layout pointer in ff_layout_mirror_prepare_stats()
   - Fix incorrectly marking the pNFS MDS with USE_PNFS_DS in some cases"

* tag 'nfs-for-6.6-4' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFSv4.1: fixup use EXCHGID4_FLAG_USE_PNFS_DS for DS server
  pNFS/flexfiles: Check the layout validity in ff_layout_mirror_prepare_stats
  pNFS: Fix a hang in nfs4_evict_inode()
  NFS: Fix potential oops in nfs_inode_remove_request()
  nfs42: client needs to strip file mode's suid/sgid bit after ALLOCATE op

fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/write.c

index a1dc338..ef817a0 100644 (file)
@@ -2520,9 +2520,9 @@ ff_layout_mirror_prepare_stats(struct pnfs_layout_hdr *lo,
        return i;
 }
 
-static int
-ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
+static int ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
 {
+       struct pnfs_layout_hdr *lo;
        struct nfs4_flexfile_layout *ff_layout;
        const int dev_count = PNFS_LAYOUTSTATS_MAXDEV;
 
@@ -2533,11 +2533,14 @@ ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
                return -ENOMEM;
 
        spin_lock(&args->inode->i_lock);
-       ff_layout = FF_LAYOUT_FROM_HDR(NFS_I(args->inode)->layout);
-       args->num_dev = ff_layout_mirror_prepare_stats(&ff_layout->generic_hdr,
-                                                      &args->devinfo[0],
-                                                      dev_count,
-                                                      NFS4_FF_OP_LAYOUTSTATS);
+       lo = NFS_I(args->inode)->layout;
+       if (lo && pnfs_layout_is_valid(lo)) {
+               ff_layout = FF_LAYOUT_FROM_HDR(lo);
+               args->num_dev = ff_layout_mirror_prepare_stats(
+                       &ff_layout->generic_hdr, &args->devinfo[0], dev_count,
+                       NFS4_FF_OP_LAYOUTSTATS);
+       } else
+               args->num_dev = 0;
        spin_unlock(&args->inode->i_lock);
        if (!args->num_dev) {
                kfree(args->devinfo);
index 063e00a..28704f9 100644 (file)
@@ -81,7 +81,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
        if (status == 0) {
                if (nfs_should_remove_suid(inode)) {
                        spin_lock(&inode->i_lock);
-                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
+                       nfs_set_cache_invalid(inode,
+                               NFS_INO_REVAL_FORCED | NFS_INO_INVALID_MODE);
                        spin_unlock(&inode->i_lock);
                }
                status = nfs_post_op_update_inode_force_wcc(inode,
index 7016eaa..5ee283e 100644 (file)
@@ -8870,8 +8870,6 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cre
        /* Save the EXCHANGE_ID verifier session trunk tests */
        memcpy(clp->cl_confirm.data, argp->verifier.data,
               sizeof(clp->cl_confirm.data));
-       if (resp->flags & EXCHGID4_FLAG_USE_PNFS_DS)
-               set_bit(NFS_CS_DS, &clp->cl_flags);
 out:
        trace_nfs4_exchange_id(clp, status);
        rpc_put_task(task);
index 306cba0..84343ae 100644 (file)
@@ -2634,31 +2634,44 @@ pnfs_should_return_unused_layout(struct pnfs_layout_hdr *lo,
        return mode == 0;
 }
 
-static int
-pnfs_layout_return_unused_byserver(struct nfs_server *server, void *data)
+static int pnfs_layout_return_unused_byserver(struct nfs_server *server,
+                                             void *data)
 {
        const struct pnfs_layout_range *range = data;
+       const struct cred *cred;
        struct pnfs_layout_hdr *lo;
        struct inode *inode;
+       nfs4_stateid stateid;
+       enum pnfs_iomode iomode;
+
 restart:
        rcu_read_lock();
        list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
-               if (!pnfs_layout_can_be_returned(lo) ||
+               inode = lo->plh_inode;
+               if (!inode || !pnfs_layout_can_be_returned(lo) ||
                    test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags))
                        continue;
-               inode = lo->plh_inode;
                spin_lock(&inode->i_lock);
-               if (!pnfs_should_return_unused_layout(lo, range)) {
+               if (!lo->plh_inode ||
+                   !pnfs_should_return_unused_layout(lo, range)) {
                        spin_unlock(&inode->i_lock);
                        continue;
                }
+               pnfs_get_layout_hdr(lo);
+               pnfs_set_plh_return_info(lo, range->iomode, 0);
+               if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs,
+                                                   range, 0) != 0 ||
+                   !pnfs_prepare_layoutreturn(lo, &stateid, &cred, &iomode)) {
+                       spin_unlock(&inode->i_lock);
+                       rcu_read_unlock();
+                       pnfs_put_layout_hdr(lo);
+                       cond_resched();
+                       goto restart;
+               }
                spin_unlock(&inode->i_lock);
-               inode = pnfs_grab_inode_layout_hdr(lo);
-               if (!inode)
-                       continue;
                rcu_read_unlock();
-               pnfs_mark_layout_for_return(inode, range);
-               iput(inode);
+               pnfs_send_layoutreturn(lo, &stateid, &cred, iomode, false);
+               pnfs_put_layout_hdr(lo);
                cond_resched();
                goto restart;
        }
index 7720b5e..9d82d50 100644 (file)
@@ -788,6 +788,8 @@ static void nfs_inode_add_request(struct nfs_page *req)
  */
 static void nfs_inode_remove_request(struct nfs_page *req)
 {
+       struct nfs_inode *nfsi = NFS_I(nfs_page_to_inode(req));
+
        if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) {
                struct folio *folio = nfs_page_to_folio(req->wb_head);
                struct address_space *mapping = folio_file_mapping(folio);
@@ -802,7 +804,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        }
 
        if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
-               atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests);
+               atomic_long_dec(&nfsi->nrequests);
                nfs_release_request(req);
        }
 }