]> err.no Git - linux-2.6/commitdiff
NFS: Add a global LRU list for the ACCESS cache
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 25 Jul 2006 15:28:18 +0000 (11:28 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Sat, 23 Sep 2006 03:24:29 +0000 (23:24 -0400)
...in order to allow the addition of a memory shrinker.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/dir.c
fs/nfs/inode.c
include/linux/nfs_fs.h

index 094afded2b115eff67ad8167476dceebc11949cb..bf4f5ffda703c5f28ac6446bc6a7bbf4d6c98162 100644 (file)
@@ -1638,10 +1638,17 @@ out:
        return error;
 }
 
+static DEFINE_SPINLOCK(nfs_access_lru_lock);
+static LIST_HEAD(nfs_access_lru_list);
+static atomic_long_t nfs_access_nr_entries;
+
 static void nfs_access_free_entry(struct nfs_access_entry *entry)
 {
        put_rpccred(entry->cred);
        kfree(entry);
+       smp_mb__before_atomic_dec();
+       atomic_long_dec(&nfs_access_nr_entries);
+       smp_mb__after_atomic_dec();
 }
 
 static void __nfs_access_zap_cache(struct inode *inode)
@@ -1655,6 +1662,7 @@ static void __nfs_access_zap_cache(struct inode *inode)
        while ((n = rb_first(root_node)) != NULL) {
                entry = rb_entry(n, struct nfs_access_entry, rb_node);
                rb_erase(n, root_node);
+               list_del(&entry->lru);
                n->rb_left = dispose;
                dispose = n;
        }
@@ -1671,6 +1679,13 @@ static void __nfs_access_zap_cache(struct inode *inode)
 
 void nfs_access_zap_cache(struct inode *inode)
 {
+       /* Remove from global LRU init */
+       if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) {
+               spin_lock(&nfs_access_lru_lock);
+               list_del_init(&NFS_I(inode)->access_cache_inode_lru);
+               spin_unlock(&nfs_access_lru_lock);
+       }
+
        spin_lock(&inode->i_lock);
        /* This will release the spinlock */
        __nfs_access_zap_cache(inode);
@@ -1711,12 +1726,14 @@ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs
        res->jiffies = cache->jiffies;
        res->cred = cache->cred;
        res->mask = cache->mask;
+       list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
        err = 0;
 out:
        spin_unlock(&inode->i_lock);
        return err;
 out_stale:
        rb_erase(&cache->rb_node, &nfsi->access_cache);
+       list_del(&cache->lru);
        spin_unlock(&inode->i_lock);
        nfs_access_free_entry(cache);
        return -ENOENT;
@@ -1728,7 +1745,8 @@ out_zap:
 
 static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set)
 {
-       struct rb_root *root_node = &NFS_I(inode)->access_cache;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct rb_root *root_node = &nfsi->access_cache;
        struct rb_node **p = &root_node->rb_node;
        struct rb_node *parent = NULL;
        struct nfs_access_entry *entry;
@@ -1747,10 +1765,13 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
        }
        rb_link_node(&set->rb_node, parent, p);
        rb_insert_color(&set->rb_node, root_node);
+       list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
        spin_unlock(&inode->i_lock);
        return;
 found:
        rb_replace_node(parent, &set->rb_node, root_node);
+       list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
+       list_del(&entry->lru);
        spin_unlock(&inode->i_lock);
        nfs_access_free_entry(entry);
 }
@@ -1766,6 +1787,18 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
        cache->mask = set->mask;
 
        nfs_access_add_rbtree(inode, cache);
+
+       /* Update accounting */
+       smp_mb__before_atomic_inc();
+       atomic_long_inc(&nfs_access_nr_entries);
+       smp_mb__after_atomic_inc();
+
+       /* Add inode to global LRU list */
+       if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) {
+               spin_lock(&nfs_access_lru_lock);
+               list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list);
+               spin_unlock(&nfs_access_lru_lock);
+       }
 }
 
 static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
index b94ab060bb1ee01ffaba18e26fe322f2dbd6ae01..6ed018c9aad2ebb5f4080974046695ae99657ff5 100644 (file)
@@ -1104,6 +1104,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
                INIT_LIST_HEAD(&nfsi->dirty);
                INIT_LIST_HEAD(&nfsi->commit);
                INIT_LIST_HEAD(&nfsi->open_files);
+               INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
+               INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
                INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
                atomic_set(&nfsi->data_updates, 0);
                nfsi->ndirty = 0;
index cc013ed2e52efc9d789f055c7182215634180bb1..a36e01cd6321e9d04e74d3666daa23c3bf2934fb 100644 (file)
@@ -71,6 +71,7 @@
  */
 struct nfs_access_entry {
        struct rb_node          rb_node;
+       struct list_head        lru;
        unsigned long           jiffies;
        struct rpc_cred *       cred;
        int                     mask;
@@ -148,6 +149,8 @@ struct nfs_inode {
        atomic_t                data_updates;
 
        struct rb_root          access_cache;
+       struct list_head        access_cache_entry_lru;
+       struct list_head        access_cache_inode_lru;
 #ifdef CONFIG_NFS_V3_ACL
        struct posix_acl        *acl_access;
        struct posix_acl        *acl_default;
@@ -201,6 +204,7 @@ struct nfs_inode {
 #define NFS_INO_REVALIDATING   (0)             /* revalidating attrs */
 #define NFS_INO_ADVISE_RDPLUS  (1)             /* advise readdirplus */
 #define NFS_INO_STALE          (2)             /* possible stale inode */
+#define NFS_INO_ACL_LRU_SET    (3)             /* Inode is on the LRU list */
 
 static inline struct nfs_inode *NFS_I(struct inode *inode)
 {