[PATCH 06/11] xfs_repair: invalidate dirty dir buffers when we zap a directory

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

 



From: Darrick J. Wong <darrick.wong@xxxxxxxxxx>

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@xxxxxxxxxx>
---
 libxfs/libxfs_api_defs.h |    1 +
 repair/phase6.c          |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)


diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 09f1428..3b36e0e 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -100,6 +100,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 498a3b5..2005e40 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);

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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