Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+12 -2
+12 -2
fs/dcache.c
··· 1350 1350 list_for_each_entry(alias, &inode->i_dentry, d_alias) { 1351 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 1358 if (qstr->hash != hash) 1354 1359 continue; 1355 1360 if (alias->d_parent != entry->d_parent) ··· 2318 2313 } 2319 2314 parent = dentry->d_parent; 2320 2315 prefetch(parent); 2316 + spin_lock(&dentry->d_lock); 2321 2317 error = prepend_name(buffer, buflen, &dentry->d_name); 2318 + spin_unlock(&dentry->d_lock); 2322 2319 if (!error) 2323 2320 error = prepend(buffer, buflen, "/", 1); 2324 2321 if (error) ··· 2522 2515 2523 2516 while (!IS_ROOT(dentry)) { 2524 2517 struct dentry *parent = dentry->d_parent; 2518 + int error; 2525 2519 2526 2520 prefetch(parent); 2527 - if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) || 2528 - (prepend(&end, &buflen, "/", 1) != 0)) 2521 + spin_lock(&dentry->d_lock); 2522 + error = prepend_name(&end, &buflen, &dentry->d_name); 2523 + spin_unlock(&dentry->d_lock); 2524 + if (error != 0 || prepend(&end, &buflen, "/", 1) != 0) 2529 2525 goto Elong; 2530 2526 2531 2527 retval = end;