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) |
