diff options
author | Tigran Mkrtchyan <kofemann@gmail.com> | 2012-02-13 16:55:24 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-02-15 11:20:38 -0500 |
commit | 8b70484c67cf5241cfbea0ee31b83e42e5bac163 (patch) | |
tree | 2625d76be0ddbc5b1c27ca5aca96006482e49747 | |
parent | 19ff0f288c6f2100987408ecc2cb911a2d50bc76 (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.h | 11 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 30 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 32 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 1 |
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 | |||
7 | extern void nfsd4_set_openstateid(struct nfsd4_compound_state *, struct nfsd4_open *); | ||
8 | extern void nfsd4_get_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *); | ||
9 | extern 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) | |||
1000 | typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, | 1001 | typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, |
1001 | void *); | 1002 | void *); |
1002 | typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op); | 1003 | typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op); |
1004 | typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *); | ||
1005 | typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *); | ||
1003 | 1006 | ||
1004 | enum nfsd4_op_flags { | 1007 | enum 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 | ||
1030 | struct nfsd4_operation { | 1037 | struct 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 | ||
1038 | static struct nfsd4_operation nfsd4_ops[]; | 1047 | static 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 | ||
1226 | encode_op: | 1245 | encode_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 | |||
4699 | static void | ||
4700 | get_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 | |||
4706 | static void | ||
4707 | put_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid) | ||
4708 | { | ||
4709 | if (cstate->minorversion) | ||
4710 | cstate->current_stateid = stateid; | ||
4711 | } | ||
4712 | |||
4713 | void | ||
4714 | nfsd4_set_openstateid(struct nfsd4_compound_state *cstate, struct nfsd4_open *open) | ||
4715 | { | ||
4716 | put_stateid(cstate, &open->op_stateid); | ||
4717 | } | ||
4718 | |||
4719 | void | ||
4720 | nfsd4_get_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close) | ||
4721 | { | ||
4722 | get_stateid(cstate, &close->cl_stateid); | ||
4723 | } | ||
4724 | |||
4725 | void | ||
4726 | nfsd4_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 | ||
59 | static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs) | 60 | static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs) |