Commit d3edfd9e authored by Jeff Layton's avatar Jeff Layton Committed by Chuck Lever
Browse files

nfsd: implement OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION



Allow clients to request getting a delegation xor an open stateid if a
delegation isn't available. This allows the client to avoid sending a
final CLOSE for the (useless) open stateid, when it is granted a
delegation.

If this flag is requested by the client and there isn't already a new
open stateid, discard the new open stateid before replying.

Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 7e13f4f8
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -6242,6 +6242,17 @@ static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
	 */
}

/* Are we returning only a delegation stateid? */
static bool open_xor_delegation(struct nfsd4_open *open)
{
	if (!(open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION))
		return false;
	/* Did we actually get a delegation? */
	if (!deleg_is_read(open->op_delegate_type) && !deleg_is_write(open->op_delegate_type))
		return false;
	return true;
}

/**
 * nfsd4_process_open2 - finish open processing
 * @rqstp: the RPC transaction being executed
@@ -6339,6 +6350,17 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
	* OPEN succeeds even if we fail.
	*/
	nfs4_open_delegation(open, stp, &resp->cstate.current_fh);

	/*
	 * If there is an existing open stateid, it must be updated and
	 * returned. Only respect WANT_OPEN_XOR_DELEGATION when a new
	 * open stateid would have to be created.
	 */
	if (new_stp && open_xor_delegation(open)) {
		memcpy(&open->op_stateid, &zero_stateid, sizeof(open->op_stateid));
		open->op_rflags |= OPEN4_RESULT_NO_OPEN_STATEID;
		release_open_stateid(stp);
	}
nodeleg:
	status = nfs_ok;
	trace_nfsd_open(&stp->st_stid.sc_stateid);
@@ -6355,7 +6377,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
	/*
	* To finish the open response, we just need to set the rflags.
	*/
	open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
	open->op_rflags |= NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
	if (nfsd4_has_session(&resp->cstate))
		open->op_rflags |= NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK;
	else if (!(open->op_openowner->oo_flags & NFS4_OO_CONFIRMED))
+2 −1
Original line number Diff line number Diff line
@@ -3421,7 +3421,8 @@ static __be32 nfsd4_encode_fattr4_xattr_support(struct xdr_stream *xdr,
#define NFSD_OA_SHARE_ACCESS_WANT	(BIT(OPEN_ARGS_SHARE_ACCESS_WANT_ANY_DELEG)		| \
					 BIT(OPEN_ARGS_SHARE_ACCESS_WANT_NO_DELEG)		| \
					 BIT(OPEN_ARGS_SHARE_ACCESS_WANT_CANCEL)		| \
					 BIT(OPEN_ARGS_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS))
					 BIT(OPEN_ARGS_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS)	| \
					 BIT(OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION))

#define NFSD_OA_OPEN_CLAIM	(BIT(OPEN_ARGS_OPEN_CLAIM_NULL)		| \
				 BIT(OPEN_ARGS_OPEN_CLAIM_PREVIOUS)	| \