aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/dcache.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 92099f61bc64..a7675e0109f0 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -192,6 +192,7 @@ static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char
192 192
193static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount) 193static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
194{ 194{
195 const unsigned char *cs;
195 /* 196 /*
196 * Be careful about RCU walk racing with rename: 197 * Be careful about RCU walk racing with rename:
197 * use ACCESS_ONCE to fetch the name pointer. 198 * use ACCESS_ONCE to fetch the name pointer.
@@ -208,7 +209,9 @@ static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *c
208 * early because the data cannot match (there can 209 * early because the data cannot match (there can
209 * be no NUL in the ct/tcount data) 210 * be no NUL in the ct/tcount data)
210 */ 211 */
211 return dentry_string_cmp(ACCESS_ONCE(dentry->d_name.name), ct, tcount); 212 cs = ACCESS_ONCE(dentry->d_name.name);
213 smp_read_barrier_depends();
214 return dentry_string_cmp(cs, ct, tcount);
212} 215}
213 216
214static void __d_free(struct rcu_head *head) 217static void __d_free(struct rcu_head *head)
@@ -1271,6 +1274,13 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
1271 if (!dentry) 1274 if (!dentry)
1272 return NULL; 1275 return NULL;
1273 1276
1277 /*
1278 * We guarantee that the inline name is always NUL-terminated.
1279 * This way the memcpy() done by the name switching in rename
1280 * will still always have a NUL at the end, even if we might
1281 * be overwriting an internal NUL character
1282 */
1283 dentry->d_iname[DNAME_INLINE_LEN-1] = 0;
1274 if (name->len > DNAME_INLINE_LEN-1) { 1284 if (name->len > DNAME_INLINE_LEN-1) {
1275 dname = kmalloc(name->len + 1, GFP_KERNEL); 1285 dname = kmalloc(name->len + 1, GFP_KERNEL);
1276 if (!dname) { 1286 if (!dname) {
@@ -1280,13 +1290,16 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
1280 } else { 1290 } else {
1281 dname = dentry->d_iname; 1291 dname = dentry->d_iname;
1282 } 1292 }
1283 dentry->d_name.name = dname;
1284 1293
1285 dentry->d_name.len = name->len; 1294 dentry->d_name.len = name->len;
1286 dentry->d_name.hash = name->hash; 1295 dentry->d_name.hash = name->hash;
1287 memcpy(dname, name->name, name->len); 1296 memcpy(dname, name->name, name->len);
1288 dname[name->len] = 0; 1297 dname[name->len] = 0;
1289 1298
1299 /* Make sure we always see the terminating NUL character */
1300 smp_wmb();
1301 dentry->d_name.name = dname;
1302
1290 dentry->d_count = 1; 1303 dentry->d_count = 1;
1291 dentry->d_flags = 0; 1304 dentry->d_flags = 0;
1292 spin_lock_init(&dentry->d_lock); 1305 spin_lock_init(&dentry->d_lock);