All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chandan Babu R <chandan.babu@oracle.com>
To: linux-xfs@vger.kernel.org
Cc: Chandan Babu R <chandan.babu@oracle.com>,
	djwong@kernel.org, cem@kernel.org
Subject: [PATCH V2 22/23] mdrestore: Define mdrestore ops for v2 format
Date: Tue,  6 Jun 2023 14:58:05 +0530	[thread overview]
Message-ID: <20230606092806.1604491-23-chandan.babu@oracle.com> (raw)
In-Reply-To: <20230606092806.1604491-1-chandan.babu@oracle.com>

This commit adds functionality to restore metadump stored in v2 format.

Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
 mdrestore/xfs_mdrestore.c | 251 +++++++++++++++++++++++++++++++++++---
 1 file changed, 233 insertions(+), 18 deletions(-)

diff --git a/mdrestore/xfs_mdrestore.c b/mdrestore/xfs_mdrestore.c
index c395ae90..7b484071 100644
--- a/mdrestore/xfs_mdrestore.c
+++ b/mdrestore/xfs_mdrestore.c
@@ -12,7 +12,8 @@ struct mdrestore_ops {
 	void (*read_header)(void *header, FILE *md_fp);
 	void (*show_info)(void *header, const char *md_file);
 	void (*restore)(void *header, FILE *md_fp, int ddev_fd,
-			bool is_target_file);
+			bool is_data_target_file, int logdev_fd,
+			bool is_log_target_file);
 };
 
 static struct mdrestore {
@@ -20,6 +21,7 @@ static struct mdrestore {
 	bool			show_progress;
 	bool			show_info;
 	bool			progress_since_warning;
+	bool			external_log;
 } mdrestore;
 
 static void
@@ -143,10 +145,12 @@ show_info_v1(
 
 static void
 restore_v1(
-	void			*header,
-	FILE			*md_fp,
-	int			ddev_fd,
-	bool			is_target_file)
+	void		*header,
+	FILE		*md_fp,
+	int		ddev_fd,
+	bool		is_data_target_file,
+	int		logdev_fd,
+	bool		is_log_target_file)
 {
 	struct xfs_metablock	*metablock;
 	struct xfs_metablock	*mbp;
@@ -203,7 +207,7 @@ restore_v1(
 
 	((struct xfs_dsb*)block_buffer)->sb_inprogress = 1;
 
-	verify_device_size(ddev_fd, is_target_file, sb.sb_dblocks,
+	verify_device_size(ddev_fd, is_data_target_file, sb.sb_dblocks,
 			sb.sb_blocksize);
 
 	bytes_read = 0;
@@ -264,6 +268,195 @@ static struct mdrestore_ops mdrestore_ops_v1 = {
 	.restore	= restore_v1,
 };
 
+static void
+read_header_v2(
+	void				*header,
+	FILE				*md_fp)
+{
+	struct xfs_metadump_header	*xmh = header;
+	bool				want_external_log;
+
+	xmh->xmh_magic = cpu_to_be32(XFS_MD_MAGIC_V2);
+
+	if (fread((uint8_t *)xmh + sizeof(xmh->xmh_magic),
+			sizeof(*xmh) - sizeof(xmh->xmh_magic), 1, md_fp) != 1)
+		fatal("error reading from metadump file\n");
+
+	want_external_log = !!(be32_to_cpu(xmh->xmh_incompat_flags) &
+			XFS_MD2_INCOMPAT_EXTERNALLOG);
+
+	if (want_external_log && !mdrestore.external_log)
+		fatal("External Log device is required\n");
+}
+
+static void
+show_info_v2(
+	void				*header,
+	const char			*md_file)
+{
+	struct xfs_metadump_header	*xmh;
+	uint32_t			incompat_flags;
+
+	xmh = header;
+	incompat_flags = be32_to_cpu(xmh->xmh_incompat_flags);
+
+	printf("%s: %sobfuscated, %s log, external log contents are %sdumped, %s metadata blocks,\n",
+		md_file,
+		incompat_flags & XFS_MD2_INCOMPAT_OBFUSCATED ? "":"not ",
+		incompat_flags & XFS_MD2_INCOMPAT_DIRTYLOG ? "dirty":"clean",
+		incompat_flags & XFS_MD2_INCOMPAT_EXTERNALLOG ? "":"not ",
+		incompat_flags & XFS_MD2_INCOMPAT_FULLBLOCKS ? "full":"zeroed");
+}
+
+#define MDR_IO_BUF_SIZE (8 * 1024 * 1024)
+
+static void
+dump_meta_extent(
+	FILE		*md_fp,
+	int		dev_fd,
+	char		*device,
+	void		*buf,
+	uint64_t	offset,
+	int		len)
+{
+	int		io_size;
+
+	io_size = min(len, MDR_IO_BUF_SIZE);
+
+	do {
+		if (fread(buf, io_size, 1, md_fp) != 1)
+			fatal("error reading from metadump file\n");
+		if (pwrite(dev_fd, buf, io_size, offset) < 0)
+			fatal("error writing to %s device at offset %llu: %s\n",
+				device, offset, strerror(errno));
+		len -= io_size;
+		offset += io_size;
+
+		io_size = min(len, io_size);
+	} while (len);
+}
+
+static void
+restore_v2(
+	void			*header,
+	FILE			*md_fp,
+	int			ddev_fd,
+	bool			is_data_target_file,
+	int			logdev_fd,
+	bool			is_log_target_file)
+{
+	struct xfs_sb		sb;
+	struct xfs_meta_extent	xme;
+	char			*block_buffer;
+	int64_t			bytes_read;
+	uint64_t		offset;
+	int			len;
+
+	block_buffer = malloc(MDR_IO_BUF_SIZE);
+	if (block_buffer == NULL)
+		fatal("Unable to allocate input buffer memory\n");
+
+	if (fread(&xme, sizeof(xme), 1, md_fp) != 1)
+		fatal("error reading from metadump file\n");
+
+	if (xme.xme_addr != 0 || xme.xme_len == 1)
+		fatal("Invalid superblock disk address/length\n");
+
+	len = BBTOB(be32_to_cpu(xme.xme_len));
+
+	if (fread(block_buffer, len, 1, md_fp) != 1)
+		fatal("error reading from metadump file\n");
+
+	libxfs_sb_from_disk(&sb, (struct xfs_dsb *)block_buffer);
+
+	if (sb.sb_magicnum != XFS_SB_MAGIC)
+		fatal("bad magic number for primary superblock\n");
+
+	((struct xfs_dsb *)block_buffer)->sb_inprogress = 1;
+
+	verify_device_size(ddev_fd, is_data_target_file, sb.sb_dblocks,
+			sb.sb_blocksize);
+
+	if (sb.sb_logstart == 0) {
+		ASSERT(mdrestore.external_log == true);
+		verify_device_size(logdev_fd, is_log_target_file, sb.sb_logblocks,
+				sb.sb_blocksize);
+	}
+
+	if (pwrite(ddev_fd, block_buffer, len, 0) < 0)
+		fatal("error writing primary superblock: %s\n",
+			strerror(errno));
+
+	bytes_read = len;
+
+	do {
+		char *device;
+		int fd;
+
+		if (fread(&xme, sizeof(xme), 1, md_fp) != 1) {
+			if (feof(md_fp))
+				break;
+			fatal("error reading from metadump file\n");
+		}
+
+		offset = BBTOB(be64_to_cpu(xme.xme_addr) & XME_ADDR_DADDR_MASK);
+		switch (be64_to_cpu(xme.xme_addr) & XME_ADDR_DEVICE_MASK) {
+		case XME_ADDR_DATA_DEVICE:
+			device = "data";
+			fd = ddev_fd;
+			break;
+		case XME_ADDR_LOG_DEVICE:
+			device = "log";
+			fd = logdev_fd;
+			break;
+		default:
+			fatal("Invalid device found in metadump\n");
+			break;
+		}
+
+		len = BBTOB(be32_to_cpu(xme.xme_len));
+
+		dump_meta_extent(md_fp, fd, device, block_buffer, offset, len);
+
+		bytes_read += len;
+
+		if (mdrestore.show_progress) {
+			static int64_t mb_read;
+			int64_t mb_now = bytes_read >> 20;
+
+			if (mb_now != mb_read) {
+				print_progress("%lld MB read", mb_now);
+				mb_read = mb_now;
+			}
+		}
+	} while (1);
+
+	if (mdrestore.progress_since_warning)
+		putchar('\n');
+
+	memset(block_buffer, 0, sb.sb_sectsize);
+	sb.sb_inprogress = 0;
+	libxfs_sb_to_disk((struct xfs_dsb *)block_buffer, &sb);
+	if (xfs_sb_version_hascrc(&sb)) {
+		xfs_update_cksum(block_buffer, sb.sb_sectsize,
+				offsetof(struct xfs_sb, sb_crc));
+	}
+
+	if (pwrite(ddev_fd, block_buffer, sb.sb_sectsize, 0) < 0)
+		fatal("error writing primary superblock: %s\n",
+			strerror(errno));
+
+	free(block_buffer);
+
+	return;
+}
+
+static struct mdrestore_ops mdrestore_ops_v2 = {
+	.read_header	= read_header_v2,
+	.show_info	= show_info_v2,
+	.restore	= restore_v2,
+};
+
 static void
 usage(void)
 {
@@ -276,17 +469,24 @@ main(
 	int 		argc,
 	char 		**argv)
 {
-	FILE		*src_f;
-	int		dst_fd;
-	int		c;
-	bool		is_target_file;
-	uint32_t	magic;
-	void		*header;
-	struct xfs_metablock	mb;
+	union {
+		struct xfs_metadump_header	xmh;
+		struct xfs_metablock		mb;
+	} md;
+	FILE				*src_f;
+	char				*logdev = NULL;
+	void				*header;
+	uint32_t			magic;
+	int				data_dev_fd;
+	int				log_dev_fd;
+	int				c;
+	bool				is_data_dev_file;
+	bool				is_log_dev_file;
 
 	mdrestore.show_progress = false;
 	mdrestore.show_info = false;
 	mdrestore.progress_since_warning = false;
+	mdrestore.external_log = false;
 
 	progname = basename(argv[0]);
 
@@ -332,11 +532,17 @@ main(
 	if (fread(&magic, sizeof(magic), 1, src_f) != 1)
 		fatal("Unable to read metadump magic from metadump file\n");
 
+	header = &md;
+
 	switch (be32_to_cpu(magic)) {
 	case XFS_MD_MAGIC_V1:
-		header = &mb;
 		mdrestore.mdrops = &mdrestore_ops_v1;
 		break;
+
+	case XFS_MD_MAGIC_V2:
+		mdrestore.mdrops = &mdrestore_ops_v2;
+		break;
+
 	default:
 		fatal("specified file is not a metadata dump\n");
 		break;
@@ -353,12 +559,21 @@ main(
 
 	optind++;
 
-	/* check and open target */
-	dst_fd = open_device(argv[optind], &is_target_file);
+	/* check and open data device */
+	data_dev_fd = open_device(argv[optind], &is_data_dev_file);
+
+	log_dev_fd = -1;
+	if (mdrestore.external_log)
+		/* check and open log device */
+		log_dev_fd = open_device(logdev, &is_log_dev_file);
+
+	mdrestore.mdrops->restore(header, src_f, data_dev_fd, is_data_dev_file,
+				log_dev_fd, is_log_dev_file);
 
-	mdrestore.mdrops->restore(header, src_f, dst_fd, is_target_file);
+	close(data_dev_fd);
+	if (mdrestore.external_log)
+		close(log_dev_fd);
 
-	close(dst_fd);
 	if (src_f != stdin)
 		fclose(src_f);
 
-- 
2.39.1


  parent reply	other threads:[~2023-06-06  9:31 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <2ExBvYxYPnyiGvOJzODNvNXx_bfn5RWAck_7UcV7OvxkF6fgAy6UZtI6d2-FdmxoIeBLPPX0vwW9uaJxBa5Rmg==@protonmail.internalid>
2023-06-06  9:27 ` [PATCH V2 00/23] Metadump v2 Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 01/23] metadump: Use boolean values true/false instead of 1/0 Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 02/23] mdrestore: Fix logic used to check if target device is large enough Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 03/23] metadump: Declare boolean variables with bool type Chandan Babu R
2023-06-06 15:17     ` Darrick J. Wong
2023-06-06  9:27   ` [PATCH V2 04/23] metadump: Define and use struct metadump Chandan Babu R
2023-07-12 18:12     ` Darrick J. Wong
2023-07-20 13:13       ` Carlos Maiolino
2023-07-20 17:22         ` Darrick J. Wong
2023-06-06  9:27   ` [PATCH V2 05/23] metadump: Add initialization and release functions Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 06/23] metadump: Postpone invocation of init_metadump() Chandan Babu R
2023-07-12 17:00     ` Darrick J. Wong
2023-06-06  9:27   ` [PATCH V2 07/23] metadump: Introduce struct metadump_ops Chandan Babu R
2023-07-12 17:06     ` Darrick J. Wong
2023-06-06  9:27   ` [PATCH V2 08/23] metadump: Introduce metadump v1 operations Chandan Babu R
2023-07-12 17:10     ` Darrick J. Wong
2023-07-13  4:36       ` Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 09/23] metadump: Rename XFS_MD_MAGIC to XFS_MD_MAGIC_V1 Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 10/23] metadump: Define metadump v2 ondisk format structures and macros Chandan Babu R
2023-07-12 17:18     ` Darrick J. Wong
2023-07-13  4:37       ` Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 11/23] metadump: Define metadump ops for v2 format Chandan Babu R
2023-07-12 17:22     ` Darrick J. Wong
2023-07-13  4:45       ` Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 12/23] xfs_db: Add support to read from external log device Chandan Babu R
2023-07-12 17:35     ` Darrick J. Wong
2023-07-13  5:24       ` Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 13/23] metadump: Add support for passing version option Chandan Babu R
2023-06-06  9:27   ` [PATCH V2 14/23] mdrestore: Declare boolean variables with bool type Chandan Babu R
2023-07-12 17:35     ` Darrick J. Wong
2023-06-06  9:27   ` [PATCH V2 15/23] mdrestore: Define and use struct mdrestore Chandan Babu R
2023-07-12 18:12     ` Darrick J. Wong
2023-06-06  9:27   ` [PATCH V2 16/23] mdrestore: Detect metadump v1 magic before reading the header Chandan Babu R
2023-07-12 17:38     ` Darrick J. Wong
2023-06-06  9:28   ` [PATCH V2 17/23] mdrestore: Add open_device(), read_header() and show_info() functions Chandan Babu R
2023-07-12 17:46     ` Darrick J. Wong
2023-07-13  5:27       ` Chandan Babu R
2023-06-06  9:28   ` [PATCH V2 18/23] mdrestore: Introduce struct mdrestore_ops Chandan Babu R
2023-06-06  9:28   ` [PATCH V2 19/23] mdrestore: Replace metadump header pointer argument with generic pointer type Chandan Babu R
2023-07-12 17:55     ` Darrick J. Wong
2023-07-13  6:08       ` Chandan Babu R
2023-06-06  9:28   ` [PATCH V2 20/23] mdrestore: Introduce mdrestore v1 operations Chandan Babu R
2023-07-12 17:57     ` Darrick J. Wong
2023-06-06  9:28   ` [PATCH V2 21/23] mdrestore: Extract target device size verification into a function Chandan Babu R
2023-06-06  9:28   ` Chandan Babu R [this message]
2023-07-12 18:10     ` [PATCH V2 22/23] mdrestore: Define mdrestore ops for v2 format Darrick J. Wong
2023-07-13  6:27       ` Chandan Babu R
2023-07-13 14:22         ` Darrick J. Wong
2023-06-06  9:28   ` [PATCH V2 23/23] mdrestore: Add support for passing log device as an argument Chandan Babu R
2023-07-12 18:10     ` Darrick J. Wong
     [not found]       ` <181e7cbefa39e2dc59f2564c25966ac0d05aa6530483b7eb5d649de9a3d1cf7f@mu.id>
2023-07-13  6:48         ` Chandan Babu R
2023-06-06 12:10   ` [PATCH V2 00/23] Metadump v2 Carlos Maiolino
2023-06-06 12:38     ` Chandan Babu R
2023-06-06 16:04       ` Carlos Maiolino

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=20230606092806.1604491-23-chandan.babu@oracle.com \
    --to=chandan.babu@oracle.com \
    --cc=cem@kernel.org \
    --cc=djwong@kernel.org \
    --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.