linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / net / sunrpc / cache.c
index 00cb388..dcaa0c4 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/proc_fs.h>
 #include <linux/net.h>
 #include <linux/workqueue.h>
-#include <linux/mutex.h>
 #include <asm/ioctls.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/cache.h>
 static void cache_defer_req(struct cache_req *req, struct cache_head *item);
 static void cache_revisit_request(struct cache_head *item);
 
-static void cache_init(struct cache_head *h)
+void cache_init(struct cache_head *h)
 {
        time_t now = get_seconds();
        h->next = NULL;
        h->flags = 0;
-       kref_init(&h->ref);
+       atomic_set(&h->refcnt, 1);
        h->expiry_time = now + CACHE_NEW_EXPIRY;
        h->last_refresh = now;
 }
 
-struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
-                                      struct cache_head *key, int hash)
-{
-       struct cache_head **head,  **hp;
-       struct cache_head *new = NULL;
-
-       head = &detail->hash_table[hash];
-
-       read_lock(&detail->hash_lock);
-
-       for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
-               struct cache_head *tmp = *hp;
-               if (detail->match(tmp, key)) {
-                       cache_get(tmp);
-                       read_unlock(&detail->hash_lock);
-                       return tmp;
-               }
-       }
-       read_unlock(&detail->hash_lock);
-       /* Didn't find anything, insert an empty entry */
-
-       new = detail->alloc();
-       if (!new)
-               return NULL;
-       /* must fully initialise 'new', else
-        * we might get lose if we need to
-        * cache_put it soon.
-        */
-       cache_init(new);
-       detail->init(new, key);
-
-       write_lock(&detail->hash_lock);
-
-       /* check if entry appeared while we slept */
-       for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
-               struct cache_head *tmp = *hp;
-               if (detail->match(tmp, key)) {
-                       cache_get(tmp);
-                       write_unlock(&detail->hash_lock);
-                       cache_put(new, detail);
-                       return tmp;
-               }
-       }
-       new->next = *head;
-       *head = new;
-       detail->entries++;
-       cache_get(new);
-       write_unlock(&detail->hash_lock);
-
-       return new;
-}
-EXPORT_SYMBOL(sunrpc_cache_lookup);
-
-
-static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
-
-static int cache_fresh_locked(struct cache_head *head, time_t expiry)
-{
-       head->expiry_time = expiry;
-       head->last_refresh = get_seconds();
-       return !test_and_set_bit(CACHE_VALID, &head->flags);
-}
-
-static void cache_fresh_unlocked(struct cache_head *head,
-                       struct cache_detail *detail, int new)
-{
-       if (new)
-               cache_revisit_request(head);
-       if (test_and_clear_bit(CACHE_PENDING, &head->flags)) {
-               cache_revisit_request(head);
-               queue_loose(detail, head);
-       }
-}
-
-struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
-                                      struct cache_head *new, struct cache_head *old, int hash)
-{
-       /* The 'old' entry is to be replaced by 'new'.
-        * If 'old' is not VALID, we update it directly,
-        * otherwise we need to replace it
-        */
-       struct cache_head **head;
-       struct cache_head *tmp;
-       int is_new;
-
-       if (!test_bit(CACHE_VALID, &old->flags)) {
-               write_lock(&detail->hash_lock);
-               if (!test_bit(CACHE_VALID, &old->flags)) {
-                       if (test_bit(CACHE_NEGATIVE, &new->flags))
-                               set_bit(CACHE_NEGATIVE, &old->flags);
-                       else
-                               detail->update(old, new);
-                       is_new = cache_fresh_locked(old, new->expiry_time);
-                       write_unlock(&detail->hash_lock);
-                       cache_fresh_unlocked(old, detail, is_new);
-                       return old;
-               }
-               write_unlock(&detail->hash_lock);
-       }
-       /* We need to insert a new entry */
-       tmp = detail->alloc();
-       if (!tmp) {
-               cache_put(old, detail);
-               return NULL;
-       }
-       cache_init(tmp);
-       detail->init(tmp, old);
-       head = &detail->hash_table[hash];
-
-       write_lock(&detail->hash_lock);
-       if (test_bit(CACHE_NEGATIVE, &new->flags))
-               set_bit(CACHE_NEGATIVE, &tmp->flags);
-       else
-               detail->update(tmp, new);
-       tmp->next = *head;
-       *head = tmp;
-       detail->entries++;
-       cache_get(tmp);
-       is_new = cache_fresh_locked(tmp, new->expiry_time);
-       cache_fresh_locked(old, 0);
-       write_unlock(&detail->hash_lock);
-       cache_fresh_unlocked(tmp, detail, is_new);
-       cache_fresh_unlocked(old, detail, 0);
-       cache_put(old, detail);
-       return tmp;
-}
-EXPORT_SYMBOL(sunrpc_cache_update);
 
 static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
 /*
@@ -221,8 +93,7 @@ int cache_check(struct cache_detail *detail,
                                clear_bit(CACHE_PENDING, &h->flags);
                                if (rv == -EAGAIN) {
                                        set_bit(CACHE_NEGATIVE, &h->flags);
-                                       cache_fresh_unlocked(h, detail,
-                                            cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY));
+                                       cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY);
                                        rv = -ENOENT;
                                }
                                break;
@@ -238,11 +109,25 @@ int cache_check(struct cache_detail *detail,
        if (rv == -EAGAIN)
                cache_defer_req(rqstp, h);
 
-       if (rv)
-               cache_put(h, detail);
+       if (rv && h)
+               detail->cache_put(h, detail);
        return rv;
 }
 
+static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
+
+void cache_fresh(struct cache_detail *detail,
+                struct cache_head *head, time_t expiry)
+{
+
+       head->expiry_time = expiry;
+       head->last_refresh = get_seconds();
+       if (!test_and_set_bit(CACHE_VALID, &head->flags))
+               cache_revisit_request(head);
+       if (test_and_clear_bit(CACHE_PENDING, &head->flags))
+               queue_loose(detail, head);
+}
+
 /*
  * caches need to be periodically cleaned.
  * For this we maintain a list of cache_detail and
@@ -436,7 +321,7 @@ static int cache_clean(void)
                        if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
                                queue_loose(current_detail, ch);
 
-                       if (atomic_read(&ch->ref.refcount) == 1)
+                       if (atomic_read(&ch->refcnt) == 1)
                                break;
                }
                if (ch) {
@@ -451,7 +336,7 @@ static int cache_clean(void)
                        current_index ++;
                spin_unlock(&cache_list_lock);
                if (ch)
-                       cache_put(ch, d);
+                       d->cache_put(ch, d);
        } else
                spin_unlock(&cache_list_lock);
 
@@ -567,7 +452,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
                /* there was one too many */
                dreq->revisit(dreq, 1);
        }
-       if (!test_bit(CACHE_PENDING, &item->flags)) {
+       if (test_bit(CACHE_VALID, &item->flags)) {
                /* must have just been validated... */
                cache_revisit_request(item);
        }
@@ -647,7 +532,7 @@ void cache_clean_deferred(void *owner)
  */
 
 static DEFINE_SPINLOCK(queue_lock);
-static DEFINE_MUTEX(queue_io_mutex);
+static DECLARE_MUTEX(queue_io_sem);
 
 struct cache_queue {
        struct list_head        list;
@@ -676,7 +561,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
        if (count == 0)
                return 0;
 
-       mutex_lock(&queue_io_mutex); /* protect against multiple concurrent
+       down(&queue_io_sem); /* protect against multiple concurrent
                              * readers on this file */
  again:
        spin_lock(&queue_lock);
@@ -689,7 +574,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
        }
        if (rp->q.list.next == &cd->queue) {
                spin_unlock(&queue_lock);
-               mutex_unlock(&queue_io_mutex);
+               up(&queue_io_sem);
                BUG_ON(rp->offset);
                return 0;
        }
@@ -728,7 +613,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
                    !test_bit(CACHE_PENDING, &rq->item->flags)) {
                        list_del(&rq->q.list);
                        spin_unlock(&queue_lock);
-                       cache_put(rq->item, cd);
+                       cd->cache_put(rq->item, cd);
                        kfree(rq->buf);
                        kfree(rq);
                } else
@@ -736,11 +621,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
        }
        if (err == -EAGAIN)
                goto again;
-       mutex_unlock(&queue_io_mutex);
+       up(&queue_io_sem);
        return err ? err :  count;
 }
 
-static char write_buf[8192]; /* protected by queue_io_mutex */
+static char write_buf[8192]; /* protected by queue_io_sem */
 
 static ssize_t
 cache_write(struct file *filp, const char __user *buf, size_t count,
@@ -754,10 +639,10 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
        if (count >= sizeof(write_buf))
                return -EINVAL;
 
-       mutex_lock(&queue_io_mutex);
+       down(&queue_io_sem);
 
        if (copy_from_user(write_buf, buf, count)) {
-               mutex_unlock(&queue_io_mutex);
+               up(&queue_io_sem);
                return -EFAULT;
        }
        write_buf[count] = '\0';
@@ -766,7 +651,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
        else
                err = -EINVAL;
 
-       mutex_unlock(&queue_io_mutex);
+       up(&queue_io_sem);
        return err ? err : count;
 }
 
@@ -908,10 +793,10 @@ static void queue_loose(struct cache_detail *detail, struct cache_head *ch)
                        if (cr->item != ch)
                                continue;
                        if (cr->readers != 0)
-                               continue;
+                               break;
                        list_del(&cr->q.list);
                        spin_unlock(&queue_lock);
-                       cache_put(cr->item, detail);
+                       detail->cache_put(cr->item, detail);
                        kfree(cr->buf);
                        kfree(cr);
                        return;
@@ -1196,8 +1081,8 @@ static int c_show(struct seq_file *m, void *p)
                return cd->cache_show(m, cd, NULL);
 
        ifdebug(CACHE)
-               seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
-                          cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
+               seq_printf(m, "# expiry=%ld refcnt=%d\n",
+                          cp->expiry_time, atomic_read(&cp->refcnt));
        cache_get(cp);
        if (cache_check(cd, cp, NULL))
                /* cache_check does a cache_put on failure */