diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 83 | 
1 files changed, 80 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index a644460f3a5e..c7bfd2180e3f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1732,6 +1732,35 @@ nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,  	return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid);  } +static __be32 +nfsd4_decode_get_dir_delegation(struct nfsd4_compoundargs *argp, +		union nfsd4_op_u *u) +{ +	struct nfsd4_get_dir_delegation *gdd = &u->get_dir_delegation; +	__be32 status; + +	memset(gdd, 0, sizeof(*gdd)); + +	if (xdr_stream_decode_bool(argp->xdr, &gdd->gdda_signal_deleg_avail) < 0) +		return nfserr_bad_xdr; +	status = nfsd4_decode_bitmap4(argp, gdd->gdda_notification_types, +				      ARRAY_SIZE(gdd->gdda_notification_types)); +	if (status) +		return status; +	status = nfsd4_decode_nfstime4(argp, &gdd->gdda_child_attr_delay); +	if (status) +		return status; +	status = nfsd4_decode_nfstime4(argp, &gdd->gdda_dir_attr_delay); +	if (status) +		return status; +	status = nfsd4_decode_bitmap4(argp, gdd->gdda_child_attributes, +					ARRAY_SIZE(gdd->gdda_child_attributes)); +	if (status) +		return status; +	return nfsd4_decode_bitmap4(argp, gdd->gdda_dir_attributes, +					ARRAY_SIZE(gdd->gdda_dir_attributes)); +} +  #ifdef CONFIG_NFSD_PNFS  static __be32  nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp, @@ -2370,7 +2399,7 @@ static const nfsd4_dec nfsd4_dec_ops[] = {  	[OP_CREATE_SESSION]	= nfsd4_decode_create_session,  	[OP_DESTROY_SESSION]	= nfsd4_decode_destroy_session,  	[OP_FREE_STATEID]	= nfsd4_decode_free_stateid, -	[OP_GET_DIR_DELEGATION]	= nfsd4_decode_notsupp, +	[OP_GET_DIR_DELEGATION]	= nfsd4_decode_get_dir_delegation,  #ifdef CONFIG_NFSD_PNFS  	[OP_GETDEVICEINFO]	= nfsd4_decode_getdeviceinfo,  	[OP_GETDEVICELIST]	= nfsd4_decode_notsupp, @@ -4963,6 +4992,49 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,  	return nfs_ok;  } +static __be32 +nfsd4_encode_get_dir_delegation(struct nfsd4_compoundres *resp, __be32 nfserr, +				union nfsd4_op_u *u) +{ +	struct nfsd4_get_dir_delegation *gdd = &u->get_dir_delegation; +	struct xdr_stream *xdr = resp->xdr; +	__be32 status = nfserr_resource; + +	switch(gdd->gddrnf_status) { +	case GDD4_OK: +		if (xdr_stream_encode_u32(xdr, GDD4_OK) != XDR_UNIT) +			break; +		status = nfsd4_encode_verifier4(xdr, &gdd->gddr_cookieverf); +		if (status) +			break; +		status = nfsd4_encode_stateid4(xdr, &gdd->gddr_stateid); +		if (status) +			break; +		status = nfsd4_encode_bitmap4(xdr, gdd->gddr_notification[0], 0, 0); +		if (status) +			break; +		status = nfsd4_encode_bitmap4(xdr, gdd->gddr_child_attributes[0], +						   gdd->gddr_child_attributes[1], +						   gdd->gddr_child_attributes[2]); +		if (status) +			break; +		status = nfsd4_encode_bitmap4(xdr, gdd->gddr_dir_attributes[0], +						   gdd->gddr_dir_attributes[1], +						   gdd->gddr_dir_attributes[2]); +		break; +	default: +		pr_warn("nfsd: bad gddrnf_status (%u)\n", gdd->gddrnf_status); +		gdd->gddrnf_will_signal_deleg_avail = 0; +		fallthrough; +	case GDD4_UNAVAIL: +		if (xdr_stream_encode_u32(xdr, GDD4_UNAVAIL) != XDR_UNIT) +			break; +		status = nfsd4_encode_bool(xdr, gdd->gddrnf_will_signal_deleg_avail); +		break; +	} +	return status; +} +  #ifdef CONFIG_NFSD_PNFS  static __be32  nfsd4_encode_device_addr4(struct xdr_stream *xdr, @@ -5199,7 +5271,12 @@ nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr,  	if (nfserr != nfs_ok)  		return nfserr;  	/* osr_complete<1> */ -	if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT) +	if (os->completed) { +		if (xdr_stream_encode_u32(xdr, 1) != XDR_UNIT) +			return nfserr_resource; +		if (xdr_stream_encode_be32(xdr, os->status) != XDR_UNIT) +			return nfserr_resource; +	} else if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)  		return nfserr_resource;  	return nfs_ok;  } @@ -5579,7 +5656,7 @@ static const nfsd4_enc nfsd4_enc_ops[] = {  	[OP_CREATE_SESSION]	= nfsd4_encode_create_session,  	[OP_DESTROY_SESSION]	= nfsd4_encode_noop,  	[OP_FREE_STATEID]	= nfsd4_encode_noop, -	[OP_GET_DIR_DELEGATION]	= nfsd4_encode_noop, +	[OP_GET_DIR_DELEGATION]	= nfsd4_encode_get_dir_delegation,  #ifdef CONFIG_NFSD_PNFS  	[OP_GETDEVICEINFO]	= nfsd4_encode_getdeviceinfo,  	[OP_GETDEVICELIST]	= nfsd4_encode_noop,  |