diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-25 11:28:18 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-22 23:24:29 -0400 |
commit | cfcea3e8c66c2dcde98d5c2693d4bff50b5cac97 (patch) | |
tree | ee7b995a48c43de7355fa33079ee7aaad020d6f3 | |
parent | 1c3c07e9f6cc50dab2aeb8051325e317d4f6c70e (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>
-rw-r--r-- | fs/nfs/dir.c | 35 | ||||
-rw-r--r-- | fs/nfs/inode.c | 2 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 4 |
3 files changed, 40 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 | ||
1641 | static DEFINE_SPINLOCK(nfs_access_lru_lock); | ||
1642 | static LIST_HEAD(nfs_access_lru_list); | ||
1643 | static atomic_long_t nfs_access_nr_entries; | ||
1644 | |||
1641 | static void nfs_access_free_entry(struct nfs_access_entry *entry) | 1645 | static 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 | ||
1647 | static void __nfs_access_zap_cache(struct inode *inode) | 1654 | static 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 | ||
1672 | void nfs_access_zap_cache(struct inode *inode) | 1680 | void 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; |
1715 | out: | 1731 | out: |
1716 | spin_unlock(&inode->i_lock); | 1732 | spin_unlock(&inode->i_lock); |
1717 | return err; | 1733 | return err; |
1718 | out_stale: | 1734 | out_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 | ||
1729 | static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set) | 1746 | static 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; |
1752 | found: | 1771 | found: |
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 | ||
1771 | static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | 1804 | static 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; |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index cc013ed2e52e..a36e01cd6321 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -71,6 +71,7 @@ | |||
71 | */ | 71 | */ |
72 | struct nfs_access_entry { | 72 | struct nfs_access_entry { |
73 | struct rb_node rb_node; | 73 | struct rb_node rb_node; |
74 | struct list_head lru; | ||
74 | unsigned long jiffies; | 75 | unsigned long jiffies; |
75 | struct rpc_cred * cred; | 76 | struct rpc_cred * cred; |
76 | int mask; | 77 | int mask; |
@@ -148,6 +149,8 @@ struct nfs_inode { | |||
148 | atomic_t data_updates; | 149 | atomic_t data_updates; |
149 | 150 | ||
150 | struct rb_root access_cache; | 151 | struct rb_root access_cache; |
152 | struct list_head access_cache_entry_lru; | ||
153 | struct list_head access_cache_inode_lru; | ||
151 | #ifdef CONFIG_NFS_V3_ACL | 154 | #ifdef CONFIG_NFS_V3_ACL |
152 | struct posix_acl *acl_access; | 155 | struct posix_acl *acl_access; |
153 | struct posix_acl *acl_default; | 156 | struct posix_acl *acl_default; |
@@ -201,6 +204,7 @@ struct nfs_inode { | |||
201 | #define NFS_INO_REVALIDATING (0) /* revalidating attrs */ | 204 | #define NFS_INO_REVALIDATING (0) /* revalidating attrs */ |
202 | #define NFS_INO_ADVISE_RDPLUS (1) /* advise readdirplus */ | 205 | #define NFS_INO_ADVISE_RDPLUS (1) /* advise readdirplus */ |
203 | #define NFS_INO_STALE (2) /* possible stale inode */ | 206 | #define NFS_INO_STALE (2) /* possible stale inode */ |
207 | #define NFS_INO_ACL_LRU_SET (3) /* Inode is on the LRU list */ | ||
204 | 208 | ||
205 | static inline struct nfs_inode *NFS_I(struct inode *inode) | 209 | static inline struct nfs_inode *NFS_I(struct inode *inode) |
206 | { | 210 | { |