Commit 92d82e99 authored by Chuck Lever's avatar Chuck Lever

NFSD: Remove a layering violation when encoding lock_denied

An XDR encoder is responsible for marshaling results, not releasing
memory that was allocated by the upper layer. We have .op_release
for that purpose.

Move the release of the ld_owner.data string to op_release functions
for LOCK and LOCKT.
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 4bbe42e8
...@@ -3210,6 +3210,7 @@ static const struct nfsd4_operation nfsd4_ops[] = { ...@@ -3210,6 +3210,7 @@ static const struct nfsd4_operation nfsd4_ops[] = {
}, },
[OP_LOCK] = { [OP_LOCK] = {
.op_func = nfsd4_lock, .op_func = nfsd4_lock,
.op_release = nfsd4_lock_release,
.op_flags = OP_MODIFIES_SOMETHING | .op_flags = OP_MODIFIES_SOMETHING |
OP_NONTRIVIAL_ERROR_ENCODE, OP_NONTRIVIAL_ERROR_ENCODE,
.op_name = "OP_LOCK", .op_name = "OP_LOCK",
...@@ -3218,6 +3219,7 @@ static const struct nfsd4_operation nfsd4_ops[] = { ...@@ -3218,6 +3219,7 @@ static const struct nfsd4_operation nfsd4_ops[] = {
}, },
[OP_LOCKT] = { [OP_LOCKT] = {
.op_func = nfsd4_lockt, .op_func = nfsd4_lockt,
.op_release = nfsd4_lockt_release,
.op_flags = OP_NONTRIVIAL_ERROR_ENCODE, .op_flags = OP_NONTRIVIAL_ERROR_ENCODE,
.op_name = "OP_LOCKT", .op_name = "OP_LOCKT",
.op_rsize_bop = nfsd4_lock_rsize, .op_rsize_bop = nfsd4_lock_rsize,
......
...@@ -7773,6 +7773,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -7773,6 +7773,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return status; return status;
} }
void nfsd4_lock_release(union nfsd4_op_u *u)
{
struct nfsd4_lock *lock = &u->lock;
struct nfsd4_lock_denied *deny = &lock->lk_denied;
kfree(deny->ld_owner.data);
}
/* /*
* The NFSv4 spec allows a client to do a LOCKT without holding an OPEN, * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN,
* so we do a temporary open here just to get an open file to pass to * so we do a temporary open here just to get an open file to pass to
...@@ -7878,6 +7886,14 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -7878,6 +7886,14 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return status; return status;
} }
void nfsd4_lockt_release(union nfsd4_op_u *u)
{
struct nfsd4_lockt *lockt = &u->lockt;
struct nfsd4_lock_denied *deny = &lockt->lt_denied;
kfree(deny->ld_owner.data);
}
__be32 __be32
nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
union nfsd4_op_u *u) union nfsd4_op_u *u)
......
...@@ -3990,28 +3990,16 @@ nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld) ...@@ -3990,28 +3990,16 @@ nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld)
struct xdr_netobj *conf = &ld->ld_owner; struct xdr_netobj *conf = &ld->ld_owner;
__be32 *p; __be32 *p;
again:
p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len)); p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len));
if (!p) { if (!p)
/*
* Don't fail to return the result just because we can't
* return the conflicting open:
*/
if (conf->len) {
kfree(conf->data);
conf->len = 0;
conf->data = NULL;
goto again;
}
return nfserr_resource; return nfserr_resource;
}
p = xdr_encode_hyper(p, ld->ld_start); p = xdr_encode_hyper(p, ld->ld_start);
p = xdr_encode_hyper(p, ld->ld_length); p = xdr_encode_hyper(p, ld->ld_length);
*p++ = cpu_to_be32(ld->ld_type); *p++ = cpu_to_be32(ld->ld_type);
if (conf->len) { if (conf->len) {
p = xdr_encode_opaque_fixed(p, &ld->ld_clientid, 8); p = xdr_encode_opaque_fixed(p, &ld->ld_clientid, 8);
p = xdr_encode_opaque(p, conf->data, conf->len); p = xdr_encode_opaque(p, conf->data, conf->len);
kfree(conf->data);
} else { /* non - nfsv4 lock in conflict, no clientid nor owner */ } else { /* non - nfsv4 lock in conflict, no clientid nor owner */
p = xdr_encode_hyper(p, (u64)0); /* clientid */ p = xdr_encode_hyper(p, (u64)0); /* clientid */
*p++ = cpu_to_be32(0); /* length of owner name */ *p++ = cpu_to_be32(0); /* length of owner name */
......
...@@ -292,12 +292,8 @@ struct nfsd4_lock { ...@@ -292,12 +292,8 @@ struct nfsd4_lock {
} v; } v;
/* response */ /* response */
union { stateid_t lk_resp_stateid;
struct { struct nfsd4_lock_denied lk_denied;
stateid_t stateid;
} ok;
struct nfsd4_lock_denied denied;
} u;
}; };
#define lk_new_open_seqid v.new.open_seqid #define lk_new_open_seqid v.new.open_seqid
#define lk_new_open_stateid v.new.open_stateid #define lk_new_open_stateid v.new.open_stateid
...@@ -307,20 +303,15 @@ struct nfsd4_lock { ...@@ -307,20 +303,15 @@ struct nfsd4_lock {
#define lk_old_lock_stateid v.old.lock_stateid #define lk_old_lock_stateid v.old.lock_stateid
#define lk_old_lock_seqid v.old.lock_seqid #define lk_old_lock_seqid v.old.lock_seqid
#define lk_resp_stateid u.ok.stateid
#define lk_denied u.denied
struct nfsd4_lockt { struct nfsd4_lockt {
u32 lt_type; u32 lt_type;
clientid_t lt_clientid; clientid_t lt_clientid;
struct xdr_netobj lt_owner; struct xdr_netobj lt_owner;
u64 lt_offset; u64 lt_offset;
u64 lt_length; u64 lt_length;
struct nfsd4_lock_denied lt_denied; struct nfsd4_lock_denied lt_denied;
}; };
struct nfsd4_locku { struct nfsd4_locku {
u32 lu_type; u32 lu_type;
u32 lu_seqid; u32 lu_seqid;
...@@ -942,8 +933,10 @@ extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp, ...@@ -942,8 +933,10 @@ extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
struct nfsd4_compound_state *, union nfsd4_op_u *u); struct nfsd4_compound_state *, union nfsd4_op_u *u);
extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *, extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
union nfsd4_op_u *u); union nfsd4_op_u *u);
extern void nfsd4_lock_release(union nfsd4_op_u *u);
extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *, extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
union nfsd4_op_u *u); union nfsd4_op_u *u);
extern void nfsd4_lockt_release(union nfsd4_op_u *u);
extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *, extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
union nfsd4_op_u *u); union nfsd4_op_u *u);
extern __be32 extern __be32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment