Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c49b5209 authored by Fred Isaman's avatar Fred Isaman Committed by Trond Myklebust
Browse files

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: default avatarFred Isaman <fred.isaman@gmail.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 6e01260c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -322,6 +322,8 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
static u32 do_callback_layoutrecall(struct nfs_client *clp,
				    struct cb_layoutrecallargs *args)
{
	write_seqcount_begin(&clp->cl_callback_count);
	write_seqcount_end(&clp->cl_callback_count);
	if (args->cbl_recall_type == RETURN_FILE)
		return initiate_file_draining(clp, args);
	return initiate_bulk_draining(clp, args);
+7 −1
Original line number Diff line number Diff line
@@ -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);
}
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ struct nfs41_impl_id;
struct nfs_client {
	refcount_t		cl_count;
	atomic_t		cl_mds_count;
	seqcount_t		cl_callback_count;
	int			cl_cons_state;	/* current construction state (-ve: init error) */
#define NFS_CS_READY		0		/* ready to be used */
#define NFS_CS_INITING		1		/* busy initialising */
+1 −0
Original line number Diff line number Diff line
@@ -271,6 +271,7 @@ struct nfs4_layoutget {
	struct nfs4_layoutget_args args;
	struct nfs4_layoutget_res res;
	struct rpc_cred *cred;
	unsigned callback_count;
	gfp_t gfp_flags;
};