]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | Patch-mainline: submitted 04aug2009 |
2 | References: bnc#498708 | |
3 | From: NeilBrown <neilb@suse.de> | |
4 | Date: Tue, 4 Aug 2009 15:06:37 +1000 | |
5 | Subject: [PATCH 04/12] sunrpc/cache: recheck cache validity after cache_defer_req | |
6 | ||
7 | If cache_defer_req did not leave the request on a queue, then it could | |
8 | possibly have waited long enough that the cache became valid. So check the | |
9 | status after the call. | |
10 | ||
11 | Signed-off-by: NeilBrown <neilb@suse.de> | |
12 | ||
13 | --- | |
14 | net/sunrpc/cache.c | 53 +++++++++++++++++++++++++++++++++-------------------- | |
15 | 1 file changed, 33 insertions(+), 20 deletions(-) | |
16 | ||
17 | --- linux-2.6.27-SLE11_BRANCH.orig/net/sunrpc/cache.c | |
18 | +++ linux-2.6.27-SLE11_BRANCH/net/sunrpc/cache.c | |
19 | @@ -173,6 +173,22 @@ struct cache_head *sunrpc_cache_update(s | |
20 | EXPORT_SYMBOL(sunrpc_cache_update); | |
21 | ||
22 | static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); | |
23 | + | |
24 | +static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) | |
25 | +{ | |
26 | + if (!test_bit(CACHE_VALID, &h->flags) || | |
27 | + h->expiry_time < get_seconds()) | |
28 | + return -EAGAIN; | |
29 | + else if (detail->flush_time > h->last_refresh) | |
30 | + return -EAGAIN; | |
31 | + else { | |
32 | + /* entry is valid */ | |
33 | + if (test_bit(CACHE_NEGATIVE, &h->flags)) | |
34 | + return -ENOENT; | |
35 | + else | |
36 | + return 0; | |
37 | + } | |
38 | +} | |
39 | /* | |
40 | * This is the generic cache management routine for all | |
41 | * the authentication caches. | |
42 | @@ -181,8 +197,10 @@ static int cache_make_upcall(struct cach | |
43 | * | |
44 | * | |
45 | * Returns 0 if the cache_head can be used, or cache_puts it and returns | |
46 | - * -EAGAIN if upcall is pending, | |
47 | - * -ETIMEDOUT if upcall failed and should be retried, | |
48 | + * -EAGAIN if upcall is pending and request has been queued | |
49 | + * -ETIMEDOUT if upcall failed or request could not be queue or | |
50 | + * upcall completed but item is still invalid (implying that | |
51 | + * the cache item has been replaced with a newer one). | |
52 | * -ENOENT if cache entry was negative | |
53 | */ | |
54 | int cache_check(struct cache_detail *detail, | |
55 | @@ -192,17 +210,7 @@ int cache_check(struct cache_detail *det | |
56 | long refresh_age, age; | |
57 | ||
58 | /* First decide return status as best we can */ | |
59 | - if (!test_bit(CACHE_VALID, &h->flags) || | |
60 | - h->expiry_time < get_seconds()) | |
61 | - rv = -EAGAIN; | |
62 | - else if (detail->flush_time > h->last_refresh) | |
63 | - rv = -EAGAIN; | |
64 | - else { | |
65 | - /* entry is valid */ | |
66 | - if (test_bit(CACHE_NEGATIVE, &h->flags)) | |
67 | - rv = -ENOENT; | |
68 | - else rv = 0; | |
69 | - } | |
70 | + rv = cache_is_valid(detail, h); | |
71 | ||
72 | /* now see if we want to start an upcall */ | |
73 | refresh_age = (h->expiry_time - h->last_refresh); | |
74 | @@ -234,10 +242,14 @@ int cache_check(struct cache_detail *det | |
75 | } | |
76 | } | |
77 | ||
78 | - if (rv == -EAGAIN) | |
79 | - if (cache_defer_req(rqstp, h) != 0) | |
80 | - rv = -ETIMEDOUT; | |
81 | - | |
82 | + if (rv == -EAGAIN) { | |
83 | + if (cache_defer_req(rqstp, h) == 0) { | |
84 | + /* Request is not deferred */ | |
85 | + rv = cache_is_valid(detail, h); | |
86 | + if (rv == -EAGAIN) | |
87 | + rv = -ETIMEDOUT; | |
88 | + } | |
89 | + } | |
90 | if (rv) | |
91 | cache_put(h, detail); | |
92 | return rv; | |
93 | @@ -558,11 +570,11 @@ static int cache_defer_req(struct cache_ | |
94 | * or continue and drop the oldest below | |
95 | */ | |
96 | if (net_random()&1) | |
97 | - return -ETIMEDOUT; | |
98 | + return 0; | |
99 | } | |
100 | dreq = req->defer(req); | |
101 | if (dreq == NULL) | |
102 | - return -ETIMEDOUT; | |
103 | + return 0; | |
104 | ||
105 | dreq->item = item; | |
106 | ||
107 | @@ -592,8 +604,9 @@ static int cache_defer_req(struct cache_ | |
108 | if (!test_bit(CACHE_PENDING, &item->flags)) { | |
109 | /* must have just been validated... */ | |
110 | cache_revisit_request(item); | |
111 | + return 0; | |
112 | } | |
113 | - return 0; | |
114 | + return 1; | |
115 | } | |
116 | ||
117 | static void cache_revisit_request(struct cache_head *item) |