|
@@ -505,6 +505,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
|
|
|
struct dentry *upper;
|
|
|
struct dentry *opaquedir = NULL;
|
|
|
int err;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
if (WARN_ON(!workdir))
|
|
|
return -EROFS;
|
|
@@ -534,46 +535,39 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
|
|
|
if (err)
|
|
|
goto out_dput;
|
|
|
|
|
|
- whiteout = ovl_whiteout(workdir, dentry);
|
|
|
- err = PTR_ERR(whiteout);
|
|
|
- if (IS_ERR(whiteout))
|
|
|
+ upper = lookup_one_len(dentry->d_name.name, upperdir,
|
|
|
+ dentry->d_name.len);
|
|
|
+ err = PTR_ERR(upper);
|
|
|
+ if (IS_ERR(upper))
|
|
|
goto out_unlock;
|
|
|
|
|
|
- upper = ovl_dentry_upper(dentry);
|
|
|
- if (!upper) {
|
|
|
- upper = lookup_one_len(dentry->d_name.name, upperdir,
|
|
|
- dentry->d_name.len);
|
|
|
- err = PTR_ERR(upper);
|
|
|
- if (IS_ERR(upper))
|
|
|
- goto kill_whiteout;
|
|
|
-
|
|
|
- err = ovl_do_rename(wdir, whiteout, udir, upper, 0);
|
|
|
- dput(upper);
|
|
|
- if (err)
|
|
|
- goto kill_whiteout;
|
|
|
- } else {
|
|
|
- int flags = 0;
|
|
|
+ err = -ESTALE;
|
|
|
+ if ((opaquedir && upper != opaquedir) ||
|
|
|
+ (!opaquedir && ovl_dentry_upper(dentry) &&
|
|
|
+ upper != ovl_dentry_upper(dentry))) {
|
|
|
+ goto out_dput_upper;
|
|
|
+ }
|
|
|
|
|
|
- if (opaquedir)
|
|
|
- upper = opaquedir;
|
|
|
- err = -ESTALE;
|
|
|
- if (upper->d_parent != upperdir)
|
|
|
- goto kill_whiteout;
|
|
|
+ whiteout = ovl_whiteout(workdir, dentry);
|
|
|
+ err = PTR_ERR(whiteout);
|
|
|
+ if (IS_ERR(whiteout))
|
|
|
+ goto out_dput_upper;
|
|
|
|
|
|
- if (is_dir)
|
|
|
- flags |= RENAME_EXCHANGE;
|
|
|
+ if (d_is_dir(upper))
|
|
|
+ flags = RENAME_EXCHANGE;
|
|
|
|
|
|
- err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
|
|
|
- if (err)
|
|
|
- goto kill_whiteout;
|
|
|
+ err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
|
|
|
+ if (err)
|
|
|
+ goto kill_whiteout;
|
|
|
+ if (flags)
|
|
|
+ ovl_cleanup(wdir, upper);
|
|
|
|
|
|
- if (is_dir)
|
|
|
- ovl_cleanup(wdir, upper);
|
|
|
- }
|
|
|
ovl_dentry_version_inc(dentry->d_parent);
|
|
|
out_d_drop:
|
|
|
d_drop(dentry);
|
|
|
dput(whiteout);
|
|
|
+out_dput_upper:
|
|
|
+ dput(upper);
|
|
|
out_unlock:
|
|
|
unlock_rename(workdir, upperdir);
|
|
|
out_dput:
|