aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-12-11 12:10:10 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-12-20 18:50:05 -0500
commitc6a9428401c00a27d3c17264934d14e284570c97 (patch)
tree84d5e256e78615794a694cf5b6af80a92e8d01f9
parent5d18f8133cad85ccbb7fa6fd351d75025da32504 (diff)
vfs: fix renameat to retry on ESTALE errors
...as always, rename is the messiest of the bunch. We have to track whether to retry or not via a separate flag since the error handling is already quite complex. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namei.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 8a262c2efff8..43a97ee1d4c8 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3840,15 +3840,17 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
3840 struct nameidata oldnd, newnd; 3840 struct nameidata oldnd, newnd;
3841 struct filename *from; 3841 struct filename *from;
3842 struct filename *to; 3842 struct filename *to;
3843 unsigned int lookup_flags = 0;
3844 bool should_retry = false;
3843 int error; 3845 int error;
3844 3846retry:
3845 from = user_path_parent(olddfd, oldname, &oldnd, 0); 3847 from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags);
3846 if (IS_ERR(from)) { 3848 if (IS_ERR(from)) {
3847 error = PTR_ERR(from); 3849 error = PTR_ERR(from);
3848 goto exit; 3850 goto exit;
3849 } 3851 }
3850 3852
3851 to = user_path_parent(newdfd, newname, &newnd, 0); 3853 to = user_path_parent(newdfd, newname, &newnd, lookup_flags);
3852 if (IS_ERR(to)) { 3854 if (IS_ERR(to)) {
3853 error = PTR_ERR(to); 3855 error = PTR_ERR(to);
3854 goto exit1; 3856 goto exit1;
@@ -3920,11 +3922,18 @@ exit3:
3920 unlock_rename(new_dir, old_dir); 3922 unlock_rename(new_dir, old_dir);
3921 mnt_drop_write(oldnd.path.mnt); 3923 mnt_drop_write(oldnd.path.mnt);
3922exit2: 3924exit2:
3925 if (retry_estale(error, lookup_flags))
3926 should_retry = true;
3923 path_put(&newnd.path); 3927 path_put(&newnd.path);
3924 putname(to); 3928 putname(to);
3925exit1: 3929exit1:
3926 path_put(&oldnd.path); 3930 path_put(&oldnd.path);
3927 putname(from); 3931 putname(from);
3932 if (should_retry) {
3933 should_retry = false;
3934 lookup_flags |= LOOKUP_REVAL;
3935 goto retry;
3936 }
3928exit: 3937exit:
3929 return error; 3938 return error;
3930} 3939}