All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 3/5] xfs: use atomic extent swapping to repair rt metadata
Date: Tue, 28 Apr 2020 19:46:33 -0700	[thread overview]
Message-ID: <158812839291.169849.5779915521845398306.stgit@magnolia> (raw)
In-Reply-To: <158812837421.169849.625434931406278072.stgit@magnolia>

From: Darrick J. Wong <darrick.wong@oracle.com>

When repairing realtime volume metadata online, stage the new directory
contents in a temporary file and use the atomic extent swapping
mechanism to commit the results in bulk.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/scrub/repair.c           |   34 ++++++++++++++++++++--------
 fs/xfs/scrub/rtbitmap.c         |   12 ++++++++++
 fs/xfs/scrub/rtbitmap_repair.c  |   48 +++++++++++++++++++++++++++++++++++++--
 fs/xfs/scrub/rtsummary.c        |   12 ++++++++++
 fs/xfs/scrub/rtsummary_repair.c |   46 ++++++++++++++++++++++++++++++++++++-
 5 files changed, 137 insertions(+), 15 deletions(-)


diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index 0ec483d511cd..5b876b02b9f4 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -1636,13 +1636,13 @@ xrep_fallocate(
 	xfs_filblks_t		len)
 {
 	struct xfs_bmbt_irec	map;
+	struct xfs_inode	*ip = sc->tempip;
 	xfs_fileoff_t		end = off + len;
 	int			nmaps;
 	int			error = 0;
 
-	error = xrep_ino_dqattach(sc);
-	if (error)
-		return error;
+	ASSERT(sc->tempip != NULL);
+	ASSERT(!XFS_NOT_DQATTACHED(sc->mp, ip));
 
 	while (off < len) {
 		/*
@@ -1650,7 +1650,7 @@ xrep_fallocate(
 		 * in ok shape.
 		 */
 		nmaps = 1;
-		error = xfs_bmapi_read(sc->ip, off, end - off, &map, &nmaps,
+		error = xfs_bmapi_read(ip, off, end - off, &map, &nmaps,
 				XFS_DATA_FORK);
 		if (error)
 			break;
@@ -1672,15 +1672,21 @@ xrep_fallocate(
 		 * allocated to it.
 		 */
 		nmaps = 1;
-		error = xfs_bmapi_write(sc->tp, sc->ip, off, end - off,
+		error = xfs_bmapi_write(sc->tp, ip, off, end - off,
 				XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO, 0, &map,
 				&nmaps);
 		if (error)
 			break;
 
-		error = xfs_trans_roll_inode(&sc->tp, sc->ip);
+		/*
+		 * Roll the transaction with the inode we're fixing and the
+		 * temp inode, so that neither can pin the log.
+		 */
+		xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
+		error = xfs_trans_roll_inode(&sc->tp, ip);
 		if (error)
 			break;
+		xfs_trans_ijoin(sc->tp, sc->ip, 0);
 		off += map.br_startblock;
 	}
 
@@ -1701,6 +1707,7 @@ xrep_set_file_contents(
 {
 	struct list_head	buffers_list;
 	struct xfs_mount	*mp = sc->mp;
+	struct xfs_inode	*ip = sc->tempip;
 	struct xfs_buf		*bp;
 	xfs_rtblock_t		off = 0;
 	loff_t			pos = 0;
@@ -1744,12 +1751,19 @@ xrep_set_file_contents(
 	}
 
 	/* Set the new inode size, if needed. */
-	if (sc->ip->i_d.di_size != isize) {
-		sc->ip->i_d.di_size = isize;
-		xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
+	if (ip->i_d.di_size != isize) {
+		ip->i_d.di_size = isize;
+		xfs_trans_log_inode(sc->tp, ip, XFS_ILOG_CORE);
 	}
 
-	return xfs_trans_roll_inode(&sc->tp, sc->ip);
+	/*
+	 * Roll transaction, being careful to keep the tempfile and the
+	 * metadata inode joined.
+	 */
+	xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
+	error = xfs_trans_roll_inode(&sc->tp, ip);
+	xfs_trans_ijoin(sc->tp, sc->ip, 0);
+	return error;
 out:
 	xfs_buf_delwri_cancel(&buffers_list);
 	return error;
diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c
index 8488d137bf92..c3396d9ead49 100644
--- a/fs/xfs/scrub/rtbitmap.c
+++ b/fs/xfs/scrub/rtbitmap.c
@@ -20,6 +20,7 @@
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 #include "scrub/btree.h"
+#include "scrub/repair.h"
 
 /* Set us up with the realtime metadata locked. */
 int
@@ -29,6 +30,17 @@ xchk_setup_rt(
 {
 	int			error;
 
+#ifdef CONFIG_XFS_ONLINE_REPAIR
+	if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) {
+		if (!xfs_sb_version_hasatomicswap(&sc->mp->m_sb))
+			return -EOPNOTSUPP;
+
+		error = xrep_create_tempfile(sc, S_IFREG);
+		if (error)
+			return error;
+	}
+#endif
+
 	error = xchk_setup_fs(sc, ip);
 	if (error)
 		return error;
diff --git a/fs/xfs/scrub/rtbitmap_repair.c b/fs/xfs/scrub/rtbitmap_repair.c
index 229dd23d9d3e..d812efe8dd2a 100644
--- a/fs/xfs/scrub/rtbitmap_repair.c
+++ b/fs/xfs/scrub/rtbitmap_repair.c
@@ -18,6 +18,7 @@
 #include "xfs_bmap.h"
 #include "xfs_rmap.h"
 #include "xfs_rtrmap_btree.h"
+#include "xfs_swapext.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 #include "scrub/trace.h"
@@ -207,7 +208,29 @@ xrep_rtbitmap_get_buf(
 	xfs_fileoff_t		off,
 	struct xfs_buf		**bpp)
 {
-	return xfs_rtbuf_get(sc->mp, sc->tp, off, 0, bpp);
+	struct xfs_bmbt_irec	map;
+	struct xfs_buf		*bp;
+	struct xfs_mount	*mp = sc->mp;
+	int			nmap = 1;
+	int			error;
+
+	error = xfs_bmapi_read(sc->tempip, off, 1, &map, &nmap,
+			XFS_DATA_FORK);
+	if (error)
+		return error;
+
+	if (nmap == 0 || !xfs_bmap_is_real_extent(&map))
+		return -EFSCORRUPTED;
+
+	error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
+			XFS_FSB_TO_DADDR(mp, map.br_startblock),
+			mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
+	if (error)
+		return error;
+
+	xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTBITMAP_BUF);
+	*bpp = bp;
+	return 0;
 }
 
 /* Repair the realtime bitmap. */
@@ -221,8 +244,12 @@ xrep_rtbitmap(
 	xfs_fileoff_t		bmp_bytes;
 	int			error;
 
-	/* We require the realtime rmapbt to rebuild anything. */
-	if (!xfs_sb_version_hasrtrmapbt(&sc->mp->m_sb))
+	/*
+	 * We require the realtime rmapbt and atomic file updates to rebuild
+	 * anything.
+	 */
+	if (!xfs_sb_version_hasrtrmapbt(&sc->mp->m_sb) ||
+	    !xfs_sb_version_hasatomicswap(&sc->mp->m_sb))
 		return -EOPNOTSUPP;
 
 	bmp_bytes = XFS_FSB_TO_B(sc->mp, sc->mp->m_sb.sb_rbmblocks);
@@ -240,8 +267,17 @@ xrep_rtbitmap(
 	if (error)
 		goto out;
 
+	/*
+	 * Trylock the temporary file.  We had better be the only ones holding
+	 * onto this inode...
+	 */
+	if (!xfs_ilock_nowait(sc->tempip, XFS_ILOCK_EXCL))
+		return -EAGAIN;
+	sc->temp_ilock_flags = XFS_ILOCK_EXCL;
+
 	/* Make sure we have space allocated for the entire bitmap file. */
 	xfs_trans_ijoin(sc->tp, sc->ip, 0);
+	xfs_trans_ijoin(sc->tp, sc->tempip, 0);
 	error = xrep_fallocate(sc, 0, sc->mp->m_sb.sb_rbmblocks);
 	if (error)
 		goto out;
@@ -249,6 +285,12 @@ xrep_rtbitmap(
 	/* Copy the bitmap file that we generated. */
 	error = xrep_set_file_contents(sc, xrep_rtbitmap_get_buf, rb.bmpfile,
 			bmp_bytes);
+	if (error)
+		goto out;
+
+	/* Now swap the extents. */
+	error = xfs_swapext_atomic(&sc->tp, sc->ip, sc->tempip, XFS_DATA_FORK,
+			0, 0, sc->mp->m_sb.sb_rbmblocks, 0);
 out:
 	fput(rb.bmpfile);
 	return error;
diff --git a/fs/xfs/scrub/rtsummary.c b/fs/xfs/scrub/rtsummary.c
index e2b4638fa7cc..ccb220c184f1 100644
--- a/fs/xfs/scrub/rtsummary.c
+++ b/fs/xfs/scrub/rtsummary.c
@@ -20,6 +20,7 @@
 #include "scrub/common.h"
 #include "scrub/trace.h"
 #include "scrub/xfile.h"
+#include "scrub/repair.h"
 
 /*
  * Realtime Summary
@@ -61,6 +62,17 @@ xchk_setup_rtsummary(
 	struct xfs_mount	*mp = sc->mp;
 	int			error;
 
+#ifdef CONFIG_XFS_ONLINE_REPAIR
+	if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) {
+		if (!xfs_sb_version_hasatomicswap(&sc->mp->m_sb))
+			return -EOPNOTSUPP;
+
+		error = xrep_create_tempfile(sc, S_IFREG);
+		if (error)
+			return error;
+	}
+#endif
+
 	error = xchk_setup_fs(sc, ip);
 	if (error)
 		return error;
diff --git a/fs/xfs/scrub/rtsummary_repair.c b/fs/xfs/scrub/rtsummary_repair.c
index 78814b6a9c71..9c1fd759b730 100644
--- a/fs/xfs/scrub/rtsummary_repair.c
+++ b/fs/xfs/scrub/rtsummary_repair.c
@@ -16,6 +16,7 @@
 #include "xfs_inode.h"
 #include "xfs_bit.h"
 #include "xfs_bmap.h"
+#include "xfs_swapext.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 #include "scrub/trace.h"
@@ -28,7 +29,29 @@ xrep_rtsum_get_buf(
 	xfs_fileoff_t		off,
 	struct xfs_buf		**bpp)
 {
-	return xfs_rtbuf_get(sc->mp, sc->tp, off, 1, bpp);
+	struct xfs_bmbt_irec	map;
+	struct xfs_buf		*bp;
+	struct xfs_mount	*mp = sc->mp;
+	int			nmap = 1;
+	int			error;
+
+	error = xfs_bmapi_read(sc->tempip, off, 1, &map, &nmap,
+			XFS_DATA_FORK);
+	if (error)
+		return error;
+
+	if (nmap == 0 || !xfs_bmap_is_real_extent(&map))
+		return -EFSCORRUPTED;
+
+	error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
+			XFS_FSB_TO_DADDR(mp, map.br_startblock),
+			mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
+	if (error)
+		return error;
+
+	xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTSUMMARY_BUF);
+	*bpp = bp;
+	return 0;
 }
 
 /* Repair the realtime summary. */
@@ -38,18 +61,37 @@ xrep_rtsummary(
 {
 	int			error;
 
+	/* We require atomic file swap to be able to fix rt summaries. */
+	if (!xfs_sb_version_hasatomicswap(&sc->mp->m_sb))
+		return -EOPNOTSUPP;
+
 	/* Make sure any problems with the fork are fixed. */
 	error = xrep_metadata_inode_forks(sc);
 	if (error)
 		return error;
 
+	/*
+	 * Trylock the temporary file.  We had better be the only ones holding
+	 * onto this inode...
+	 */
+	if (!xfs_ilock_nowait(sc->tempip, XFS_ILOCK_EXCL))
+		return -EAGAIN;
+	sc->temp_ilock_flags = XFS_ILOCK_EXCL;
+
 	/* Make sure we have space allocated for the entire summary file. */
 	xfs_trans_ijoin(sc->tp, sc->ip, 0);
+	xfs_trans_ijoin(sc->tp, sc->tempip, 0);
 	error = xrep_fallocate(sc, 0, XFS_B_TO_FSB(sc->mp, sc->mp->m_rsumsize));
 	if (error)
 		return error;
 
 	/* Copy the rtsummary file that we generated. */
-	return xrep_set_file_contents(sc, xrep_rtsum_get_buf, sc->xfile,
+	error = xrep_set_file_contents(sc, xrep_rtsum_get_buf, sc->xfile,
 			sc->mp->m_rsumsize);
+	if (error)
+		return error;
+
+	/* Now swap the extents. */
+	return xfs_swapext_atomic(&sc->tp, sc->ip, sc->tempip, XFS_DATA_FORK,
+			0, 0, XFS_B_TO_FSB(sc->mp, sc->mp->m_rsumsize), 0);
 }


  parent reply	other threads:[~2020-04-29  2:46 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-29  2:46 [PATCH RFCRAP 0/5] xfs: atomic file metadata repairs Darrick J. Wong
2020-04-29  2:46 ` [PATCH 1/5] xfs: parent repair should try the dcache first Darrick J. Wong
2020-04-29  2:46 ` [PATCH 2/5] xfs: create temporary files and directories for online repair Darrick J. Wong
2020-04-29  2:46 ` Darrick J. Wong [this message]
2020-04-29  2:46 ` [PATCH 4/5] xfs: use atomic extent swapping to repair extended attributes Darrick J. Wong
2020-04-29  2:46 ` [PATCH 5/5] xfs: use atomic extent swapping to repair directories Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=158812839291.169849.5779915521845398306.stgit@magnolia \
    --to=darrick.wong@oracle.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.