pNFS: If we have to delay the layout callback, mark the layout for return
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 28 Dec 2015 15:28:59 +0000 (10:28 -0500)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 28 Dec 2015 19:33:04 +0000 (14:33 -0500)
If the client needs to delay the layout callback, then speed up the recall
process by marking the remaining layout segments to be actively returned
by the client.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/callback_proc.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h

index 716cbff244501d57c616931c2d0ac059db3d7394..34852ece4057f90cdab96ae0e07dd42978cccfdc 100644 (file)
@@ -181,9 +181,19 @@ static u32 initiate_file_draining(struct nfs_client *clp,
        pnfs_layoutcommit_inode(ino, false);
 
        spin_lock(&ino->i_lock);
-       if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
-           pnfs_mark_matching_lsegs_invalid(lo, &free_me_list,
+       /*
+        * Enforce RFC5661 Section 12.5.5.2.1.5 (Bulk Recall and Return)
+        */
+       if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
+               rv = NFS4ERR_DELAY;
+               goto unlock;
+       }
+
+       if (pnfs_mark_matching_lsegs_invalid(lo, &free_me_list,
                                        &args->cbl_range)) {
+               pnfs_mark_matching_lsegs_return(lo,
+                               &free_me_list,
+                               &args->cbl_range);
                rv = NFS4ERR_DELAY;
                goto unlock;
        }
index b3fb6bb02275f1e53dcb3ccde80c45c4a381b2cd..360fe95c97b5daa5b6732c63a44743144b8a17b6 100644 (file)
@@ -1756,7 +1756,7 @@ out_forget_reply:
        goto out;
 }
 
-static void
+void
 pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
                                struct list_head *tmp_list,
                                struct pnfs_layout_range *return_range)
@@ -1768,6 +1768,8 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
        if (list_empty(&lo->plh_segs))
                return;
 
+       assert_spin_locked(&lo->plh_inode->i_lock);
+
        list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
                if (should_free_lseg(&lseg->pls_range, return_range)) {
                        dprintk("%s: marking lseg %p iomode %d "
index be24a759b655989be973f79bd7a9157c9dc9d075..d93c2ebc0fd354c9e40f2fadffdadf7935cbff81 100644 (file)
@@ -266,6 +266,9 @@ int pnfs_choose_layoutget_stateid(nfs4_stateid *dst,
 int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
                                struct list_head *tmp_list,
                                struct pnfs_layout_range *recall_range);
+void pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
+                               struct list_head *tmp_list,
+                               struct pnfs_layout_range *recall_range);
 bool pnfs_roc(struct inode *ino);
 void pnfs_roc_release(struct inode *ino);
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);