diff options
author | Nick Piggin <npiggin@kernel.dk> | 2010-08-17 14:37:34 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-18 08:35:47 -0400 |
commit | b04f784e5d19ed58892833dae845738972cea260 (patch) | |
tree | 6060e063b5a51461fd60630d57318778fe987148 /fs/namei.c | |
parent | 2a4419b5b2a77f3f4537c14f7ad7df95770655dd (diff) |
fs: remove extra lookup in __lookup_hash
fs: remove extra lookup in __lookup_hash
Optimize lookup for create operations, where no dentry should often be
common-case. In cases where it is not, such as unlink, the added overhead
is much smaller than the removed.
Also, move comments about __d_lookup racyness to the __d_lookup call site.
d_lookup is intuitive; __d_lookup is what needs commenting. So in that same
vein, add kerneldoc comments to __d_lookup and clean up some of the comments:
- We are interested in how the RCU lookup works here, particularly with
renames. Make that explicit, and point to the document where it is explained
in more detail.
- RCU is pretty standard now, and macros make implementations pretty mindless.
If we want to know about RCU barrier details, we look in RCU code.
- Delete some boring legacy comments because we don't care much about how the
code used to work, more about the interesting parts of how it works now. So
comments about lazy LRU may be interesting, but would better be done in the
LRU or refcount management code.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 32 |
1 files changed, 16 insertions, 16 deletions
diff --git a/fs/namei.c b/fs/namei.c index b815a4d2e1d6..11de7c39ff76 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -735,6 +735,11 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
735 | return err; | 735 | return err; |
736 | } | 736 | } |
737 | 737 | ||
738 | /* | ||
739 | * Rename seqlock is not required here because in the off chance | ||
740 | * of a false negative due to a concurrent rename, we're going to | ||
741 | * do the non-racy lookup, below. | ||
742 | */ | ||
738 | dentry = __d_lookup(nd->path.dentry, name); | 743 | dentry = __d_lookup(nd->path.dentry, name); |
739 | if (!dentry) | 744 | if (!dentry) |
740 | goto need_lookup; | 745 | goto need_lookup; |
@@ -754,17 +759,13 @@ need_lookup: | |||
754 | mutex_lock(&dir->i_mutex); | 759 | mutex_lock(&dir->i_mutex); |
755 | /* | 760 | /* |
756 | * First re-do the cached lookup just in case it was created | 761 | * First re-do the cached lookup just in case it was created |
757 | * while we waited for the directory semaphore.. | 762 | * while we waited for the directory semaphore, or the first |
758 | * | 763 | * lookup failed due to an unrelated rename. |
759 | * FIXME! This could use version numbering or similar to | ||
760 | * avoid unnecessary cache lookups. | ||
761 | * | ||
762 | * The "dcache_lock" is purely to protect the RCU list walker | ||
763 | * from concurrent renames at this point (we mustn't get false | ||
764 | * negatives from the RCU list walk here, unlike the optimistic | ||
765 | * fast walk). | ||
766 | * | 764 | * |
767 | * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup | 765 | * This could use version numbering or similar to avoid unnecessary |
766 | * cache lookups, but then we'd have to do the first lookup in the | ||
767 | * non-racy way. However in the common case here, everything should | ||
768 | * be hot in cache, so would it be a big win? | ||
768 | */ | 769 | */ |
769 | dentry = d_lookup(parent, name); | 770 | dentry = d_lookup(parent, name); |
770 | if (likely(!dentry)) { | 771 | if (likely(!dentry)) { |
@@ -1136,13 +1137,12 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
1136 | goto out; | 1137 | goto out; |
1137 | } | 1138 | } |
1138 | 1139 | ||
1139 | dentry = __d_lookup(base, name); | 1140 | /* |
1140 | 1141 | * Don't bother with __d_lookup: callers are for creat as | |
1141 | /* lockess __d_lookup may fail due to concurrent d_move() | 1142 | * well as unlink, so a lot of the time it would cost |
1142 | * in some unrelated directory, so try with d_lookup | 1143 | * a double lookup. |
1143 | */ | 1144 | */ |
1144 | if (!dentry) | 1145 | dentry = d_lookup(base, name); |
1145 | dentry = d_lookup(base, name); | ||
1146 | 1146 | ||
1147 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) | 1147 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) |
1148 | dentry = do_revalidate(dentry, nd); | 1148 | dentry = do_revalidate(dentry, nd); |