aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/cache.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-03-30 22:35:56 -0500
committerSteve French <sfrench@us.ibm.com>2006-03-30 22:35:56 -0500
commitd62e54abca1146981fc9f98f85ff398a113a22c2 (patch)
tree870420dbc4c65e716dcef8a802aafdc0ef97a8b4 /net/sunrpc/cache.c
parentfd4a0b92db6a57cba8d03efbe1cebf91f9124ce0 (diff)
parentce362c009250340358a7221f3cdb7954cbf19c01 (diff)
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r--net/sunrpc/cache.c180
1 files changed, 145 insertions, 35 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index dcaa0c4453ff..3ac4193a78ed 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -26,6 +26,7 @@
26#include <linux/proc_fs.h> 26#include <linux/proc_fs.h>
27#include <linux/net.h> 27#include <linux/net.h>
28#include <linux/workqueue.h> 28#include <linux/workqueue.h>
29#include <linux/mutex.h>
29#include <asm/ioctls.h> 30#include <asm/ioctls.h>
30#include <linux/sunrpc/types.h> 31#include <linux/sunrpc/types.h>
31#include <linux/sunrpc/cache.h> 32#include <linux/sunrpc/cache.h>
@@ -36,16 +37,138 @@
36static 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);
37static void cache_revisit_request(struct cache_head *item); 38static void cache_revisit_request(struct cache_head *item);
38 39
39void cache_init(struct cache_head *h) 40static void cache_init(struct cache_head *h)
40{ 41{
41 time_t now = get_seconds(); 42 time_t now = get_seconds();
42 h->next = NULL; 43 h->next = NULL;
43 h->flags = 0; 44 h->flags = 0;
44 atomic_set(&h->refcnt, 1); 45 kref_init(&h->ref);
45 h->expiry_time = now + CACHE_NEW_EXPIRY; 46 h->expiry_time = now + CACHE_NEW_EXPIRY;
46 h->last_refresh = now; 47 h->last_refresh = now;
47} 48}
48 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);
49 172
50static 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);
51/* 174/*
@@ -93,7 +216,8 @@ int cache_check(struct cache_detail *detail,
93 clear_bit(CACHE_PENDING, &h->flags); 216 clear_bit(CACHE_PENDING, &h->flags);
94 if (rv == -EAGAIN) { 217 if (rv == -EAGAIN) {
95 set_bit(CACHE_NEGATIVE, &h->flags); 218 set_bit(CACHE_NEGATIVE, &h->flags);
96 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));
97 rv = -ENOENT; 221 rv = -ENOENT;
98 } 222 }
99 break; 223 break;
@@ -109,25 +233,11 @@ int cache_check(struct cache_detail *detail,
109 if (rv == -EAGAIN) 233 if (rv == -EAGAIN)
110 cache_defer_req(rqstp, h); 234 cache_defer_req(rqstp, h);
111 235
112 if (rv && h) 236 if (rv)
113 detail->cache_put(h, detail); 237 cache_put(h, detail);
114 return rv; 238 return rv;
115} 239}
116 240
117static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
118
119void cache_fresh(struct cache_detail *detail,
120 struct cache_head *head, time_t expiry)
121{
122
123 head->expiry_time = expiry;
124 head->last_refresh = get_seconds();
125 if (!test_and_set_bit(CACHE_VALID, &head->flags))
126 cache_revisit_request(head);
127 if (test_and_clear_bit(CACHE_PENDING, &head->flags))
128 queue_loose(detail, head);
129}
130
131/* 241/*
132 * caches need to be periodically cleaned. 242 * caches need to be periodically cleaned.
133 * For this we maintain a list of cache_detail and 243 * For this we maintain a list of cache_detail and
@@ -321,7 +431,7 @@ static int cache_clean(void)
321 if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) 431 if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
322 queue_loose(current_detail, ch); 432 queue_loose(current_detail, ch);
323 433
324 if (atomic_read(&ch->refcnt) == 1) 434 if (atomic_read(&ch->ref.refcount) == 1)
325 break; 435 break;
326 } 436 }
327 if (ch) { 437 if (ch) {
@@ -336,7 +446,7 @@ static int cache_clean(void)
336 current_index ++; 446 current_index ++;
337 spin_unlock(&cache_list_lock); 447 spin_unlock(&cache_list_lock);
338 if (ch) 448 if (ch)
339 d->cache_put(ch, d); 449 cache_put(ch, d);
340 } else 450 } else
341 spin_unlock(&cache_list_lock); 451 spin_unlock(&cache_list_lock);
342 452
@@ -452,7 +562,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
452 /* there was one too many */ 562 /* there was one too many */
453 dreq->revisit(dreq, 1); 563 dreq->revisit(dreq, 1);
454 } 564 }
455 if (test_bit(CACHE_VALID, &item->flags)) { 565 if (!test_bit(CACHE_PENDING, &item->flags)) {
456 /* must have just been validated... */ 566 /* must have just been validated... */
457 cache_revisit_request(item); 567 cache_revisit_request(item);
458 } 568 }
@@ -532,7 +642,7 @@ void cache_clean_deferred(void *owner)
532 */ 642 */
533 643
534static DEFINE_SPINLOCK(queue_lock); 644static DEFINE_SPINLOCK(queue_lock);
535static DECLARE_MUTEX(queue_io_sem); 645static DEFINE_MUTEX(queue_io_mutex);
536 646
537struct cache_queue { 647struct cache_queue {
538 struct list_head list; 648 struct list_head list;
@@ -561,7 +671,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
561 if (count == 0) 671 if (count == 0)
562 return 0; 672 return 0;
563 673
564 down(&queue_io_sem); /* protect against multiple concurrent 674 mutex_lock(&queue_io_mutex); /* protect against multiple concurrent
565 * readers on this file */ 675 * readers on this file */
566 again: 676 again:
567 spin_lock(&queue_lock); 677 spin_lock(&queue_lock);
@@ -574,7 +684,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
574 } 684 }
575 if (rp->q.list.next == &cd->queue) { 685 if (rp->q.list.next == &cd->queue) {
576 spin_unlock(&queue_lock); 686 spin_unlock(&queue_lock);
577 up(&queue_io_sem); 687 mutex_unlock(&queue_io_mutex);
578 BUG_ON(rp->offset); 688 BUG_ON(rp->offset);
579 return 0; 689 return 0;
580 } 690 }
@@ -613,7 +723,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
613 !test_bit(CACHE_PENDING, &rq->item->flags)) { 723 !test_bit(CACHE_PENDING, &rq->item->flags)) {
614 list_del(&rq->q.list); 724 list_del(&rq->q.list);
615 spin_unlock(&queue_lock); 725 spin_unlock(&queue_lock);
616 cd->cache_put(rq->item, cd); 726 cache_put(rq->item, cd);
617 kfree(rq->buf); 727 kfree(rq->buf);
618 kfree(rq); 728 kfree(rq);
619 } else 729 } else
@@ -621,11 +731,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
621 } 731 }
622 if (err == -EAGAIN) 732 if (err == -EAGAIN)
623 goto again; 733 goto again;
624 up(&queue_io_sem); 734 mutex_unlock(&queue_io_mutex);
625 return err ? err : count; 735 return err ? err : count;
626} 736}
627 737
628static char write_buf[8192]; /* protected by queue_io_sem */ 738static char write_buf[8192]; /* protected by queue_io_mutex */
629 739
630static ssize_t 740static ssize_t
631cache_write(struct file *filp, const char __user *buf, size_t count, 741cache_write(struct file *filp, const char __user *buf, size_t count,
@@ -639,10 +749,10 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
639 if (count >= sizeof(write_buf)) 749 if (count >= sizeof(write_buf))
640 return -EINVAL; 750 return -EINVAL;
641 751
642 down(&queue_io_sem); 752 mutex_lock(&queue_io_mutex);
643 753
644 if (copy_from_user(write_buf, buf, count)) { 754 if (copy_from_user(write_buf, buf, count)) {
645 up(&queue_io_sem); 755 mutex_unlock(&queue_io_mutex);
646 return -EFAULT; 756 return -EFAULT;
647 } 757 }
648 write_buf[count] = '\0'; 758 write_buf[count] = '\0';
@@ -651,7 +761,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
651 else 761 else
652 err = -EINVAL; 762 err = -EINVAL;
653 763
654 up(&queue_io_sem); 764 mutex_unlock(&queue_io_mutex);
655 return err ? err : count; 765 return err ? err : count;
656} 766}
657 767
@@ -793,10 +903,10 @@ static void queue_loose(struct cache_detail *detail, struct cache_head *ch)
793 if (cr->item != ch) 903 if (cr->item != ch)
794 continue; 904 continue;
795 if (cr->readers != 0) 905 if (cr->readers != 0)
796 break; 906 continue;
797 list_del(&cr->q.list); 907 list_del(&cr->q.list);
798 spin_unlock(&queue_lock); 908 spin_unlock(&queue_lock);
799 detail->cache_put(cr->item, detail); 909 cache_put(cr->item, detail);
800 kfree(cr->buf); 910 kfree(cr->buf);
801 kfree(cr); 911 kfree(cr);
802 return; 912 return;
@@ -1081,8 +1191,8 @@ static int c_show(struct seq_file *m, void *p)
1081 return cd->cache_show(m, cd, NULL); 1191 return cd->cache_show(m, cd, NULL);
1082 1192
1083 ifdebug(CACHE) 1193 ifdebug(CACHE)
1084 seq_printf(m, "# expiry=%ld refcnt=%d\n", 1194 seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
1085 cp->expiry_time, atomic_read(&cp->refcnt)); 1195 cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
1086 cache_get(cp); 1196 cache_get(cp);
1087 if (cache_check(cd, cp, NULL)) 1197 if (cache_check(cd, cp, NULL))
1088 /* cache_check does a cache_put on failure */ 1198 /* cache_check does a cache_put on failure */