aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-09-15 15:02:41 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-09-19 06:33:57 -0400
commitd3b313a463c64c54d57c6af09c4a5d20106c1d1c (patch)
tree9ade49e59a3771f2a4dedf50baf0f44d55b11b46 /fs/nfsd
parent2da1cec713bc6d3ec9732e7d48b8bc0453580fd3 (diff)
nfsd4: construct stateid from clientid and counter
Including the full clientid in the on-the-wire stateid allows more reliable detection of bad vs. expired stateid's, simplifies code, and ensures we won't reuse the opaque part of the stateid (as we currently do when the same openowner closes and reopens the same file). Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c58
-rw-r--r--fs/nfsd/state.h18
2 files changed, 18 insertions, 58 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index fdd03f6ae044..922f47dd0d74 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -49,9 +49,7 @@
49time_t nfsd4_lease = 90; /* default lease time */ 49time_t nfsd4_lease = 90; /* default lease time */
50time_t nfsd4_grace = 90; 50time_t nfsd4_grace = 90;
51static time_t boot_time; 51static time_t boot_time;
52static u32 current_ownerid = 1; 52static u32 current_stateid = 1;
53static u32 current_fileid = 1;
54static u32 current_delegid = 1;
55static stateid_t zerostateid; /* bits all 0 */ 53static stateid_t zerostateid; /* bits all 0 */
56static stateid_t onestateid; /* bits all 1 */ 54static stateid_t onestateid; /* bits all 1 */
57static u64 current_sessionid = 1; 55static u64 current_sessionid = 1;
@@ -136,11 +134,6 @@ unsigned int max_delegations;
136#define OPEN_OWNER_HASH_SIZE (1 << OPEN_OWNER_HASH_BITS) 134#define OPEN_OWNER_HASH_SIZE (1 << OPEN_OWNER_HASH_BITS)
137#define OPEN_OWNER_HASH_MASK (OPEN_OWNER_HASH_SIZE - 1) 135#define OPEN_OWNER_HASH_MASK (OPEN_OWNER_HASH_SIZE - 1)
138 136
139static unsigned int open_ownerid_hashval(const u32 id)
140{
141 return id & OPEN_OWNER_HASH_MASK;
142}
143
144static unsigned int open_ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) 137static unsigned int open_ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername)
145{ 138{
146 unsigned int ret; 139 unsigned int ret;
@@ -150,7 +143,6 @@ static unsigned int open_ownerstr_hashval(u32 clientid, struct xdr_netobj *owner
150 return ret & OPEN_OWNER_HASH_MASK; 143 return ret & OPEN_OWNER_HASH_MASK;
151} 144}
152 145
153static struct list_head open_ownerid_hashtbl[OPEN_OWNER_HASH_SIZE];
154static struct list_head open_ownerstr_hashtbl[OPEN_OWNER_HASH_SIZE]; 146static struct list_head open_ownerstr_hashtbl[OPEN_OWNER_HASH_SIZE];
155 147
156/* hash table for nfs4_file */ 148/* hash table for nfs4_file */
@@ -255,9 +247,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
255 dp->dl_file = fp; 247 dp->dl_file = fp;
256 dp->dl_type = type; 248 dp->dl_type = type;
257 dp->dl_stid.sc_type = NFS4_DELEG_STID; 249 dp->dl_stid.sc_type = NFS4_DELEG_STID;
258 dp->dl_stid.sc_stateid.si_boot = boot_time; 250 dp->dl_stid.sc_stateid.si_opaque.so_clid = clp->cl_clientid;
259 dp->dl_stid.sc_stateid.si_stateownerid = current_delegid++; 251 dp->dl_stid.sc_stateid.si_opaque.so_id = current_stateid++;
260 dp->dl_stid.sc_stateid.si_fileid = 0;
261 dp->dl_stid.sc_stateid.si_generation = 1; 252 dp->dl_stid.sc_stateid.si_generation = 1;
262 hash_stid(&dp->dl_stid); 253 hash_stid(&dp->dl_stid);
263 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle); 254 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
@@ -457,7 +448,6 @@ static void unhash_lockowner(struct nfs4_lockowner *lo)
457{ 448{
458 struct nfs4_ol_stateid *stp; 449 struct nfs4_ol_stateid *stp;
459 450
460 list_del(&lo->lo_owner.so_idhash);
461 list_del(&lo->lo_owner.so_strhash); 451 list_del(&lo->lo_owner.so_strhash);
462 list_del(&lo->lo_perstateid); 452 list_del(&lo->lo_perstateid);
463 while (!list_empty(&lo->lo_owner.so_stateids)) { 453 while (!list_empty(&lo->lo_owner.so_stateids)) {
@@ -502,7 +492,6 @@ static void unhash_openowner(struct nfs4_openowner *oo)
502{ 492{
503 struct nfs4_ol_stateid *stp; 493 struct nfs4_ol_stateid *stp;
504 494
505 list_del(&oo->oo_owner.so_idhash);
506 list_del(&oo->oo_owner.so_strhash); 495 list_del(&oo->oo_owner.so_strhash);
507 list_del(&oo->oo_perclient); 496 list_del(&oo->oo_perclient);
508 while (!list_empty(&oo->oo_owner.so_stateids)) { 497 while (!list_empty(&oo->oo_owner.so_stateids)) {
@@ -1081,9 +1070,8 @@ static void gen_confirm(struct nfs4_client *clp)
1081static int 1070static int
1082same_stateid(stateid_t *id_one, stateid_t *id_two) 1071same_stateid(stateid_t *id_one, stateid_t *id_two)
1083{ 1072{
1084 if (id_one->si_stateownerid != id_two->si_stateownerid) 1073 return 0 == memcmp(&id_one->si_opaque, &id_two->si_opaque,
1085 return 0; 1074 sizeof(stateid_opaque_t));
1086 return id_one->si_fileid == id_two->si_fileid;
1087} 1075}
1088 1076
1089static struct nfs4_stid *find_stateid(stateid_t *t) 1077static struct nfs4_stid *find_stateid(stateid_t *t)
@@ -2198,7 +2186,6 @@ alloc_init_file(struct inode *ino)
2198 INIT_LIST_HEAD(&fp->fi_stateids); 2186 INIT_LIST_HEAD(&fp->fi_stateids);
2199 INIT_LIST_HEAD(&fp->fi_delegations); 2187 INIT_LIST_HEAD(&fp->fi_delegations);
2200 fp->fi_inode = igrab(ino); 2188 fp->fi_inode = igrab(ino);
2201 fp->fi_id = current_fileid++;
2202 fp->fi_had_conflict = false; 2189 fp->fi_had_conflict = false;
2203 fp->fi_lease = NULL; 2190 fp->fi_lease = NULL;
2204 memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); 2191 memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
@@ -2295,7 +2282,6 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj
2295 sop->so_owner.len = owner->len; 2282 sop->so_owner.len = owner->len;
2296 2283
2297 INIT_LIST_HEAD(&sop->so_stateids); 2284 INIT_LIST_HEAD(&sop->so_stateids);
2298 sop->so_id = current_ownerid++;
2299 sop->so_client = clp; 2285 sop->so_client = clp;
2300 init_nfs4_replay(&sop->so_replay); 2286 init_nfs4_replay(&sop->so_replay);
2301 return sop; 2287 return sop;
@@ -2303,10 +2289,6 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj
2303 2289
2304static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) 2290static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval)
2305{ 2291{
2306 unsigned int idhashval;
2307
2308 idhashval = open_ownerid_hashval(oo->oo_owner.so_id);
2309 list_add(&oo->oo_owner.so_idhash, &open_ownerid_hashtbl[idhashval]);
2310 list_add(&oo->oo_owner.so_strhash, &open_ownerstr_hashtbl[strhashval]); 2292 list_add(&oo->oo_owner.so_strhash, &open_ownerstr_hashtbl[strhashval]);
2311 list_add(&oo->oo_perclient, &clp->cl_openowners); 2293 list_add(&oo->oo_perclient, &clp->cl_openowners);
2312} 2294}
@@ -2331,6 +2313,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2331static inline void 2313static inline void
2332init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) { 2314init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
2333 struct nfs4_openowner *oo = open->op_openowner; 2315 struct nfs4_openowner *oo = open->op_openowner;
2316 struct nfs4_client *clp = oo->oo_owner.so_client;
2334 2317
2335 INIT_LIST_HEAD(&stp->st_lockowners); 2318 INIT_LIST_HEAD(&stp->st_lockowners);
2336 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); 2319 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
@@ -2339,9 +2322,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd
2339 stp->st_stateowner = &oo->oo_owner; 2322 stp->st_stateowner = &oo->oo_owner;
2340 get_nfs4_file(fp); 2323 get_nfs4_file(fp);
2341 stp->st_file = fp; 2324 stp->st_file = fp;
2342 stp->st_stid.sc_stateid.si_boot = boot_time; 2325 stp->st_stid.sc_stateid.si_opaque.so_clid = clp->cl_clientid;
2343 stp->st_stid.sc_stateid.si_stateownerid = oo->oo_owner.so_id; 2326 stp->st_stid.sc_stateid.si_opaque.so_id = current_stateid++;
2344 stp->st_stid.sc_stateid.si_fileid = fp->fi_id;
2345 /* note will be incremented before first return to client: */ 2327 /* note will be incremented before first return to client: */
2346 stp->st_stid.sc_stateid.si_generation = 0; 2328 stp->st_stid.sc_stateid.si_generation = 0;
2347 hash_stid(&stp->st_stid); 2329 hash_stid(&stp->st_stid);
@@ -3095,8 +3077,6 @@ nfs4_laundromat(void)
3095 test_val = u; 3077 test_val = u;
3096 break; 3078 break;
3097 } 3079 }
3098 dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
3099 oo->oo_owner.so_id);
3100 release_openowner(oo); 3080 release_openowner(oo);
3101 } 3081 }
3102 if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT) 3082 if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
@@ -3141,7 +3121,7 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp)
3141static int 3121static int
3142STALE_STATEID(stateid_t *stateid) 3122STALE_STATEID(stateid_t *stateid)
3143{ 3123{
3144 if (stateid->si_boot == boot_time) 3124 if (stateid->si_opaque.so_clid.cl_boot == boot_time)
3145 return 0; 3125 return 0;
3146 dprintk("NFSD: stale stateid " STATEID_FMT "!\n", 3126 dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
3147 STATEID_VAL(stateid)); 3127 STATEID_VAL(stateid));
@@ -3710,11 +3690,6 @@ last_byte_offset(u64 start, u64 len)
3710 return end > start ? end - 1: NFS4_MAX_UINT64; 3690 return end > start ? end - 1: NFS4_MAX_UINT64;
3711} 3691}
3712 3692
3713static unsigned int lockownerid_hashval(u32 id)
3714{
3715 return id & LOCK_HASH_MASK;
3716}
3717
3718static inline unsigned int 3693static inline unsigned int
3719lock_ownerstr_hashval(struct inode *inode, u32 cl_id, 3694lock_ownerstr_hashval(struct inode *inode, u32 cl_id,
3720 struct xdr_netobj *ownername) 3695 struct xdr_netobj *ownername)
@@ -3724,7 +3699,6 @@ lock_ownerstr_hashval(struct inode *inode, u32 cl_id,
3724 & LOCK_HASH_MASK; 3699 & LOCK_HASH_MASK;
3725} 3700}
3726 3701
3727static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
3728static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; 3702static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
3729 3703
3730/* 3704/*
@@ -3795,10 +3769,6 @@ find_lockowner_str(struct inode *inode, clientid_t *clid,
3795 3769
3796static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp) 3770static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp)
3797{ 3771{
3798 unsigned int idhashval;
3799
3800 idhashval = lockownerid_hashval(lo->lo_owner.so_id);
3801 list_add(&lo->lo_owner.so_idhash, &lock_ownerid_hashtbl[idhashval]);
3802 list_add(&lo->lo_owner.so_strhash, &lock_ownerstr_hashtbl[strhashval]); 3772 list_add(&lo->lo_owner.so_strhash, &lock_ownerstr_hashtbl[strhashval]);
3803 list_add(&lo->lo_perstateid, &open_stp->st_lockowners); 3773 list_add(&lo->lo_perstateid, &open_stp->st_lockowners);
3804} 3774}
@@ -3831,6 +3801,7 @@ static struct nfs4_ol_stateid *
3831alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct nfs4_ol_stateid *open_stp) 3801alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct nfs4_ol_stateid *open_stp)
3832{ 3802{
3833 struct nfs4_ol_stateid *stp; 3803 struct nfs4_ol_stateid *stp;
3804 struct nfs4_client *clp = lo->lo_owner.so_client;
3834 3805
3835 stp = nfs4_alloc_stateid(); 3806 stp = nfs4_alloc_stateid();
3836 if (stp == NULL) 3807 if (stp == NULL)
@@ -3841,9 +3812,8 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct
3841 stp->st_stid.sc_type = NFS4_LOCK_STID; 3812 stp->st_stid.sc_type = NFS4_LOCK_STID;
3842 get_nfs4_file(fp); 3813 get_nfs4_file(fp);
3843 stp->st_file = fp; 3814 stp->st_file = fp;
3844 stp->st_stid.sc_stateid.si_boot = boot_time; 3815 stp->st_stid.sc_stateid.si_opaque.so_clid = clp->cl_clientid;
3845 stp->st_stid.sc_stateid.si_stateownerid = lo->lo_owner.so_id; 3816 stp->st_stid.sc_stateid.si_opaque.so_id = current_stateid++;
3846 stp->st_stid.sc_stateid.si_fileid = fp->fi_id;
3847 /* note will be incremented before first return to client: */ 3817 /* note will be incremented before first return to client: */
3848 stp->st_stid.sc_stateid.si_generation = 0; 3818 stp->st_stid.sc_stateid.si_generation = 0;
3849 hash_stid(&stp->st_stid); 3819 hash_stid(&stp->st_stid);
@@ -4252,7 +4222,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
4252 * data structures. */ 4222 * data structures. */
4253 INIT_LIST_HEAD(&matches); 4223 INIT_LIST_HEAD(&matches);
4254 for (i = 0; i < LOCK_HASH_SIZE; i++) { 4224 for (i = 0; i < LOCK_HASH_SIZE; i++) {
4255 list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) { 4225 list_for_each_entry(sop, &lock_ownerstr_hashtbl[i], so_strhash) {
4256 if (!same_owner_str(sop, owner, clid)) 4226 if (!same_owner_str(sop, owner, clid))
4257 continue; 4227 continue;
4258 list_for_each_entry(stp, &sop->so_stateids, 4228 list_for_each_entry(stp, &sop->so_stateids,
@@ -4398,12 +4368,10 @@ nfs4_state_init(void)
4398 } 4368 }
4399 for (i = 0; i < OPEN_OWNER_HASH_SIZE; i++) { 4369 for (i = 0; i < OPEN_OWNER_HASH_SIZE; i++) {
4400 INIT_LIST_HEAD(&open_ownerstr_hashtbl[i]); 4370 INIT_LIST_HEAD(&open_ownerstr_hashtbl[i]);
4401 INIT_LIST_HEAD(&open_ownerid_hashtbl[i]);
4402 } 4371 }
4403 for (i = 0; i < STATEID_HASH_SIZE; i++) 4372 for (i = 0; i < STATEID_HASH_SIZE; i++)
4404 INIT_LIST_HEAD(&stateid_hashtbl[i]); 4373 INIT_LIST_HEAD(&stateid_hashtbl[i]);
4405 for (i = 0; i < LOCK_HASH_SIZE; i++) { 4374 for (i = 0; i < LOCK_HASH_SIZE; i++) {
4406 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
4407 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]); 4375 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
4408 } 4376 }
4409 memset(&onestateid, ~0, sizeof(stateid_t)); 4377 memset(&onestateid, ~0, sizeof(stateid_t));
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index e807abb116f6..d6aec4f8d3dd 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -45,24 +45,20 @@ typedef struct {
45} clientid_t; 45} clientid_t;
46 46
47typedef struct { 47typedef struct {
48 u32 so_boot; 48 clientid_t so_clid;
49 u32 so_stateownerid; 49 u32 so_id;
50 u32 so_fileid;
51} stateid_opaque_t; 50} stateid_opaque_t;
52 51
53typedef struct { 52typedef struct {
54 u32 si_generation; 53 u32 si_generation;
55 stateid_opaque_t si_opaque; 54 stateid_opaque_t si_opaque;
56} stateid_t; 55} stateid_t;
57#define si_boot si_opaque.so_boot
58#define si_stateownerid si_opaque.so_stateownerid
59#define si_fileid si_opaque.so_fileid
60 56
61#define STATEID_FMT "(%08x/%08x/%08x/%08x)" 57#define STATEID_FMT "(%08x/%08x/%08x/%08x)"
62#define STATEID_VAL(s) \ 58#define STATEID_VAL(s) \
63 (s)->si_boot, \ 59 (s)->si_opaque.so_clid.cl_boot, \
64 (s)->si_stateownerid, \ 60 (s)->si_opaque.so_clid.cl_id, \
65 (s)->si_fileid, \ 61 (s)->si_opaque.so_id, \
66 (s)->si_generation 62 (s)->si_generation
67 63
68struct nfsd4_callback { 64struct nfsd4_callback {
@@ -353,11 +349,9 @@ struct nfs4_replay {
353*/ 349*/
354 350
355struct nfs4_stateowner { 351struct nfs4_stateowner {
356 struct list_head so_idhash; /* hash by so_id */
357 struct list_head so_strhash; /* hash by op_name */ 352 struct list_head so_strhash; /* hash by op_name */
358 struct list_head so_stateids; 353 struct list_head so_stateids;
359 int so_is_open_owner; /* 1=openowner,0=lockowner */ 354 int so_is_open_owner; /* 1=openowner,0=lockowner */
360 u32 so_id;
361 struct nfs4_client * so_client; 355 struct nfs4_client * so_client;
362 /* after increment in ENCODE_SEQID_OP_TAIL, represents the next 356 /* after increment in ENCODE_SEQID_OP_TAIL, represents the next
363 * sequence id expected from the client: */ 357 * sequence id expected from the client: */
@@ -415,8 +409,6 @@ struct nfs4_file {
415 struct file_lock *fi_lease; 409 struct file_lock *fi_lease;
416 atomic_t fi_delegees; 410 atomic_t fi_delegees;
417 struct inode *fi_inode; 411 struct inode *fi_inode;
418 u32 fi_id; /* used with stateowner->so_id
419 * for stateid_hashtbl hash */
420 bool fi_had_conflict; 412 bool fi_had_conflict;
421}; 413};
422 414