]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: invalidate dirty dir buffers when we zap a directory
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 23 May 2018 21:30:48 +0000 (16:30 -0500)
committerEric Sandeen <sandeen@redhat.com>
Wed, 23 May 2018 21:30:48 +0000 (16:30 -0500)
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 <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/libxfs_api_defs.h
repair/phase6.c

index 48cf25be0a600fd1c97df82874bff696390e1624..fd471de757673714f2b27413805ce4ae3e547805 100644 (file)
 #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
index 498a3b554c6aa24f495de64cc026e2b991fdb02b..2005e4066dda3c639b32cd8b1f651874ece909df 100644 (file)
@@ -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);