diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 132 | 
1 files changed, 123 insertions, 9 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c3ccd2c4683..d869a5e5464 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -338,7 +338,11 @@ static int nfs4_stat_to_errno(int);  				1 /* layoutupdate4 layout type */ + \  				1 /* NULL filelayout layoutupdate4 payload */)  #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) - +#define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ +				encode_stateid_maxsz + \ +				1 /* FIXME: opaque lrf_body always empty at the moment */) +#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \ +				1 + decode_stateid_maxsz)  #else /* CONFIG_NFS_V4_1 */  #define encode_sequence_maxsz	0  #define decode_sequence_maxsz	0 @@ -760,7 +764,14 @@ static int nfs4_stat_to_errno(int);  				decode_putfh_maxsz + \  				decode_layoutcommit_maxsz + \  				decode_getattr_maxsz) - +#define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \ +				encode_sequence_maxsz + \ +				encode_putfh_maxsz + \ +				encode_layoutreturn_maxsz) +#define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \ +				decode_sequence_maxsz + \ +				decode_putfh_maxsz + \ +				decode_layoutreturn_maxsz)  const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +  				      compound_encode_hdr_maxsz + @@ -1864,6 +1875,7 @@ encode_layoutget(struct xdr_stream *xdr,  static int  encode_layoutcommit(struct xdr_stream *xdr, +		    struct inode *inode,  		    const struct nfs4_layoutcommit_args *args,  		    struct compound_hdr *hdr)  { @@ -1872,7 +1884,7 @@ encode_layoutcommit(struct xdr_stream *xdr,  	dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten,  		NFS_SERVER(args->inode)->pnfs_curr_ld->id); -	p = reserve_space(xdr, 48 + NFS4_STATEID_SIZE); +	p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE);  	*p++ = cpu_to_be32(OP_LAYOUTCOMMIT);  	/* Only whole file layouts */  	p = xdr_encode_hyper(p, 0); /* offset */ @@ -1883,12 +1895,49 @@ encode_layoutcommit(struct xdr_stream *xdr,  	p = xdr_encode_hyper(p, args->lastbytewritten);  	*p++ = cpu_to_be32(0); /* Never send time_modify_changed */  	*p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ -	*p++ = cpu_to_be32(0); /* no file layout payload */ + +	if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) +		NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit( +			NFS_I(inode)->layout, xdr, args); +	else { +		p = reserve_space(xdr, 4); +		*p = cpu_to_be32(0); /* no layout-type payload */ +	}  	hdr->nops++;  	hdr->replen += decode_layoutcommit_maxsz;  	return 0;  } + +static void +encode_layoutreturn(struct xdr_stream *xdr, +		    const struct nfs4_layoutreturn_args *args, +		    struct compound_hdr *hdr) +{ +	__be32 *p; + +	p = reserve_space(xdr, 20); +	*p++ = cpu_to_be32(OP_LAYOUTRETURN); +	*p++ = cpu_to_be32(0);		/* reclaim. always 0 for now */ +	*p++ = cpu_to_be32(args->layout_type); +	*p++ = cpu_to_be32(IOMODE_ANY); +	*p = cpu_to_be32(RETURN_FILE); +	p = reserve_space(xdr, 16 + NFS4_STATEID_SIZE); +	p = xdr_encode_hyper(p, 0); +	p = xdr_encode_hyper(p, NFS4_MAX_UINT64); +	spin_lock(&args->inode->i_lock); +	xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); +	spin_unlock(&args->inode->i_lock); +	if (NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn) { +		NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn( +			NFS_I(args->inode)->layout, xdr, args); +	} else { +		p = reserve_space(xdr, 4); +		*p = cpu_to_be32(0); +	} +	hdr->nops++; +	hdr->replen += decode_layoutreturn_maxsz; +}  #endif /* CONFIG_NFS_V4_1 */  /* @@ -2706,10 +2755,12 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,  /*   *  Encode LAYOUTCOMMIT request   */ -static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, -				     struct xdr_stream *xdr, -				     struct nfs4_layoutcommit_args *args) +static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, +				      struct xdr_stream *xdr, +				      struct nfs4_layoutcommit_args *args)  { +	struct nfs4_layoutcommit_data *data = +		container_of(args, struct nfs4_layoutcommit_data, args);  	struct compound_hdr hdr = {  		.minorversion = nfs4_xdr_minorversion(&args->seq_args),  	}; @@ -2717,10 +2768,27 @@ static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,  	encode_compound_hdr(xdr, req, &hdr);  	encode_sequence(xdr, &args->seq_args, &hdr);  	encode_putfh(xdr, NFS_FH(args->inode), &hdr); -	encode_layoutcommit(xdr, args, &hdr); +	encode_layoutcommit(xdr, data->args.inode, args, &hdr);  	encode_getfattr(xdr, args->bitmask, &hdr);  	encode_nops(&hdr); -	return 0; +} + +/* + * Encode LAYOUTRETURN request + */ +static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req, +				      struct xdr_stream *xdr, +				      struct nfs4_layoutreturn_args *args) +{ +	struct compound_hdr hdr = { +		.minorversion = nfs4_xdr_minorversion(&args->seq_args), +	}; + +	encode_compound_hdr(xdr, req, &hdr); +	encode_sequence(xdr, &args->seq_args, &hdr); +	encode_putfh(xdr, NFS_FH(args->inode), &hdr); +	encode_layoutreturn(xdr, args, &hdr); +	encode_nops(&hdr);  }  #endif /* CONFIG_NFS_V4_1 */ @@ -5203,6 +5271,27 @@ out_overflow:  	return -EIO;  } +static int decode_layoutreturn(struct xdr_stream *xdr, +			       struct nfs4_layoutreturn_res *res) +{ +	__be32 *p; +	int status; + +	status = decode_op_hdr(xdr, OP_LAYOUTRETURN); +	if (status) +		return status; +	p = xdr_inline_decode(xdr, 4); +	if (unlikely(!p)) +		goto out_overflow; +	res->lrs_present = be32_to_cpup(p); +	if (res->lrs_present) +		status = decode_stateid(xdr, &res->stateid); +	return status; +out_overflow: +	print_overflow_msg(__func__, xdr); +	return -EIO; +} +  static int decode_layoutcommit(struct xdr_stream *xdr,  			       struct rpc_rqst *req,  			       struct nfs4_layoutcommit_res *res) @@ -6320,6 +6409,30 @@ out:  }  /* + * Decode LAYOUTRETURN response + */ +static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp, +				     struct xdr_stream *xdr, +				     struct nfs4_layoutreturn_res *res) +{ +	struct compound_hdr hdr; +	int status; + +	status = decode_compound_hdr(xdr, &hdr); +	if (status) +		goto out; +	status = decode_sequence(xdr, &res->seq_res, rqstp); +	if (status) +		goto out; +	status = decode_putfh(xdr); +	if (status) +		goto out; +	status = decode_layoutreturn(xdr, res); +out: +	return status; +} + +/*   * Decode LAYOUTCOMMIT response   */  static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, @@ -6547,6 +6660,7 @@ struct rpc_procinfo	nfs4_procedures[] = {  	PROC(GETDEVICEINFO,	enc_getdeviceinfo,	dec_getdeviceinfo),  	PROC(LAYOUTGET,		enc_layoutget,		dec_layoutget),  	PROC(LAYOUTCOMMIT,	enc_layoutcommit,	dec_layoutcommit), +	PROC(LAYOUTRETURN,	enc_layoutreturn,	dec_layoutreturn),  #endif /* CONFIG_NFS_V4_1 */  };  |