@@ -484,6 +484,32 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
DECODE_TAIL;
}
+static __be32 nfsd4_decode_clientid4(struct nfsd4_compoundargs *argp,
+ clientid_t *clientid)
+{
+ __be32 *p;
+
+ p = xdr_inline_decode(argp->xdr, NFS4_CLIENTID_SIZE);
+ if (!p)
+ goto xdr_error;
+ memcpy(clientid, p, sizeof(*clientid));
+ return nfs_ok;
+xdr_error:
+ return nfserr_bad_xdr;
+}
+
+static __be32 nfsd4_decode_state_owner4(struct nfsd4_compoundargs *argp,
+ clientid_t *clientid,
+ struct xdr_netobj *owner)
+{
+ __be32 status;
+
+ status = nfsd4_decode_clientid4(argp, clientid);
+ if (status)
+ return status;
+ return nfsd4_decode_opaque(argp, owner);
+}
+
static __be32
nfsd4_decode_stateid4(struct nfsd4_compoundargs *argp, stateid_t *sid)
{
@@ -706,44 +732,77 @@ nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
return nfsd4_decode_component4(argp, &link->li_name, &link->li_namelen);
}
+static __be32
+nfsd4_decode_open_to_lock_owner4(struct nfsd4_compoundargs *argp,
+ struct nfsd4_lock *lock)
+{
+ __be32 status;
+
+ lock->lk_is_new = 1;
+
+ if (xdr_stream_decode_u32(argp->xdr, &lock->lk_new_open_seqid) < 0)
+ goto xdr_error;
+ status = nfsd4_decode_stateid4(argp, &lock->lk_new_open_stateid);
+ if (status)
+ goto out;
+ if (xdr_stream_decode_u32(argp->xdr, &lock->lk_new_lock_seqid) < 0)
+ goto xdr_error;
+ status = nfsd4_decode_state_owner4(argp, &lock->lk_new_clientid,
+ &lock->lk_new_owner);
+
+out:
+ return status;
+xdr_error:
+ return nfserr_bad_xdr;
+}
+
+static __be32
+nfsd4_decode_exist_lock_owner4(struct nfsd4_compoundargs *argp,
+ struct nfsd4_lock *lock)
+{
+ __be32 status;
+
+ lock->lk_is_new = 0;
+
+ status = nfsd4_decode_stateid4(argp, &lock->lk_old_lock_stateid);
+ if (status)
+ goto out;
+ if (xdr_stream_decode_u32(argp->xdr, &lock->lk_old_lock_seqid) < 0)
+ goto xdr_error;
+
+ status = nfs_ok;
+out:
+ return status;
+xdr_error:
+ return nfserr_bad_xdr;
+}
+
static __be32
nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
{
- DECODE_HEAD;
+ __be32 *p;
- /*
- * type, reclaim(boolean), offset, length, new_lock_owner(boolean)
- */
- READ_BUF(28);
- lock->lk_type = be32_to_cpup(p++);
+ if (xdr_stream_decode_u32(argp->xdr, &lock->lk_type) < 0)
+ goto xdr_error;
if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
goto xdr_error;
- lock->lk_reclaim = be32_to_cpup(p++);
- p = xdr_decode_hyper(p, &lock->lk_offset);
- p = xdr_decode_hyper(p, &lock->lk_length);
- lock->lk_is_new = be32_to_cpup(p++);
-
- if (lock->lk_is_new) {
- READ_BUF(4);
- lock->lk_new_open_seqid = be32_to_cpup(p++);
- status = nfsd4_decode_stateid4(argp, &lock->lk_new_open_stateid);
- if (status)
- return status;
- READ_BUF(8 + sizeof(clientid_t));
- lock->lk_new_lock_seqid = be32_to_cpup(p++);
- COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
- lock->lk_new_owner.len = be32_to_cpup(p++);
- READ_BUF(lock->lk_new_owner.len);
- READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
- } else {
- status = nfsd4_decode_stateid4(argp, &lock->lk_old_lock_stateid);
- if (status)
- return status;
- READ_BUF(4);
- lock->lk_old_lock_seqid = be32_to_cpup(p++);
- }
+ p = xdr_inline_decode(argp->xdr, sizeof(__be32));
+ if (!p)
+ goto xdr_error;
+ lock->lk_reclaim = (*p == xdr_zero) ? 0 : 1;
+ if (xdr_stream_decode_u64(argp->xdr, &lock->lk_offset) < 0)
+ goto xdr_error;
+ if (xdr_stream_decode_u64(argp->xdr, &lock->lk_length) < 0)
+ goto xdr_error;
+ p = xdr_inline_decode(argp->xdr, sizeof(__be32));
+ if (!p)
+ goto xdr_error;
+ if (*p != xdr_zero)
+ return nfsd4_decode_open_to_lock_owner4(argp, lock);
+ return nfsd4_decode_exist_lock_owner4(argp, lock);
- DECODE_TAIL;
+xdr_error:
+ return nfserr_bad_xdr;
}
static __be32
@@ -21,6 +21,7 @@
#define NFS4_STATEID_SEQID_SIZE 4
#define NFS4_STATEID_OTHER_SIZE 12
#define NFS4_STATEID_SIZE (NFS4_STATEID_SEQID_SIZE + NFS4_STATEID_OTHER_SIZE)
+#define NFS4_CLIENTID_SIZE 8
#define NFS4_FHSIZE 128
#define NFS4_MAXPATHLEN PATH_MAX
#define NFS4_MAXNAMLEN NAME_MAX
Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/nfsd/nfs4xdr.c | 121 +++++++++++++++++++++++++++++++++------------ include/uapi/linux/nfs4.h | 1 2 files changed, 91 insertions(+), 31 deletions(-)