diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-10 13:14:12 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-10 19:54:35 -0700 |
commit | 26fe575028703948880fce4355a210c76bb0536e (patch) | |
tree | 0a7d04289e1eb1f1739659ebc9498d40f2add5da /fs/dcache.c | |
parent | ee983e89670704b2a05e897b161f2674a42d1508 (diff) | |
download | lwn-26fe575028703948880fce4355a210c76bb0536e.tar.gz lwn-26fe575028703948880fce4355a210c76bb0536e.zip |
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.c | 16 |
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) struct dentry *res = NULL; if (root_inode) { - static const struct qstr name = { .name = "/", .len = 1 }; + static const struct qstr name = QSTR_INIT("/", 1); res = __d_alloc(root_inode->i_sb, &name); if (res) @@ -1816,10 +1816,9 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent, const struct qstr *name, unsigned *seqp, struct inode *inode) { - unsigned int len = name->len; - unsigned int hash = name->hash; + u64 hashlen = name->hash_len; const unsigned char *str = name->name; - struct hlist_bl_head *b = d_hash(parent, hash); + struct hlist_bl_head *b = d_hash(parent, hashlen_hash(hashlen)); struct hlist_bl_node *node; struct dentry *dentry; @@ -1846,9 +1845,6 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent, hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { unsigned seq; - if (dentry->d_name.hash != hash) - continue; - seqretry: /* * The dentry sequence count protects us from concurrent @@ -1871,6 +1867,8 @@ seqretry: *seqp = seq; if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) { + if (dentry->d_name.hash != hashlen_hash(hashlen)) + continue; switch (slow_dentry_cmp(parent, inode, dentry, seq, name)) { case D_COMP_OK: return dentry; @@ -1881,9 +1879,9 @@ seqretry: } } - if (dentry->d_name.len != len) + if (dentry->d_name.hash_len != hashlen) continue; - if (!dentry_cmp(dentry, str, len)) + if (!dentry_cmp(dentry, str, hashlen_len(hashlen))) return dentry; } return NULL; |