diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-03-06 14:20:52 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-03-14 00:15:46 -0400 |
commit | 949a852e46dda07caaa0ff02e181f55d24e3ebf8 (patch) | |
tree | 7f2d5177638fb4fd6257a2e2571a3c556de08ce9 | |
parent | e3c13928086f1ed3620329b9fff678df2294d327 (diff) |
namei: teach lookup_slow() to skip revalidate
... and make mountpoint_last() use it. That makes all
candidates for lookup with parent locked shared go
through lookup_slow().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/namei.c | 58 | ||||
-rw-r--r-- | include/linux/namei.h | 1 |
2 files changed, 36 insertions, 23 deletions
diff --git a/fs/namei.c b/fs/namei.c index cb70a817d439..dbb8ec1a2006 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1605,7 +1605,29 @@ static struct dentry *lookup_slow(const struct qstr *name, | |||
1605 | { | 1605 | { |
1606 | struct dentry *dentry; | 1606 | struct dentry *dentry; |
1607 | inode_lock(dir->d_inode); | 1607 | inode_lock(dir->d_inode); |
1608 | dentry = __lookup_hash(name, dir, flags); | 1608 | dentry = d_lookup(dir, name); |
1609 | if (unlikely(dentry)) { | ||
1610 | if ((dentry->d_flags & DCACHE_OP_REVALIDATE) && | ||
1611 | !(flags & LOOKUP_NO_REVAL)) { | ||
1612 | int error = d_revalidate(dentry, flags); | ||
1613 | if (unlikely(error <= 0)) { | ||
1614 | if (!error) | ||
1615 | d_invalidate(dentry); | ||
1616 | dput(dentry); | ||
1617 | dentry = ERR_PTR(error); | ||
1618 | } | ||
1619 | } | ||
1620 | if (dentry) { | ||
1621 | inode_unlock(dir->d_inode); | ||
1622 | return dentry; | ||
1623 | } | ||
1624 | } | ||
1625 | dentry = d_alloc(dir, name); | ||
1626 | if (unlikely(!dentry)) { | ||
1627 | inode_unlock(dir->d_inode); | ||
1628 | return ERR_PTR(-ENOMEM); | ||
1629 | } | ||
1630 | dentry = lookup_real(dir->d_inode, dentry, flags); | ||
1609 | inode_unlock(dir->d_inode); | 1631 | inode_unlock(dir->d_inode); |
1610 | return dentry; | 1632 | return dentry; |
1611 | } | 1633 | } |
@@ -2425,31 +2447,21 @@ mountpoint_last(struct nameidata *nd, struct path *path) | |||
2425 | if (error) | 2447 | if (error) |
2426 | return error; | 2448 | return error; |
2427 | dentry = dget(nd->path.dentry); | 2449 | dentry = dget(nd->path.dentry); |
2428 | goto done; | 2450 | } else { |
2429 | } | 2451 | dentry = d_lookup(dir, &nd->last); |
2430 | |||
2431 | inode_lock(dir->d_inode); | ||
2432 | dentry = d_lookup(dir, &nd->last); | ||
2433 | if (!dentry) { | ||
2434 | /* | ||
2435 | * No cached dentry. Mounted dentries are pinned in the cache, | ||
2436 | * so that means that this dentry is probably a symlink or the | ||
2437 | * path doesn't actually point to a mounted dentry. | ||
2438 | */ | ||
2439 | dentry = d_alloc(dir, &nd->last); | ||
2440 | if (!dentry) { | 2452 | if (!dentry) { |
2441 | inode_unlock(dir->d_inode); | 2453 | /* |
2442 | return -ENOMEM; | 2454 | * No cached dentry. Mounted dentries are pinned in the |
2443 | } | 2455 | * cache, so that means that this dentry is probably |
2444 | dentry = lookup_real(dir->d_inode, dentry, nd->flags); | 2456 | * a symlink or the path doesn't actually point |
2445 | if (IS_ERR(dentry)) { | 2457 | * to a mounted dentry. |
2446 | inode_unlock(dir->d_inode); | 2458 | */ |
2447 | return PTR_ERR(dentry); | 2459 | dentry = lookup_slow(&nd->last, dir, |
2460 | nd->flags | LOOKUP_NO_REVAL); | ||
2461 | if (IS_ERR(dentry)) | ||
2462 | return PTR_ERR(dentry); | ||
2448 | } | 2463 | } |
2449 | } | 2464 | } |
2450 | inode_unlock(dir->d_inode); | ||
2451 | |||
2452 | done: | ||
2453 | if (d_is_negative(dentry)) { | 2465 | if (d_is_negative(dentry)) { |
2454 | dput(dentry); | 2466 | dput(dentry); |
2455 | return -ENOENT; | 2467 | return -ENOENT; |
diff --git a/include/linux/namei.h b/include/linux/namei.h index d0f25d81b46a..77d01700daf7 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -31,6 +31,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; | |||
31 | #define LOOKUP_PARENT 0x0010 | 31 | #define LOOKUP_PARENT 0x0010 |
32 | #define LOOKUP_REVAL 0x0020 | 32 | #define LOOKUP_REVAL 0x0020 |
33 | #define LOOKUP_RCU 0x0040 | 33 | #define LOOKUP_RCU 0x0040 |
34 | #define LOOKUP_NO_REVAL 0x0080 | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Intent data | 37 | * Intent data |