From 5d0d1d292902e6990c09514e521da28343741e25 Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Sun, 18 Jan 2009 21:00:46 -0500 Subject: [PATCH] Unionfs: create whiteout in correct dir after rename with copyup Fixes bug #625: a file renamed/moved into a directory, if resulted in a copyup with a whiteout creation, could cause the whiteout to be created in the wrong dir. Signed-off-by: Erez Zadok --- fs/unionfs/rename.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c index 800d9ee74c4..92f04073680 100644 --- a/fs/unionfs/rename.c +++ b/fs/unionfs/rename.c @@ -162,7 +162,7 @@ static int do_unionfs_rename(struct inode *old_dir, struct dentry *new_parent) { int err = 0; - int bindex, bwh_old; + int bindex; int old_bstart, old_bend; int new_bstart, new_bend; int do_copyup = -1; @@ -171,7 +171,6 @@ static int do_unionfs_rename(struct inode *old_dir, int revert = 0; old_bstart = dbstart(old_dentry); - bwh_old = old_bstart; old_bend = dbend(old_dentry); new_bstart = dbstart(new_dentry); @@ -242,7 +241,19 @@ static int do_unionfs_rename(struct inode *old_dir, /* if copyup failed, try next branch to the left */ if (err) continue; - bwh_old = bindex; + /* + * create whiteout before calling __unionfs_rename + * because the latter will change the old_dentry's + * lower name and parent dir, resulting in the + * whiteout getting created in the wrong dir. + */ + err = create_whiteout(old_dentry, bindex); + if (err) { + printk(KERN_ERR "unionfs: can't create a " + "whiteout for %s in rename (err=%d)\n", + old_dentry->d_name.name, err); + continue; + } err = __unionfs_rename(old_dir, old_dentry, old_parent, new_dir, new_dentry, new_parent, bindex); @@ -260,16 +271,10 @@ static int do_unionfs_rename(struct inode *old_dir, /* * Create whiteout for source, only if: * (1) There is more than one underlying instance of source. - * (2) We did a copy_up + * (We did a copy_up is taken care of above). */ - if ((old_bstart != old_bend) || (do_copyup != -1)) { - if (bwh_old < 0) { - printk(KERN_ERR "unionfs: rename error (bwh_old=%d)\n", - bwh_old); - err = -EIO; - goto out; - } - err = create_whiteout(old_dentry, bwh_old); + if ((old_bstart != old_bend) && (do_copyup == -1)) { + err = create_whiteout(old_dentry, old_bstart); if (err) { /* can't fix anything now, so we exit with -EIO */ printk(KERN_ERR "unionfs: can't create a whiteout for " -- 2.34.1