|
@@ -181,6 +181,11 @@ static bool ovl_type_origin(struct dentry *dentry)
|
|
return OVL_TYPE_ORIGIN(ovl_path_type(dentry));
|
|
return OVL_TYPE_ORIGIN(ovl_path_type(dentry));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool ovl_may_have_whiteouts(struct dentry *dentry)
|
|
|
|
+{
|
|
|
|
+ return ovl_test_flag(OVL_WHITEOUTS, d_inode(dentry));
|
|
|
|
+}
|
|
|
|
+
|
|
static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
|
|
static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
|
|
struct cattr *attr, struct dentry *hardlink)
|
|
struct cattr *attr, struct dentry *hardlink)
|
|
{
|
|
{
|
|
@@ -697,8 +702,9 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir)
|
|
struct dentry *opaquedir = NULL;
|
|
struct dentry *opaquedir = NULL;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
- /* Redirect dir can be !ovl_lower_positive && OVL_TYPE_MERGE */
|
|
|
|
- if (is_dir && ovl_dentry_get_redirect(dentry)) {
|
|
|
|
|
|
+ /* Redirect/origin dir can be !ovl_lower_positive && not clean */
|
|
|
|
+ if (is_dir && (ovl_dentry_get_redirect(dentry) ||
|
|
|
|
+ ovl_may_have_whiteouts(dentry))) {
|
|
opaquedir = ovl_check_empty_and_clear(dentry);
|
|
opaquedir = ovl_check_empty_and_clear(dentry);
|
|
err = PTR_ERR(opaquedir);
|
|
err = PTR_ERR(opaquedir);
|
|
if (IS_ERR(opaquedir))
|
|
if (IS_ERR(opaquedir))
|
|
@@ -945,7 +951,8 @@ 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 && new_is_dir && ovl_type_merge_or_lower(new)) {
|
|
|
|
|
|
+ if (overwrite && new_is_dir && (ovl_type_merge_or_lower(new) ||
|
|
|
|
+ ovl_may_have_whiteouts(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)) {
|