aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-25 11:28:18 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-22 23:24:29 -0400
commitcfcea3e8c66c2dcde98d5c2693d4bff50b5cac97 (patch)
treeee7b995a48c43de7355fa33079ee7aaad020d6f3 /fs/nfs
parent1c3c07e9f6cc50dab2aeb8051325e317d4f6c70e (diff)
NFS: Add a global LRU list for the ACCESS cache
...in order to allow the addition of a memory shrinker. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c35
-rw-r--r--fs/nfs/inode.c2
2 files changed, 36 insertions, 1 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 094afded2b11..bf4f5ffda703 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1638,10 +1638,17 @@ out:
1638 return error; 1638 return error;
1639} 1639}
1640 1640
1641static DEFINE_SPINLOCK(nfs_access_lru_lock);
1642static LIST_HEAD(nfs_access_lru_list);
1643static atomic_long_t nfs_access_nr_entries;
1644
1641static void nfs_access_free_entry(struct nfs_access_entry *entry) 1645static void nfs_access_free_entry(struct nfs_access_entry *entry)
1642{ 1646{
1643 put_rpccred(entry->cred); 1647 put_rpccred(entry->cred);
1644 kfree(entry); 1648 kfree(entry);
1649 smp_mb__before_atomic_dec();
1650 atomic_long_dec(&nfs_access_nr_entries);
1651 smp_mb__after_atomic_dec();
1645} 1652}
1646 1653
1647static void __nfs_access_zap_cache(struct inode *inode) 1654static void __nfs_access_zap_cache(struct inode *inode)
@@ -1655,6 +1662,7 @@ static void __nfs_access_zap_cache(struct inode *inode)
1655 while ((n = rb_first(root_node)) != NULL) { 1662 while ((n = rb_first(root_node)) != NULL) {
1656 entry = rb_entry(n, struct nfs_access_entry, rb_node); 1663 entry = rb_entry(n, struct nfs_access_entry, rb_node);
1657 rb_erase(n, root_node); 1664 rb_erase(n, root_node);
1665 list_del(&entry->lru);
1658 n->rb_left = dispose; 1666 n->rb_left = dispose;
1659 dispose = n; 1667 dispose = n;
1660 } 1668 }
@@ -1671,6 +1679,13 @@ static void __nfs_access_zap_cache(struct inode *inode)
1671 1679
1672void nfs_access_zap_cache(struct inode *inode) 1680void nfs_access_zap_cache(struct inode *inode)
1673{ 1681{
1682 /* Remove from global LRU init */
1683 if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) {
1684 spin_lock(&nfs_access_lru_lock);
1685 list_del_init(&NFS_I(inode)->access_cache_inode_lru);
1686 spin_unlock(&nfs_access_lru_lock);
1687 }
1688
1674 spin_lock(&inode->i_lock); 1689 spin_lock(&inode->i_lock);
1675 /* This will release the spinlock */ 1690 /* This will release the spinlock */
1676 __nfs_access_zap_cache(inode); 1691 __nfs_access_zap_cache(inode);
@@ -1711,12 +1726,14 @@ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs
1711 res->jiffies = cache->jiffies; 1726 res->jiffies = cache->jiffies;
1712 res->cred = cache->cred; 1727 res->cred = cache->cred;
1713 res->mask = cache->mask; 1728 res->mask = cache->mask;
1729 list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
1714 err = 0; 1730 err = 0;
1715out: 1731out:
1716 spin_unlock(&inode->i_lock); 1732 spin_unlock(&inode->i_lock);
1717 return err; 1733 return err;
1718out_stale: 1734out_stale:
1719 rb_erase(&cache->rb_node, &nfsi->access_cache); 1735 rb_erase(&cache->rb_node, &nfsi->access_cache);
1736 list_del(&cache->lru);
1720 spin_unlock(&inode->i_lock); 1737 spin_unlock(&inode->i_lock);
1721 nfs_access_free_entry(cache); 1738 nfs_access_free_entry(cache);
1722 return -ENOENT; 1739 return -ENOENT;
@@ -1728,7 +1745,8 @@ out_zap:
1728 1745
1729static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set) 1746static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set)
1730{ 1747{
1731 struct rb_root *root_node = &NFS_I(inode)->access_cache; 1748 struct nfs_inode *nfsi = NFS_I(inode);
1749 struct rb_root *root_node = &nfsi->access_cache;
1732 struct rb_node **p = &root_node->rb_node; 1750 struct rb_node **p = &root_node->rb_node;
1733 struct rb_node *parent = NULL; 1751 struct rb_node *parent = NULL;
1734 struct nfs_access_entry *entry; 1752 struct nfs_access_entry *entry;
@@ -1747,10 +1765,13 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
1747 } 1765 }
1748 rb_link_node(&set->rb_node, parent, p); 1766 rb_link_node(&set->rb_node, parent, p);
1749 rb_insert_color(&set->rb_node, root_node); 1767 rb_insert_color(&set->rb_node, root_node);
1768 list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
1750 spin_unlock(&inode->i_lock); 1769 spin_unlock(&inode->i_lock);
1751 return; 1770 return;
1752found: 1771found:
1753 rb_replace_node(parent, &set->rb_node, root_node); 1772 rb_replace_node(parent, &set->rb_node, root_node);
1773 list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
1774 list_del(&entry->lru);
1754 spin_unlock(&inode->i_lock); 1775 spin_unlock(&inode->i_lock);
1755 nfs_access_free_entry(entry); 1776 nfs_access_free_entry(entry);
1756} 1777}
@@ -1766,6 +1787,18 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
1766 cache->mask = set->mask; 1787 cache->mask = set->mask;
1767 1788
1768 nfs_access_add_rbtree(inode, cache); 1789 nfs_access_add_rbtree(inode, cache);
1790
1791 /* Update accounting */
1792 smp_mb__before_atomic_inc();
1793 atomic_long_inc(&nfs_access_nr_entries);
1794 smp_mb__after_atomic_inc();
1795
1796 /* Add inode to global LRU list */
1797 if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) {
1798 spin_lock(&nfs_access_lru_lock);
1799 list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list);
1800 spin_unlock(&nfs_access_lru_lock);
1801 }
1769} 1802}
1770 1803
1771static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) 1804static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index b94ab060bb1e..6ed018c9aad2 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1104,6 +1104,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
1104 INIT_LIST_HEAD(&nfsi->dirty); 1104 INIT_LIST_HEAD(&nfsi->dirty);
1105 INIT_LIST_HEAD(&nfsi->commit); 1105 INIT_LIST_HEAD(&nfsi->commit);
1106 INIT_LIST_HEAD(&nfsi->open_files); 1106 INIT_LIST_HEAD(&nfsi->open_files);
1107 INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
1108 INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
1107 INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); 1109 INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
1108 atomic_set(&nfsi->data_updates, 0); 1110 atomic_set(&nfsi->data_updates, 0);
1109 nfsi->ndirty = 0; 1111 nfsi->ndirty = 0;