[PATCH] ext2: avoid drop_nlink() during unlink of zero-nlink inode in ext2_unlink()

Ziyi Guo posted 1 patch 1 month, 2 weeks ago
fs/ext2/namei.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
[PATCH] ext2: avoid drop_nlink() during unlink of zero-nlink inode in ext2_unlink()
Posted by Ziyi Guo 1 month, 2 weeks ago
ext2_unlink() calls inode_dec_link_count() unconditionally, which
invokes drop_nlink(). If the inode was loaded from a corrupted disk
image with i_links_count == 0, drop_nlink()
triggers WARN_ON(inode->i_nlink == 0)

Follow the ext4 pattern from __ext4_unlink(): check i_nlink before
decrementing. If already zero, skip the decrement.

Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
---
 fs/ext2/namei.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index bde617a66cec..c746cf169a4d 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -293,7 +293,10 @@ static int ext2_unlink(struct inode *dir, struct dentry *dentry)
 		goto out;
 
 	inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
-	inode_dec_link_count(inode);
+
+	if (inode->i_nlink)
+		inode_dec_link_count(inode);
+
 	err = 0;
 out:
 	return err;
-- 
2.34.1
Re: [PATCH] ext2: avoid drop_nlink() during unlink of zero-nlink inode in ext2_unlink()
Posted by Jan Kara 1 month ago
On Wed 11-02-26 02:20:52, Ziyi Guo wrote:
> ext2_unlink() calls inode_dec_link_count() unconditionally, which
> invokes drop_nlink(). If the inode was loaded from a corrupted disk
> image with i_links_count == 0, drop_nlink()
> triggers WARN_ON(inode->i_nlink == 0)
> 
> Follow the ext4 pattern from __ext4_unlink(): check i_nlink before
> decrementing. If already zero, skip the decrement.
> 
> Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>

Thanks! I've merged the patch to my tree now.

								Honza

> ---
>  fs/ext2/namei.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
> index bde617a66cec..c746cf169a4d 100644
> --- a/fs/ext2/namei.c
> +++ b/fs/ext2/namei.c
> @@ -293,7 +293,10 @@ static int ext2_unlink(struct inode *dir, struct dentry *dentry)
>  		goto out;
>  
>  	inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
> -	inode_dec_link_count(inode);
> +
> +	if (inode->i_nlink)
> +		inode_dec_link_count(inode);
> +
>  	err = 0;
>  out:
>  	return err;
> -- 
> 2.34.1
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR