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 /fs/nfsd/nfs4state.c | |
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>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 112 |
1 files changed, 46 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 |
3349 | nfsd4_free_delegation_stateid(stateid_t *stateid) | 3365 | nfsd4_free_delegation_stateid(stateid_t *stateid) |
3350 | { | 3366 | { |
3351 | struct nfs4_delegation *dp = search_for_delegation(stateid); | 3367 | struct nfs4_delegation *dp = find_deleg_stateid(stateid); |
3352 | if (dp) | 3368 | if (dp) |
3353 | return nfserr_locks_held; | 3369 | return nfserr_locks_held; |
3370 | |||
3354 | return nfserr_bad_stateid; | 3371 | return nfserr_bad_stateid; |
3355 | } | 3372 | } |
3356 | 3373 | ||
@@ -3391,7 +3408,7 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3391 | goto out; | 3408 | goto out; |
3392 | } | 3409 | } |
3393 | 3410 | ||
3394 | stp = find_stateid(stateid); | 3411 | stp = find_ol_stateid(stateid); |
3395 | if (!stp) { | 3412 | if (!stp) { |
3396 | ret = nfserr_bad_stateid; | 3413 | ret = nfserr_bad_stateid; |
3397 | goto out; | 3414 | goto out; |
@@ -3460,7 +3477,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, | |||
3460 | status = nfs4_nospecial_stateid_checks(stateid); | 3477 | status = nfs4_nospecial_stateid_checks(stateid); |
3461 | if (status) | 3478 | if (status) |
3462 | return status; | 3479 | return status; |
3463 | *stpp = find_stateid_by_type(stateid, typemask); | 3480 | *stpp = find_ol_stateid_by_type(stateid, typemask); |
3464 | if (*stpp == NULL) | 3481 | if (*stpp == NULL) |
3465 | return nfserr_expired; | 3482 | return nfserr_expired; |
3466 | cstate->replay_owner = (*stpp)->st_stateowner; | 3483 | cstate->replay_owner = (*stpp)->st_stateowner; |
@@ -3672,7 +3689,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3672 | if (!is_delegation_stateid(stateid)) | 3689 | if (!is_delegation_stateid(stateid)) |
3673 | goto out; | 3690 | goto out; |
3674 | status = nfserr_expired; | 3691 | status = nfserr_expired; |
3675 | dp = find_delegation_stateid(inode, stateid); | 3692 | dp = find_deleg_stateid(stateid); |
3676 | if (!dp) | 3693 | if (!dp) |
3677 | goto out; | 3694 | goto out; |
3678 | status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); | 3695 | status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); |
@@ -3733,43 +3750,6 @@ lock_ownerstr_hashval(struct inode *inode, u32 cl_id, | |||
3733 | static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE]; | 3750 | static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE]; |
3734 | static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; | 3751 | static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; |
3735 | 3752 | ||
3736 | static struct nfs4_delegation * | ||
3737 | search_for_delegation(stateid_t *stid) | ||
3738 | { | ||
3739 | struct nfs4_file *fp; | ||
3740 | struct nfs4_delegation *dp; | ||
3741 | struct list_head *pos; | ||
3742 | int i; | ||
3743 | |||
3744 | for (i = 0; i < FILE_HASH_SIZE; i++) { | ||
3745 | list_for_each_entry(fp, &file_hashtbl[i], fi_hash) { | ||
3746 | list_for_each(pos, &fp->fi_delegations) { | ||
3747 | dp = list_entry(pos, struct nfs4_delegation, dl_perfile); | ||
3748 | if (same_stateid(&dp->dl_stid.sc_stateid, stid)) | ||
3749 | return dp; | ||
3750 | } | ||
3751 | } | ||
3752 | } | ||
3753 | return NULL; | ||
3754 | } | ||
3755 | |||
3756 | static struct nfs4_delegation * | ||
3757 | find_delegation_stateid(struct inode *ino, stateid_t *stid) | ||
3758 | { | ||
3759 | struct nfs4_file *fp; | ||
3760 | struct nfs4_delegation *dl; | ||
3761 | |||
3762 | dprintk("NFSD: %s: stateid=" STATEID_FMT "\n", __func__, | ||
3763 | STATEID_VAL(stid)); | ||
3764 | |||
3765 | fp = find_file(ino); | ||
3766 | if (!fp) | ||
3767 | return NULL; | ||
3768 | dl = find_delegation_file(fp, stid); | ||
3769 | put_nfs4_file(fp); | ||
3770 | return dl; | ||
3771 | } | ||
3772 | |||
3773 | /* | 3753 | /* |
3774 | * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that | 3754 | * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that |
3775 | * we can't properly handle lock requests that go beyond the (2^63 - 1)-th | 3755 | * we can't properly handle lock requests that go beyond the (2^63 - 1)-th |