nfs41: don't use a layout if it is marked for returning
authorPeng Tao <tao.peng@primarydata.com>
Fri, 5 Sep 2014 16:53:24 +0000 (00:53 +0800)
committerTom Haynes <loghyr@primarydata.com>
Tue, 3 Feb 2015 19:06:41 +0000 (11:06 -0800)
And if we are to return the same type of layouts, don't bother
sending more layoutgets.

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

index f358262a95f98b0d6de29d3b13b4e7749c804dc9..19432842b2dc7fc4df5a68cd4551650fe7983f55 100644 (file)
@@ -7540,6 +7540,7 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
                return;
        if (pnfs_choose_layoutget_stateid(&lgp->args.stateid,
                                          NFS_I(lgp->args.inode)->layout,
+                                         &lgp->args.range,
                                          lgp->args.ctx->state)) {
                rpc_exit(task, NFS4_OK);
        }
index 0bd149baca71e0900883a496b7d9ce8c96bd69b0..853b544f2efc46ad396cd91e00e9801fc03484e2 100644 (file)
@@ -740,25 +740,37 @@ pnfs_layout_stateid_blocked(const struct pnfs_layout_hdr *lo,
        return !pnfs_seqid_is_newer(seqid, lo->plh_barrier);
 }
 
+static bool
+pnfs_layout_returning(const struct pnfs_layout_hdr *lo,
+                     struct pnfs_layout_range *range)
+{
+       return test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags) &&
+               (lo->plh_return_iomode == IOMODE_ANY ||
+                lo->plh_return_iomode == range->iomode);
+}
+
 /* lget is set to 1 if called from inside send_layoutget call chain */
 static bool
-pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo, int lget)
+pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo,
+                       struct pnfs_layout_range *range, int lget)
 {
        return lo->plh_block_lgets ||
                test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
                (list_empty(&lo->plh_segs) &&
-                (atomic_read(&lo->plh_outstanding) > lget));
+                (atomic_read(&lo->plh_outstanding) > lget)) ||
+               pnfs_layout_returning(lo, range);
 }
 
 int
 pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
+                             struct pnfs_layout_range *range,
                              struct nfs4_state *open_state)
 {
        int status = 0;
 
        dprintk("--> %s\n", __func__);
        spin_lock(&lo->plh_inode->i_lock);
-       if (pnfs_layoutgets_blocked(lo, 1)) {
+       if (pnfs_layoutgets_blocked(lo, range, 1)) {
                status = -EAGAIN;
        } else if (!nfs4_valid_open_stateid(open_state)) {
                status = -EBADF;
@@ -1192,6 +1204,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
 
        list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
                if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) &&
+                   !test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags) &&
                    pnfs_lseg_range_match(&lseg->pls_range, range)) {
                        ret = pnfs_get_lseg(lseg);
                        break;
@@ -1351,7 +1364,7 @@ lookup_again:
                        goto out_unlock;
        }
 
-       if (pnfs_layoutgets_blocked(lo, 0))
+       if (pnfs_layoutgets_blocked(lo, &arg, 0))
                goto out_unlock;
        atomic_inc(&lo->plh_outstanding);
        spin_unlock(&ino->i_lock);
@@ -1432,7 +1445,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                goto out_forget_reply;
        }
 
-       if (pnfs_layoutgets_blocked(lo, 1)) {
+       if (pnfs_layoutgets_blocked(lo, &lgp->args.range, 1)) {
                dprintk("%s forget reply due to state\n", __func__);
                goto out_forget_reply;
        }
index bea2030eec74f25b2df5402ab0f45fe3f4256c83..9e6edd1ebbc61ad17458e05e5232b54e7943d219 100644 (file)
@@ -249,6 +249,7 @@ void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
                             bool update_barrier);
 int pnfs_choose_layoutget_stateid(nfs4_stateid *dst,
                                  struct pnfs_layout_hdr *lo,
+                                 struct pnfs_layout_range *range,
                                  struct nfs4_state *open_state);
 int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
                                struct list_head *tmp_list,