diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-09-23 17:01:19 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-09-26 17:35:28 -0400 |
commit | 38c2f4b12a455cb3a108fd5c79a10df2ba3ec9a7 (patch) | |
tree | 125aa30a29a2863b448d66b2b0d31d4f65db0533 /fs/nfsd | |
parent | 36279ac10c3d69372af875f1affafd375db687a9 (diff) |
nfsd4: look up stateid's per clientid
Use a separate stateid idr per client, and lookup a stateid by first
finding the client, then looking up the stateid relative to that client.
Also some minor refactoring.
This allows us to improve error returns: we can return expired when the
clientid is not found and bad_stateid when the clientid is found but not
the stateid, as opposed to returning expired for both cases.
I hope this will also help to replace the state lock mostly by a
per-client lock, but that hasn't been done yet.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 112 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 3 | ||||
-rw-r--r-- | fs/nfsd/state.h | 4 |
3 files changed, 54 insertions, 65 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index daf75fa4c027..931155f51ecc 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -32,7 +32,6 @@ | |||
32 | * | 32 | * |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/idr.h> | ||
36 | #include <linux/file.h> | 35 | #include <linux/file.h> |
37 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
38 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
@@ -149,8 +148,6 @@ static struct list_head open_ownerstr_hashtbl[OPEN_OWNER_HASH_SIZE]; | |||
149 | #define FILE_HASH_BITS 8 | 148 | #define FILE_HASH_BITS 8 |
150 | #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) | 149 | #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) |
151 | 150 | ||
152 | struct idr stateids; | ||
153 | |||
154 | static unsigned int file_hashval(struct inode *ino) | 151 | static unsigned int file_hashval(struct inode *ino) |
155 | { | 152 | { |
156 | /* XXX: why are we hashing on inode pointer, anyway? */ | 153 | /* XXX: why are we hashing on inode pointer, anyway? */ |
@@ -209,13 +206,14 @@ static void nfs4_file_put_access(struct nfs4_file *fp, int oflag) | |||
209 | static inline int get_new_stid(struct nfs4_stid *stid) | 206 | static inline int get_new_stid(struct nfs4_stid *stid) |
210 | { | 207 | { |
211 | static int min_stateid = 0; | 208 | static int min_stateid = 0; |
209 | struct idr *stateids = &stid->sc_client->cl_stateids; | ||
212 | int new_stid; | 210 | int new_stid; |
213 | int error; | 211 | int error; |
214 | 212 | ||
215 | if (!idr_pre_get(&stateids, GFP_KERNEL)) | 213 | if (!idr_pre_get(stateids, GFP_KERNEL)) |
216 | return -ENOMEM; | 214 | return -ENOMEM; |
217 | 215 | ||
218 | error = idr_get_new_above(&stateids, stid, min_stateid, &new_stid); | 216 | error = idr_get_new_above(stateids, stid, min_stateid, &new_stid); |
219 | /* | 217 | /* |
220 | * All this code is currently serialized; the preallocation | 218 | * All this code is currently serialized; the preallocation |
221 | * above should still be ours: | 219 | * above should still be ours: |
@@ -324,7 +322,9 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp) | |||
324 | 322 | ||
325 | static void unhash_stid(struct nfs4_stid *s) | 323 | static void unhash_stid(struct nfs4_stid *s) |
326 | { | 324 | { |
327 | idr_remove(&stateids, s->sc_stateid.si_opaque.so_id); | 325 | struct idr *stateids = &s->sc_client->cl_stateids; |
326 | |||
327 | idr_remove(stateids, s->sc_stateid.si_opaque.so_id); | ||
328 | } | 328 | } |
329 | 329 | ||
330 | /* Called under the state lock. */ | 330 | /* Called under the state lock. */ |
@@ -1126,16 +1126,16 @@ static void gen_confirm(struct nfs4_client *clp) | |||
1126 | *p++ = i++; | 1126 | *p++ = i++; |
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | static struct nfs4_stid *find_stateid(stateid_t *t) | 1129 | static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) |
1130 | { | 1130 | { |
1131 | return idr_find(&stateids, t->si_opaque.so_id); | 1131 | return idr_find(&cl->cl_stateids, t->si_opaque.so_id); |
1132 | } | 1132 | } |
1133 | 1133 | ||
1134 | static struct nfs4_stid *find_stateid_by_type(stateid_t *t, char typemask) | 1134 | static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask) |
1135 | { | 1135 | { |
1136 | struct nfs4_stid *s; | 1136 | struct nfs4_stid *s; |
1137 | 1137 | ||
1138 | s = find_stateid(t); | 1138 | s = find_stateid(cl, t); |
1139 | if (!s) | 1139 | if (!s) |
1140 | return NULL; | 1140 | return NULL; |
1141 | if (typemask & s->sc_type) | 1141 | if (typemask & s->sc_type) |
@@ -1143,16 +1143,6 @@ static struct nfs4_stid *find_stateid_by_type(stateid_t *t, char typemask) | |||
1143 | return NULL; | 1143 | return NULL; |
1144 | } | 1144 | } |
1145 | 1145 | ||
1146 | static struct nfs4_ol_stateid *find_ol_stateid_by_type(stateid_t *t, char typemask) | ||
1147 | { | ||
1148 | struct nfs4_stid *s; | ||
1149 | |||
1150 | s = find_stateid_by_type(t, typemask); | ||
1151 | if (!s) | ||
1152 | return NULL; | ||
1153 | return openlockstateid(s); | ||
1154 | } | ||
1155 | |||
1156 | static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | 1146 | static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, |
1157 | struct svc_rqst *rqstp, nfs4_verifier *verf) | 1147 | struct svc_rqst *rqstp, nfs4_verifier *verf) |
1158 | { | 1148 | { |
@@ -1175,6 +1165,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | |||
1175 | } | 1165 | } |
1176 | } | 1166 | } |
1177 | 1167 | ||
1168 | idr_init(&clp->cl_stateids); | ||
1178 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); | 1169 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); |
1179 | atomic_set(&clp->cl_refcount, 0); | 1170 | atomic_set(&clp->cl_refcount, 0); |
1180 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; | 1171 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
@@ -2611,24 +2602,24 @@ static int share_access_to_flags(u32 share_access) | |||
2611 | return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; | 2602 | return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; |
2612 | } | 2603 | } |
2613 | 2604 | ||
2614 | static struct nfs4_delegation *find_deleg_stateid(stateid_t *s) | 2605 | static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, stateid_t *s) |
2615 | { | 2606 | { |
2616 | struct nfs4_stid *ret; | 2607 | struct nfs4_stid *ret; |
2617 | 2608 | ||
2618 | ret = find_stateid_by_type(s, NFS4_DELEG_STID); | 2609 | ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID); |
2619 | if (!ret) | 2610 | if (!ret) |
2620 | return NULL; | 2611 | return NULL; |
2621 | return delegstateid(ret); | 2612 | return delegstateid(ret); |
2622 | } | 2613 | } |
2623 | 2614 | ||
2624 | static __be32 | 2615 | static __be32 |
2625 | nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, | 2616 | nfs4_check_deleg(struct nfs4_client *cl, struct nfs4_file *fp, struct nfsd4_open *open, |
2626 | struct nfs4_delegation **dp) | 2617 | struct nfs4_delegation **dp) |
2627 | { | 2618 | { |
2628 | int flags; | 2619 | int flags; |
2629 | __be32 status = nfserr_bad_stateid; | 2620 | __be32 status = nfserr_bad_stateid; |
2630 | 2621 | ||
2631 | *dp = find_deleg_stateid(&open->op_delegate_stateid); | 2622 | *dp = find_deleg_stateid(cl, &open->op_delegate_stateid); |
2632 | if (*dp == NULL) | 2623 | if (*dp == NULL) |
2633 | goto out; | 2624 | goto out; |
2634 | flags = share_access_to_flags(open->op_share_access); | 2625 | flags = share_access_to_flags(open->op_share_access); |
@@ -2920,6 +2911,7 @@ __be32 | |||
2920 | nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) | 2911 | nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) |
2921 | { | 2912 | { |
2922 | struct nfsd4_compoundres *resp = rqstp->rq_resp; | 2913 | struct nfsd4_compoundres *resp = rqstp->rq_resp; |
2914 | struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; | ||
2923 | struct nfs4_file *fp = NULL; | 2915 | struct nfs4_file *fp = NULL; |
2924 | struct inode *ino = current_fh->fh_dentry->d_inode; | 2916 | struct inode *ino = current_fh->fh_dentry->d_inode; |
2925 | struct nfs4_ol_stateid *stp = NULL; | 2917 | struct nfs4_ol_stateid *stp = NULL; |
@@ -2939,7 +2931,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
2939 | if (fp) { | 2931 | if (fp) { |
2940 | if ((status = nfs4_check_open(fp, open, &stp))) | 2932 | if ((status = nfs4_check_open(fp, open, &stp))) |
2941 | goto out; | 2933 | goto out; |
2942 | status = nfs4_check_deleg(fp, open, &dp); | 2934 | status = nfs4_check_deleg(cl, fp, open, &dp); |
2943 | if (status) | 2935 | if (status) |
2944 | goto out; | 2936 | goto out; |
2945 | } else { | 2937 | } else { |
@@ -3256,7 +3248,7 @@ static int check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_sess | |||
3256 | return nfserr_old_stateid; | 3248 | return nfserr_old_stateid; |
3257 | } | 3249 | } |
3258 | 3250 | ||
3259 | __be32 nfs4_validate_stateid(stateid_t *stateid) | 3251 | __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) |
3260 | { | 3252 | { |
3261 | struct nfs4_stid *s; | 3253 | struct nfs4_stid *s; |
3262 | struct nfs4_ol_stateid *ols; | 3254 | struct nfs4_ol_stateid *ols; |
@@ -3265,7 +3257,7 @@ __be32 nfs4_validate_stateid(stateid_t *stateid) | |||
3265 | if (STALE_STATEID(stateid)) | 3257 | if (STALE_STATEID(stateid)) |
3266 | return nfserr_stale_stateid; | 3258 | return nfserr_stale_stateid; |
3267 | 3259 | ||
3268 | s = find_stateid(stateid); | 3260 | s = find_stateid(cl, stateid); |
3269 | if (!s) | 3261 | if (!s) |
3270 | return nfserr_stale_stateid; | 3262 | return nfserr_stale_stateid; |
3271 | status = check_stateid_generation(stateid, &s->sc_stateid, 1); | 3263 | status = check_stateid_generation(stateid, &s->sc_stateid, 1); |
@@ -3280,6 +3272,24 @@ __be32 nfs4_validate_stateid(stateid_t *stateid) | |||
3280 | return nfs_ok; | 3272 | return nfs_ok; |
3281 | } | 3273 | } |
3282 | 3274 | ||
3275 | static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) | ||
3276 | { | ||
3277 | struct nfs4_client *cl; | ||
3278 | |||
3279 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) | ||
3280 | return nfserr_bad_stateid; | ||
3281 | if (STALE_STATEID(stateid)) | ||
3282 | return nfserr_stale_stateid; | ||
3283 | cl = find_confirmed_client(&stateid->si_opaque.so_clid); | ||
3284 | if (!cl) | ||
3285 | return nfserr_expired; | ||
3286 | *s = find_stateid_by_type(cl, stateid, typemask); | ||
3287 | if (!*s) | ||
3288 | return nfserr_bad_stateid; | ||
3289 | return nfs_ok; | ||
3290 | |||
3291 | } | ||
3292 | |||
3283 | /* | 3293 | /* |
3284 | * Checks for stateid operations | 3294 | * Checks for stateid operations |
3285 | */ | 3295 | */ |
@@ -3303,18 +3313,9 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
3303 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) | 3313 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) |
3304 | return check_special_stateids(current_fh, stateid, flags); | 3314 | return check_special_stateids(current_fh, stateid, flags); |
3305 | 3315 | ||
3306 | status = nfserr_stale_stateid; | 3316 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); |
3307 | if (STALE_STATEID(stateid)) | 3317 | if (status) |
3308 | goto out; | 3318 | return status; |
3309 | |||
3310 | /* | ||
3311 | * We assume that any stateid that has the current boot time, | ||
3312 | * but that we can't find, is expired: | ||
3313 | */ | ||
3314 | status = nfserr_expired; | ||
3315 | s = find_stateid(stateid); | ||
3316 | if (!s) | ||
3317 | goto out; | ||
3318 | status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); | 3319 | status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); |
3319 | if (status) | 3320 | if (status) |
3320 | goto out; | 3321 | goto out; |
@@ -3384,10 +3385,11 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3384 | { | 3385 | { |
3385 | stateid_t *stateid = &free_stateid->fr_stateid; | 3386 | stateid_t *stateid = &free_stateid->fr_stateid; |
3386 | struct nfs4_stid *s; | 3387 | struct nfs4_stid *s; |
3388 | struct nfs4_client *cl = cstate->session->se_client; | ||
3387 | __be32 ret = nfserr_bad_stateid; | 3389 | __be32 ret = nfserr_bad_stateid; |
3388 | 3390 | ||
3389 | nfs4_lock_state(); | 3391 | nfs4_lock_state(); |
3390 | s = find_stateid(stateid); | 3392 | s = find_stateid(cl, stateid); |
3391 | if (!s) | 3393 | if (!s) |
3392 | goto out; | 3394 | goto out; |
3393 | switch (s->sc_type) { | 3395 | switch (s->sc_type) { |
@@ -3419,15 +3421,6 @@ setlkflg (int type) | |||
3419 | RD_STATE : WR_STATE; | 3421 | RD_STATE : WR_STATE; |
3420 | } | 3422 | } |
3421 | 3423 | ||
3422 | static __be32 nfs4_nospecial_stateid_checks(stateid_t *stateid) | ||
3423 | { | ||
3424 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) | ||
3425 | return nfserr_bad_stateid; | ||
3426 | if (STALE_STATEID(stateid)) | ||
3427 | return nfserr_stale_stateid; | ||
3428 | return nfs_ok; | ||
3429 | } | ||
3430 | |||
3431 | static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_t *stateid, u32 seqid, struct nfs4_ol_stateid *stp) | 3424 | static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_t *stateid, u32 seqid, struct nfs4_ol_stateid *stp) |
3432 | { | 3425 | { |
3433 | struct svc_fh *current_fh = &cstate->current_fh; | 3426 | struct svc_fh *current_fh = &cstate->current_fh; |
@@ -3458,17 +3451,16 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, | |||
3458 | struct nfs4_ol_stateid **stpp) | 3451 | struct nfs4_ol_stateid **stpp) |
3459 | { | 3452 | { |
3460 | __be32 status; | 3453 | __be32 status; |
3454 | struct nfs4_stid *s; | ||
3461 | 3455 | ||
3462 | dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__, | 3456 | dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__, |
3463 | seqid, STATEID_VAL(stateid)); | 3457 | seqid, STATEID_VAL(stateid)); |
3464 | 3458 | ||
3465 | *stpp = NULL; | 3459 | *stpp = NULL; |
3466 | status = nfs4_nospecial_stateid_checks(stateid); | 3460 | status = nfsd4_lookup_stateid(stateid, typemask, &s); |
3467 | if (status) | 3461 | if (status) |
3468 | return status; | 3462 | return status; |
3469 | *stpp = find_ol_stateid_by_type(stateid, typemask); | 3463 | *stpp = openlockstateid(s); |
3470 | if (*stpp == NULL) | ||
3471 | return nfserr_expired; | ||
3472 | cstate->replay_owner = (*stpp)->st_stateowner; | 3464 | cstate->replay_owner = (*stpp)->st_stateowner; |
3473 | renew_client((*stpp)->st_stateowner->so_client); | 3465 | renew_client((*stpp)->st_stateowner->so_client); |
3474 | 3466 | ||
@@ -3673,6 +3665,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3673 | { | 3665 | { |
3674 | struct nfs4_delegation *dp; | 3666 | struct nfs4_delegation *dp; |
3675 | stateid_t *stateid = &dr->dr_stateid; | 3667 | stateid_t *stateid = &dr->dr_stateid; |
3668 | struct nfs4_stid *s; | ||
3676 | struct inode *inode; | 3669 | struct inode *inode; |
3677 | __be32 status; | 3670 | __be32 status; |
3678 | 3671 | ||
@@ -3681,16 +3674,10 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3681 | inode = cstate->current_fh.fh_dentry->d_inode; | 3674 | inode = cstate->current_fh.fh_dentry->d_inode; |
3682 | 3675 | ||
3683 | nfs4_lock_state(); | 3676 | nfs4_lock_state(); |
3684 | status = nfserr_bad_stateid; | 3677 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s); |
3685 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) | 3678 | if (status) |
3686 | goto out; | ||
3687 | status = nfserr_stale_stateid; | ||
3688 | if (STALE_STATEID(stateid)) | ||
3689 | goto out; | ||
3690 | status = nfserr_expired; | ||
3691 | dp = find_deleg_stateid(stateid); | ||
3692 | if (!dp) | ||
3693 | goto out; | 3679 | goto out; |
3680 | dp = delegstateid(s); | ||
3694 | status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); | 3681 | status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); |
3695 | if (status) | 3682 | if (status) |
3696 | goto out; | 3683 | goto out; |
@@ -4409,7 +4396,6 @@ nfs4_state_init(void) | |||
4409 | for (i = 0; i < OPEN_OWNER_HASH_SIZE; i++) { | 4396 | for (i = 0; i < OPEN_OWNER_HASH_SIZE; i++) { |
4410 | INIT_LIST_HEAD(&open_ownerstr_hashtbl[i]); | 4397 | INIT_LIST_HEAD(&open_ownerstr_hashtbl[i]); |
4411 | } | 4398 | } |
4412 | idr_init(&stateids); | ||
4413 | for (i = 0; i < LOCK_HASH_SIZE; i++) { | 4399 | for (i = 0; i < LOCK_HASH_SIZE; i++) { |
4414 | INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]); | 4400 | INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]); |
4415 | } | 4401 | } |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 2429fffa31dd..5779acde7e70 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -3287,6 +3287,7 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, | |||
3287 | struct nfsd4_test_stateid *test_stateid) | 3287 | struct nfsd4_test_stateid *test_stateid) |
3288 | { | 3288 | { |
3289 | struct nfsd4_compoundargs *argp; | 3289 | struct nfsd4_compoundargs *argp; |
3290 | struct nfs4_client *cl = resp->cstate.session->se_client; | ||
3290 | stateid_t si; | 3291 | stateid_t si; |
3291 | __be32 *p; | 3292 | __be32 *p; |
3292 | int i; | 3293 | int i; |
@@ -3302,7 +3303,7 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, | |||
3302 | nfs4_lock_state(); | 3303 | nfs4_lock_state(); |
3303 | for (i = 0; i < test_stateid->ts_num_ids; i++) { | 3304 | for (i = 0; i < test_stateid->ts_num_ids; i++) { |
3304 | nfsd4_decode_stateid(argp, &si); | 3305 | nfsd4_decode_stateid(argp, &si); |
3305 | valid = nfs4_validate_stateid(&si); | 3306 | valid = nfs4_validate_stateid(cl, &si); |
3306 | RESERVE_SPACE(4); | 3307 | RESERVE_SPACE(4); |
3307 | *p++ = htonl(valid); | 3308 | *p++ = htonl(valid); |
3308 | resp->p = p; | 3309 | resp->p = p; |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 55a4d6a108a2..13f6f9f5ceec 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #ifndef _NFSD4_STATE_H | 35 | #ifndef _NFSD4_STATE_H |
36 | #define _NFSD4_STATE_H | 36 | #define _NFSD4_STATE_H |
37 | 37 | ||
38 | #include <linux/idr.h> | ||
38 | #include <linux/sunrpc/svc_xprt.h> | 39 | #include <linux/sunrpc/svc_xprt.h> |
39 | #include <linux/nfsd/nfsfh.h> | 40 | #include <linux/nfsd/nfsfh.h> |
40 | #include "nfsfh.h" | 41 | #include "nfsfh.h" |
@@ -231,6 +232,7 @@ struct nfs4_client { | |||
231 | struct list_head cl_idhash; /* hash by cl_clientid.id */ | 232 | struct list_head cl_idhash; /* hash by cl_clientid.id */ |
232 | struct list_head cl_strhash; /* hash by cl_name */ | 233 | struct list_head cl_strhash; /* hash by cl_name */ |
233 | struct list_head cl_openowners; | 234 | struct list_head cl_openowners; |
235 | struct idr cl_stateids; /* stateid lookup */ | ||
234 | struct list_head cl_delegations; | 236 | struct list_head cl_delegations; |
235 | struct list_head cl_lru; /* tail queue */ | 237 | struct list_head cl_lru; /* tail queue */ |
236 | struct xdr_netobj cl_name; /* id generated by client */ | 238 | struct xdr_netobj cl_name; /* id generated by client */ |
@@ -508,7 +510,7 @@ extern void nfsd4_recdir_purge_old(void); | |||
508 | extern int nfsd4_create_clid_dir(struct nfs4_client *clp); | 510 | extern int nfsd4_create_clid_dir(struct nfs4_client *clp); |
509 | extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); | 511 | extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); |
510 | extern void release_session_client(struct nfsd4_session *); | 512 | extern void release_session_client(struct nfsd4_session *); |
511 | extern __be32 nfs4_validate_stateid(stateid_t *); | 513 | extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *); |
512 | extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); | 514 | extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); |
513 | 515 | ||
514 | #endif /* NFSD4_STATE_H */ | 516 | #endif /* NFSD4_STATE_H */ |