nfs41: introduce NFS_LAYOUT_RETURN_BEFORE_CLOSE
authorPeng Tao <tao.peng@primarydata.com>
Mon, 17 Nov 2014 01:30:41 +0000 (09:30 +0800)
committerTom Haynes <loghyr@primarydata.com>
Tue, 3 Feb 2015 19:06:50 +0000 (11:06 -0800)
When it is set, generic pnfs would try to send layoutreturn right
before last close/delegation_return regard less NFS_LAYOUT_ROC is
set or not. LD can then make sure layoutreturn is always sent
rather than being omitted.

The difference against NFS_LAYOUT_RETURN is that
NFS_LAYOUT_RETURN_BEFORE_CLOSE does not block usage of the layout so
LD can set it and expect generic layer to try pnfs path at the
same time.

Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Tom Haynes <loghyr@primarydata.com>
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h

index 2397c0f080d30d5c2b6003fb9f98370722afce0c..7e1a97a54f99df89e955e1db2937b42d1d68070c 100644 (file)
@@ -7797,6 +7797,8 @@ static void nfs4_layoutreturn_release(void *calldata)
        if (lrp->res.lrs_present)
                pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
        clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
+       clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags);
+       rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);
        lo->plh_block_lgets--;
        spin_unlock(&lo->plh_inode->i_lock);
        pnfs_put_layout_hdr(lrp->args.layout);
index 0a0e209e8262eab99a5eb9f5e61c253ebac4baf2..d3c2ca71a76d88301c2e8de65e34c400f0082ad8 100644 (file)
@@ -909,6 +909,7 @@ pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, nfs4_stateid stateid,
                status = -ENOMEM;
                spin_lock(&ino->i_lock);
                lo->plh_block_lgets--;
+               rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq);
                spin_unlock(&ino->i_lock);
                pnfs_put_layout_hdr(lo);
                goto out;
@@ -926,11 +927,6 @@ pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, nfs4_stateid stateid,
 
        status = nfs4_proc_layoutreturn(lrp, sync);
 out:
-       if (status) {
-               spin_lock(&ino->i_lock);
-               clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
-               spin_unlock(&ino->i_lock);
-       }
        dprintk("<-- %s status: %d\n", __func__, status);
        return status;
 }
@@ -1028,8 +1024,9 @@ bool pnfs_roc(struct inode *ino)
 {
        struct pnfs_layout_hdr *lo;
        struct pnfs_layout_segment *lseg, *tmp;
+       nfs4_stateid stateid;
        LIST_HEAD(tmp_list);
-       bool found = false;
+       bool found = false, layoutreturn = false;
 
        spin_lock(&ino->i_lock);
        lo = NFS_I(ino)->layout;
@@ -1050,7 +1047,20 @@ bool pnfs_roc(struct inode *ino)
        return true;
 
 out_nolayout:
+       if (lo) {
+               stateid = lo->plh_stateid;
+               layoutreturn =
+                       test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
+                                          &lo->plh_flags);
+               if (layoutreturn) {
+                       lo->plh_block_lgets++;
+                       pnfs_get_layout_hdr(lo);
+               }
+       }
        spin_unlock(&ino->i_lock);
+       if (layoutreturn)
+               pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, 0,
+                                      NFS4_MAX_UINT64, true);
        return false;
 }
 
@@ -1085,8 +1095,9 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
        struct nfs_inode *nfsi = NFS_I(ino);
        struct pnfs_layout_hdr *lo;
        struct pnfs_layout_segment *lseg;
+       nfs4_stateid stateid;
        u32 current_seqid;
-       bool found = false;
+       bool found = false, layoutreturn = false;
 
        spin_lock(&ino->i_lock);
        list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list)
@@ -1103,7 +1114,22 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
         */
        *barrier = current_seqid + atomic_read(&lo->plh_outstanding);
 out:
+       if (!found) {
+               stateid = lo->plh_stateid;
+               layoutreturn =
+                       test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
+                                          &lo->plh_flags);
+               if (layoutreturn) {
+                       lo->plh_block_lgets++;
+                       pnfs_get_layout_hdr(lo);
+               }
+       }
        spin_unlock(&ino->i_lock);
+       if (layoutreturn) {
+               rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
+               pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, 0,
+                                      NFS4_MAX_UINT64, false);
+       }
        return found;
 }
 
index b79f494d59ac45c85a6ef95959da4fc3f4950cf5..080bf90498d4ac2ffbcd9864bd19c784b436fbd6 100644 (file)
@@ -96,6 +96,7 @@ enum {
        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
        NFS_LAYOUT_RETURN,              /* Return this layout ASAP */
+       NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */
        NFS_LAYOUT_INVALID_STID,        /* layout stateid id is invalid */
        NFS_LAYOUT_FIRST_LAYOUTGET,     /* Serialize first layoutget */
 };