aboutsummaryrefslogtreecommitdiffstats
path: root/fs/affs/namei.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:27 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:19 -0500
commit621e155a3591962420eacdd39f6f0aa29ceb221e (patch)
tree387a9fb396f1bf24514b712c294182e36ba51076 /fs/affs/namei.c
parentfb2d5b86aff355a27ebfc132d3c99f4a940cc3fe (diff)
fs: change d_compare for rcu-walk
Change d_compare so it may be called from lock-free RCU lookups. This does put significant restrictions on what may be done from the callback, however there don't seem to have been any problems with in-tree fses. If some strange use case pops up that _really_ cannot cope with the rcu-walk rules, we can just add new rcu-unaware callbacks, which would cause name lookup to drop out of rcu-walk mode. For in-tree filesystems, this is just a mechanical change. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/affs/namei.c')
-rw-r--r--fs/affs/namei.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 914d1c0bc07..547d5deb0d4 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -14,10 +14,16 @@ typedef int (*toupper_t)(int);
14 14
15static int affs_toupper(int ch); 15static int affs_toupper(int ch);
16static int affs_hash_dentry(struct dentry *, struct qstr *); 16static int affs_hash_dentry(struct dentry *, struct qstr *);
17static int affs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 17static int affs_compare_dentry(const struct dentry *parent,
18 const struct inode *pinode,
19 const struct dentry *dentry, const struct inode *inode,
20 unsigned int len, const char *str, const struct qstr *name);
18static int affs_intl_toupper(int ch); 21static int affs_intl_toupper(int ch);
19static int affs_intl_hash_dentry(struct dentry *, struct qstr *); 22static int affs_intl_hash_dentry(struct dentry *, struct qstr *);
20static int affs_intl_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 23static int affs_intl_compare_dentry(const struct dentry *parent,
24 const struct inode *pinode,
25 const struct dentry *dentry, const struct inode *inode,
26 unsigned int len, const char *str, const struct qstr *name);
21 27
22const struct dentry_operations affs_dentry_operations = { 28const struct dentry_operations affs_dentry_operations = {
23 .d_hash = affs_hash_dentry, 29 .d_hash = affs_hash_dentry,
@@ -88,29 +94,29 @@ affs_intl_hash_dentry(struct dentry *dentry, struct qstr *qstr)
88 return __affs_hash_dentry(dentry, qstr, affs_intl_toupper); 94 return __affs_hash_dentry(dentry, qstr, affs_intl_toupper);
89} 95}
90 96
91static inline int 97static inline int __affs_compare_dentry(unsigned int len,
92__affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b, toupper_t toupper) 98 const char *str, const struct qstr *name, toupper_t toupper)
93{ 99{
94 const u8 *aname = a->name; 100 const u8 *aname = str;
95 const u8 *bname = b->name; 101 const u8 *bname = name->name;
96 int len;
97 102
98 /* 'a' is the qstr of an already existing dentry, so the name 103 /*
99 * must be valid. 'b' must be validated first. 104 * 'str' is the name of an already existing dentry, so the name
105 * must be valid. 'name' must be validated first.
100 */ 106 */
101 107
102 if (affs_check_name(b->name,b->len)) 108 if (affs_check_name(name->name, name->len))
103 return 1; 109 return 1;
104 110
105 /* If the names are longer than the allowed 30 chars, 111 /*
112 * If the names are longer than the allowed 30 chars,
106 * the excess is ignored, so their length may differ. 113 * the excess is ignored, so their length may differ.
107 */ 114 */
108 len = a->len;
109 if (len >= 30) { 115 if (len >= 30) {
110 if (b->len < 30) 116 if (name->len < 30)
111 return 1; 117 return 1;
112 len = 30; 118 len = 30;
113 } else if (len != b->len) 119 } else if (len != name->len)
114 return 1; 120 return 1;
115 121
116 for (; len > 0; len--) 122 for (; len > 0; len--)
@@ -121,14 +127,18 @@ __affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b, tou
121} 127}
122 128
123static int 129static int
124affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 130affs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
131 const struct dentry *dentry, const struct inode *inode,
132 unsigned int len, const char *str, const struct qstr *name)
125{ 133{
126 return __affs_compare_dentry(dentry, a, b, affs_toupper); 134 return __affs_compare_dentry(len, str, name, affs_toupper);
127} 135}
128static int 136static int
129affs_intl_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 137affs_intl_compare_dentry(const struct dentry *parent,const struct inode *pinode,
138 const struct dentry *dentry, const struct inode *inode,
139 unsigned int len, const char *str, const struct qstr *name)
130{ 140{
131 return __affs_compare_dentry(dentry, a, b, affs_intl_toupper); 141 return __affs_compare_dentry(len, str, name, affs_intl_toupper);
132} 142}
133 143
134/* 144/*