diff options
Diffstat (limited to 'fs/dcache.c')
| -rw-r--r-- | fs/dcache.c | 66 |
1 files changed, 23 insertions, 43 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 5a23073138df..87bdb5329c3c 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -1730,7 +1730,7 @@ EXPORT_SYMBOL(d_add_ci); | |||
| 1730 | * Do the slow-case of the dentry name compare. | 1730 | * Do the slow-case of the dentry name compare. |
| 1731 | * | 1731 | * |
| 1732 | * Unlike the dentry_cmp() function, we need to atomically | 1732 | * Unlike the dentry_cmp() function, we need to atomically |
| 1733 | * load the name, length and inode information, so that the | 1733 | * load the name and length information, so that the |
| 1734 | * filesystem can rely on them, and can use the 'name' and | 1734 | * filesystem can rely on them, and can use the 'name' and |
| 1735 | * 'len' information without worrying about walking off the | 1735 | * 'len' information without worrying about walking off the |
| 1736 | * end of memory etc. | 1736 | * end of memory etc. |
| @@ -1748,22 +1748,18 @@ enum slow_d_compare { | |||
| 1748 | 1748 | ||
| 1749 | static noinline enum slow_d_compare slow_dentry_cmp( | 1749 | static noinline enum slow_d_compare slow_dentry_cmp( |
| 1750 | const struct dentry *parent, | 1750 | const struct dentry *parent, |
| 1751 | struct inode *inode, | ||
| 1752 | struct dentry *dentry, | 1751 | struct dentry *dentry, |
| 1753 | unsigned int seq, | 1752 | unsigned int seq, |
| 1754 | const struct qstr *name) | 1753 | const struct qstr *name) |
| 1755 | { | 1754 | { |
| 1756 | int tlen = dentry->d_name.len; | 1755 | int tlen = dentry->d_name.len; |
| 1757 | const char *tname = dentry->d_name.name; | 1756 | const char *tname = dentry->d_name.name; |
| 1758 | struct inode *i = dentry->d_inode; | ||
| 1759 | 1757 | ||
| 1760 | if (read_seqcount_retry(&dentry->d_seq, seq)) { | 1758 | if (read_seqcount_retry(&dentry->d_seq, seq)) { |
| 1761 | cpu_relax(); | 1759 | cpu_relax(); |
| 1762 | return D_COMP_SEQRETRY; | 1760 | return D_COMP_SEQRETRY; |
| 1763 | } | 1761 | } |
| 1764 | if (parent->d_op->d_compare(parent, inode, | 1762 | if (parent->d_op->d_compare(parent, dentry, tlen, tname, name)) |
| 1765 | dentry, i, | ||
| 1766 | tlen, tname, name)) | ||
| 1767 | return D_COMP_NOMATCH; | 1763 | return D_COMP_NOMATCH; |
| 1768 | return D_COMP_OK; | 1764 | return D_COMP_OK; |
| 1769 | } | 1765 | } |
| @@ -1773,7 +1769,6 @@ static noinline enum slow_d_compare slow_dentry_cmp( | |||
| 1773 | * @parent: parent dentry | 1769 | * @parent: parent dentry |
| 1774 | * @name: qstr of name we wish to find | 1770 | * @name: qstr of name we wish to find |
| 1775 | * @seqp: returns d_seq value at the point where the dentry was found | 1771 | * @seqp: returns d_seq value at the point where the dentry was found |
| 1776 | * @inode: returns dentry->d_inode when the inode was found valid. | ||
| 1777 | * Returns: dentry, or NULL | 1772 | * Returns: dentry, or NULL |
| 1778 | * | 1773 | * |
| 1779 | * __d_lookup_rcu is the dcache lookup function for rcu-walk name | 1774 | * __d_lookup_rcu is the dcache lookup function for rcu-walk name |
| @@ -1800,7 +1795,7 @@ static noinline enum slow_d_compare slow_dentry_cmp( | |||
| 1800 | */ | 1795 | */ |
| 1801 | struct dentry *__d_lookup_rcu(const struct dentry *parent, | 1796 | struct dentry *__d_lookup_rcu(const struct dentry *parent, |
| 1802 | const struct qstr *name, | 1797 | const struct qstr *name, |
| 1803 | unsigned *seqp, struct inode *inode) | 1798 | unsigned *seqp) |
| 1804 | { | 1799 | { |
| 1805 | u64 hashlen = name->hash_len; | 1800 | u64 hashlen = name->hash_len; |
| 1806 | const unsigned char *str = name->name; | 1801 | const unsigned char *str = name->name; |
| @@ -1834,11 +1829,10 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent, | |||
| 1834 | seqretry: | 1829 | seqretry: |
| 1835 | /* | 1830 | /* |
| 1836 | * The dentry sequence count protects us from concurrent | 1831 | * The dentry sequence count protects us from concurrent |
| 1837 | * renames, and thus protects inode, parent and name fields. | 1832 | * renames, and thus protects parent and name fields. |
| 1838 | * | 1833 | * |
| 1839 | * The caller must perform a seqcount check in order | 1834 | * The caller must perform a seqcount check in order |
| 1840 | * to do anything useful with the returned dentry, | 1835 | * to do anything useful with the returned dentry. |
| 1841 | * including using the 'd_inode' pointer. | ||
| 1842 | * | 1836 | * |
| 1843 | * NOTE! We do a "raw" seqcount_begin here. That means that | 1837 | * NOTE! We do a "raw" seqcount_begin here. That means that |
| 1844 | * we don't wait for the sequence count to stabilize if it | 1838 | * we don't wait for the sequence count to stabilize if it |
| @@ -1852,12 +1846,12 @@ seqretry: | |||
| 1852 | continue; | 1846 | continue; |
| 1853 | if (d_unhashed(dentry)) | 1847 | if (d_unhashed(dentry)) |
| 1854 | continue; | 1848 | continue; |
| 1855 | *seqp = seq; | ||
| 1856 | 1849 | ||
| 1857 | if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) { | 1850 | if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) { |
| 1858 | if (dentry->d_name.hash != hashlen_hash(hashlen)) | 1851 | if (dentry->d_name.hash != hashlen_hash(hashlen)) |
| 1859 | continue; | 1852 | continue; |
| 1860 | switch (slow_dentry_cmp(parent, inode, dentry, seq, name)) { | 1853 | *seqp = seq; |
| 1854 | switch (slow_dentry_cmp(parent, dentry, seq, name)) { | ||
| 1861 | case D_COMP_OK: | 1855 | case D_COMP_OK: |
| 1862 | return dentry; | 1856 | return dentry; |
| 1863 | case D_COMP_NOMATCH: | 1857 | case D_COMP_NOMATCH: |
| @@ -1869,6 +1863,7 @@ seqretry: | |||
| 1869 | 1863 | ||
| 1870 | if (dentry->d_name.hash_len != hashlen) | 1864 | if (dentry->d_name.hash_len != hashlen) |
| 1871 | continue; | 1865 | continue; |
| 1866 | *seqp = seq; | ||
| 1872 | if (!dentry_cmp(dentry, str, hashlen_len(hashlen))) | 1867 | if (!dentry_cmp(dentry, str, hashlen_len(hashlen))) |
| 1873 | return dentry; | 1868 | return dentry; |
| 1874 | } | 1869 | } |
| @@ -1966,9 +1961,7 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name) | |||
| 1966 | if (parent->d_flags & DCACHE_OP_COMPARE) { | 1961 | if (parent->d_flags & DCACHE_OP_COMPARE) { |
| 1967 | int tlen = dentry->d_name.len; | 1962 | int tlen = dentry->d_name.len; |
| 1968 | const char *tname = dentry->d_name.name; | 1963 | const char *tname = dentry->d_name.name; |
| 1969 | if (parent->d_op->d_compare(parent, parent->d_inode, | 1964 | if (parent->d_op->d_compare(parent, dentry, tlen, tname, name)) |
| 1970 | dentry, dentry->d_inode, | ||
| 1971 | tlen, tname, name)) | ||
| 1972 | goto next; | 1965 | goto next; |
| 1973 | } else { | 1966 | } else { |
| 1974 | if (dentry->d_name.len != len) | 1967 | if (dentry->d_name.len != len) |
| @@ -2005,7 +1998,7 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name) | |||
| 2005 | */ | 1998 | */ |
| 2006 | name->hash = full_name_hash(name->name, name->len); | 1999 | name->hash = full_name_hash(name->name, name->len); |
| 2007 | if (dir->d_flags & DCACHE_OP_HASH) { | 2000 | if (dir->d_flags & DCACHE_OP_HASH) { |
| 2008 | int err = dir->d_op->d_hash(dir, dir->d_inode, name); | 2001 | int err = dir->d_op->d_hash(dir, name); |
| 2009 | if (unlikely(err < 0)) | 2002 | if (unlikely(err < 0)) |
| 2010 | return ERR_PTR(err); | 2003 | return ERR_PTR(err); |
| 2011 | } | 2004 | } |
| @@ -2975,34 +2968,21 @@ rename_retry: | |||
| 2975 | goto again; | 2968 | goto again; |
| 2976 | } | 2969 | } |
| 2977 | 2970 | ||
| 2978 | /** | 2971 | void d_tmpfile(struct dentry *dentry, struct inode *inode) |
| 2979 | * find_inode_number - check for dentry with name | ||
| 2980 | * @dir: directory to check | ||
| 2981 | * @name: Name to find. | ||
| 2982 | * | ||
| 2983 | * Check whether a dentry already exists for the given name, | ||
| 2984 | * and return the inode number if it has an inode. Otherwise | ||
| 2985 | * 0 is returned. | ||
| 2986 | * | ||
| 2987 | * This routine is used to post-process directory listings for | ||
| 2988 | * filesystems using synthetic inode numbers, and is necessary | ||
| 2989 | * to keep getcwd() working. | ||
| 2990 | */ | ||
| 2991 | |||
| 2992 | ino_t find_inode_number(struct dentry *dir, struct qstr *name) | ||
| 2993 | { | 2972 | { |
| 2994 | struct dentry * dentry; | 2973 | inode_dec_link_count(inode); |
| 2995 | ino_t ino = 0; | 2974 | BUG_ON(dentry->d_name.name != dentry->d_iname || |
| 2996 | 2975 | !hlist_unhashed(&dentry->d_alias) || | |
| 2997 | dentry = d_hash_and_lookup(dir, name); | 2976 | !d_unlinked(dentry)); |
| 2998 | if (!IS_ERR_OR_NULL(dentry)) { | 2977 | spin_lock(&dentry->d_parent->d_lock); |
| 2999 | if (dentry->d_inode) | 2978 | spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); |
| 3000 | ino = dentry->d_inode->i_ino; | 2979 | dentry->d_name.len = sprintf(dentry->d_iname, "#%llu", |
| 3001 | dput(dentry); | 2980 | (unsigned long long)inode->i_ino); |
| 3002 | } | 2981 | spin_unlock(&dentry->d_lock); |
| 3003 | return ino; | 2982 | spin_unlock(&dentry->d_parent->d_lock); |
| 2983 | d_instantiate(dentry, inode); | ||
| 3004 | } | 2984 | } |
| 3005 | EXPORT_SYMBOL(find_inode_number); | 2985 | EXPORT_SYMBOL(d_tmpfile); |
| 3006 | 2986 | ||
| 3007 | static __initdata unsigned long dhash_entries; | 2987 | static __initdata unsigned long dhash_entries; |
| 3008 | static int __init set_dhash_entries(char *str) | 2988 | static int __init set_dhash_entries(char *str) |
