summaryrefslogtreecommitdiff
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorFred Isaman <fred.isaman@gmail.com>2016-10-05 16:37:12 +0300
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-05-31 22:03:11 +0300
commitc49b5209f99abe082d3d4cd94f0ad924baea34ed (patch)
tree315980082bc9f161fd2363668f9f42c067aebee8 /fs/nfs/pnfs.c
parent6e01260ceeca299b82d466660935534c5c909d54 (diff)
downloadlinux-c49b5209f99abe082d3d4cd94f0ad924baea34ed.tar.xz
pnfs: Add barrier to prevent lgopen using LAYOUTGET during recall
Since the LAYOUTGET on OPEN can be sent without prior inode information, existing methods to prevent LAYOUTGET from being sent while processing CB_LAYOUTRECALL don't work. Track if a recall occurred while LAYOUTGET was being sent, and if so ignore the results. Signed-off-by: Fred Isaman <fred.isaman@gmail.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 3dfe9fa264a5..a29fdea2db91 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1017,6 +1017,7 @@ pnfs_alloc_init_layoutget_args(struct inode *ino,
nfs4_stateid_copy(&lgp->args.stateid, stateid);
lgp->gfp_flags = gfp_flags;
lgp->cred = get_rpccred(ctx->cred);
+ lgp->callback_count = raw_seqcount_begin(&server->nfs_client->cl_callback_count);
return lgp;
}
@@ -2101,6 +2102,7 @@ void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
{
struct pnfs_layout_hdr *lo;
struct pnfs_layout_segment *lseg;
+ struct nfs_server *srv = NFS_SERVER(ino);
u32 iomode;
if (!lgp)
@@ -2116,7 +2118,7 @@ void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
/* FIXME - Any error not listed above permanently
* halts lgopen attempts.
*/
- NFS_SERVER(ino)->caps &= ~NFS_CAP_LGOPEN;
+ srv->caps &= ~NFS_CAP_LGOPEN;
}
return;
}
@@ -2129,6 +2131,9 @@ void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
lo = NFS_I(lgp->args.inode)->layout;
pnfs_get_layout_hdr(lo);
+ if (read_seqcount_retry(&srv->nfs_client->cl_callback_count,
+ lgp->callback_count))
+ goto out;
lseg = pnfs_layout_process(lgp);
atomic_dec(&lo->plh_outstanding);
if (IS_ERR(lseg)) {
@@ -2139,6 +2144,7 @@ void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
pnfs_put_lseg(lseg);
}
+out:
pnfs_clear_first_layoutget(lo);
pnfs_put_layout_hdr(lo);
}