diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-04 14:35:59 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-14 09:15:25 -0400 |
commit | ef7562d5283a91da3ba5c14de3221f47b7f08823 (patch) | |
tree | bf517d1a2c205ad475480c958449b2bc25de61b4 /fs/namei.c | |
parent | 4455ca6223cc59cbc0a75f4be8bce9e84cc0d6b8 (diff) |
make handle_dots() leave RCU mode on error
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/fs/namei.c b/fs/namei.c index f09887a45831..ea14bfb04785 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1052,7 +1052,7 @@ static int follow_dotdot_rcu(struct nameidata *nd) | |||
1052 | 1052 | ||
1053 | seq = read_seqcount_begin(&parent->d_seq); | 1053 | seq = read_seqcount_begin(&parent->d_seq); |
1054 | if (read_seqcount_retry(&old->d_seq, nd->seq)) | 1054 | if (read_seqcount_retry(&old->d_seq, nd->seq)) |
1055 | return -ECHILD; | 1055 | goto failed; |
1056 | inode = parent->d_inode; | 1056 | inode = parent->d_inode; |
1057 | nd->path.dentry = parent; | 1057 | nd->path.dentry = parent; |
1058 | nd->seq = seq; | 1058 | nd->seq = seq; |
@@ -1065,8 +1065,14 @@ static int follow_dotdot_rcu(struct nameidata *nd) | |||
1065 | } | 1065 | } |
1066 | __follow_mount_rcu(nd, &nd->path, &inode, true); | 1066 | __follow_mount_rcu(nd, &nd->path, &inode, true); |
1067 | nd->inode = inode; | 1067 | nd->inode = inode; |
1068 | |||
1069 | return 0; | 1068 | return 0; |
1069 | |||
1070 | failed: | ||
1071 | nd->flags &= ~LOOKUP_RCU; | ||
1072 | nd->root.mnt = NULL; | ||
1073 | rcu_read_unlock(); | ||
1074 | br_read_unlock(vfsmount_lock); | ||
1075 | return -ECHILD; | ||
1070 | } | 1076 | } |
1071 | 1077 | ||
1072 | /* | 1078 | /* |
@@ -1405,9 +1411,8 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1405 | * parent relationships. | 1411 | * parent relationships. |
1406 | */ | 1412 | */ |
1407 | if (unlikely(type != LAST_NORM)) { | 1413 | if (unlikely(type != LAST_NORM)) { |
1408 | err = handle_dots(nd, type); | 1414 | if (handle_dots(nd, type)) |
1409 | if (err) | 1415 | return -ECHILD; |
1410 | goto return_err; | ||
1411 | continue; | 1416 | continue; |
1412 | } | 1417 | } |
1413 | 1418 | ||
@@ -1441,12 +1446,8 @@ last_component: | |||
1441 | nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; | 1446 | nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; |
1442 | if (lookup_flags & LOOKUP_PARENT) | 1447 | if (lookup_flags & LOOKUP_PARENT) |
1443 | goto lookup_parent; | 1448 | goto lookup_parent; |
1444 | if (unlikely(type != LAST_NORM)) { | 1449 | if (unlikely(type != LAST_NORM)) |
1445 | err = handle_dots(nd, type); | 1450 | return handle_dots(nd, type); |
1446 | if (err) | ||
1447 | goto return_err; | ||
1448 | return 0; | ||
1449 | } | ||
1450 | err = do_lookup(nd, &this, &next, &inode); | 1451 | err = do_lookup(nd, &this, &next, &inode); |
1451 | if (err) | 1452 | if (err) |
1452 | break; | 1453 | break; |