diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-04 14:44:37 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-14 09:15:26 -0400 |
commit | 951361f954596bd134d4270df834f47d151f98a6 (patch) | |
tree | 719622960d2ec96473636333ddc8b85ab8151505 /fs/namei.c | |
parent | a7472baba22dd5d68580f528374f93421b33667e (diff) | |
download | lwn-951361f954596bd134d4270df834f47d151f98a6.tar.gz lwn-951361f954596bd134d4270df834f47d151f98a6.zip |
get rid of the last LOOKUP_RCU dependencies in link_path_walk()
New helper: terminate_walk(). An error has happened during pathname
resolution and we either drop nd->path or terminate RCU, depending
the mode we had been in. After that, nd is essentially empty.
Switch link_path_walk() to using that for cleanup.
Now the top-level logics in link_path_walk() is back to sanity. RCU
dependencies are in the lower-level functions.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/namei.c b/fs/namei.c index 53bba7c1a520..85f6e39b4034 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1343,6 +1343,18 @@ static inline int handle_dots(struct nameidata *nd, int type) return 0; } +static void terminate_walk(struct nameidata *nd) +{ + if (!(nd->flags & LOOKUP_RCU)) { + path_put(&nd->path); + } else { + nd->flags &= ~LOOKUP_RCU; + nd->root.mnt = NULL; + rcu_read_unlock(); + br_read_unlock(vfsmount_lock); + } +} + /* * Name resolution. * This is the basic name resolution function, turning a pathname into @@ -1482,14 +1494,7 @@ lookup_parent: nd->last_type = type; return 0; } - if (!(nd->flags & LOOKUP_RCU)) - path_put(&nd->path); - if (nd->flags & LOOKUP_RCU) { - nd->flags &= ~LOOKUP_RCU; - nd->root.mnt = NULL; - rcu_read_unlock(); - br_read_unlock(vfsmount_lock); - } + terminate_walk(nd); return err; } |