Re: overlayfs v8 problems with whiteout links

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jordi Pujol <jordipujolp@xxxxxxxxx> writes:

> A Dimarts 26 Abril 2011 17:50:54, Miklos Szeredi va escriure:
>> It doesn't look like the correct fix, however.  Even though
>> ovl_dentry_lower() returns NULL, the lower file should normally exist.
> it solves the problem, but we should investigate why,
>
>> 
>> Please look a the ovl_do_lookup() logic: if oe->opaque is set to true,
>> then oe->lowerdentry will be set to NULL, even when the lower dentry
>> does actually exist.
>> 
>> So your patch might cover up the problem that you've been observing
>> (because it won't create the whiteouts in some cases), but it will
>> introduce another bug.
>> 
> Agree, the working line in this patch is checking for ovl_dentry_lower in 
> ovl_do_remove, the other lines are part of the test; should not be used.
>
> another patch is attached,

I think I found the real cause of the problem, see attached patch.  Can
you please test?

Thanks,
Miklos

commit 999204befc34af97bea495dad0ad1d8dfc5a0fe1
Author: Miklos Szeredi <mszeredi@xxxxxxx>
Date:   Wed Apr 27 13:23:27 2011 +0200

    ovl: fix remove after rename
    
    If the destination of the rename didn't exist on either the upper or
    the lower tree then the renamed object was erronously set to opaque.
    
    This caused the object to be replaced by a whiteout on unlink/rmdir.
    This in turn could result in the whiteout "showing through", since
    whiteouts are not handled in directories existing on the upper layer
    only, causing failure to remove an empty directory, for example.
    
    Reported-by: Jordi Pujol <jordipujolp@xxxxxxxxx>
    Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxx>

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 81f5fb9..c4ea1d3 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -461,6 +461,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
 {
 	int err;
 	enum ovl_path_type old_type;
+	enum ovl_path_type new_type;
 	struct dentry *old_upperdir;
 	struct dentry *new_upperdir;
 	struct dentry *olddentry;
@@ -476,8 +477,6 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
 		return -EXDEV;
 
 	if (new->d_inode) {
-		enum ovl_path_type new_type;
-
 		new_type = ovl_path_type(new);
 
 		if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) {
@@ -497,6 +496,8 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
 			if (err)
 				return err;
 		}
+	} else {
+		new_type = OVL_PATH_UPPER;
 	}
 
 	err = ovl_copy_up(old);
@@ -534,8 +535,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
 		goto out_dput;
 
 	old_opaque = ovl_dentry_is_opaque(old);
-	new_opaque = ovl_dentry_is_opaque(new) ||
-		ovl_path_type(new) != OVL_PATH_UPPER;
+	new_opaque = ovl_dentry_is_opaque(new) || new_type != OVL_PATH_UPPER;
 
 	if (is_dir && !old_opaque && new_opaque) {
 		err = ovl_set_opaque(olddentry);

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux