linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ext4: fix bug for rename with RENAME_WHITEOUT
@ 2020-12-29  8:56 yangerkun
  2020-12-29  8:57 ` yangerkun
  0 siblings, 1 reply; 2+ messages in thread
From: yangerkun @ 2020-12-29  8:56 UTC (permalink / raw)
  To: linux-ext4, tytso, adilger.kernel, jack
  Cc: yi.zhang, lihaotian9, lutianxiong, linfeilong, yangerkun

ext4_rename will create a special inode for whiteout and use this 'ino'
to replace the source file's dir entry 'ino'. Once error happens
latter(small ext4 img, and consume all space, so the rename with dst
path not exist will fail due to the ENOSPC return from ext4_add_entry in
ext4_rename), the cleanup do drop the nlink for whiteout, but forget to
restore 'ino' with source file. This will lead to "deleted inode
referenced".

Signed-off-by: yangerkun <yangerkun@huawei.com>
---
 fs/ext4/namei.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index b17a082b7db1..0e89e5a0c758 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3593,9 +3593,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
 			return retval2;
 		}
 	}
-	brelse(ent->bh);
-	ent->bh = NULL;
-
 	return retval;
 }
 
@@ -3794,6 +3791,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 		}
 	}
 
+	old_file_type = old.de->file_type;
 	if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
 		ext4_handle_sync(handle);
 
@@ -3821,7 +3819,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	force_reread = (new.dir->i_ino == old.dir->i_ino &&
 			ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
 
-	old_file_type = old.de->file_type;
 	if (whiteout) {
 		/*
 		 * Do this before adding a new entry, so the old entry is sure
@@ -3919,15 +3916,18 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	retval = 0;
 
 end_rename:
-	brelse(old.dir_bh);
-	brelse(old.bh);
-	brelse(new.bh);
 	if (whiteout) {
+		ext4_setent(handle, &old,
+			    old.inode->i_ino, old_file_type);
 		if (retval)
 			drop_nlink(whiteout);
 		unlock_new_inode(whiteout);
 		iput(whiteout);
+
 	}
+	brelse(old.dir_bh);
+	brelse(old.bh);
+	brelse(new.bh);
 	if (handle)
 		ext4_journal_stop(handle);
 	return retval;
-- 
2.25.4


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] ext4: fix bug for rename with RENAME_WHITEOUT
  2020-12-29  8:56 [PATCH] ext4: fix bug for rename with RENAME_WHITEOUT yangerkun
@ 2020-12-29  8:57 ` yangerkun
  0 siblings, 0 replies; 2+ messages in thread
From: yangerkun @ 2020-12-29  8:57 UTC (permalink / raw)
  To: linux-ext4, tytso, adilger.kernel, jack
  Cc: yi.zhang, lihaotian9, lutianxiong, linfeilong



在 2020/12/29 16:56, yangerkun 写道:
> ext4_rename will create a special inode for whiteout and use this 'ino'
> to replace the source file's dir entry 'ino'. Once error happens
> latter(small ext4 img, and consume all space, so the rename with dst
> path not exist will fail due to the ENOSPC return from ext4_add_entry in
> ext4_rename), the cleanup do drop the nlink for whiteout, but forget to
> restore 'ino' with source file. This will lead to "deleted inode
> referenced".
> 
> Signed-off-by: yangerkun <yangerkun@huawei.com>
> ---
>   fs/ext4/namei.c | 14 +++++++-------
>   1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
> index b17a082b7db1..0e89e5a0c758 100644
> --- a/fs/ext4/namei.c
> +++ b/fs/ext4/namei.c
> @@ -3593,9 +3593,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
>   			return retval2;
>   		}
>   	}
> -	brelse(ent->bh);
> -	ent->bh = NULL;
> -
>   	return retval;
>   }
>   
> @@ -3794,6 +3791,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
>   		}
>   	}
>   
> +	old_file_type = old.de->file_type;
>   	if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
>   		ext4_handle_sync(handle);
>   
> @@ -3821,7 +3819,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
>   	force_reread = (new.dir->i_ino == old.dir->i_ino &&
>   			ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
>   
> -	old_file_type = old.de->file_type;
>   	if (whiteout) {
>   		/*
>   		 * Do this before adding a new entry, so the old entry is sure
> @@ -3919,15 +3916,18 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
>   	retval = 0;
>   
>   end_rename:
> -	brelse(old.dir_bh);
> -	brelse(old.bh);
> -	brelse(new.bh);
>   	if (whiteout) {
> +		ext4_setent(handle, &old,
> +			    old.inode->i_ino, old_file_type);
>   		if (retval)
>   			drop_nlink(whiteout);
>   		unlock_new_inode(whiteout);
>   		iput(whiteout);
> +

This is a mistake... Will send v2.

>   	}
> +	brelse(old.dir_bh);
> +	brelse(old.bh);
> +	brelse(new.bh);
>   	if (handle)
>   		ext4_journal_stop(handle);
>   	return retval;
> 

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-12-29  8:58 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-29  8:56 [PATCH] ext4: fix bug for rename with RENAME_WHITEOUT yangerkun
2020-12-29  8:57 ` yangerkun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).