From: Darrick J. Wong Date: Wed, 23 May 2018 21:30:48 +0000 (-0500) Subject: xfs_repair: invalidate dirty dir buffers when we zap a directory X-Git-Tag: v4.17.0-rc1~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9c559f4e4fb4587b3090d63385d6cbed760d3a8;p=thirdparty%2Fxfsprogs-dev.git xfs_repair: invalidate dirty dir buffers when we zap a directory If we decide to rebuild a directory in phase 6, we need to find and invalidate all of the old directory buffers so that they don't get written out, which can trigger write verifier errors when we finish. This fixes the write verifier errors in phase 7 that can occur via xfs/382. Signed-off-by: Darrick J. Wong Reviewed-by: Eric Sandeen Signed-off-by: Eric Sandeen --- diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 48cf25be0..fd471de75 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -101,6 +101,7 @@ #define xfs_dir2_data_make_free libxfs_dir2_data_make_free #define xfs_dir2_data_use_free libxfs_dir2_data_use_free #define xfs_dir2_shrink_inode libxfs_dir2_shrink_inode +#define xfs_da_get_buf libxfs_da_get_buf #define xfs_inode_from_disk libxfs_inode_from_disk #define xfs_inode_to_disk libxfs_inode_to_disk diff --git a/repair/phase6.c b/repair/phase6.c index 498a3b554..2005e4066 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -1311,6 +1311,48 @@ entry_junked( return !no_modify; } +/* Find and invalidate all the directory's buffers. */ +static int +dir_binval( + struct xfs_trans *tp, + struct xfs_inode *ip, + int whichfork) +{ + struct xfs_iext_cursor icur; + struct xfs_bmbt_irec rec; + struct xfs_ifork *ifp; + struct xfs_da_geometry *geo; + struct xfs_buf *bp; + xfs_dablk_t dabno, end_dabno; + int error = 0; + + if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && + ip->i_d.di_format != XFS_DINODE_FMT_BTREE) + return 0; + + geo = tp->t_mountp->m_dir_geo; + ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + for_each_xfs_iext(ifp, &icur, &rec) { + dabno = xfs_dir2_db_to_da(geo, rec.br_startoff + + geo->fsbcount - 1); + end_dabno = xfs_dir2_db_to_da(geo, rec.br_startoff + + rec.br_blockcount); + for (; dabno <= end_dabno; dabno += geo->fsbcount) { + bp = NULL; + error = -libxfs_da_get_buf(tp, ip, dabno, -2, &bp, + whichfork); + if (error) + return error; + if (!bp) + continue; + libxfs_trans_binval(tp, bp); + libxfs_trans_brelse(tp, bp); + } + } + + return error; +} + /* * Unexpected failure during the rebuild will leave the entries in * lost+found on the next run @@ -1361,6 +1403,10 @@ longform_dir2_rebuild( res_failed(error); libxfs_trans_ijoin(tp, ip, 0); + error = dir_binval(tp, ip, XFS_DATA_FORK); + if (error) + res_failed(error); + if ((error = -libxfs_bmap_last_offset(ip, &lastblock, XFS_DATA_FORK))) do_error(_("xfs_bmap_last_offset failed -- error - %d\n"), error);