aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-10 16:14:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-10 22:54:35 -0400
commit26fe575028703948880fce4355a210c76bb0536e (patch)
tree0a7d04289e1eb1f1739659ebc9498d40f2add5da /fs/dcache.c
parentee983e89670704b2a05e897b161f2674a42d1508 (diff)
vfs: make it possible to access the dentry hash/len as one 64-bit entry
This allows comparing hash and len in one operation on 64-bit architectures. Right now only __d_lookup_rcu() takes advantage of this, since that is the case we care most about. The use of anonymous struct/unions hides the alternate 64-bit approach from most users, the exception being a few cases where we initialize a 'struct qstr' with a static initializer. This makes the problematic cases use a new QSTR_INIT() helper function for that (but initializing just the name pointer with a "{ .name = xyzzy }" initializer remains valid, as does just copying another qstr structure). Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index e6707a1f72c6..92099f61bc64 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1502,7 +1502,7 @@ struct dentry *d_make_root(struct inode *root_inode)
1502 struct dentry *res = NULL; 1502 struct dentry *res = NULL;
1503 1503
1504 if (root_inode) { 1504 if (root_inode) {
1505 static const struct qstr name = { .name = "/", .len = 1 }; 1505 static const struct qstr name = QSTR_INIT("/", 1);
1506 1506
1507 res = __d_alloc(root_inode->i_sb, &name); 1507 res = __d_alloc(root_inode->i_sb, &name);
1508 if (res) 1508 if (res)
@@ -1816,10 +1816,9 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
1816 const struct qstr *name, 1816 const struct qstr *name,
1817 unsigned *seqp, struct inode *inode) 1817 unsigned *seqp, struct inode *inode)
1818{ 1818{
1819 unsigned int len = name->len; 1819 u64 hashlen = name->hash_len;
1820 unsigned int hash = name->hash;
1821 const unsigned char *str = name->name; 1820 const unsigned char *str = name->name;
1822 struct hlist_bl_head *b = d_hash(parent, hash); 1821 struct hlist_bl_head *b = d_hash(parent, hashlen_hash(hashlen));
1823 struct hlist_bl_node *node; 1822 struct hlist_bl_node *node;
1824 struct dentry *dentry; 1823 struct dentry *dentry;
1825 1824
@@ -1846,9 +1845,6 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
1846 hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { 1845 hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
1847 unsigned seq; 1846 unsigned seq;
1848 1847
1849 if (dentry->d_name.hash != hash)
1850 continue;
1851
1852seqretry: 1848seqretry:
1853 /* 1849 /*
1854 * The dentry sequence count protects us from concurrent 1850 * The dentry sequence count protects us from concurrent
@@ -1871,6 +1867,8 @@ seqretry:
1871 *seqp = seq; 1867 *seqp = seq;
1872 1868
1873 if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) { 1869 if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
1870 if (dentry->d_name.hash != hashlen_hash(hashlen))
1871 continue;
1874 switch (slow_dentry_cmp(parent, inode, dentry, seq, name)) { 1872 switch (slow_dentry_cmp(parent, inode, dentry, seq, name)) {
1875 case D_COMP_OK: 1873 case D_COMP_OK:
1876 return dentry; 1874 return dentry;
@@ -1881,9 +1879,9 @@ seqretry:
1881 } 1879 }
1882 } 1880 }
1883 1881
1884 if (dentry->d_name.len != len) 1882 if (dentry->d_name.hash_len != hashlen)
1885 continue; 1883 continue;
1886 if (!dentry_cmp(dentry, str, len)) 1884 if (!dentry_cmp(dentry, str, hashlen_len(hashlen)))
1887 return dentry; 1885 return dentry;
1888 } 1886 }
1889 return NULL; 1887 return NULL;