diff options
| author | J. Bruce Fields <bfields@redhat.com> | 2011-09-09 09:06:12 -0400 |
|---|---|---|
| committer | J. Bruce Fields <bfields@redhat.com> | 2011-09-13 18:30:34 -0400 |
| commit | f459e4535904e16ca9f0cc202c78345c332bbbad (patch) | |
| tree | 274b39ad09a1a4241a72f55e17fbd4631020f176 | |
| parent | 36d44c6038f6d3f8786187a5558c2f3b39a7af95 (diff) | |
nfsd4: hash deleg stateid's like any other
It's simpler to look up delegation stateid's in the same hash table as
any other stateid.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
| -rw-r--r-- | fs/nfsd/nfs4state.c | 112 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 5 |
2 files changed, 51 insertions, 66 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 581a5d01b005..24685a02690f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -60,8 +60,6 @@ static u64 current_sessionid = 1; | |||
| 60 | #define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t))) | 60 | #define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t))) |
| 61 | 61 | ||
| 62 | /* forward declarations */ | 62 | /* forward declarations */ |
| 63 | static struct nfs4_delegation * search_for_delegation(stateid_t *stid); | ||
| 64 | static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid); | ||
| 65 | static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); | 63 | static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); |
| 66 | 64 | ||
| 67 | /* Locking: */ | 65 | /* Locking: */ |
| @@ -256,10 +254,12 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv | |||
| 256 | get_nfs4_file(fp); | 254 | get_nfs4_file(fp); |
| 257 | dp->dl_file = fp; | 255 | dp->dl_file = fp; |
| 258 | dp->dl_type = type; | 256 | dp->dl_type = type; |
| 257 | dp->dl_stid.sc_type = NFS4_DELEG_STID; | ||
| 259 | dp->dl_stid.sc_stateid.si_boot = boot_time; | 258 | dp->dl_stid.sc_stateid.si_boot = boot_time; |
| 260 | dp->dl_stid.sc_stateid.si_stateownerid = current_delegid++; | 259 | dp->dl_stid.sc_stateid.si_stateownerid = current_delegid++; |
| 261 | dp->dl_stid.sc_stateid.si_fileid = 0; | 260 | dp->dl_stid.sc_stateid.si_fileid = 0; |
| 262 | dp->dl_stid.sc_stateid.si_generation = 1; | 261 | dp->dl_stid.sc_stateid.si_generation = 1; |
| 262 | hash_stid(&dp->dl_stid); | ||
| 263 | fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); | 263 | fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); |
| 264 | dp->dl_time = 0; | 264 | dp->dl_time = 0; |
| 265 | atomic_set(&dp->dl_count, 1); | 265 | atomic_set(&dp->dl_count, 1); |
| @@ -292,6 +292,7 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp) | |||
| 292 | static void | 292 | static void |
| 293 | unhash_delegation(struct nfs4_delegation *dp) | 293 | unhash_delegation(struct nfs4_delegation *dp) |
| 294 | { | 294 | { |
| 295 | list_del_init(&dp->dl_stid.sc_hash); | ||
| 295 | list_del_init(&dp->dl_perclnt); | 296 | list_del_init(&dp->dl_perclnt); |
| 296 | spin_lock(&recall_lock); | 297 | spin_lock(&recall_lock); |
| 297 | list_del_init(&dp->dl_perfile); | 298 | list_del_init(&dp->dl_perfile); |
| @@ -1077,7 +1078,7 @@ same_stateid(stateid_t *id_one, stateid_t *id_two) | |||
| 1077 | return id_one->si_fileid == id_two->si_fileid; | 1078 | return id_one->si_fileid == id_two->si_fileid; |
| 1078 | } | 1079 | } |
| 1079 | 1080 | ||
| 1080 | static struct nfs4_ol_stateid *find_stateid(stateid_t *t) | 1081 | static struct nfs4_stid *find_stateid(stateid_t *t) |
| 1081 | { | 1082 | { |
| 1082 | struct nfs4_stid *s; | 1083 | struct nfs4_stid *s; |
| 1083 | unsigned int hashval; | 1084 | unsigned int hashval; |
| @@ -1085,22 +1086,42 @@ static struct nfs4_ol_stateid *find_stateid(stateid_t *t) | |||
| 1085 | hashval = stateid_hashval(t->si_stateownerid, t->si_fileid); | 1086 | hashval = stateid_hashval(t->si_stateownerid, t->si_fileid); |
| 1086 | list_for_each_entry(s, &stateid_hashtbl[hashval], sc_hash) | 1087 | list_for_each_entry(s, &stateid_hashtbl[hashval], sc_hash) |
| 1087 | if (same_stateid(&s->sc_stateid, t)) | 1088 | if (same_stateid(&s->sc_stateid, t)) |
| 1088 | return openlockstateid(s); | 1089 | return s; |
| 1089 | return NULL; | 1090 | return NULL; |
| 1090 | } | 1091 | } |
| 1091 | 1092 | ||
| 1092 | static struct nfs4_ol_stateid *find_stateid_by_type(stateid_t *t, char typemask) | 1093 | static struct nfs4_ol_stateid *find_ol_stateid(stateid_t *t) |
| 1093 | { | 1094 | { |
| 1094 | struct nfs4_ol_stateid *s; | 1095 | struct nfs4_stid *s; |
| 1096 | |||
| 1097 | s = find_stateid(t); | ||
| 1098 | if (!s) | ||
| 1099 | return NULL; | ||
| 1100 | return openlockstateid(s); | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | static struct nfs4_stid *find_stateid_by_type(stateid_t *t, char typemask) | ||
| 1104 | { | ||
| 1105 | struct nfs4_stid *s; | ||
| 1095 | 1106 | ||
| 1096 | s = find_stateid(t); | 1107 | s = find_stateid(t); |
| 1097 | if (!s) | 1108 | if (!s) |
| 1098 | return NULL; | 1109 | return NULL; |
| 1099 | if (typemask & s->st_stid.sc_type) | 1110 | if (typemask & s->sc_type) |
| 1100 | return s; | 1111 | return s; |
| 1101 | return NULL; | 1112 | return NULL; |
| 1102 | } | 1113 | } |
| 1103 | 1114 | ||
| 1115 | static struct nfs4_ol_stateid *find_ol_stateid_by_type(stateid_t *t, char typemask) | ||
| 1116 | { | ||
| 1117 | struct nfs4_stid *s; | ||
| 1118 | |||
| 1119 | s = find_stateid_by_type(t, typemask); | ||
| 1120 | if (!s) | ||
| 1121 | return NULL; | ||
| 1122 | return openlockstateid(s); | ||
| 1123 | } | ||
| 1124 | |||
| 1104 | static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | 1125 | static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, |
| 1105 | struct svc_rqst *rqstp, nfs4_verifier *verf) | 1126 | struct svc_rqst *rqstp, nfs4_verifier *verf) |
| 1106 | { | 1127 | { |
| @@ -2573,26 +2594,21 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) | |||
| 2573 | return nfs_ok; | 2594 | return nfs_ok; |
| 2574 | } | 2595 | } |
| 2575 | 2596 | ||
| 2576 | static struct nfs4_delegation * | 2597 | static int share_access_to_flags(u32 share_access) |
| 2577 | find_delegation_file(struct nfs4_file *fp, stateid_t *stid) | ||
| 2578 | { | 2598 | { |
| 2579 | struct nfs4_delegation *dp; | 2599 | share_access &= ~NFS4_SHARE_WANT_MASK; |
| 2580 | 2600 | ||
| 2581 | spin_lock(&recall_lock); | 2601 | return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; |
| 2582 | list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) | ||
| 2583 | if (dp->dl_stid.sc_stateid.si_stateownerid == stid->si_stateownerid) { | ||
| 2584 | spin_unlock(&recall_lock); | ||
| 2585 | return dp; | ||
| 2586 | } | ||
| 2587 | spin_unlock(&recall_lock); | ||
| 2588 | return NULL; | ||
| 2589 | } | 2602 | } |
| 2590 | 2603 | ||
| 2591 | static int share_access_to_flags(u32 share_access) | 2604 | static struct nfs4_delegation *find_deleg_stateid(stateid_t *s) |
| 2592 | { | 2605 | { |
| 2593 | share_access &= ~NFS4_SHARE_WANT_MASK; | 2606 | struct nfs4_stid *ret; |
| 2594 | 2607 | ||
| 2595 | return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; | 2608 | ret = find_stateid_by_type(s, NFS4_DELEG_STID); |
| 2609 | if (!ret) | ||
| 2610 | return NULL; | ||
| 2611 | return delegstateid(ret); | ||
| 2596 | } | 2612 | } |
| 2597 | 2613 | ||
| 2598 | static __be32 | 2614 | static __be32 |
| @@ -2602,7 +2618,7 @@ nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, | |||
| 2602 | int flags; | 2618 | int flags; |
| 2603 | __be32 status = nfserr_bad_stateid; | 2619 | __be32 status = nfserr_bad_stateid; |
| 2604 | 2620 | ||
| 2605 | *dp = find_delegation_file(fp, &open->op_delegate_stateid); | 2621 | *dp = find_deleg_stateid(&open->op_delegate_stateid); |
| 2606 | if (*dp == NULL) | 2622 | if (*dp == NULL) |
| 2607 | goto out; | 2623 | goto out; |
| 2608 | flags = share_access_to_flags(open->op_share_access); | 2624 | flags = share_access_to_flags(open->op_share_access); |
| @@ -3252,7 +3268,7 @@ __be32 nfs4_validate_stateid(stateid_t *stateid, bool has_session) | |||
| 3252 | goto out; | 3268 | goto out; |
| 3253 | 3269 | ||
| 3254 | status = nfserr_expired; | 3270 | status = nfserr_expired; |
| 3255 | stp = find_stateid(stateid); | 3271 | stp = find_ol_stateid(stateid); |
| 3256 | if (!stp) | 3272 | if (!stp) |
| 3257 | goto out; | 3273 | goto out; |
| 3258 | status = nfserr_bad_stateid; | 3274 | status = nfserr_bad_stateid; |
| @@ -3301,7 +3317,7 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
| 3301 | */ | 3317 | */ |
| 3302 | status = nfserr_expired; | 3318 | status = nfserr_expired; |
| 3303 | if (is_delegation_stateid(stateid)) { | 3319 | if (is_delegation_stateid(stateid)) { |
| 3304 | dp = find_delegation_stateid(ino, stateid); | 3320 | dp = find_deleg_stateid(stateid); |
| 3305 | if (!dp) | 3321 | if (!dp) |
| 3306 | goto out; | 3322 | goto out; |
| 3307 | status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); | 3323 | status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); |
| @@ -3316,7 +3332,7 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
| 3316 | BUG_ON(!*filpp); | 3332 | BUG_ON(!*filpp); |
| 3317 | } | 3333 | } |
| 3318 | } else { /* open or lock stateid */ | 3334 | } else { /* open or lock stateid */ |
| 3319 | stp = find_stateid(stateid); | 3335 | stp = find_ol_stateid(stateid); |
| 3320 | if (!stp) | 3336 | if (!stp) |
| 3321 | goto out; | 3337 | goto out; |
| 3322 | status = nfserr_bad_stateid; | 3338 | status = nfserr_bad_stateid; |
| @@ -3348,9 +3364,10 @@ out: | |||
| 3348 | static __be32 | 3364 | static __be32 |
