|
@@ -761,13 +761,18 @@ static int ovl_rmdir(struct inode *dir, struct dentry *dentry)
|
|
return ovl_do_remove(dentry, true);
|
|
return ovl_do_remove(dentry, true);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool ovl_type_merge_or_lower(struct dentry *dentry)
|
|
|
|
+{
|
|
|
|
+ enum ovl_path_type type = ovl_path_type(dentry);
|
|
|
|
+
|
|
|
|
+ return OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type);
|
|
|
|
+}
|
|
|
|
+
|
|
static int ovl_rename(struct inode *olddir, struct dentry *old,
|
|
static int ovl_rename(struct inode *olddir, struct dentry *old,
|
|
struct inode *newdir, struct dentry *new,
|
|
struct inode *newdir, struct dentry *new,
|
|
unsigned int flags)
|
|
unsigned int flags)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
- enum ovl_path_type old_type;
|
|
|
|
- enum ovl_path_type new_type;
|
|
|
|
struct dentry *old_upperdir;
|
|
struct dentry *old_upperdir;
|
|
struct dentry *new_upperdir;
|
|
struct dentry *new_upperdir;
|
|
struct dentry *olddentry;
|
|
struct dentry *olddentry;
|
|
@@ -778,7 +783,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
|
|
bool cleanup_whiteout = false;
|
|
bool cleanup_whiteout = false;
|
|
bool overwrite = !(flags & RENAME_EXCHANGE);
|
|
bool overwrite = !(flags & RENAME_EXCHANGE);
|
|
bool is_dir = d_is_dir(old);
|
|
bool is_dir = d_is_dir(old);
|
|
- bool new_is_dir = false;
|
|
|
|
|
|
+ bool new_is_dir = d_is_dir(new);
|
|
struct dentry *opaquedir = NULL;
|
|
struct dentry *opaquedir = NULL;
|
|
const struct cred *old_cred = NULL;
|
|
const struct cred *old_cred = NULL;
|
|
|
|
|
|
@@ -789,22 +794,11 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
|
|
flags &= ~RENAME_NOREPLACE;
|
|
flags &= ~RENAME_NOREPLACE;
|
|
|
|
|
|
/* Don't copy up directory trees */
|
|
/* Don't copy up directory trees */
|
|
- old_type = ovl_path_type(old);
|
|
|
|
err = -EXDEV;
|
|
err = -EXDEV;
|
|
- if (OVL_TYPE_MERGE_OR_LOWER(old_type) && is_dir)
|
|
|
|
|
|
+ if (is_dir && ovl_type_merge_or_lower(old))
|
|
|
|
+ goto out;
|
|
|
|
+ if (!overwrite && new_is_dir && ovl_type_merge_or_lower(new))
|
|
goto out;
|
|
goto out;
|
|
-
|
|
|
|
- if (new->d_inode) {
|
|
|
|
- if (d_is_dir(new))
|
|
|
|
- new_is_dir = true;
|
|
|
|
-
|
|
|
|
- new_type = ovl_path_type(new);
|
|
|
|
- err = -EXDEV;
|
|
|
|
- if (!overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir)
|
|
|
|
- goto out;
|
|
|
|
- } else {
|
|
|
|
- new_type = __OVL_PATH_UPPER;
|
|
|
|
- }
|
|
|
|
|
|
|
|
err = ovl_want_write(old);
|
|
err = ovl_want_write(old);
|
|
if (err)
|
|
if (err)
|
|
@@ -828,7 +822,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
|
|
|
|
|
|
old_cred = ovl_override_creds(old->d_sb);
|
|
old_cred = ovl_override_creds(old->d_sb);
|
|
|
|
|
|
- if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
|
|
|
|
|
|
+ if (overwrite && new_is_dir && ovl_type_merge_or_lower(new)) {
|
|
opaquedir = ovl_check_empty_and_clear(new);
|
|
opaquedir = ovl_check_empty_and_clear(new);
|
|
err = PTR_ERR(opaquedir);
|
|
err = PTR_ERR(opaquedir);
|
|
if (IS_ERR(opaquedir)) {
|
|
if (IS_ERR(opaquedir)) {
|