aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/dcache.c16
-rw-r--r--fs/ext2/namei.c2
-rw-r--r--fs/ext3/namei.c2
-rw-r--r--fs/ext4/namei.c5
-rw-r--r--fs/gfs2/dir.c2
-rw-r--r--fs/libfs.c4
-rw-r--r--fs/nfs/dir.c5
-rw-r--r--fs/nfs/nfs3proc.c3
-rw-r--r--fs/nfs/nfs4proc.c3
-rw-r--r--fs/nfs/proc.c3
-rw-r--r--fs/nilfs2/namei.c2
-rw-r--r--fs/ubifs/tnc.c2
-rw-r--r--fs/ubifs/xattr.c6
-rw-r--r--fs/udf/namei.c2
-rw-r--r--fs/ufs/super.c5
-rw-r--r--include/linux/dcache.h19
-rw-r--r--net/sunrpc/clnt.c4
-rw-r--r--net/sunrpc/rpc_pipe.c7
18 files changed, 44 insertions, 48 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;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index dffb86536285..f663a67d7bf0 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -79,7 +79,7 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str
79 79
80struct dentry *ext2_get_parent(struct dentry *child) 80struct dentry *ext2_get_parent(struct dentry *child)
81{ 81{
82 struct qstr dotdot = {.name = "..", .len = 2}; 82 struct qstr dotdot = QSTR_INIT("..", 2);
83 unsigned long ino = ext2_inode_by_name(child->d_inode, &dotdot); 83 unsigned long ino = ext2_inode_by_name(child->d_inode, &dotdot);
84 if (!ino) 84 if (!ino)
85 return ERR_PTR(-ENOENT); 85 return ERR_PTR(-ENOENT);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index d7940b24cf68..eeb63dfc5d20 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1045,7 +1045,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
1045struct dentry *ext3_get_parent(struct dentry *child) 1045struct dentry *ext3_get_parent(struct dentry *child)
1046{ 1046{
1047 unsigned long ino; 1047 unsigned long ino;
1048 struct qstr dotdot = {.name = "..", .len = 2}; 1048 struct qstr dotdot = QSTR_INIT("..", 2);
1049 struct ext3_dir_entry_2 * de; 1049 struct ext3_dir_entry_2 * de;
1050 struct buffer_head *bh; 1050 struct buffer_head *bh;
1051 1051
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 349d7b3671c8..e2a3f4b0ff78 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1052,10 +1052,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
1052struct dentry *ext4_get_parent(struct dentry *child) 1052struct dentry *ext4_get_parent(struct dentry *child)
1053{ 1053{
1054 __u32 ino; 1054 __u32 ino;
1055 static const struct qstr dotdot = { 1055 static const struct qstr dotdot = QSTR_INIT("..", 2);
1056 .name = "..",
1057 .len = 2,
1058 };
1059 struct ext4_dir_entry_2 * de; 1056 struct ext4_dir_entry_2 * de;
1060 struct buffer_head *bh; 1057 struct buffer_head *bh;
1061 1058
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index a836056343f0..8aaeb07a07b5 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -821,7 +821,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
821 struct buffer_head *bh; 821 struct buffer_head *bh;
822 struct gfs2_leaf *leaf; 822 struct gfs2_leaf *leaf;
823 struct gfs2_dirent *dent; 823 struct gfs2_dirent *dent;
824 struct qstr name = { .name = "", .len = 0, .hash = 0 }; 824 struct qstr name = { .name = "" };
825 825
826 error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL); 826 error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
827 if (error) 827 if (error)
diff --git a/fs/libfs.c b/fs/libfs.c
index 18d08f5db53a..f86ec27a4230 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -68,7 +68,7 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct na
68 68
69int dcache_dir_open(struct inode *inode, struct file *file) 69int dcache_dir_open(struct inode *inode, struct file *file)
70{ 70{
71 static struct qstr cursor_name = {.len = 1, .name = "."}; 71 static struct qstr cursor_name = QSTR_INIT(".", 1);
72 72
73 file->private_data = d_alloc(file->f_path.dentry, &cursor_name); 73 file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
74 74
@@ -225,7 +225,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
225 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); 225 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
226 struct dentry *dentry; 226 struct dentry *dentry;
227 struct inode *root; 227 struct inode *root;
228 struct qstr d_name = {.name = name, .len = strlen(name)}; 228 struct qstr d_name = QSTR_INIT(name, strlen(name));
229 229
230 if (IS_ERR(s)) 230 if (IS_ERR(s))
231 return ERR_CAST(s); 231 return ERR_CAST(s);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8789210c6905..eedd24d0ad2e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -477,10 +477,7 @@ different:
477static 477static
478void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) 478void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
479{ 479{
480 struct qstr filename = { 480 struct qstr filename = QSTR_INIT(entry->name, entry->len);
481 .len = entry->len,
482 .name = entry->name,
483 };
484 struct dentry *dentry; 481 struct dentry *dentry;
485 struct dentry *alias; 482 struct dentry *alias;
486 struct inode *dir = parent->d_inode; 483 struct inode *dir = parent->d_inode;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 5242eae6711a..75c68299358e 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -398,8 +398,7 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
398{ 398{
399 struct nfs_removeargs arg = { 399 struct nfs_removeargs arg = {
400 .fh = NFS_FH(dir), 400 .fh = NFS_FH(dir),
401 .name.len = name->len, 401 .name = *name,
402 .name.name = name->name,
403 }; 402 };
404 struct nfs_removeres res; 403 struct nfs_removeres res;
405 struct rpc_message msg = { 404 struct rpc_message msg = {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 99650aaf8937..ab985f6f0da8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2782,8 +2782,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
2782 struct nfs_server *server = NFS_SERVER(dir); 2782 struct nfs_server *server = NFS_SERVER(dir);
2783 struct nfs_removeargs args = { 2783 struct nfs_removeargs args = {
2784 .fh = NFS_FH(dir), 2784 .fh = NFS_FH(dir),
2785 .name.len = name->len, 2785 .name = *name,
2786 .name.name = name->name,
2787 .bitmask = server->attr_bitmask, 2786 .bitmask = server->attr_bitmask,
2788 }; 2787 };
2789 struct nfs_removeres res = { 2788 struct nfs_removeres res = {
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index b63b6f4d14fb..d6408b6437de 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -335,8 +335,7 @@ nfs_proc_remove(struct inode *dir, struct qstr *name)
335{ 335{
336 struct nfs_removeargs arg = { 336 struct nfs_removeargs arg = {
337 .fh = NFS_FH(dir), 337 .fh = NFS_FH(dir),
338 .name.len = name->len, 338 .name = *name,
339 .name.name = name->name,
340 }; 339 };
341 struct rpc_message msg = { 340 struct rpc_message msg = {
342 .rpc_proc = &nfs_procedures[NFSPROC_REMOVE], 341 .rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index fce2bbee66d4..0bb2c2010b95 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -441,7 +441,7 @@ static struct dentry *nilfs_get_parent(struct dentry *child)
441{ 441{
442 unsigned long ino; 442 unsigned long ino;
443 struct inode *inode; 443 struct inode *inode;
444 struct qstr dotdot = {.name = "..", .len = 2}; 444 struct qstr dotdot = QSTR_INIT("..", 2);
445 struct nilfs_root *root; 445 struct nilfs_root *root;
446 446
447 ino = nilfs_inode_by_name(child->d_inode, &dotdot); 447 ino = nilfs_inode_by_name(child->d_inode, &dotdot);
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 16ad84d8402f..abd51331345e 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -2361,7 +2361,7 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,
2361 * by passing 'ubifs_tnc_remove_nm()' the same key but 2361 * by passing 'ubifs_tnc_remove_nm()' the same key but
2362 * an unmatchable name. 2362 * an unmatchable name.
2363 */ 2363 */
2364 struct qstr noname = { .len = 0, .name = "" }; 2364 struct qstr noname = { .name = "" };
2365 2365
2366 err = dbg_check_tnc(c, 0); 2366 err = dbg_check_tnc(c, 0);
2367 mutex_unlock(&c->tnc_mutex); 2367 mutex_unlock(&c->tnc_mutex);
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 85b272268754..7a8bafa19c9f 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -298,7 +298,7 @@ int ubifs_setxattr(struct dentry *dentry, const char *name,
298{ 298{
299 struct inode *inode, *host = dentry->d_inode; 299 struct inode *inode, *host = dentry->d_inode;
300 struct ubifs_info *c = host->i_sb->s_fs_info; 300 struct ubifs_info *c = host->i_sb->s_fs_info;
301 struct qstr nm = { .name = name, .len = strlen(name) }; 301 struct qstr nm = QSTR_INIT(name, strlen(name));
302 struct ubifs_dent_node *xent; 302 struct ubifs_dent_node *xent;
303 union ubifs_key key; 303 union ubifs_key key;
304 int err, type; 304 int err, type;
@@ -361,7 +361,7 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
361{ 361{
362 struct inode *inode, *host = dentry->d_inode; 362 struct inode *inode, *host = dentry->d_inode;
363 struct ubifs_info *c = host->i_sb->s_fs_info; 363 struct ubifs_info *c = host->i_sb->s_fs_info;
364 struct qstr nm = { .name = name, .len = strlen(name) }; 364 struct qstr nm = QSTR_INIT(name, strlen(name));
365 struct ubifs_inode *ui; 365 struct ubifs_inode *ui;
366 struct ubifs_dent_node *xent; 366 struct ubifs_dent_node *xent;
367 union ubifs_key key; 367 union ubifs_key key;
@@ -524,7 +524,7 @@ int ubifs_removexattr(struct dentry *dentry, const char *name)
524{ 524{
525 struct inode *inode, *host = dentry->d_inode; 525 struct inode *inode, *host = dentry->d_inode;
526 struct ubifs_info *c = host->i_sb->s_fs_info; 526 struct ubifs_info *c = host->i_sb->s_fs_info;
527 struct qstr nm = { .name = name, .len = strlen(name) }; 527 struct qstr nm = QSTR_INIT(name, strlen(name));
528 struct ubifs_dent_node *xent; 528 struct ubifs_dent_node *xent;
529 union ubifs_key key; 529 union ubifs_key key;
530 int err; 530 int err;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 38de8f234b94..a165c66e3eef 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1193,7 +1193,7 @@ static struct dentry *udf_get_parent(struct dentry *child)
1193{ 1193{
1194 struct kernel_lb_addr tloc; 1194 struct kernel_lb_addr tloc;
1195 struct inode *inode = NULL; 1195 struct inode *inode = NULL;
1196 struct qstr dotdot = {.name = "..", .len = 2}; 1196 struct qstr dotdot = QSTR_INIT("..", 2);
1197 struct fileIdentDesc cfi; 1197 struct fileIdentDesc cfi;
1198 struct udf_fileident_bh fibh; 1198 struct udf_fileident_bh fibh;
1199 1199
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index ac8e279eccc6..302f340d0071 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -146,10 +146,7 @@ static struct dentry *ufs_fh_to_parent(struct super_block *sb, struct fid *fid,
146 146
147static struct dentry *ufs_get_parent(struct dentry *child) 147static struct dentry *ufs_get_parent(struct dentry *child)
148{ 148{
149 struct qstr dot_dot = { 149 struct qstr dot_dot = QSTR_INIT("..", 2);
150 .name = "..",
151 .len = 2,
152 };
153 ino_t ino; 150 ino_t ino;
154 151
155 ino = ufs_inode_by_name(child->d_inode, &dot_dot); 152 ino = ufs_inode_by_name(child->d_inode, &dot_dot);
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 8239f64d1c2e..094789ff3e9f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -25,6 +25,13 @@ struct vfsmount;
25 25
26#define IS_ROOT(x) ((x) == (x)->d_parent) 26#define IS_ROOT(x) ((x) == (x)->d_parent)
27 27
28/* The hash is always the low bits of hash_len */
29#ifdef __LITTLE_ENDIAN
30 #define HASH_LEN_DECLARE u32 hash; u32 len;
31#else
32 #define HASH_LEN_DECLARE u32 len; u32 hash;
33#endif
34
28/* 35/*
29 * "quick string" -- eases parameter passing, but more importantly 36 * "quick string" -- eases parameter passing, but more importantly
30 * saves "metadata" about the string (ie length and the hash). 37 * saves "metadata" about the string (ie length and the hash).
@@ -33,11 +40,19 @@ struct vfsmount;
33 * dentry. 40 * dentry.
34 */ 41 */
35struct qstr { 42struct qstr {
36 unsigned int hash; 43 union {
37 unsigned int len; 44 struct {
45 HASH_LEN_DECLARE;
46 };
47 u64 hash_len;
48 };
38 const unsigned char *name; 49 const unsigned char *name;
39}; 50};
40 51
52#define QSTR_INIT(n,l) { { { .len = l } }, .name = n }
53#define hashlen_hash(hashlen) ((u32) (hashlen))
54#define hashlen_len(hashlen) ((u32)((hashlen) >> 32))
55
41struct dentry_stat_t { 56struct dentry_stat_t {
42 int nr_dentry; 57 int nr_dentry;
43 int nr_unused; 58 int nr_unused;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index adf2990acebf..7fee13b331d1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -127,9 +127,7 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
127{ 127{
128 static uint32_t clntid; 128 static uint32_t clntid;
129 char name[15]; 129 char name[15];
130 struct qstr q = { 130 struct qstr q = { .name = name };
131 .name = name,
132 };
133 struct dentry *dir, *dentry; 131 struct dentry *dir, *dentry;
134 int error; 132 int error;
135 133
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 3b62cf288031..fd2423991c2d 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1059,12 +1059,9 @@ static const struct rpc_filelist files[] = {
1059struct dentry *rpc_d_lookup_sb(const struct super_block *sb, 1059struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
1060 const unsigned char *dir_name) 1060 const unsigned char *dir_name)
1061{ 1061{
1062 struct qstr dir = { 1062 struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
1063 .name = dir_name,
1064 .len = strlen(dir_name),
1065 .hash = full_name_hash(dir_name, strlen(dir_name)),
1066 };
1067 1063
1064 dir.hash = full_name_hash(dir.name, dir.len);
1068 return d_lookup(sb->s_root, &dir); 1065 return d_lookup(sb->s_root, &dir);
1069} 1066}
1070EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); 1067EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);