aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r--net/sunrpc/cache.c163
1 files changed, 136 insertions, 27 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 0acccfeeb284..3ac4193a78ed 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -37,16 +37,138 @@
37static void cache_defer_req(struct cache_req *req, struct cache_head *item); 37static void cache_defer_req(struct cache_req *req, struct cache_head *item);
38static void cache_revisit_request(struct cache_head *item); 38static void cache_revisit_request(struct cache_head *item);
39 39
40void cache_init(struct cache_head *h) 40static void cache_init(struct cache_head *h)
41{ 41{
42 time_t now = get_seconds(); 42 time_t now = get_seconds();
43 h->next = NULL; 43 h->next = NULL;
44 h->flags = 0; 44 h->flags = 0;
45 atomic_set(&h->refcnt, 1); 45 kref_init(&h->ref);
46 h->expiry_time = now + CACHE_NEW_EXPIRY; 46 h->expiry_time = now + CACHE_NEW_EXPIRY;
47 h->last_refresh = now; 47 h->last_refresh = now;
48} 48}
49 49
50struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
51 struct cache_head *key, int hash)
52{
53 struct cache_head **head, **hp;
54 struct cache_head *new = NULL;
55
56 head = &detail->hash_table[hash];
57
58 read_lock(&detail->hash_lock);
59
60 for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
61 struct cache_head *tmp = *hp;
62 if (detail->match(tmp, key)) {
63 cache_get(tmp);
64 read_unlock(&detail->hash_lock);
65 return tmp;
66 }
67 }
68 read_unlock(&detail->hash_lock);
69 /* Didn't find anything, insert an empty entry */
70
71 new = detail->alloc();
72 if (!new)
73 return NULL;
74 cache_init(new);
75
76 write_lock(&detail->hash_lock);
77
78 /* check if entry appeared while we slept */
79 for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
80 struct cache_head *tmp = *hp;
81 if (detail->match(tmp, key)) {
82 cache_get(tmp);
83 write_unlock(&detail->hash_lock);
84 cache_put(new, detail);
85 return tmp;
86 }
87 }
88 detail->init(new, key);
89 new->next = *head;
90 *head = new;
91 detail->entries++;
92 cache_get(new);
93 write_unlock(&detail->hash_lock);
94
95 return new;
96}
97EXPORT_SYMBOL(sunrpc_cache_lookup);
98
99
100static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
101
102static int cache_fresh_locked(struct cache_head *head, time_t expiry)
103{
104 head->expiry_time = expiry;
105 head->last_refresh = get_seconds();
106 return !test_and_set_bit(CACHE_VALID, &head->flags);
107}
108
109static void cache_fresh_unlocked(struct cache_head *head,
110 struct cache_detail *detail, int new)
111{
112 if (new)
113 cache_revisit_request(head);
114 if (test_and_clear_bit(CACHE_PENDING, &head->flags)) {
115 cache_revisit_request(head);
116 queue_loose(detail, head);
117 }
118}
119
120struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
121 struct cache_head *new, struct cache_head *old, int hash)
122{
123 /* The 'old' entry is to be replaced by 'new'.
124 * If 'old' is not VALID, we update it directly,
125 * otherwise we need to replace it
126 */
127 struct cache_head **head;
128 struct cache_head *tmp;
129 int is_new;
130
131 if (!test_bit(CACHE_VALID, &old->flags)) {
132 write_lock(&detail->hash_lock);
133 if (!test_bit(CACHE_VALID, &old->flags)) {
134 if (test_bit(CACHE_NEGATIVE, &new->flags))
135 set_bit(CACHE_NEGATIVE, &old->flags);
136 else
137 detail->update(old, new);
138 is_new = cache_fresh_locked(old, new->expiry_time);
139 write_unlock(&detail->hash_lock);
140 cache_fresh_unlocked(old, detail, is_new);
141 return old;
142 }
143 write_unlock(&detail->hash_lock);
144 }
145 /* We need to insert a new entry */
146 tmp = detail->alloc();
147 if (!tmp) {
148 cache_put(old, detail);
149 return NULL;
150 }
151 cache_init(tmp);
152 detail->init(tmp, old);
153 head = &detail->hash_table[hash];
154
155 write_lock(&detail->hash_lock);
156 if (test_bit(CACHE_NEGATIVE, &new->flags))
157 set_bit(CACHE_NEGATIVE, &tmp->flags);
158 else
159 detail->update(tmp, new);
160 tmp->next = *head;
161 *head = tmp;
162 cache_get(tmp);
163 is_new = cache_fresh_locked(tmp, new->expiry_time);
164 cache_fresh_locked(old, 0);
165 write_unlock(&detail->hash_lock);
166 cache_fresh_unlocked(tmp, detail, is_new);
167 cache_fresh_unlocked(old, detail, 0);
168 cache_put(old, detail);
169 return tmp;
170}
171EXPORT_SYMBOL(sunrpc_cache_update);
50 172
51static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); 173static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
52/* 174/*
@@ -94,7 +216,8 @@ int cache_check(struct cache_detail *detail,
94 clear_bit(CACHE_PENDING, &h->flags); 216 clear_bit(CACHE_PENDING, &h->flags);
95 if (rv == -EAGAIN) { 217 if (rv == -EAGAIN) {
96 set_bit(CACHE_NEGATIVE, &h->flags); 218 set_bit(CACHE_NEGATIVE, &h->flags);
97 cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY); 219 cache_fresh_unlocked(h, detail,
220 cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY));
98 rv = -ENOENT; 221 rv = -ENOENT;
99 } 222 }
100 break; 223 break;
@@ -110,25 +233,11 @@ int cache_check(struct cache_detail *detail,
110 if (rv == -EAGAIN) 233 if (rv == -EAGAIN)
111 cache_defer_req(rqstp, h); 234 cache_defer_req(rqstp, h);
112 235
113 if (rv && h) 236 if (rv)
114 detail->cache_put(h, detail); 237 cache_put(h, detail);
115 return rv; 238 return rv;
116} 239}
117 240
118static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
119
120void cache_fresh(struct cache_detail *detail,
121 struct cache_head *head, time_t expiry)
122{
123
124 head->expiry_time = expiry;
125 head->last_refresh = get_seconds();
126 if (!test_and_set_bit(CACHE_VALID, &head->flags))
127 cache_revisit_request(head);
128 if (test_and_clear_bit(CACHE_PENDING, &head->flags))
129 queue_loose(detail, head);
130}
131
132/* 241/*
133 * caches need to be periodically cleaned. 242 * caches need to be periodically cleaned.
134 * For this we maintain a list of cache_detail and 243 * For this we maintain a list of cache_detail and
@@ -322,7 +431,7 @@ static int cache_clean(void)
322 if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) 431 if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
323 queue_loose(current_detail, ch); 432 queue_loose(current_detail, ch);
324 433
325 if (atomic_read(&ch->refcnt) == 1) 434 if (atomic_read(&ch->ref.refcount) == 1)
326 break; 435 break;
327 } 436 }
328 if (ch) { 437 if (ch) {
@@ -337,7 +446,7 @@ static int cache_clean(void)
337 current_index ++; 446 current_index ++;
338 spin_unlock(&cache_list_lock); 447 spin_unlock(&cache_list_lock);
339 if (ch) 448 if (ch)
340 d->cache_put(ch, d); 449 cache_put(ch, d);
341 } else 450 } else
342 spin_unlock(&cache_list_lock); 451 spin_unlock(&cache_list_lock);
343 452
@@ -453,7 +562,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
453 /* there was one too many */ 562 /* there was one too many */
454 dreq->revisit(dreq, 1); 563 dreq->revisit(dreq, 1);
455 } 564 }
456 if (test_bit(CACHE_VALID, &item->flags)) { 565 if (!test_bit(CACHE_PENDING, &item->flags)) {
457 /* must have just been validated... */ 566 /* must have just been validated... */
458 cache_revisit_request(item); 567 cache_revisit_request(item);
459 } 568 }
@@ -614,7 +723,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
614 !test_bit(CACHE_PENDING, &rq->item->flags)) { 723 !test_bit(CACHE_PENDING, &rq->item->flags)) {
615 list_del(&rq->q.list); 724 list_del(&rq->q.list);
616 spin_unlock(&queue_lock); 725 spin_unlock(&queue_lock);
617 cd->cache_put(rq->item, cd); 726 cache_put(rq->item, cd);
618 kfree(rq->buf); 727 kfree(rq->buf);
619 kfree(rq); 728 kfree(rq);
620 } else 729 } else
@@ -794,10 +903,10 @@ static void queue_loose(struct cache_detail *detail, struct cache_head *ch)
794 if (cr->item != ch) 903 if (cr->item != ch)
795 continue; 904 continue;
796 if (cr->readers != 0) 905 if (cr->readers != 0)
797 break; 906 continue;
798 list_del(&cr->q.list); 907 list_del(&cr->q.list);
799 spin_unlock(&queue_lock); 908 spin_unlock(&queue_lock);
800 detail->cache_put(cr->item, detail); 909 cache_put(cr->item, detail);
801 kfree(cr->buf); 910 kfree(cr->buf);
802 kfree(cr); 911 kfree(cr);
803 return; 912 return;
@@ -1082,8 +1191,8 @@ static int c_show(struct seq_file *m, void *p)
1082 return cd->cache_show(m, cd, NULL); 1191 return cd->cache_show(m, cd, NULL);
1083 1192
1084 ifdebug(CACHE) 1193 ifdebug(CACHE)
1085 seq_printf(m, "# expiry=%ld refcnt=%d\n", 1194 seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
1086 cp->expiry_time, atomic_read(&cp->refcnt)); 1195 cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
1087 cache_get(cp); 1196 cache_get(cp);
1088 if (cache_check(cd, cp, NULL)) 1197 if (cache_check(cd, cp, NULL))
1089 /* cache_check does a cache_put on failure */ 1198 /* cache_check does a cache_put on failure */