aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTigran Mkrtchyan <kofemann@gmail.com>2012-02-13 16:55:24 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-02-15 11:20:38 -0500
commit8b70484c67cf5241cfbea0ee31b83e42e5bac163 (patch)
tree2625d76be0ddbc5b1c27ca5aca96006482e49747
parent19ff0f288c6f2100987408ecc2cb911a2d50bc76 (diff)
nfsd41: handle current stateid in open and close
Signed-off-by: Tigran Mkrtchyan <kofemann@gmail.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/current_stateid.h11
-rw-r--r--fs/nfsd/nfs4proc.c30
-rw-r--r--fs/nfsd/nfs4state.c32
-rw-r--r--fs/nfsd/xdr4.h1
4 files changed, 70 insertions, 4 deletions
diff --git a/fs/nfsd/current_stateid.h b/fs/nfsd/current_stateid.h
new file mode 100644
index 000000000000..a83dd508cb8c
--- /dev/null
+++ b/fs/nfsd/current_stateid.h
@@ -0,0 +1,11 @@
1#ifndef _NFSD4_CURRENT_STATE_H
2#define _NFSD4_CURRENT_STATE_H
3
4#include "state.h"
5#include "xdr4.h"
6
7extern void nfsd4_set_openstateid(struct nfsd4_compound_state *, struct nfsd4_open *);
8extern void nfsd4_get_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *);
9extern void nfsd4_set_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *);
10
11#endif /* _NFSD4_CURRENT_STATE_H */
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 896da74ec563..b08f6e50fc48 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -39,6 +39,7 @@
39#include "cache.h" 39#include "cache.h"
40#include "xdr4.h" 40#include "xdr4.h"
41#include "vfs.h" 41#include "vfs.h"
42#include "current_stateid.h"
42 43
43#define NFSDDBG_FACILITY NFSDDBG_PROC 44#define NFSDDBG_FACILITY NFSDDBG_PROC
44 45
@@ -1000,6 +1001,8 @@ static inline void nfsd4_increment_op_stats(u32 opnum)
1000typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, 1001typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
1001 void *); 1002 void *);
1002typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op); 1003typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op);
1004typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *);
1005typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *);
1003 1006
1004enum nfsd4_op_flags { 1007enum nfsd4_op_flags {
1005 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ 1008 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
@@ -1025,6 +1028,10 @@ enum nfsd4_op_flags {
1025 * the v4.0 case). 1028 * the v4.0 case).
1026 */ 1029 */
1027 OP_CACHEME = 1 << 6, 1030 OP_CACHEME = 1 << 6,
1031 /*
1032 * These are ops which clear current state id.
1033 */
1034 OP_CLEAR_STATEID = 1 << 7,
1028}; 1035};
1029 1036
1030struct nfsd4_operation { 1037struct nfsd4_operation {
@@ -1033,6 +1040,8 @@ struct nfsd4_operation {
1033 char *op_name; 1040 char *op_name;
1034 /* Try to get response size before operation */ 1041 /* Try to get response size before operation */
1035 nfsd4op_rsize op_rsize_bop; 1042 nfsd4op_rsize op_rsize_bop;
1043 stateid_setter op_get_currentstateid;
1044 stateid_getter op_set_currentstateid;
1036}; 1045};
1037 1046
1038static struct nfsd4_operation nfsd4_ops[]; 1047static struct nfsd4_operation nfsd4_ops[];
@@ -1215,13 +1224,23 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1215 if (op->status) 1224 if (op->status)
1216 goto encode_op; 1225 goto encode_op;
1217 1226
1218 if (opdesc->op_func) 1227 if (opdesc->op_func) {
1228 if (opdesc->op_get_currentstateid)
1229 opdesc->op_get_currentstateid(cstate, &op->u);
1219 op->status = opdesc->op_func(rqstp, cstate, &op->u); 1230 op->status = opdesc->op_func(rqstp, cstate, &op->u);
1220 else 1231 } else
1221 BUG_ON(op->status == nfs_ok); 1232 BUG_ON(op->status == nfs_ok);
1222 1233
1223 if (!op->status && need_wrongsec_check(rqstp)) 1234 if (!op->status) {
1224 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); 1235 if (opdesc->op_set_currentstateid)
1236 opdesc->op_set_currentstateid(cstate, &op->u);
1237
1238 if (opdesc->op_flags & OP_CLEAR_STATEID)
1239 cstate->current_stateid = NULL;
1240
1241 if (need_wrongsec_check(rqstp))
1242 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
1243 }
1225 1244
1226encode_op: 1245encode_op:
1227 /* Only from SEQUENCE */ 1246 /* Only from SEQUENCE */
@@ -1413,6 +1432,8 @@ static struct nfsd4_operation nfsd4_ops[] = {
1413 .op_flags = OP_MODIFIES_SOMETHING, 1432 .op_flags = OP_MODIFIES_SOMETHING,
1414 .op_name = "OP_CLOSE", 1433 .op_name = "OP_CLOSE",
1415 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1434 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1435 .op_get_currentstateid = (stateid_getter)nfsd4_get_closestateid,
1436 .op_set_currentstateid = (stateid_setter)nfsd4_set_closestateid,
1416 }, 1437 },
1417 [OP_COMMIT] = { 1438 [OP_COMMIT] = {
1418 .op_func = (nfsd4op_func)nfsd4_commit, 1439 .op_func = (nfsd4op_func)nfsd4_commit,
@@ -1483,6 +1504,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1483 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING, 1504 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
1484 .op_name = "OP_OPEN", 1505 .op_name = "OP_OPEN",
1485 .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize, 1506 .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize,
1507 .op_set_currentstateid = (stateid_setter)nfsd4_set_openstateid,
1486 }, 1508 },
1487 [OP_OPEN_CONFIRM] = { 1509 [OP_OPEN_CONFIRM] = {
1488 .op_func = (nfsd4op_func)nfsd4_open_confirm, 1510 .op_func = (nfsd4op_func)nfsd4_open_confirm,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 905808bc94bb..2604e7ea8582 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4695,3 +4695,35 @@ nfs4_state_shutdown(void)
4695 nfs4_unlock_state(); 4695 nfs4_unlock_state();
4696 nfsd4_destroy_callback_queue(); 4696 nfsd4_destroy_callback_queue();
4697} 4697}
4698
4699static void
4700get_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
4701{
4702 if (cstate->current_stateid && CURRENT_STATEID(stateid))
4703 memcpy(stateid, cstate->current_stateid, sizeof(stateid_t));
4704}
4705
4706static void
4707put_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
4708{
4709 if (cstate->minorversion)
4710 cstate->current_stateid = stateid;
4711}
4712
4713void
4714nfsd4_set_openstateid(struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
4715{
4716 put_stateid(cstate, &open->op_stateid);
4717}
4718
4719void
4720nfsd4_get_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
4721{
4722 get_stateid(cstate, &close->cl_stateid);
4723}
4724
4725void
4726nfsd4_set_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
4727{
4728 get_stateid(cstate, &close->cl_stateid);
4729}
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 21dccdfcb7a6..b49ffe83e604 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -54,6 +54,7 @@ struct nfsd4_compound_state {
54 size_t iovlen; 54 size_t iovlen;
55 u32 minorversion; 55 u32 minorversion;
56 u32 status; 56 u32 status;
57 const stateid_t *current_stateid;
57}; 58};
58 59
59static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs) 60static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs)