diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 341 |
1 files changed, 280 insertions, 61 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e7ffb4deb3e5..7432f1a43f3d 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -30,7 +30,9 @@ | |||
30 | #include <linux/nfs_mount.h> | 30 | #include <linux/nfs_mount.h> |
31 | #include <linux/pagemap.h> | 31 | #include <linux/pagemap.h> |
32 | #include <linux/smp_lock.h> | 32 | #include <linux/smp_lock.h> |
33 | #include <linux/pagevec.h> | ||
33 | #include <linux/namei.h> | 34 | #include <linux/namei.h> |
35 | #include <linux/mount.h> | ||
34 | 36 | ||
35 | #include "nfs4_fs.h" | 37 | #include "nfs4_fs.h" |
36 | #include "delegation.h" | 38 | #include "delegation.h" |
@@ -870,14 +872,14 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | |||
870 | return (nd->intent.open.flags & O_EXCL) != 0; | 872 | return (nd->intent.open.flags & O_EXCL) != 0; |
871 | } | 873 | } |
872 | 874 | ||
873 | static inline int nfs_reval_fsid(struct inode *dir, | 875 | static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir, |
874 | struct nfs_fh *fh, struct nfs_fattr *fattr) | 876 | struct nfs_fh *fh, struct nfs_fattr *fattr) |
875 | { | 877 | { |
876 | struct nfs_server *server = NFS_SERVER(dir); | 878 | struct nfs_server *server = NFS_SERVER(dir); |
877 | 879 | ||
878 | if (!nfs_fsid_equal(&server->fsid, &fattr->fsid)) | 880 | if (!nfs_fsid_equal(&server->fsid, &fattr->fsid)) |
879 | /* Revalidate fsid on root dir */ | 881 | /* Revalidate fsid on root dir */ |
880 | return __nfs_revalidate_inode(server, dir->i_sb->s_root->d_inode); | 882 | return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode); |
881 | return 0; | 883 | return 0; |
882 | } | 884 | } |
883 | 885 | ||
@@ -902,9 +904,15 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
902 | 904 | ||
903 | lock_kernel(); | 905 | lock_kernel(); |
904 | 906 | ||
905 | /* If we're doing an exclusive create, optimize away the lookup */ | 907 | /* |
906 | if (nfs_is_exclusive_create(dir, nd)) | 908 | * If we're doing an exclusive create, optimize away the lookup |
907 | goto no_entry; | 909 | * but don't hash the dentry. |
910 | */ | ||
911 | if (nfs_is_exclusive_create(dir, nd)) { | ||
912 | d_instantiate(dentry, NULL); | ||
913 | res = NULL; | ||
914 | goto out_unlock; | ||
915 | } | ||
908 | 916 | ||
909 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); | 917 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); |
910 | if (error == -ENOENT) | 918 | if (error == -ENOENT) |
@@ -913,7 +921,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
913 | res = ERR_PTR(error); | 921 | res = ERR_PTR(error); |
914 | goto out_unlock; | 922 | goto out_unlock; |
915 | } | 923 | } |
916 | error = nfs_reval_fsid(dir, &fhandle, &fattr); | 924 | error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr); |
917 | if (error < 0) { | 925 | if (error < 0) { |
918 | res = ERR_PTR(error); | 926 | res = ERR_PTR(error); |
919 | goto out_unlock; | 927 | goto out_unlock; |
@@ -922,8 +930,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
922 | res = (struct dentry *)inode; | 930 | res = (struct dentry *)inode; |
923 | if (IS_ERR(res)) | 931 | if (IS_ERR(res)) |
924 | goto out_unlock; | 932 | goto out_unlock; |
933 | |||
925 | no_entry: | 934 | no_entry: |
926 | res = d_add_unique(dentry, inode); | 935 | res = d_materialise_unique(dentry, inode); |
927 | if (res != NULL) | 936 | if (res != NULL) |
928 | dentry = res; | 937 | dentry = res; |
929 | nfs_renew_times(dentry); | 938 | nfs_renew_times(dentry); |
@@ -1117,11 +1126,13 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1117 | dput(dentry); | 1126 | dput(dentry); |
1118 | return NULL; | 1127 | return NULL; |
1119 | } | 1128 | } |
1120 | alias = d_add_unique(dentry, inode); | 1129 | |
1130 | alias = d_materialise_unique(dentry, inode); | ||
1121 | if (alias != NULL) { | 1131 | if (alias != NULL) { |
1122 | dput(dentry); | 1132 | dput(dentry); |
1123 | dentry = alias; | 1133 | dentry = alias; |
1124 | } | 1134 | } |
1135 | |||
1125 | nfs_renew_times(dentry); | 1136 | nfs_renew_times(dentry); |
1126 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1137 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1127 | return dentry; | 1138 | return dentry; |
@@ -1143,23 +1154,22 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | |||
1143 | struct inode *dir = dentry->d_parent->d_inode; | 1154 | struct inode *dir = dentry->d_parent->d_inode; |
1144 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1155 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); |
1145 | if (error) | 1156 | if (error) |
1146 | goto out_err; | 1157 | return error; |
1147 | } | 1158 | } |
1148 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1159 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1149 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 1160 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
1150 | error = server->rpc_ops->getattr(server, fhandle, fattr); | 1161 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); |
1151 | if (error < 0) | 1162 | if (error < 0) |
1152 | goto out_err; | 1163 | return error; |
1153 | } | 1164 | } |
1154 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1165 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); |
1155 | error = PTR_ERR(inode); | 1166 | error = PTR_ERR(inode); |
1156 | if (IS_ERR(inode)) | 1167 | if (IS_ERR(inode)) |
1157 | goto out_err; | 1168 | return error; |
1158 | d_instantiate(dentry, inode); | 1169 | d_instantiate(dentry, inode); |
1170 | if (d_unhashed(dentry)) | ||
1171 | d_rehash(dentry); | ||
1159 | return 0; | 1172 | return 0; |
1160 | out_err: | ||
1161 | d_drop(dentry); | ||
1162 | return error; | ||
1163 | } | 1173 | } |
1164 | 1174 | ||
1165 | /* | 1175 | /* |
@@ -1440,48 +1450,82 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1440 | return error; | 1450 | return error; |
1441 | } | 1451 | } |
1442 | 1452 | ||
1443 | static int | 1453 | /* |
1444 | nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | 1454 | * To create a symbolic link, most file systems instantiate a new inode, |
1455 | * add a page to it containing the path, then write it out to the disk | ||
1456 | * using prepare_write/commit_write. | ||
1457 | * | ||
1458 | * Unfortunately the NFS client can't create the in-core inode first | ||
1459 | * because it needs a file handle to create an in-core inode (see | ||
1460 | * fs/nfs/inode.c:nfs_fhget). We only have a file handle *after* the | ||
1461 | * symlink request has completed on the server. | ||
1462 | * | ||
1463 | * So instead we allocate a raw page, copy the symname into it, then do | ||
1464 | * the SYMLINK request with the page as the buffer. If it succeeds, we | ||
1465 | * now have a new file handle and can instantiate an in-core NFS inode | ||
1466 | * and move the raw page into its mapping. | ||
1467 | */ | ||
1468 | static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | ||
1445 | { | 1469 | { |
1470 | struct pagevec lru_pvec; | ||
1471 | struct page *page; | ||
1472 | char *kaddr; | ||
1446 | struct iattr attr; | 1473 | struct iattr attr; |
1447 | struct nfs_fattr sym_attr; | 1474 | unsigned int pathlen = strlen(symname); |
1448 | struct nfs_fh sym_fh; | ||
1449 | struct qstr qsymname; | ||
1450 | int error; | 1475 | int error; |
1451 | 1476 | ||
1452 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, | 1477 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, |
1453 | dir->i_ino, dentry->d_name.name, symname); | 1478 | dir->i_ino, dentry->d_name.name, symname); |
1454 | 1479 | ||
1455 | #ifdef NFS_PARANOIA | 1480 | if (pathlen > PAGE_SIZE) |
1456 | if (dentry->d_inode) | 1481 | return -ENAMETOOLONG; |
1457 | printk("nfs_proc_symlink: %s/%s not negative!\n", | ||
1458 | dentry->d_parent->d_name.name, dentry->d_name.name); | ||
1459 | #endif | ||
1460 | /* | ||
1461 | * Fill in the sattr for the call. | ||
1462 | * Note: SunOS 4.1.2 crashes if the mode isn't initialized! | ||
1463 | */ | ||
1464 | attr.ia_valid = ATTR_MODE; | ||
1465 | attr.ia_mode = S_IFLNK | S_IRWXUGO; | ||
1466 | 1482 | ||
1467 | qsymname.name = symname; | 1483 | attr.ia_mode = S_IFLNK | S_IRWXUGO; |
1468 | qsymname.len = strlen(symname); | 1484 | attr.ia_valid = ATTR_MODE; |
1469 | 1485 | ||
1470 | lock_kernel(); | 1486 | lock_kernel(); |
1487 | |||
1488 | page = alloc_page(GFP_KERNEL); | ||
1489 | if (!page) { | ||
1490 | unlock_kernel(); | ||
1491 | return -ENOMEM; | ||
1492 | } | ||
1493 | |||
1494 | kaddr = kmap_atomic(page, KM_USER0); | ||
1495 | memcpy(kaddr, symname, pathlen); | ||
1496 | if (pathlen < PAGE_SIZE) | ||
1497 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); | ||
1498 | kunmap_atomic(kaddr, KM_USER0); | ||
1499 | |||
1471 | nfs_begin_data_update(dir); | 1500 | nfs_begin_data_update(dir); |
1472 | error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname, | 1501 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); |
1473 | &attr, &sym_fh, &sym_attr); | ||
1474 | nfs_end_data_update(dir); | 1502 | nfs_end_data_update(dir); |
1475 | if (!error) { | 1503 | if (error != 0) { |
1476 | error = nfs_instantiate(dentry, &sym_fh, &sym_attr); | 1504 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", |
1477 | } else { | 1505 | dir->i_sb->s_id, dir->i_ino, |
1478 | if (error == -EEXIST) | 1506 | dentry->d_name.name, symname, error); |
1479 | printk("nfs_proc_symlink: %s/%s already exists??\n", | ||
1480 | dentry->d_parent->d_name.name, dentry->d_name.name); | ||
1481 | d_drop(dentry); | 1507 | d_drop(dentry); |
1508 | __free_page(page); | ||
1509 | unlock_kernel(); | ||
1510 | return error; | ||
1482 | } | 1511 | } |
1512 | |||
1513 | /* | ||
1514 | * No big deal if we can't add this page to the page cache here. | ||
1515 | * READLINK will get the missing page from the server if needed. | ||
1516 | */ | ||
1517 | pagevec_init(&lru_pvec, 0); | ||
1518 | if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0, | ||
1519 | GFP_KERNEL)) { | ||
1520 | if (!pagevec_add(&lru_pvec, page)) | ||
1521 | __pagevec_lru_add(&lru_pvec); | ||
1522 | SetPageUptodate(page); | ||
1523 | unlock_page(page); | ||
1524 | } else | ||
1525 | __free_page(page); | ||
1526 | |||
1483 | unlock_kernel(); | 1527 | unlock_kernel(); |
1484 | return error; | 1528 | return 0; |
1485 | } | 1529 | } |
1486 | 1530 | ||
1487 | static int | 1531 | static int |
@@ -1625,8 +1669,7 @@ out: | |||
1625 | if (rehash) | 1669 | if (rehash) |
1626 | d_rehash(rehash); | 1670 | d_rehash(rehash); |
1627 | if (!error) { | 1671 | if (!error) { |
1628 | if (!S_ISDIR(old_inode->i_mode)) | 1672 | d_move(old_dentry, new_dentry); |
1629 | d_move(old_dentry, new_dentry); | ||
1630 | nfs_renew_times(new_dentry); | 1673 | nfs_renew_times(new_dentry); |
1631 | nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir)); | 1674 | nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir)); |
1632 | } | 1675 | } |
@@ -1638,35 +1681,211 @@ out: | |||
1638 | return error; | 1681 | return error; |
1639 | } | 1682 | } |
1640 | 1683 | ||
1684 | static DEFINE_SPINLOCK(nfs_access_lru_lock); | ||
1685 | static LIST_HEAD(nfs_access_lru_list); | ||
1686 | static atomic_long_t nfs_access_nr_entries; | ||
1687 | |||
1688 | static void nfs_access_free_entry(struct nfs_access_entry *entry) | ||
1689 | { | ||
1690 | put_rpccred(entry->cred); | ||
1691 | kfree(entry); | ||
1692 | smp_mb__before_atomic_dec(); | ||
1693 | atomic_long_dec(&nfs_access_nr_entries); | ||
1694 | smp_mb__after_atomic_dec(); | ||
1695 | } | ||
1696 | |||
1697 | int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | ||
1698 | { | ||
1699 | LIST_HEAD(head); | ||
1700 | struct nfs_inode *nfsi; | ||
1701 | struct nfs_access_entry *cache; | ||
1702 | |||
1703 | spin_lock(&nfs_access_lru_lock); | ||
1704 | restart: | ||
1705 | list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { | ||
1706 | struct inode *inode; | ||
1707 | |||
1708 | if (nr_to_scan-- == 0) | ||
1709 | break; | ||
1710 | inode = igrab(&nfsi->vfs_inode); | ||
1711 | if (inode == NULL) | ||
1712 | continue; | ||
1713 | spin_lock(&inode->i_lock); | ||
1714 | if (list_empty(&nfsi->access_cache_entry_lru)) | ||
1715 | goto remove_lru_entry; | ||
1716 | cache = list_entry(nfsi->access_cache_entry_lru.next, | ||
1717 | struct nfs_access_entry, lru); | ||
1718 | list_move(&cache->lru, &head); | ||
1719 | rb_erase(&cache->rb_node, &nfsi->access_cache); | ||
1720 | if (!list_empty(&nfsi->access_cache_entry_lru)) | ||
1721 | list_move_tail(&nfsi->access_cache_inode_lru, | ||
1722 | &nfs_access_lru_list); | ||
1723 | else { | ||
1724 | remove_lru_entry: | ||
1725 | list_del_init(&nfsi->access_cache_inode_lru); | ||
1726 | clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags); | ||
1727 | } | ||
1728 | spin_unlock(&inode->i_lock); | ||
1729 | iput(inode); | ||
1730 | goto restart; | ||
1731 | } | ||
1732 | spin_unlock(&nfs_access_lru_lock); | ||
1733 | while (!list_empty(&head)) { | ||
1734 | cache = list_entry(head.next, struct nfs_access_entry, lru); | ||
1735 | list_del(&cache->lru); | ||
1736 | nfs_access_free_entry(cache); | ||
1737 | } | ||
1738 | return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure; | ||
1739 | } | ||
1740 | |||
1741 | static void __nfs_access_zap_cache(struct inode *inode) | ||
1742 | { | ||
1743 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1744 | struct rb_root *root_node = &nfsi->access_cache; | ||
1745 | struct rb_node *n, *dispose = NULL; | ||
1746 | struct nfs_access_entry *entry; | ||
1747 | |||
1748 | /* Unhook entries from the cache */ | ||
1749 | while ((n = rb_first(root_node)) != NULL) { | ||
1750 | entry = rb_entry(n, struct nfs_access_entry, rb_node); | ||
1751 | rb_erase(n, root_node); | ||
1752 | list_del(&entry->lru); | ||
1753 | n->rb_left = dispose; | ||
1754 | dispose = n; | ||
1755 | } | ||
1756 | nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; | ||
1757 | spin_unlock(&inode->i_lock); | ||
1758 | |||
1759 | /* Now kill them all! */ | ||
1760 | while (dispose != NULL) { | ||
1761 | n = dispose; | ||
1762 | dispose = n->rb_left; | ||
1763 | nfs_access_free_entry(rb_entry(n, struct nfs_access_entry, rb_node)); | ||
1764 | } | ||
1765 | } | ||
1766 | |||
1767 | void nfs_access_zap_cache(struct inode *inode) | ||
1768 | { | ||
1769 | /* Remove from global LRU init */ | ||
1770 | if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { | ||
1771 | spin_lock(&nfs_access_lru_lock); | ||
1772 | list_del_init(&NFS_I(inode)->access_cache_inode_lru); | ||
1773 | spin_unlock(&nfs_access_lru_lock); | ||
1774 | } | ||
1775 | |||
1776 | spin_lock(&inode->i_lock); | ||
1777 | /* This will release the spinlock */ | ||
1778 | __nfs_access_zap_cache(inode); | ||
1779 | } | ||
1780 | |||
1781 | static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred) | ||
1782 | { | ||
1783 | struct rb_node *n = NFS_I(inode)->access_cache.rb_node; | ||
1784 | struct nfs_access_entry *entry; | ||
1785 | |||
1786 | while (n != NULL) { | ||
1787 | entry = rb_entry(n, struct nfs_access_entry, rb_node); | ||
1788 | |||
1789 | if (cred < entry->cred) | ||
1790 | n = n->rb_left; | ||
1791 | else if (cred > entry->cred) | ||
1792 | n = n->rb_right; | ||
1793 | else | ||
1794 | return entry; | ||
1795 | } | ||
1796 | return NULL; | ||
1797 | } | ||
1798 | |||
1641 | int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) | 1799 | int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) |
1642 | { | 1800 | { |
1643 | struct nfs_inode *nfsi = NFS_I(inode); | 1801 | struct nfs_inode *nfsi = NFS_I(inode); |
1644 | struct nfs_access_entry *cache = &nfsi->cache_access; | 1802 | struct nfs_access_entry *cache; |
1803 | int err = -ENOENT; | ||
1645 | 1804 | ||
1646 | if (cache->cred != cred | 1805 | spin_lock(&inode->i_lock); |
1647 | || time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode)) | 1806 | if (nfsi->cache_validity & NFS_INO_INVALID_ACCESS) |
1648 | || (nfsi->cache_validity & NFS_INO_INVALID_ACCESS)) | 1807 | goto out_zap; |
1649 | return -ENOENT; | 1808 | cache = nfs_access_search_rbtree(inode, cred); |
1650 | memcpy(res, cache, sizeof(*res)); | 1809 | if (cache == NULL) |
1651 | return 0; | 1810 | goto out; |
1811 | if (time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) | ||
1812 | goto out_stale; | ||
1813 | res->jiffies = cache->jiffies; | ||
1814 | res->cred = cache->cred; | ||
1815 | res->mask = cache->mask; | ||
1816 | list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru); | ||
1817 | err = 0; | ||
1818 | out: | ||
1819 | spin_unlock(&inode->i_lock); | ||
1820 | return err; | ||
1821 | out_stale: | ||
1822 | rb_erase(&cache->rb_node, &nfsi->access_cache); | ||
1823 | list_del(&cache->lru); | ||
1824 | spin_unlock(&inode->i_lock); | ||
1825 | nfs_access_free_entry(cache); | ||
1826 | return -ENOENT; | ||
1827 | out_zap: | ||
1828 | /* This will release the spinlock */ | ||
1829 | __nfs_access_zap_cache(inode); | ||
1830 | return -ENOENT; | ||
1652 | } | 1831 | } |
1653 | 1832 | ||
1654 | void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | 1833 | static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set) |
1655 | { | 1834 | { |
1656 | struct nfs_inode *nfsi = NFS_I(inode); | 1835 | struct nfs_inode *nfsi = NFS_I(inode); |
1657 | struct nfs_access_entry *cache = &nfsi->cache_access; | 1836 | struct rb_root *root_node = &nfsi->access_cache; |
1837 | struct rb_node **p = &root_node->rb_node; | ||
1838 | struct rb_node *parent = NULL; | ||
1839 | struct nfs_access_entry *entry; | ||
1658 | 1840 | ||
1659 | if (cache->cred != set->cred) { | ||
1660 | if (cache->cred) | ||
1661 | put_rpccred(cache->cred); | ||
1662 | cache->cred = get_rpccred(set->cred); | ||
1663 | } | ||
1664 | /* FIXME: replace current access_cache BKL reliance with inode->i_lock */ | ||
1665 | spin_lock(&inode->i_lock); | 1841 | spin_lock(&inode->i_lock); |
1666 | nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; | 1842 | while (*p != NULL) { |
1843 | parent = *p; | ||
1844 | entry = rb_entry(parent, struct nfs_access_entry, rb_node); | ||
1845 | |||
1846 | if (set->cred < entry->cred) | ||
1847 | p = &parent->rb_left; | ||
1848 | else if (set->cred > entry->cred) | ||
1849 | p = &parent->rb_right; | ||
1850 | else | ||
1851 | goto found; | ||
1852 | } | ||
1853 | rb_link_node(&set->rb_node, parent, p); | ||
1854 | rb_insert_color(&set->rb_node, root_node); | ||
1855 | list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); | ||
1667 | spin_unlock(&inode->i_lock); | 1856 | spin_unlock(&inode->i_lock); |
1857 | return; | ||
1858 | found: | ||
1859 | rb_replace_node(parent, &set->rb_node, root_node); | ||
1860 | list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); | ||
1861 | list_del(&entry->lru); | ||
1862 | spin_unlock(&inode->i_lock); | ||
1863 | nfs_access_free_entry(entry); | ||
1864 | } | ||
1865 | |||
1866 | void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | ||
1867 | { | ||
1868 | struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); | ||
1869 | if (cache == NULL) | ||
1870 | return; | ||
1871 | RB_CLEAR_NODE(&cache->rb_node); | ||
1668 | cache->jiffies = set->jiffies; | 1872 | cache->jiffies = set->jiffies; |
1873 | cache->cred = get_rpccred(set->cred); | ||
1669 | cache->mask = set->mask; | 1874 | cache->mask = set->mask; |
1875 | |||
1876 | nfs_access_add_rbtree(inode, cache); | ||
1877 | |||
1878 | /* Update accounting */ | ||
1879 | smp_mb__before_atomic_inc(); | ||
1880 | atomic_long_inc(&nfs_access_nr_entries); | ||
1881 | smp_mb__after_atomic_inc(); | ||
1882 | |||
1883 | /* Add inode to global LRU list */ | ||
1884 | if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { | ||
1885 | spin_lock(&nfs_access_lru_lock); | ||
1886 | list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list); | ||
1887 | spin_unlock(&nfs_access_lru_lock); | ||
1888 | } | ||
1670 | } | 1889 | } |
1671 | 1890 | ||
1672 | static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | 1891 | static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) |