diff options
Diffstat (limited to 'fs/dcache.c')
| -rw-r--r-- | fs/dcache.c | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 4d13bf50b7b1..83293be48149 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -1332,31 +1332,13 @@ EXPORT_SYMBOL(d_add_ci); | |||
| 1332 | * d_lookup - search for a dentry | 1332 | * d_lookup - search for a dentry |
| 1333 | * @parent: parent dentry | 1333 | * @parent: parent dentry |
| 1334 | * @name: qstr of name we wish to find | 1334 | * @name: qstr of name we wish to find |
| 1335 | * Returns: dentry, or NULL | ||
| 1335 | * | 1336 | * |
| 1336 | * Searches the children of the parent dentry for the name in question. If | 1337 | * d_lookup searches the children of the parent dentry for the name in |
| 1337 | * the dentry is found its reference count is incremented and the dentry | 1338 | * question. If the dentry is found its reference count is incremented and the |
| 1338 | * is returned. The caller must use dput to free the entry when it has | 1339 | * dentry is returned. The caller must use dput to free the entry when it has |
| 1339 | * finished using it. %NULL is returned on failure. | 1340 | * finished using it. %NULL is returned if the dentry does not exist. |
| 1340 | * | ||
| 1341 | * __d_lookup is dcache_lock free. The hash list is protected using RCU. | ||
| 1342 | * Memory barriers are used while updating and doing lockless traversal. | ||
| 1343 | * To avoid races with d_move while rename is happening, d_lock is used. | ||
| 1344 | * | ||
| 1345 | * Overflows in memcmp(), while d_move, are avoided by keeping the length | ||
| 1346 | * and name pointer in one structure pointed by d_qstr. | ||
| 1347 | * | ||
| 1348 | * rcu_read_lock() and rcu_read_unlock() are used to disable preemption while | ||
| 1349 | * lookup is going on. | ||
| 1350 | * | ||
| 1351 | * The dentry unused LRU is not updated even if lookup finds the required dentry | ||
| 1352 | * in there. It is updated in places such as prune_dcache, shrink_dcache_sb, | ||
| 1353 | * select_parent and __dget_locked. This laziness saves lookup from dcache_lock | ||
| 1354 | * acquisition. | ||
| 1355 | * | ||
| 1356 | * d_lookup() is protected against the concurrent renames in some unrelated | ||
| 1357 | * directory using the seqlockt_t rename_lock. | ||
| 1358 | */ | 1341 | */ |
| 1359 | |||
| 1360 | struct dentry * d_lookup(struct dentry * parent, struct qstr * name) | 1342 | struct dentry * d_lookup(struct dentry * parent, struct qstr * name) |
| 1361 | { | 1343 | { |
| 1362 | struct dentry * dentry = NULL; | 1344 | struct dentry * dentry = NULL; |
| @@ -1372,6 +1354,21 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name) | |||
| 1372 | } | 1354 | } |
| 1373 | EXPORT_SYMBOL(d_lookup); | 1355 | EXPORT_SYMBOL(d_lookup); |
| 1374 | 1356 | ||
| 1357 | /* | ||
| 1358 | * __d_lookup - search for a dentry (racy) | ||
| 1359 | * @parent: parent dentry | ||
| 1360 | * @name: qstr of name we wish to find | ||
| 1361 | * Returns: dentry, or NULL | ||
| 1362 | * | ||
| 1363 | * __d_lookup is like d_lookup, however it may (rarely) return a | ||
| 1364 | * false-negative result due to unrelated rename activity. | ||
| 1365 | * | ||
| 1366 | * __d_lookup is slightly faster by avoiding rename_lock read seqlock, | ||
| 1367 | * however it must be used carefully, eg. with a following d_lookup in | ||
| 1368 | * the case of failure. | ||
| 1369 | * | ||
| 1370 | * __d_lookup callers must be commented. | ||
| 1371 | */ | ||
| 1375 | struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) | 1372 | struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) |
| 1376 | { | 1373 | { |
| 1377 | unsigned int len = name->len; | 1374 | unsigned int len = name->len; |
| @@ -1382,6 +1379,19 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) | |||
| 1382 | struct hlist_node *node; | 1379 | struct hlist_node *node; |
| 1383 | struct dentry *dentry; | 1380 | struct dentry *dentry; |
| 1384 | 1381 | ||
| 1382 | /* | ||
| 1383 | * The hash list is protected using RCU. | ||
| 1384 | * | ||
| 1385 | * Take d_lock when comparing a candidate dentry, to avoid races | ||
| 1386 | * with d_move(). | ||
| 1387 | * | ||
| 1388 | * It is possible that concurrent renames can mess up our list | ||
| 1389 | * walk here and result in missing our dentry, resulting in the | ||
| 1390 | * false-negative result. d_lookup() protects against concurrent | ||
| 1391 | * renames using rename_lock seqlock. | ||
| 1392 | * | ||
| 1393 | * See Documentation/vfs/dcache-locking.txt for more details. | ||
| 1394 | */ | ||
| 1385 | rcu_read_lock(); | 1395 | rcu_read_lock(); |
| 1386 | 1396 | ||
| 1387 | hlist_for_each_entry_rcu(dentry, node, head, d_hash) { | 1397 | hlist_for_each_entry_rcu(dentry, node, head, d_hash) { |
| @@ -1396,8 +1406,8 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) | |||
| 1396 | 1406 | ||
| 1397 | /* | 1407 | /* |
| 1398 | * Recheck the dentry after taking the lock - d_move may have | 1408 | * Recheck the dentry after taking the lock - d_move may have |
| 1399 | * changed things. Don't bother checking the hash because we're | 1409 | * changed things. Don't bother checking the hash because |
| 1400 | * about to compare the whole name anyway. | 1410 | * we're about to compare the whole name anyway. |
| 1401 | */ | 1411 | */ |
| 1402 | if (dentry->d_parent != parent) | 1412 | if (dentry->d_parent != parent) |
| 1403 | goto next; | 1413 | goto next; |
| @@ -1925,7 +1935,7 @@ static int prepend_path(const struct path *path, struct path *root, | |||
| 1925 | bool slash = false; | 1935 | bool slash = false; |
| 1926 | int error = 0; | 1936 | int error = 0; |
| 1927 | 1937 | ||
| 1928 | spin_lock(&vfsmount_lock); | 1938 | br_read_lock(vfsmount_lock); |
| 1929 | while (dentry != root->dentry || vfsmnt != root->mnt) { | 1939 | while (dentry != root->dentry || vfsmnt != root->mnt) { |
| 1930 | struct dentry * parent; | 1940 | struct dentry * parent; |
| 1931 | 1941 | ||
| @@ -1954,7 +1964,7 @@ out: | |||
| 1954 | if (!error && !slash) | 1964 | if (!error && !slash) |
| 1955 | error = prepend(buffer, buflen, "/", 1); | 1965 | error = prepend(buffer, buflen, "/", 1); |
| 1956 | 1966 | ||
| 1957 | spin_unlock(&vfsmount_lock); | 1967 | br_read_unlock(vfsmount_lock); |
| 1958 | return error; | 1968 | return error; |
| 1959 | 1969 | ||
| 1960 | global_root: | 1970 | global_root: |
| @@ -2292,11 +2302,12 @@ int path_is_under(struct path *path1, struct path *path2) | |||
| 2292 | struct vfsmount *mnt = path1->mnt; | 2302 | struct vfsmount *mnt = path1->mnt; |
| 2293 | struct dentry *dentry = path1->dentry; | 2303 | struct dentry *dentry = path1->dentry; |
| 2294 | int res; | 2304 | int res; |
| 2295 | spin_lock(&vfsmount_lock); | 2305 | |
| 2306 | br_read_lock(vfsmount_lock); | ||
| 2296 | if (mnt != path2->mnt) { | 2307 | if (mnt != path2->mnt) { |
| 2297 | for (;;) { | 2308 | for (;;) { |
| 2298 | if (mnt->mnt_parent == mnt) { | 2309 | if (mnt->mnt_parent == mnt) { |
| 2299 | spin_unlock(&vfsmount_lock); | 2310 | br_read_unlock(vfsmount_lock); |
| 2300 | return 0; | 2311 | return 0; |
| 2301 | } | 2312 | } |
| 2302 | if (mnt->mnt_parent == path2->mnt) | 2313 | if (mnt->mnt_parent == path2->mnt) |
| @@ -2306,7 +2317,7 @@ int path_is_under(struct path *path1, struct path *path2) | |||
| 2306 | dentry = mnt->mnt_mountpoint; | 2317 | dentry = mnt->mnt_mountpoint; |
| 2307 | } | 2318 | } |
| 2308 | res = is_subdir(dentry, path2->dentry); | 2319 | res = is_subdir(dentry, path2->dentry); |
| 2309 | spin_unlock(&vfsmount_lock); | 2320 | br_read_unlock(vfsmount_lock); |
| 2310 | return res; | 2321 | return res; |
| 2311 | } | 2322 | } |
| 2312 | EXPORT_SYMBOL(path_is_under); | 2323 | EXPORT_SYMBOL(path_is_under); |
