Commit a11ada99 authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Move copy offload callback arguments into a separate structure



Refactor so that CB_OFFLOAD arguments can be passed without
allocating a whole struct nfsd4_copy object. On my system (x86_64)
this removes another 96 bytes from struct nfsd4_copy.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent e72f9bc0
Loading
Loading
Loading
Loading
+18 −19
Original line number Diff line number Diff line
@@ -688,21 +688,22 @@ static int nfs4_xdr_dec_cb_notify_lock(struct rpc_rqst *rqstp,
 * };
 */
static void encode_offload_info4(struct xdr_stream *xdr,
				 __be32 nfserr,
				 const struct nfsd4_copy *cp)
				 const struct nfsd4_cb_offload *cbo)
{
	__be32 *p;

	p = xdr_reserve_space(xdr, 4);
	*p++ = nfserr;
	if (!nfserr) {
	*p = cbo->co_nfserr;
	switch (cbo->co_nfserr) {
	case nfs_ok:
		p = xdr_reserve_space(xdr, 4 + 8 + 4 + NFS4_VERIFIER_SIZE);
		p = xdr_encode_empty_array(p);
		p = xdr_encode_hyper(p, cp->cp_res.wr_bytes_written);
		*p++ = cpu_to_be32(cp->cp_res.wr_stable_how);
		p = xdr_encode_opaque_fixed(p, cp->cp_res.wr_verifier.data,
		p = xdr_encode_hyper(p, cbo->co_res.wr_bytes_written);
		*p++ = cpu_to_be32(cbo->co_res.wr_stable_how);
		p = xdr_encode_opaque_fixed(p, cbo->co_res.wr_verifier.data,
					    NFS4_VERIFIER_SIZE);
	} else {
		break;
	default:
		p = xdr_reserve_space(xdr, 8);
		/* We always return success if bytes were written */
		p = xdr_encode_hyper(p, 0);
@@ -710,18 +711,16 @@ static void encode_offload_info4(struct xdr_stream *xdr,
}

static void encode_cb_offload4args(struct xdr_stream *xdr,
				   __be32 nfserr,
				   const struct knfsd_fh *fh,
				   const struct nfsd4_copy *cp,
				   const struct nfsd4_cb_offload *cbo,
				   struct nfs4_cb_compound_hdr *hdr)
{
	__be32 *p;

	p = xdr_reserve_space(xdr, 4);
	*p++ = cpu_to_be32(OP_CB_OFFLOAD);
	encode_nfs_fh4(xdr, fh);
	encode_stateid4(xdr, &cp->cp_res.cb_stateid);
	encode_offload_info4(xdr, nfserr, cp);
	*p = cpu_to_be32(OP_CB_OFFLOAD);
	encode_nfs_fh4(xdr, &cbo->co_fh);
	encode_stateid4(xdr, &cbo->co_res.cb_stateid);
	encode_offload_info4(xdr, cbo);

	hdr->nops++;
}
@@ -731,8 +730,8 @@ static void nfs4_xdr_enc_cb_offload(struct rpc_rqst *req,
				    const void *data)
{
	const struct nfsd4_callback *cb = data;
	const struct nfsd4_copy *cp =
		container_of(cb, struct nfsd4_copy, cp_cb);
	const struct nfsd4_cb_offload *cbo =
		container_of(cb, struct nfsd4_cb_offload, co_cb);
	struct nfs4_cb_compound_hdr hdr = {
		.ident = 0,
		.minorversion = cb->cb_clp->cl_minorversion,
@@ -740,7 +739,7 @@ static void nfs4_xdr_enc_cb_offload(struct rpc_rqst *req,

	encode_cb_compound4args(xdr, &hdr);
	encode_cb_sequence4args(xdr, cb, &hdr);
	encode_cb_offload4args(xdr, cp->nfserr, &cp->fh, cp, &hdr);
	encode_cb_offload4args(xdr, cbo, &hdr);
	encode_cb_nops(&hdr);
}

+22 −22
Original line number Diff line number Diff line
@@ -1645,9 +1645,10 @@ nfsd4_cleanup_intra_ssc(struct nfsd_file *src, struct nfsd_file *dst)

static void nfsd4_cb_offload_release(struct nfsd4_callback *cb)
{
	struct nfsd4_copy *copy = container_of(cb, struct nfsd4_copy, cp_cb);
	struct nfsd4_cb_offload *cbo =
		container_of(cb, struct nfsd4_cb_offload, co_cb);

	nfs4_put_copy(copy);
	kfree(cbo);
}

static int nfsd4_cb_offload_done(struct nfsd4_callback *cb,
@@ -1763,25 +1764,23 @@ static void cleanup_async_copy(struct nfsd4_copy *copy)
	nfs4_put_copy(copy);
}

static void nfsd4_send_cb_offload(struct nfsd4_copy *copy)
static void nfsd4_send_cb_offload(struct nfsd4_copy *copy, __be32 nfserr)
{
	struct nfsd4_copy *cb_copy;
	struct nfsd4_cb_offload *cbo;

	cb_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
	if (!cb_copy)
	cbo = kzalloc(sizeof(*cbo), GFP_KERNEL);
	if (!cbo)
		return;

	refcount_set(&cb_copy->refcount, 1);
	memcpy(&cb_copy->cp_res, &copy->cp_res, sizeof(copy->cp_res));
	cb_copy->cp_clp = copy->cp_clp;
	cb_copy->nfserr = copy->nfserr;
	memcpy(&cb_copy->fh, &copy->fh, sizeof(copy->fh));
	memcpy(&cbo->co_res, &copy->cp_res, sizeof(copy->cp_res));
	memcpy(&cbo->co_fh, &copy->fh, sizeof(copy->fh));
	cbo->co_nfserr = nfserr;

	nfsd4_init_cb(&cb_copy->cp_cb, cb_copy->cp_clp,
			&nfsd4_cb_offload_ops, NFSPROC4_CLNT_CB_OFFLOAD);
	trace_nfsd_cb_offload(copy->cp_clp, &copy->cp_res.cb_stateid,
			      &copy->fh, copy->cp_count, copy->nfserr);
	nfsd4_run_cb(&cb_copy->cp_cb);
	nfsd4_init_cb(&cbo->co_cb, copy->cp_clp, &nfsd4_cb_offload_ops,
		      NFSPROC4_CLNT_CB_OFFLOAD);
	trace_nfsd_cb_offload(copy->cp_clp, &cbo->co_res.cb_stateid,
			      &cbo->co_fh, copy->cp_count, nfserr);
	nfsd4_run_cb(&cbo->co_cb);
}

/**
@@ -1794,6 +1793,7 @@ static void nfsd4_send_cb_offload(struct nfsd4_copy *copy)
static int nfsd4_do_async_copy(void *data)
{
	struct nfsd4_copy *copy = (struct nfsd4_copy *)data;
	__be32 nfserr;

	if (nfsd4_ssc_is_inter(copy)) {
		struct file *filp;
@@ -1801,21 +1801,21 @@ static int nfsd4_do_async_copy(void *data)
		filp = nfs42_ssc_open(copy->ss_mnt, &copy->c_fh,
				      &copy->stateid);
		if (IS_ERR(filp)) {
			copy->nfserr = nfserr_offload_denied;
			nfserr = nfserr_offload_denied;
			nfsd4_interssc_disconnect(copy->ss_mnt);
			goto do_callback;
		}
		copy->nfserr = nfsd4_do_copy(copy, filp,
					     copy->nf_dst->nf_file, false);
		nfserr = nfsd4_do_copy(copy, filp, copy->nf_dst->nf_file,
				       false);
		nfsd4_cleanup_inter_ssc(copy->ss_mnt, filp, copy->nf_dst);
	} else {
		copy->nfserr = nfsd4_do_copy(copy, copy->nf_src->nf_file,
		nfserr = nfsd4_do_copy(copy, copy->nf_src->nf_file,
				       copy->nf_dst->nf_file, false);
		nfsd4_cleanup_intra_ssc(copy->nf_src, copy->nf_dst);
	}

do_callback:
	nfsd4_send_cb_offload(copy);
	nfsd4_send_cb_offload(copy, nfserr);
	cleanup_async_copy(copy);
	return 0;
}
+7 −4
Original line number Diff line number Diff line
@@ -533,6 +533,13 @@ struct nfsd42_write_res {
	stateid_t		cb_stateid;
};

struct nfsd4_cb_offload {
	struct nfsd4_callback	co_cb;
	struct nfsd42_write_res	co_res;
	__be32			co_nfserr;
	struct knfsd_fh		co_fh;
};

struct nfsd4_copy {
	/* request */
	stateid_t		cp_src_stateid;
@@ -550,10 +557,6 @@ struct nfsd4_copy {

	/* response */
	struct nfsd42_write_res	cp_res;

	/* for cb_offload */
	struct nfsd4_callback	cp_cb;
	__be32			nfserr;
	struct knfsd_fh		fh;

	struct nfs4_client      *cp_clp;