Re: [PATCH] xfs: reset child dir '..' entry when unlinking child

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

 



On Fri, Jul 02, 2021 at 08:02:33PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@xxxxxxxxxx>
> 
> While running xfs/168, I noticed a second source of post-shrink
> corruption errors causing shutdowns.
> 
> Let's say that directory B has a low inode number and is a child of
> directory A, which has a high number.  If B is empty but open, and
> unlinked from A, B's dotdot link continues to point to A.  If A is then
> unlinked and the filesystem shrunk so that A is no longer a valid inode,
> a subsequent AIL push of B will trip the inode verifiers because the
> dotdot entry points outside of the filesystem.
> 
> To avoid this problem, reset B's dotdot entry to the root directory when
> unlinking directories, since the root directory cannot be removed.
> 
> Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>

I think it is reasonable to clean dotdot for all deaddir
cases (compared with skipping validating such dotdot dirent which
sounds a bit hacky though since dotdot was actually outdated...)

Reviewed-by: Gao Xiang <hsiangkao@xxxxxxxxxxxxxxxxx>

Thanks,
Gao Xiang

> ---
>  fs/xfs/xfs_inode.c |   13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 52be5c6d0b3b..03e25246e936 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -2817,6 +2817,19 @@ xfs_remove(
>  		error = xfs_droplink(tp, ip);
>  		if (error)
>  			goto out_trans_cancel;
> +
> +		/*
> +		 * Point the unlinked child directory's ".." entry to the root
> +		 * directory to eliminate back-references to inodes that may
> +		 * get freed before the child directory is closed.  If the fs
> +		 * gets shrunk, this can lead to dirent inode validation errors.
> +		 */
> +		if (dp->i_ino != tp->t_mountp->m_sb.sb_rootino) {
> +			error = xfs_dir_replace(tp, ip, &xfs_name_dotdot,
> +					tp->t_mountp->m_sb.sb_rootino, 0);
> +			if (error)
> +				return error;
> +		}
>  	} else {
>  		/*
>  		 * When removing a non-directory we need to log the parent



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux