diff options
Diffstat (limited to 'fs/nfsd/nfs4callback.c')
| -rw-r--r-- | fs/nfsd/nfs4callback.c | 64 | 
1 files changed, 60 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 04c68d900324..211dc2aed8e1 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -448,7 +448,7 @@ static int decode_cb_sequence4res(struct xdr_stream *xdr,  {  	int status; -	if (cb->cb_minorversion == 0) +	if (cb->cb_clp->cl_minorversion == 0)  		return 0;  	status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &cb->cb_seq_status); @@ -485,7 +485,7 @@ static void nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, struct xdr_stream *xdr,  	const struct nfs4_delegation *dp = cb_to_delegation(cb);  	struct nfs4_cb_compound_hdr hdr = {  		.ident = cb->cb_clp->cl_cb_ident, -		.minorversion = cb->cb_minorversion, +		.minorversion = cb->cb_clp->cl_minorversion,  	};  	encode_cb_compound4args(xdr, &hdr); @@ -594,7 +594,7 @@ static void nfs4_xdr_enc_cb_layout(struct rpc_rqst *req,  		container_of(cb, struct nfs4_layout_stateid, ls_recall);  	struct nfs4_cb_compound_hdr hdr = {  		.ident = 0, -		.minorversion = cb->cb_minorversion, +		.minorversion = cb->cb_clp->cl_minorversion,  	};  	encode_cb_compound4args(xdr, &hdr); @@ -623,6 +623,62 @@ static int nfs4_xdr_dec_cb_layout(struct rpc_rqst *rqstp,  }  #endif /* CONFIG_NFSD_PNFS */ +static void encode_stateowner(struct xdr_stream *xdr, struct nfs4_stateowner *so) +{ +	__be32	*p; + +	p = xdr_reserve_space(xdr, 8 + 4 + so->so_owner.len); +	p = xdr_encode_opaque_fixed(p, &so->so_client->cl_clientid, 8); +	xdr_encode_opaque(p, so->so_owner.data, so->so_owner.len); +} + +static void nfs4_xdr_enc_cb_notify_lock(struct rpc_rqst *req, +					struct xdr_stream *xdr, +					const struct nfsd4_callback *cb) +{ +	const struct nfsd4_blocked_lock *nbl = +		container_of(cb, struct nfsd4_blocked_lock, nbl_cb); +	struct nfs4_lockowner *lo = (struct nfs4_lockowner *)nbl->nbl_lock.fl_owner; +	struct nfs4_cb_compound_hdr hdr = { +		.ident = 0, +		.minorversion = cb->cb_clp->cl_minorversion, +	}; + +	__be32 *p; + +	BUG_ON(hdr.minorversion == 0); + +	encode_cb_compound4args(xdr, &hdr); +	encode_cb_sequence4args(xdr, cb, &hdr); + +	p = xdr_reserve_space(xdr, 4); +	*p = cpu_to_be32(OP_CB_NOTIFY_LOCK); +	encode_nfs_fh4(xdr, &nbl->nbl_fh); +	encode_stateowner(xdr, &lo->lo_owner); +	hdr.nops++; + +	encode_cb_nops(&hdr); +} + +static int nfs4_xdr_dec_cb_notify_lock(struct rpc_rqst *rqstp, +					struct xdr_stream *xdr, +					struct nfsd4_callback *cb) +{ +	struct nfs4_cb_compound_hdr hdr; +	int status; + +	status = decode_cb_compound4res(xdr, &hdr); +	if (unlikely(status)) +		return status; + +	if (cb) { +		status = decode_cb_sequence4res(xdr, cb); +		if (unlikely(status || cb->cb_seq_status)) +			return status; +	} +	return decode_cb_op_status(xdr, OP_CB_NOTIFY_LOCK, &cb->cb_status); +} +  /*   * RPC procedure tables   */ @@ -643,6 +699,7 @@ static struct rpc_procinfo nfs4_cb_procedures[] = {  #ifdef CONFIG_NFSD_PNFS  	PROC(CB_LAYOUT,	COMPOUND,	cb_layout,	cb_layout),  #endif +	PROC(CB_NOTIFY_LOCK,	COMPOUND,	cb_notify_lock,	cb_notify_lock),  };  static struct rpc_version nfs_cb_version4 = { @@ -862,7 +919,6 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)  	struct nfs4_client *clp = cb->cb_clp;  	u32 minorversion = clp->cl_minorversion; -	cb->cb_minorversion = minorversion;  	/*  	 * cb_seq_status is only set in decode_cb_sequence4res,  	 * and so will remain 1 if an rpc level failure occurs.  |