|
@@ -985,11 +985,75 @@ nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_rel
|
|
|
DECODE_TAIL;
|
|
|
}
|
|
|
|
|
|
+static __be32
|
|
|
+nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
|
|
|
+{
|
|
|
+ return nfs_ok;
|
|
|
+}
|
|
|
+
|
|
|
+static __be32
|
|
|
+nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
|
|
|
+{
|
|
|
+ return nfserr_opnotsupp;
|
|
|
+}
|
|
|
+
|
|
|
+typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
|
|
|
+
|
|
|
+static nfsd4_dec nfsd4_dec_ops[] = {
|
|
|
+ [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
|
|
|
+ [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
|
|
|
+ [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
|
|
|
+ [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
|
|
|
+ [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
|
|
|
+ [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
|
|
|
+ [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
|
|
|
+ [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
|
|
|
+ [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
|
|
|
+ [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
|
|
|
+ [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
|
|
|
+ [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
|
|
|
+ [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
|
|
|
+ [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
|
|
|
+ [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
|
|
|
+ [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
|
|
|
+ [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
|
|
|
+ [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm,
|
|
|
+ [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
|
|
|
+ [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
|
|
|
+ [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_notsupp,
|
|
|
+ [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
|
|
|
+ [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
|
|
|
+ [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
|
|
|
+ [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
|
|
|
+ [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
|
|
|
+ [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
|
|
|
+ [OP_RENEW] = (nfsd4_dec)nfsd4_decode_renew,
|
|
|
+ [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
|
|
|
+ [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
|
|
|
+ [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
|
|
|
+ [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
|
|
|
+ [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_setclientid,
|
|
|
+ [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
|
|
|
+ [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
|
|
|
+ [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
|
|
|
+ [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner,
|
|
|
+};
|
|
|
+
|
|
|
+struct nfsd4_minorversion_ops {
|
|
|
+ nfsd4_dec *decoders;
|
|
|
+ int nops;
|
|
|
+};
|
|
|
+
|
|
|
+static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
|
|
|
+ [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
|
|
|
+};
|
|
|
+
|
|
|
static __be32
|
|
|
nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
|
|
{
|
|
|
DECODE_HEAD;
|
|
|
struct nfsd4_op *op;
|
|
|
+ struct nfsd4_minorversion_ops *ops;
|
|
|
int i;
|
|
|
|
|
|
/*
|
|
@@ -1019,6 +1083,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion))
|
|
|
+ argp->opcnt = 0;
|
|
|
+
|
|
|
+ ops = &nfsd4_minorversion[argp->minorversion];
|
|
|
for (i = 0; i < argp->opcnt; i++) {
|
|
|
op = &argp->ops[i];
|
|
|
op->replay = NULL;
|
|
@@ -1056,120 +1124,11 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
|
|
}
|
|
|
op->opnum = ntohl(*argp->p++);
|
|
|
|
|
|
- switch (op->opnum) {
|
|
|
- case 2: /* Reserved operation */
|
|
|
- op->opnum = OP_ILLEGAL;
|
|
|
- if (argp->minorversion == 0)
|
|
|
- op->status = nfserr_op_illegal;
|
|
|
- else
|
|
|
- op->status = nfserr_minor_vers_mismatch;
|
|
|
- break;
|
|
|
- case OP_ACCESS:
|
|
|
- op->status = nfsd4_decode_access(argp, &op->u.access);
|
|
|
- break;
|
|
|
- case OP_CLOSE:
|
|
|
- op->status = nfsd4_decode_close(argp, &op->u.close);
|
|
|
- break;
|
|
|
- case OP_COMMIT:
|
|
|
- op->status = nfsd4_decode_commit(argp, &op->u.commit);
|
|
|
- break;
|
|
|
- case OP_CREATE:
|
|
|
- op->status = nfsd4_decode_create(argp, &op->u.create);
|
|
|
- break;
|
|
|
- case OP_DELEGRETURN:
|
|
|
- op->status = nfsd4_decode_delegreturn(argp, &op->u.delegreturn);
|
|
|
- break;
|
|
|
- case OP_GETATTR:
|
|
|
- op->status = nfsd4_decode_getattr(argp, &op->u.getattr);
|
|
|
- break;
|
|
|
- case OP_GETFH:
|
|
|
- op->status = nfs_ok;
|
|
|
- break;
|
|
|
- case OP_LINK:
|
|
|
- op->status = nfsd4_decode_link(argp, &op->u.link);
|
|
|
- break;
|
|
|
- case OP_LOCK:
|
|
|
- op->status = nfsd4_decode_lock(argp, &op->u.lock);
|
|
|
- break;
|
|
|
- case OP_LOCKT:
|
|
|
- op->status = nfsd4_decode_lockt(argp, &op->u.lockt);
|
|
|
- break;
|
|
|
- case OP_LOCKU:
|
|
|
- op->status = nfsd4_decode_locku(argp, &op->u.locku);
|
|
|
- break;
|
|
|
- case OP_LOOKUP:
|
|
|
- op->status = nfsd4_decode_lookup(argp, &op->u.lookup);
|
|
|
- break;
|
|
|
- case OP_LOOKUPP:
|
|
|
- op->status = nfs_ok;
|
|
|
- break;
|
|
|
- case OP_NVERIFY:
|
|
|
- op->status = nfsd4_decode_verify(argp, &op->u.nverify);
|
|
|
- break;
|
|
|
- case OP_OPEN:
|
|
|
- op->status = nfsd4_decode_open(argp, &op->u.open);
|
|
|
- break;
|
|
|
- case OP_OPEN_CONFIRM:
|
|
|
- op->status = nfsd4_decode_open_confirm(argp, &op->u.open_confirm);
|
|
|
- break;
|
|
|
- case OP_OPEN_DOWNGRADE:
|
|
|
- op->status = nfsd4_decode_open_downgrade(argp, &op->u.open_downgrade);
|
|
|
- break;
|
|
|
- case OP_PUTFH:
|
|
|
- op->status = nfsd4_decode_putfh(argp, &op->u.putfh);
|
|
|
- break;
|
|
|
- case OP_PUTROOTFH:
|
|
|
- op->status = nfs_ok;
|
|
|
- break;
|
|
|
- case OP_READ:
|
|
|
- op->status = nfsd4_decode_read(argp, &op->u.read);
|
|
|
- break;
|
|
|
- case OP_READDIR:
|
|
|
- op->status = nfsd4_decode_readdir(argp, &op->u.readdir);
|
|
|
- break;
|
|
|
- case OP_READLINK:
|
|
|
- op->status = nfs_ok;
|
|
|
- break;
|
|
|
- case OP_REMOVE:
|
|
|
- op->status = nfsd4_decode_remove(argp, &op->u.remove);
|
|
|
- break;
|
|
|
- case OP_RENAME:
|
|
|
- op->status = nfsd4_decode_rename(argp, &op->u.rename);
|
|
|
- break;
|
|
|
- case OP_RESTOREFH:
|
|
|
- op->status = nfs_ok;
|
|
|
- break;
|
|
|
- case OP_RENEW:
|
|
|
- op->status = nfsd4_decode_renew(argp, &op->u.renew);
|
|
|
- break;
|
|
|
- case OP_SAVEFH:
|
|
|
- op->status = nfs_ok;
|
|
|
- break;
|
|
|
- case OP_SECINFO:
|
|
|
- op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
|
|
|
- break;
|
|
|
- case OP_SETATTR:
|
|
|
- op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
|
|
|
- break;
|
|
|
- case OP_SETCLIENTID:
|
|
|
- op->status = nfsd4_decode_setclientid(argp, &op->u.setclientid);
|
|
|
- break;
|
|
|
- case OP_SETCLIENTID_CONFIRM:
|
|
|
- op->status = nfsd4_decode_setclientid_confirm(argp, &op->u.setclientid_confirm);
|
|
|
- break;
|
|
|
- case OP_VERIFY:
|
|
|
- op->status = nfsd4_decode_verify(argp, &op->u.verify);
|
|
|
- break;
|
|
|
- case OP_WRITE:
|
|
|
- op->status = nfsd4_decode_write(argp, &op->u.write);
|
|
|
- break;
|
|
|
- case OP_RELEASE_LOCKOWNER:
|
|
|
- op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner);
|
|
|
- break;
|
|
|
- default:
|
|
|
+ if (op->opnum >= OP_ACCESS && op->opnum < ops->nops)
|
|
|
+ op->status = ops->decoders[op->opnum](argp, &op->u);
|
|
|
+ else {
|
|
|
op->opnum = OP_ILLEGAL;
|
|
|
op->status = nfserr_op_illegal;
|
|
|
- break;
|
|
|
}
|
|
|
|
|
|
if (op->status) {
|
|
@@ -1201,11 +1160,11 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
|
|
*p++ = htonl((u32)((n) >> 32)); \
|
|
|
*p++ = htonl((u32)(n)); \
|
|
|
} while (0)
|
|
|
-#define WRITEMEM(ptr,nbytes) do { \
|
|
|
+#define WRITEMEM(ptr,nbytes) do { if (nbytes > 0) { \
|
|
|
*(p + XDR_QUADLEN(nbytes) -1) = 0; \
|
|
|
memcpy(p, ptr, nbytes); \
|
|
|
p += XDR_QUADLEN(nbytes); \
|
|
|
-} while (0)
|
|
|
+}} while (0)
|
|
|
#define WRITECINFO(c) do { \
|
|
|
*p++ = htonl(c.atomic); \
|
|
|
*p++ = htonl(c.before_ctime_sec); \
|
|
@@ -1991,7 +1950,7 @@ fail:
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2002,9 +1961,10 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
|
|
|
WRITE32(access->ac_resp_access);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
|
|
|
{
|
|
|
ENCODE_SEQID_OP_HEAD;
|
|
@@ -2016,10 +1976,11 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2029,9 +1990,10 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
|
|
|
WRITEMEM(commit->co_verf.data, 8);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2044,6 +2006,7 @@ nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
|
|
|
WRITE32(create->cr_bmval[1]);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
static __be32
|
|
@@ -2064,9 +2027,10 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
|
|
|
return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh *fhp)
|
|
|
+static __be32
|
|
|
+nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp)
|
|
|
{
|
|
|
+ struct svc_fh *fhp = *fhpp;
|
|
|
unsigned int len;
|
|
|
ENCODE_HEAD;
|
|
|
|
|
@@ -2077,6 +2041,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh
|
|
|
WRITEMEM(&fhp->fh_handle.fh_base, len);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2104,7 +2069,7 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
|
|
|
{
|
|
|
ENCODE_SEQID_OP_HEAD;
|
|
@@ -2118,16 +2083,18 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lo
|
|
|
nfsd4_encode_lock_denied(resp, &lock->lk_denied);
|
|
|
|
|
|
ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
|
|
|
{
|
|
|
if (nfserr == nfserr_denied)
|
|
|
nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
|
|
|
{
|
|
|
ENCODE_SEQID_OP_HEAD;
|
|
@@ -2140,10 +2107,11 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
|
|
|
}
|
|
|
|
|
|
ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2153,10 +2121,11 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
|
|
|
WRITECINFO(link->li_cinfo);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
|
|
|
{
|
|
|
ENCODE_SEQID_OP_HEAD;
|
|
@@ -2219,9 +2188,10 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
|
|
|
/* XXX save filehandle here */
|
|
|
out:
|
|
|
ENCODE_SEQID_OP_TAIL(open->op_stateowner);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
|
|
|
{
|
|
|
ENCODE_SEQID_OP_HEAD;
|
|
@@ -2234,9 +2204,10 @@ nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct
|
|
|
}
|
|
|
|
|
|
ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
|
|
|
{
|
|
|
ENCODE_SEQID_OP_HEAD;
|
|
@@ -2249,6 +2220,7 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struc
|
|
|
}
|
|
|
|
|
|
ENCODE_SEQID_OP_TAIL(od->od_stateowner);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
static __be32
|
|
@@ -2443,7 +2415,7 @@ err_no_verf:
|
|
|
return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2453,9 +2425,10 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
|
|
|
WRITECINFO(remove->rm_cinfo);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2466,9 +2439,10 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
|
|
|
WRITECINFO(rename->rn_tinfo);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
|
|
|
struct nfsd4_secinfo *secinfo)
|
|
|
{
|
|
@@ -2532,13 +2506,14 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
|
|
|
out:
|
|
|
if (exp)
|
|
|
exp_put(exp);
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* The SETATTR encode routine is special -- it always encodes a bitmap,
|
|
|
* regardless of the error status.
|
|
|
*/
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2555,9 +2530,10 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
|
|
|
WRITE32(setattr->sa_bmval[1]);
|
|
|
}
|
|
|
ADJUST_ARGS();
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2574,9 +2550,10 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n
|
|
|
WRITE32(0);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static __be32
|
|
|
nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
|
|
|
{
|
|
|
ENCODE_HEAD;
|
|
@@ -2588,8 +2565,56 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
|
|
|
WRITEMEM(write->wr_verifier.data, 8);
|
|
|
ADJUST_ARGS();
|
|
|
}
|
|
|
+ return nfserr;
|
|
|
}
|
|
|
|
|
|
+static __be32
|
|
|
+nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
|
|
|
+{
|
|
|
+ return nfserr;
|
|
|
+}
|
|
|
+
|
|
|
+typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
|
|
|
+
|
|
|
+static nfsd4_enc nfsd4_enc_ops[] = {
|
|
|
+ [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access,
|
|
|
+ [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close,
|
|
|
+ [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit,
|
|
|
+ [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create,
|
|
|
+ [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr,
|
|
|
+ [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh,
|
|
|
+ [OP_LINK] = (nfsd4_enc)nfsd4_encode_link,
|
|
|
+ [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock,
|
|
|
+ [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt,
|
|
|
+ [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku,
|
|
|
+ [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open,
|
|
|
+ [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm,
|
|
|
+ [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade,
|
|
|
+ [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_READ] = (nfsd4_enc)nfsd4_encode_read,
|
|
|
+ [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir,
|
|
|
+ [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink,
|
|
|
+ [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove,
|
|
|
+ [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename,
|
|
|
+ [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo,
|
|
|
+ [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr,
|
|
|
+ [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid,
|
|
|
+ [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+ [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write,
|
|
|
+ [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop,
|
|
|
+};
|
|
|
+
|
|
|
void
|
|
|
nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
|
|
{
|
|
@@ -2601,101 +2626,12 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
|
|
statp = p++; /* to be backfilled at the end */
|
|
|
ADJUST_ARGS();
|
|
|
|
|
|
- switch (op->opnum) {
|
|
|
- case OP_ACCESS:
|
|
|
- nfsd4_encode_access(resp, op->status, &op->u.access);
|
|
|
- break;
|
|
|
- case OP_CLOSE:
|
|
|
- nfsd4_encode_close(resp, op->status, &op->u.close);
|
|
|
- break;
|
|
|
- case OP_COMMIT:
|
|
|
- nfsd4_encode_commit(resp, op->status, &op->u.commit);
|
|
|
- break;
|
|
|
- case OP_CREATE:
|
|
|
- nfsd4_encode_create(resp, op->status, &op->u.create);
|
|
|
- break;
|
|
|
- case OP_DELEGRETURN:
|
|
|
- break;
|
|
|
- case OP_GETATTR:
|
|
|
- op->status = nfsd4_encode_getattr(resp, op->status, &op->u.getattr);
|
|
|
- break;
|
|
|
- case OP_GETFH:
|
|
|
- nfsd4_encode_getfh(resp, op->status, op->u.getfh);
|
|
|
- break;
|
|
|
- case OP_LINK:
|
|
|
- nfsd4_encode_link(resp, op->status, &op->u.link);
|
|
|
- break;
|
|
|
- case OP_LOCK:
|
|
|
- nfsd4_encode_lock(resp, op->status, &op->u.lock);
|
|
|
- break;
|
|
|
- case OP_LOCKT:
|
|
|
- nfsd4_encode_lockt(resp, op->status, &op->u.lockt);
|
|
|
- break;
|
|
|
- case OP_LOCKU:
|
|
|
- nfsd4_encode_locku(resp, op->status, &op->u.locku);
|
|
|
- break;
|
|
|
- case OP_LOOKUP:
|
|
|
- break;
|
|
|
- case OP_LOOKUPP:
|
|
|
- break;
|
|
|
- case OP_NVERIFY:
|
|
|
- break;
|
|
|
- case OP_OPEN:
|
|
|
- nfsd4_encode_open(resp, op->status, &op->u.open);
|
|
|
- break;
|
|
|
- case OP_OPEN_CONFIRM:
|
|
|
- nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm);
|
|
|
- break;
|
|
|
- case OP_OPEN_DOWNGRADE:
|
|
|
- nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade);
|
|
|
- break;
|
|
|
- case OP_PUTFH:
|
|
|
- break;
|
|
|
- case OP_PUTROOTFH:
|
|
|
- break;
|
|
|
- case OP_READ:
|
|
|
- op->status = nfsd4_encode_read(resp, op->status, &op->u.read);
|
|
|
- break;
|
|
|
- case OP_READDIR:
|
|
|
- op->status = nfsd4_encode_readdir(resp, op->status, &op->u.readdir);
|
|
|
- break;
|
|
|
- case OP_READLINK:
|
|
|
- op->status = nfsd4_encode_readlink(resp, op->status, &op->u.readlink);
|
|
|
- break;
|
|
|
- case OP_REMOVE:
|
|
|
- nfsd4_encode_remove(resp, op->status, &op->u.remove);
|
|
|
- break;
|
|
|
- case OP_RENAME:
|
|
|
- nfsd4_encode_rename(resp, op->status, &op->u.rename);
|
|
|
- break;
|
|
|
- case OP_RENEW:
|
|
|
- break;
|
|
|
- case OP_RESTOREFH:
|
|
|
- break;
|
|
|
- case OP_SAVEFH:
|
|
|
- break;
|
|
|
- case OP_SECINFO:
|
|
|
- nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo);
|
|
|
- break;
|
|
|
- case OP_SETATTR:
|
|
|
- nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
|
|
|
- break;
|
|
|
- case OP_SETCLIENTID:
|
|
|
- nfsd4_encode_setclientid(resp, op->status, &op->u.setclientid);
|
|
|
- break;
|
|
|
- case OP_SETCLIENTID_CONFIRM:
|
|
|
- break;
|
|
|
- case OP_VERIFY:
|
|
|
- break;
|
|
|
- case OP_WRITE:
|
|
|
- nfsd4_encode_write(resp, op->status, &op->u.write);
|
|
|
- break;
|
|
|
- case OP_RELEASE_LOCKOWNER:
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
+ if (op->opnum == OP_ILLEGAL)
|
|
|
+ goto status;
|
|
|
+ BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
|
|
|
+ !nfsd4_enc_ops[op->opnum]);
|
|
|
+ op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u);
|
|
|
+status:
|
|
|
/*
|
|
|
* Note: We write the status directly, instead of using WRITE32(),
|
|
|
* since it is already in network byte order.
|