aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:36 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:22 -0500
commit9abca36087288fe28de4749c71ca003d4b9e3ed0 (patch)
tree1d1b08bdcffb8f8a7be217ee1c017f5154f64f6a /fs/dcache.c
parentb23fb0a60379a95e10c671f646b259ea2558421e (diff)
fs: increase d_name lock coverage
Cover d_name with d_lock in more cases, where there may be concurrent modification to it. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index de38680ee0ed..a09f0771fd27 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1350,6 +1350,11 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
1350 list_for_each_entry(alias, &inode->i_dentry, d_alias) { 1350 list_for_each_entry(alias, &inode->i_dentry, d_alias) {
1351 struct qstr *qstr = &alias->d_name; 1351 struct qstr *qstr = &alias->d_name;
1352 1352
1353 /*
1354 * Don't need alias->d_lock here, because aliases with
1355 * d_parent == entry->d_parent are not subject to name or
1356 * parent changes, because the parent inode i_mutex is held.
1357 */
1353 if (qstr->hash != hash) 1358 if (qstr->hash != hash)
1354 continue; 1359 continue;
1355 if (alias->d_parent != entry->d_parent) 1360 if (alias->d_parent != entry->d_parent)
@@ -2313,7 +2318,9 @@ static int prepend_path(const struct path *path, struct path *root,
2313 } 2318 }
2314 parent = dentry->d_parent; 2319 parent = dentry->d_parent;
2315 prefetch(parent); 2320 prefetch(parent);
2321 spin_lock(&dentry->d_lock);
2316 error = prepend_name(buffer, buflen, &dentry->d_name); 2322 error = prepend_name(buffer, buflen, &dentry->d_name);
2323 spin_unlock(&dentry->d_lock);
2317 if (!error) 2324 if (!error)
2318 error = prepend(buffer, buflen, "/", 1); 2325 error = prepend(buffer, buflen, "/", 1);
2319 if (error) 2326 if (error)
@@ -2515,10 +2522,13 @@ static char *__dentry_path(struct dentry *dentry, char *buf, int buflen)
2515 2522
2516 while (!IS_ROOT(dentry)) { 2523 while (!IS_ROOT(dentry)) {
2517 struct dentry *parent = dentry->d_parent; 2524 struct dentry *parent = dentry->d_parent;
2525 int error;
2518 2526
2519 prefetch(parent); 2527 prefetch(parent);
2520 if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) || 2528 spin_lock(&dentry->d_lock);
2521 (prepend(&end, &buflen, "/", 1) != 0)) 2529 error = prepend_name(&end, &buflen, &dentry->d_name);
2530 spin_unlock(&dentry->d_lock);
2531 if (error != 0 || prepend(&end, &buflen, "/", 1) != 0)
2522 goto Elong; 2532 goto Elong;
2523 2533
2524 retval = end; 2534 retval = end;