Merge tag 'nfs-for-4.18-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Jun 2018 21:21:34 +0000 (06:21 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Jun 2018 21:21:34 +0000 (06:21 +0900)
Pull NFS client bugfixes from Trond Myklebust:
 "Hightlights include:

   - fix an rcu deadlock in nfs_delegation_find_inode()

   - fix NFSv4 deadlocks due to not freeing the session slot in
     layoutget

   - don't send layoutreturn if the layout is already invalid

   - prevent duplicate XID allocation

   - flexfiles: Don't tie up all the rpciod threads in resends"

* tag 'nfs-for-4.18-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  pNFS/flexfiles: Process writeback resends from nfsiod context as well
  pNFS/flexfiles: Don't tie up all the rpciod threads in resends
  sunrpc: Prevent duplicate XID allocation
  pNFS: Don't send layoutreturn if the layout is already invalid
  pNFS: Always free the session slot on error in nfs4_layoutget_handle_exception
  NFS: Fix an rcu deadlock in nfs_delegation_find_inode()

1  2 
fs/nfs/flexfilelayout/flexfilelayout.c

index d4a07acad5989e1374f879f2cc46c284f9aa8c4f,1386b774ec95abbd9e163683b793555debd7c5bd..8f003792ccde1c24c3bcd444a609b888a629340f
@@@ -461,7 -461,7 +461,7 @@@ ff_layout_alloc_lseg(struct pnfs_layout
                fh_count = be32_to_cpup(p);
  
                fls->mirror_array[i]->fh_versions =
 -                      kzalloc(fh_count * sizeof(struct nfs_fh),
 +                      kcalloc(fh_count, sizeof(struct nfs_fh),
                                gfp_flags);
                if (fls->mirror_array[i]->fh_versions == NULL) {
                        rc = -ENOMEM;
@@@ -1243,17 -1243,18 +1243,18 @@@ static int ff_layout_read_done_cb(struc
                                           hdr->ds_clp, hdr->lseg,
                                           hdr->pgio_mirror_idx);
  
+       clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
+       clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
        switch (err) {
        case -NFS4ERR_RESET_TO_PNFS:
                if (ff_layout_choose_best_ds_for_read(hdr->lseg,
                                        hdr->pgio_mirror_idx + 1,
                                        &hdr->pgio_mirror_idx))
                        goto out_eagain;
-               ff_layout_read_record_layoutstats_done(task, hdr);
-               pnfs_read_resend_pnfs(hdr);
+               set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
                return task->tk_status;
        case -NFS4ERR_RESET_TO_MDS:
-               ff_layout_reset_read(hdr);
+               set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
                return task->tk_status;
        case -EAGAIN:
                goto out_eagain;
@@@ -1403,6 -1404,10 +1404,10 @@@ static void ff_layout_read_release(voi
        struct nfs_pgio_header *hdr = data;
  
        ff_layout_read_record_layoutstats_done(&hdr->task, hdr);
+       if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags))
+               pnfs_read_resend_pnfs(hdr);
+       else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
+               ff_layout_reset_read(hdr);
        pnfs_generic_rw_release(data);
  }
  
@@@ -1423,12 -1428,14 +1428,14 @@@ static int ff_layout_write_done_cb(stru
                                           hdr->ds_clp, hdr->lseg,
                                           hdr->pgio_mirror_idx);
  
+       clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
+       clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
        switch (err) {
        case -NFS4ERR_RESET_TO_PNFS:
-               ff_layout_reset_write(hdr, true);
+               set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
                return task->tk_status;
        case -NFS4ERR_RESET_TO_MDS:
-               ff_layout_reset_write(hdr, false);
+               set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
                return task->tk_status;
        case -EAGAIN:
                return -EAGAIN;
@@@ -1575,6 -1582,10 +1582,10 @@@ static void ff_layout_write_release(voi
        struct nfs_pgio_header *hdr = data;
  
        ff_layout_write_record_layoutstats_done(&hdr->task, hdr);
+       if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags))
+               ff_layout_reset_write(hdr, true);
+       else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
+               ff_layout_reset_write(hdr, false);
        pnfs_generic_rw_release(data);
  }