summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r--fs/nfsd/nfs4proc.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 7ef1b27f112..e8077766661 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1007,6 +1007,15 @@ struct nfsd4_operation {
nfsd4op_func op_func;
u32 op_flags;
char *op_name;
+ /*
+ * We use the DRC for compounds containing non-idempotent
+ * operations, *except* those that are 4.1-specific (since
+ * sessions provide their own EOS), and except for stateful
+ * operations other than setclientid and setclientid_confirm
+ * (since sequence numbers provide EOS for open, lock, etc in
+ * the v4.0 case).
+ */
+ bool op_cacheresult;
};
static struct nfsd4_operation nfsd4_ops[];
@@ -1051,6 +1060,11 @@ static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
return &nfsd4_ops[op->opnum];
}
+bool nfsd4_cache_this_op(struct nfsd4_op *op)
+{
+ return OPDESC(op)->op_cacheresult;
+}
+
static bool need_wrongsec_check(struct svc_rqst *rqstp)
{
struct nfsd4_compoundres *resp = rqstp->rq_resp;
@@ -1240,6 +1254,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_CREATE] = {
.op_func = (nfsd4op_func)nfsd4_create,
.op_name = "OP_CREATE",
+ .op_cacheresult = true,
},
[OP_DELEGRETURN] = {
.op_func = (nfsd4op_func)nfsd4_delegreturn,
@@ -1257,6 +1272,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_LINK] = {
.op_func = (nfsd4op_func)nfsd4_link,
.op_name = "OP_LINK",
+ .op_cacheresult = true,
},
[OP_LOCK] = {
.op_func = (nfsd4op_func)nfsd4_lock,
@@ -1330,10 +1346,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_REMOVE] = {
.op_func = (nfsd4op_func)nfsd4_remove,
.op_name = "OP_REMOVE",
+ .op_cacheresult = true,
},
[OP_RENAME] = {
.op_name = "OP_RENAME",
.op_func = (nfsd4op_func)nfsd4_rename,
+ .op_cacheresult = true,
},
[OP_RENEW] = {
.op_func = (nfsd4op_func)nfsd4_renew,
@@ -1359,16 +1377,19 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_SETATTR] = {
.op_func = (nfsd4op_func)nfsd4_setattr,
.op_name = "OP_SETATTR",
+ .op_cacheresult = true,
},
[OP_SETCLIENTID] = {
.op_func = (nfsd4op_func)nfsd4_setclientid,
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
.op_name = "OP_SETCLIENTID",
+ .op_cacheresult = true,
},
[OP_SETCLIENTID_CONFIRM] = {
.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
.op_name = "OP_SETCLIENTID_CONFIRM",
+ .op_cacheresult = true,
},
[OP_VERIFY] = {
.op_func = (nfsd4op_func)nfsd4_verify,
@@ -1377,6 +1398,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
[OP_WRITE] = {
.op_func = (nfsd4op_func)nfsd4_write,
.op_name = "OP_WRITE",
+ .op_cacheresult = true,
},
[OP_RELEASE_LOCKOWNER] = {
.op_func = (nfsd4op_func)nfsd4_release_lockowner,
@@ -1447,16 +1469,6 @@ static const char *nfsd4_op_name(unsigned opnum)
#define nfsd4_voidres nfsd4_voidargs
struct nfsd4_voidargs { int dummy; };
-/*
- * TODO: At the present time, the NFSv4 server does not do XID caching
- * of requests. Implementing XID caching would not be a serious problem,
- * although it would require a mild change in interfaces since one
- * doesn't know whether an NFSv4 request is idempotent until after the
- * XDR decode. However, XID caching totally confuses pynfs (Peter
- * Astrand's regression testsuite for NFSv4 servers), which reuses
- * XID's liberally, so I've left it unimplemented until pynfs generates
- * better XID's.
- */
static struct svc_procedure nfsd_procedures4[2] = {
[NFSPROC4_NULL] = {
.pc_func = (svc_procfunc) nfsd4_proc_null,