diff options
-rw-r--r-- | fs/nfsd/nfs4state.c | 40 |
1 files changed, 14 insertions, 26 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 7694fb8aae35..67e03b5d0d83 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1988,14 +1988,11 @@ laundromat_main(void *not_used) | |||
1988 | queue_delayed_work(laundry_wq, &laundromat_work, t*HZ); | 1988 | queue_delayed_work(laundry_wq, &laundromat_work, t*HZ); |
1989 | } | 1989 | } |
1990 | 1990 | ||
1991 | /* search ownerid_hashtbl[] and close_lru for stateid owner | ||
1992 | * (stateid->si_stateownerid) | ||
1993 | */ | ||
1994 | static struct nfs4_stateowner * | 1991 | static struct nfs4_stateowner * |
1995 | find_openstateowner_id(u32 st_id, int flags) { | 1992 | search_close_lru(u32 st_id, int flags) |
1993 | { | ||
1996 | struct nfs4_stateowner *local = NULL; | 1994 | struct nfs4_stateowner *local = NULL; |
1997 | 1995 | ||
1998 | dprintk("NFSD: find_openstateowner_id %d\n", st_id); | ||
1999 | if (flags & CLOSE_STATE) { | 1996 | if (flags & CLOSE_STATE) { |
2000 | list_for_each_entry(local, &close_lru, so_close_lru) { | 1997 | list_for_each_entry(local, &close_lru, so_close_lru) { |
2001 | if (local->so_id == st_id) | 1998 | if (local->so_id == st_id) |
@@ -2193,13 +2190,19 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2193 | * We return BAD_STATEID if filehandle doesn't match stateid, | 2190 | * We return BAD_STATEID if filehandle doesn't match stateid, |
2194 | * the confirmed flag is incorrecly set, or the generation | 2191 | * the confirmed flag is incorrecly set, or the generation |
2195 | * number is incorrect. | 2192 | * number is incorrect. |
2196 | * If there is no entry in the openfile table for this id, | ||
2197 | * we can't always return BAD_STATEID; | ||
2198 | * this might be a retransmitted CLOSE which has arrived after | ||
2199 | * the openfile has been released. | ||
2200 | */ | 2193 | */ |
2201 | if (!(stp = find_stateid(stateid, flags))) | 2194 | stp = find_stateid(stateid, flags); |
2202 | goto no_nfs4_stateid; | 2195 | if (stp == NULL) { |
2196 | /* | ||
2197 | * Also, we should make sure this isn't just the result of | ||
2198 | * a replayed close: | ||
2199 | */ | ||
2200 | sop = search_close_lru(stateid->si_stateownerid, flags); | ||
2201 | if (sop == NULL) | ||
2202 | return nfserr_bad_stateid; | ||
2203 | *sopp = sop; | ||
2204 | goto check_replay; | ||
2205 | } | ||
2203 | 2206 | ||
2204 | status = nfserr_bad_stateid; | 2207 | status = nfserr_bad_stateid; |
2205 | 2208 | ||
@@ -2263,21 +2266,6 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2263 | 2266 | ||
2264 | out: | 2267 | out: |
2265 | return status; | 2268 | return status; |
2266 | |||
2267 | no_nfs4_stateid: | ||
2268 | |||
2269 | /* | ||
2270 | * We determine whether this is a bad stateid or a replay, | ||
2271 | * starting by trying to look up the stateowner. | ||
2272 | * If stateowner is not found - stateid is bad. | ||
2273 | */ | ||
2274 | if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) { | ||
2275 | printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n"); | ||
2276 | status = nfserr_bad_stateid; | ||
2277 | goto out; | ||
2278 | } | ||
2279 | *sopp = sop; | ||
2280 | |||
2281 | check_replay: | 2269 | check_replay: |
2282 | if (seqid == sop->so_seqid - 1) { | 2270 | if (seqid == sop->so_seqid - 1) { |
2283 | printk("NFSD: preprocess_seqid_op: retransmission?\n"); | 2271 | printk("NFSD: preprocess_seqid_op: retransmission?\n"); |