aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-09-09 09:06:12 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-09-13 18:30:34 -0400
commitf459e4535904e16ca9f0cc202c78345c332bbbad (patch)
tree274b39ad09a1a4241a72f55e17fbd4631020f176 /fs/nfsd/nfs4state.c
parent36d44c6038f6d3f8786187a5558c2f3b39a7af95 (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.c112
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 */
63static struct nfs4_delegation * search_for_delegation(stateid_t *stid);
64static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
65static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); 63static 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, &current_fh->fh_handle); 263 fh_copy_shallow(&dp->dl_fh, &current_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)
292static void 292static void
293unhash_delegation(struct nfs4_delegation *dp) 293unhash_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
1080static struct nfs4_ol_stateid *find_stateid(stateid_t *t) 1081static 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
1092static struct nfs4_ol_stateid *find_stateid_by_type(stateid_t *t, char typemask) 1093static 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
1103static 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
1115static 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
1104static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, 1125static 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
2576static struct nfs4_delegation * 2597static int share_access_to_flags(u32 share_access)
2577find_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
2591static int share_access_to_flags(u32 share_access) 2604static 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
2598static __be32 2614static __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:
3348static __be32 3364static __be32
3349nfsd4_free_delegation_stateid(stateid_t *stateid) 3365nfsd4_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,
3733static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE]; 3750static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
3734static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; 3751static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
3735 3752
3736static struct nfs4_delegation *
3737search_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
3756static struct nfs4_delegation *
3757find_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