From patchwork Thu Dec 19 19:44:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13915644 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 757E11A9B5C for ; Thu, 19 Dec 2024 19:44:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734637470; cv=none; b=kpWI81NAh8N1IFqkJXe2ZMlXcyP8ejR3fiqkgwFCGGcQ+U2vaygKH1jnOGSLLeuzobKcfOQOg1gwjDt6QrVo0kt7T1y9vn5fUQJeDuq54t3p3ti67Tstu/ZNi9cRFxSVwY0MnolcHNRRqD1zkyDS73bubtYrGEDbo1ym+JhJJyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734637470; c=relaxed/simple; bh=WHCrrdob+Cf7GTG8fGFVAL1P9JUHQCNhEZxsYXTMKzg=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TT4hNswJjMVAF90Ost5QIaSyLG5YKRknWSEMI1tpmT5zPSidUZQ53+/HDcx6HcGx6DY0L1zTRrx8rTyffkuAa50IReIFKtjLWkOB8PITDNrtvBCAhTWHPoDuLeFPcmCkO2rVmitIru5NvQOb0KZFLYJwbi2WS9PF4dUHlV6sjio= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FbfYJhN8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FbfYJhN8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4FAAAC4CECE; Thu, 19 Dec 2024 19:44:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734637470; bh=WHCrrdob+Cf7GTG8fGFVAL1P9JUHQCNhEZxsYXTMKzg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=FbfYJhN8WwGS4Uuby2s7MRZLbslgskSmETeDly6M4hkhojlAYiWPB1pOTk7l+0djz UjkulqNoD9Cxyi06Uf6eIJuSFPwBTkW0ze+IVtRYxnB5Wb2DarkhvqU492FcSaJ7zU FN64ehecfIrF14viQgsXvlUMZtdzz4qslJfy6jN4FYUqmcd4IEmBYAca7SNqpQRi56 xPxc2+B9NITmJ9QkAK1aXdDspWbzWk6yq72A4304ldJgUErW81atryT2uuqXcaN59t /HoCeCmzF83uUAWSR7aqBHNzXeCfA5TrwsJmnYdUJT7Ox5icaH8UC2RdRoLNnjwjtz RQzOr4To6W/pQ== Date: Thu, 19 Dec 2024 11:44:29 -0800 Subject: [PATCH 1/3] xfs_db: drop the metadata checking code from blockget From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <173463582913.1574879.1807844163819986251.stgit@frogsfrogsfrogs> In-Reply-To: <173463582894.1574879.10113776916850781634.stgit@frogsfrogsfrogs> References: <173463582894.1574879.10113776916850781634.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Drop the check subcommand and all the metadata checking code from xfs_db. We haven't shipped xfs_check in xfsprogs in a decade and the last known user (fstests) stopped calling it back in July 2024. Signed-off-by: "Darrick J. Wong" Reviewed-by: Andrey Albershteyn Reviewed-by: Christoph Hellwig --- db/check.c | 294 ----------------------------------------------------- man/man8/xfs_db.8 | 12 +- 2 files changed, 5 insertions(+), 301 deletions(-) diff --git a/db/check.c b/db/check.c index 37306bd7a6ac2d..4f7785c64f5b49 100644 --- a/db/check.c +++ b/db/check.c @@ -236,14 +236,12 @@ static void check_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, int ignore_reflink); static int check_inomap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, xfs_ino_t c_ino); -static void check_linkcounts(xfs_agnumber_t agno); static int check_range(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len); static void check_rdbmap(xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type); static int check_rinomap(xfs_rfsblock_t bno, xfs_extlen_t len, xfs_ino_t c_ino); -static void check_rootdir(void); static int check_rrange(xfs_rfsblock_t bno, xfs_extlen_t len); static void check_set_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, @@ -252,11 +250,6 @@ static void check_set_dbmap(xfs_agnumber_t agno, xfs_agblock_t c_agbno); static void check_set_rdbmap(xfs_rfsblock_t bno, xfs_extlen_t len, dbm_t type1, dbm_t type2); -static void check_summary(void); -static void checknot_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, - xfs_extlen_t len, int typemask); -static void checknot_rdbmap(xfs_rfsblock_t bno, xfs_extlen_t len, - int typemask); static void dir_hash_add(xfs_dahash_t hash, xfs_dir2_dataptr_t addr); static void dir_hash_check(inodata_t *id, int v); @@ -323,7 +316,6 @@ static void quota_add(xfs_dqid_t *p, xfs_dqid_t *g, xfs_dqid_t *u, static void quota_add1(qdata_t **qt, xfs_dqid_t id, int dq, xfs_qcnt_t bc, xfs_qcnt_t ic, xfs_qcnt_t rc); -static void quota_check(char *s, qdata_t **qt); static void quota_init(void); static void scan_ag(xfs_agnumber_t agno); static void scan_freelist(xfs_agf_t *agf); @@ -376,7 +368,7 @@ static const cmdinfo_t blockfree_cmd = { "blockfree", NULL, blockfree_f, 0, 0, 0, NULL, N_("free block usage information"), NULL }; static const cmdinfo_t blockget_cmd = - { "blockget", "check", blockget_f, 0, -1, 0, + { "blockget", NULL, blockget_f, 0, -1, 0, N_("[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..."), N_("get block usage and check consistency"), NULL }; static const cmdinfo_t blocktrash_cmd = @@ -826,107 +818,9 @@ blockget_f( blist = NULL; blist_size = 0; } - if (serious_error) { + if (serious_error) exitcode = 2; - dbprefix = oldprefix; - return 0; - } - if (xfs_has_metadir(mp)) { - dbprefix = oldprefix; - return 0; - } - - check_rootdir(); - /* - * Check that there are no blocks either - * a) unaccounted for or - * b) bno-free but not cnt-free - */ - if (!tflag) { /* are we in test mode, faking out freespace? */ - for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) - checknot_dbmap(agno, 0, mp->m_sb.sb_agblocks, - (1 << DBM_UNKNOWN) | (1 << DBM_FREE1)); - } - for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) - check_linkcounts(agno); - if (mp->m_sb.sb_rblocks) { - checknot_rdbmap(0, - (xfs_extlen_t)(mp->m_sb.sb_rextents * - mp->m_sb.sb_rextsize), - 1 << DBM_UNKNOWN); - check_summary(); - } - if (mp->m_sb.sb_icount != icount) { - if (!sflag) - dbprintf(_("sb_icount %lld, counted %lld\n"), - mp->m_sb.sb_icount, icount); - error++; - } - if (mp->m_sb.sb_ifree != ifree) { - if (!sflag) - dbprintf(_("sb_ifree %lld, counted %lld\n"), - mp->m_sb.sb_ifree, ifree); - error++; - } - if (mp->m_sb.sb_fdblocks != fdblocks) { - if (!sflag) - dbprintf(_("sb_fdblocks %lld, counted %lld\n"), - mp->m_sb.sb_fdblocks, fdblocks); - error++; - } - if (lazycount && mp->m_sb.sb_fdblocks != agf_aggr_freeblks) { - if (!sflag) - dbprintf(_("sb_fdblocks %lld, aggregate AGF count %lld\n"), - mp->m_sb.sb_fdblocks, agf_aggr_freeblks); - error++; - } - if (mp->m_sb.sb_frextents != frextents) { - if (!sflag) - dbprintf(_("sb_frextents %lld, counted %lld\n"), - mp->m_sb.sb_frextents, frextents); - error++; - } - if (mp->m_sb.sb_bad_features2 != 0 && - mp->m_sb.sb_bad_features2 != mp->m_sb.sb_features2) { - if (!sflag) - dbprintf(_("sb_features2 (0x%x) not same as " - "sb_bad_features2 (0x%x)\n"), - mp->m_sb.sb_features2, - mp->m_sb.sb_bad_features2); - error++; - } - if ((sbversion & XFS_SB_VERSION_ATTRBIT) && - !xfs_has_attr(mp)) { - if (!sflag) - dbprintf(_("sb versionnum missing attr bit %x\n"), - XFS_SB_VERSION_ATTRBIT); - error++; - } - if ((sbversion & XFS_SB_VERSION_QUOTABIT) && - !xfs_has_quota(mp)) { - if (!sflag) - dbprintf(_("sb versionnum missing quota bit %x\n"), - XFS_SB_VERSION_QUOTABIT); - error++; - } - if (!(sbversion & XFS_SB_VERSION_ALIGNBIT) && - xfs_has_align(mp)) { - if (!sflag) - dbprintf(_("sb versionnum extra align bit %x\n"), - XFS_SB_VERSION_ALIGNBIT); - error++; - } - if (qudo) - quota_check("user", qudata); - if (qpdo) - quota_check("project", qpdata); - if (qgdo) - quota_check("group", qgdata); - if (sbver_err > mp->m_sb.sb_agcount / 2) - dbprintf(_("WARNING: this may be a newer XFS filesystem.\n")); - if (error) - exitcode = 3; dbprefix = oldprefix; return 0; } @@ -1388,58 +1282,6 @@ check_inomap( return rval; } -static void -check_linkcounts( - xfs_agnumber_t agno) -{ - inodata_t *ep; - inodata_t **ht; - int idx; - char *path; - - ht = inodata[agno]; - for (idx = 0; idx < inodata_hash_size; ht++, idx++) { - ep = *ht; - while (ep) { - if (ep->link_set != ep->link_add || ep->link_set == 0) { - path = inode_name(ep->ino, NULL); - if (!path && ep->link_add) - path = xstrdup("?"); - if (!sflag || ep->ilist) { - if (ep->link_add) - dbprintf(_("link count mismatch " - "for inode %lld (name " - "%s), nlink %d, " - "counted %d\n"), - ep->ino, path, - ep->link_set, - ep->link_add); - else if (ep->link_set) - dbprintf(_("disconnected inode " - "%lld, nlink %d\n"), - ep->ino, ep->link_set); - else - dbprintf(_("allocated inode %lld " - "has 0 link count\n"), - ep->ino); - } - if (path) - xfree(path); - error++; - } else if (verbose || ep->ilist) { - path = inode_name(ep->ino, NULL); - if (path) { - dbprintf(_("inode %lld name %s\n"), - ep->ino, path); - xfree(path); - } - } - ep = ep->next; - } - } - -} - static int check_range( xfs_agnumber_t agno, @@ -1556,25 +1398,6 @@ check_rinomap( return rval; } -static void -check_rootdir(void) -{ - inodata_t *id; - - id = find_inode(mp->m_sb.sb_rootino, 0); - if (id == NULL) { - if (!sflag) - dbprintf(_("root inode %lld is missing\n"), - mp->m_sb.sb_rootino); - error++; - } else if (!id->isdir) { - if (!sflag || id->ilist) - dbprintf(_("root inode %lld is not a directory\n"), - mp->m_sb.sb_rootino); - error++; - } -} - static inline void report_rrange( xfs_rfsblock_t low, @@ -1718,77 +1541,6 @@ get_suminfo( return raw->old; } -static void -check_summary(void) -{ - xfs_rfsblock_t bno; - union xfs_suminfo_raw *csp; - union xfs_suminfo_raw *fsp; - int log; - - csp = sumcompute; - fsp = sumfile; - for (log = 0; log < mp->m_rsumlevels; log++) { - for (bno = 0; - bno < mp->m_sb.sb_rbmblocks; - bno++, csp++, fsp++) { - if (csp->old != fsp->old) { - if (!sflag) - dbprintf(_("rt summary mismatch, size %d " - "block %llu, file: %d, " - "computed: %d\n"), - log, bno, - get_suminfo(mp, fsp), - get_suminfo(mp, csp)); - error++; - } - } - } -} - -static void -checknot_dbmap( - xfs_agnumber_t agno, - xfs_agblock_t agbno, - xfs_extlen_t len, - int typemask) -{ - xfs_extlen_t i; - char *p; - - if (!check_range(agno, agbno, len)) - return; - for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { - if ((1 << *p) & typemask) { - if (!sflag || CHECK_BLISTA(agno, agbno + i)) - dbprintf(_("block %u/%u type %s not expected\n"), - agno, agbno + i, typename[(dbm_t)*p]); - error++; - } - } -} - -static void -checknot_rdbmap( - xfs_rfsblock_t bno, - xfs_extlen_t len, - int typemask) -{ - xfs_extlen_t i; - char *p; - - if (!check_rrange(bno, len)) - return; - for (i = 0, p = &dbmap[mp->m_sb.sb_agcount][bno]; i < len; i++, p++) { - if ((1 << *p) & typemask) { - if (!sflag || CHECK_BLIST(bno + i)) - dbprintf(_("rtblock %llu type %s not expected\n"), - bno + i, typename[(dbm_t)*p]); - error++; - } - } -} - static void dir_hash_add( xfs_dahash_t hash, @@ -3923,48 +3675,6 @@ quota_add1( qt[qh] = qe; } -static void -quota_check( - char *s, - qdata_t **qt) -{ - int i; - qdata_t *next; - qdata_t *qp; - - for (i = 0; i < QDATA_HASH_SIZE; i++) { - qp = qt[i]; - while (qp) { - next = qp->next; - if (qp->count.bc != qp->dq.bc || - qp->count.ic != qp->dq.ic || - qp->count.rc != qp->dq.rc) { - if (!sflag) { - dbprintf(_("%s quota id %u, have/exp"), - s, qp->id); - if (qp->count.bc != qp->dq.bc) - dbprintf(_(" bc %lld/%lld"), - qp->dq.bc, - qp->count.bc); - if (qp->count.ic != qp->dq.ic) - dbprintf(_(" ic %lld/%lld"), - qp->dq.ic, - qp->count.ic); - if (qp->count.rc != qp->dq.rc) - dbprintf(_(" rc %lld/%lld"), - qp->dq.rc, - qp->count.rc); - dbprintf("\n"); - } - error++; - } - xfree(qp); - qp = next; - } - } - xfree(qt); -} - static void quota_init(void) { diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 5d72de91dd6862..06f4464a928596 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -345,7 +345,7 @@ .SH COMMANDS command can be given, presumably with different arguments than the previous one. .TP .BI "blockget [\-npvs] [\-b " bno "] ... [\-i " ino "] ..." -Get block usage and check filesystem consistency. +Get block usage. The information is saved for use by a subsequent .BR blockuse ", " ncheck ", or " blocktrash command. @@ -564,11 +564,6 @@ .SH COMMANDS half full. .RE .TP -.B check -See the -.B blockget -command. -.TP .BI "convert " "type number" " [" "type number" "] ... " type Convert from one address form to another. The known @@ -2665,8 +2660,7 @@ .SH TYPES and printable ASCII chars. .SH DIAGNOSTICS Many messages can come from the -.B check -.RB ( blockget ) +.B blockget command. If the filesystem is completely corrupt, a core dump might be produced instead of the message @@ -2676,7 +2670,7 @@ .SH DIAGNOSTICS .RE .PP If the filesystem is very large (has many files) then -.B check +.B blockget might run out of memory. In this case the message .RS .B out of memory From patchwork Thu Dec 19 19:44:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13915645 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 759091A0AFE for ; Thu, 19 Dec 2024 19:44:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734637486; cv=none; b=fPNyHlkHB4RFHnTCy0bA3q7beAH0uq0lPVVME8VqR++nTmeC85ckrP9a7HJ7JTBuFPdHB/LKWf8eLotfQu8KsnPy1mmsD/ySF2yX6bhayf7drxU7zuppd7klgMGWX3ii4D87E81DhJP3om8iCjJlyftlRCsx+TWuIXEZsfi9tBM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734637486; c=relaxed/simple; bh=GhyHGxki1LC3Tyaep0+lGJl/1UAiLpHxKVVGY8Wpnvk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WPb4fu6ld0uFUn92a3Onr2UDRz7JCu7Tm8+WcE6NcmwAmL1AGCtsLx6lyR2xEHIXt+8052ERtdfkYxZoCSug9lNYGuZ4BZUhv8EgMycEqmyibzVwCWn5K+PUf1qbnukLk8d5fR6WyhzlMCOa598IJC5tiJ0XIYBDdrpGVqBVARE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LVEt5U3b; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LVEt5U3b" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EAD5EC4CECE; Thu, 19 Dec 2024 19:44:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734637486; bh=GhyHGxki1LC3Tyaep0+lGJl/1UAiLpHxKVVGY8Wpnvk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=LVEt5U3bLHl8hE2Eu1PA5DUFKFe0gLrI/gUarvjJblw+4pfdWIN57w+gz5N5RmC2u 4cLV4ZG+co8uqTBocDSDeP8Acs90qgCa1+fD8LEvQfcNWtS2m0zrPhJrFDtm55bl+s fdR0arizYCY+d4PdurSO/6+BvFU/kjWgVd0hlSVCYPv/jlowlEukrkryGczWbwUXf+ ktMHGcAFZTSe4Ftkzj3CTTuzCug9tOdpCKUKRysbF5eSwTsVPxUL/E0HfDU13wdl+j uRNxw6svx4dkPmI0DCz6/Uj3q0qj3CKNweHOXBif3K1ttoYi9CsUJJnPzflnCOg6Qy jN4PCsP3ZSYlQ== Date: Thu, 19 Dec 2024 11:44:45 -0800 Subject: [PATCH 2/3] xfs_mdrestore: refactor open-coded fd/is_file into a structure From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <173463582928.1574879.5106855575792576842.stgit@frogsfrogsfrogs> In-Reply-To: <173463582894.1574879.10113776916850781634.stgit@frogsfrogsfrogs> References: <173463582894.1574879.10113776916850781634.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create an explicit object to track the fd and flags associated with a device onto which we are restoring metadata, and use it to reduce the amount of open-coded arguments to ->restore. This avoids some grossness in the next patch. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- mdrestore/xfs_mdrestore.c | 123 +++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 60 deletions(-) diff --git a/mdrestore/xfs_mdrestore.c b/mdrestore/xfs_mdrestore.c index c6c00270234442..c5584fec68813e 100644 --- a/mdrestore/xfs_mdrestore.c +++ b/mdrestore/xfs_mdrestore.c @@ -15,12 +15,20 @@ union mdrestore_headers { struct xfs_metadump_header v2; }; +struct mdrestore_dev { + int fd; + bool is_file; +}; + +#define DEFINE_MDRESTORE_DEV(name) \ + struct mdrestore_dev name = { .fd = -1 } + struct mdrestore_ops { void (*read_header)(union mdrestore_headers *header, FILE *md_fp); void (*show_info)(union mdrestore_headers *header, const char *md_file); void (*restore)(union mdrestore_headers *header, FILE *md_fp, - int ddev_fd, bool is_data_target_file, int logdev_fd, - bool is_log_target_file); + const struct mdrestore_dev *ddev, + const struct mdrestore_dev *logdev); }; static struct mdrestore { @@ -108,25 +116,24 @@ fixup_superblock( fatal("error writing primary superblock: %s\n", strerror(errno)); } -static int +static void open_device( - char *path, - bool *is_file) + struct mdrestore_dev *dev, + char *path) { - struct stat statbuf; - int open_flags; - int fd; + struct stat statbuf; + int open_flags; open_flags = O_RDWR; - *is_file = false; + dev->is_file = false; if (stat(path, &statbuf) < 0) { /* ok, assume it's a file and create it */ open_flags |= O_CREAT; - *is_file = true; + dev->is_file = true; } else if (S_ISREG(statbuf.st_mode)) { open_flags |= O_TRUNC; - *is_file = true; + dev->is_file = true; } else if (platform_check_ismounted(path, NULL, &statbuf, 0)) { /* * check to make sure a filesystem isn't mounted on the device @@ -136,23 +143,30 @@ open_device( path); } - fd = open(path, open_flags, 0644); - if (fd < 0) + dev->fd = open(path, open_flags, 0644); + if (dev->fd < 0) fatal("couldn't open \"%s\"\n", path); +} - return fd; +static void +close_device( + struct mdrestore_dev *dev) +{ + if (dev->fd >= 0) + close(dev->fd); + dev->fd = -1; + dev->is_file = false; } static void verify_device_size( - int dev_fd, - bool is_file, - xfs_rfsblock_t nr_blocks, - uint32_t blocksize) + const struct mdrestore_dev *dev, + xfs_rfsblock_t nr_blocks, + uint32_t blocksize) { - if (is_file) { + if (dev->is_file) { /* ensure regular files are correctly sized */ - if (ftruncate(dev_fd, nr_blocks * blocksize)) + if (ftruncate(dev->fd, nr_blocks * blocksize)) fatal("cannot set filesystem image size: %s\n", strerror(errno)); } else { @@ -161,7 +175,7 @@ verify_device_size( off_t off; off = nr_blocks * blocksize - sizeof(lb); - if (pwrite(dev_fd, lb, sizeof(lb), off) < 0) + if (pwrite(dev->fd, lb, sizeof(lb), off) < 0) fatal("failed to write last block, is target too " "small? (error: %s)\n", strerror(errno)); } @@ -195,12 +209,10 @@ show_info_v1( static void restore_v1( - union mdrestore_headers *h, - FILE *md_fp, - int ddev_fd, - bool is_data_target_file, - int logdev_fd, - bool is_log_target_file) + union mdrestore_headers *h, + FILE *md_fp, + const struct mdrestore_dev *ddev, + const struct mdrestore_dev *logdev) { struct xfs_metablock *metablock; /* header + index + blocks */ __be64 *block_index; @@ -254,8 +266,7 @@ restore_v1( ((struct xfs_dsb*)block_buffer)->sb_inprogress = 1; - verify_device_size(ddev_fd, is_data_target_file, sb.sb_dblocks, - sb.sb_blocksize); + verify_device_size(ddev, sb.sb_dblocks, sb.sb_blocksize); bytes_read = 0; @@ -263,7 +274,7 @@ restore_v1( maybe_print_progress(&mb_read, bytes_read); for (cur_index = 0; cur_index < mb_count; cur_index++) { - if (pwrite(ddev_fd, &block_buffer[cur_index << + if (pwrite(ddev->fd, &block_buffer[cur_index << h->v1.mb_blocklog], block_size, be64_to_cpu(block_index[cur_index]) << BBSHIFT) < 0) @@ -292,7 +303,7 @@ restore_v1( final_print_progress(&mb_read, bytes_read); - fixup_superblock(ddev_fd, block_buffer, &sb); + fixup_superblock(ddev->fd, block_buffer, &sb); free(metablock); } @@ -376,12 +387,10 @@ restore_meta_extent( static void restore_v2( - union mdrestore_headers *h, - FILE *md_fp, - int ddev_fd, - bool is_data_target_file, - int logdev_fd, - bool is_log_target_file) + union mdrestore_headers *h, + FILE *md_fp, + const struct mdrestore_dev *ddev, + const struct mdrestore_dev *logdev) { struct xfs_sb sb; struct xfs_meta_extent xme; @@ -415,16 +424,14 @@ restore_v2( ((struct xfs_dsb *)block_buffer)->sb_inprogress = 1; - verify_device_size(ddev_fd, is_data_target_file, sb.sb_dblocks, - sb.sb_blocksize); + verify_device_size(ddev, 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); + verify_device_size(logdev, sb.sb_logblocks, sb.sb_blocksize); } - if (pwrite(ddev_fd, block_buffer, len, 0) < 0) + if (pwrite(ddev->fd, block_buffer, len, 0) < 0) fatal("error writing primary superblock: %s\n", strerror(errno)); @@ -446,11 +453,11 @@ restore_v2( switch (be64_to_cpu(xme.xme_addr) & XME_ADDR_DEVICE_MASK) { case XME_ADDR_DATA_DEVICE: device = "data"; - fd = ddev_fd; + fd = ddev->fd; break; case XME_ADDR_LOG_DEVICE: device = "log"; - fd = logdev_fd; + fd = logdev->fd; break; default: fatal("Invalid device found in metadump\n"); @@ -467,7 +474,7 @@ restore_v2( final_print_progress(&mb_read, bytes_read); - fixup_superblock(ddev_fd, block_buffer, &sb); + fixup_superblock(ddev->fd, block_buffer, &sb); free(block_buffer); } @@ -492,13 +499,11 @@ main( char **argv) { union mdrestore_headers headers; + DEFINE_MDRESTORE_DEV(ddev); + DEFINE_MDRESTORE_DEV(logdev); FILE *src_f; - char *logdev = NULL; - int data_dev_fd = -1; - int log_dev_fd = -1; + char *logdev_path = NULL; int c; - bool is_data_dev_file = false; - bool is_log_dev_file = false; mdrestore.show_progress = false; mdrestore.show_info = false; @@ -516,7 +521,7 @@ main( mdrestore.show_info = true; break; case 'l': - logdev = optarg; + logdev_path = optarg; mdrestore.external_log = true; break; case 'V': @@ -555,7 +560,7 @@ main( switch (be32_to_cpu(headers.magic)) { case XFS_MD_MAGIC_V1: - if (logdev != NULL) + if (logdev_path != NULL) usage(); mdrestore.mdrops = &mdrestore_ops_v1; break; @@ -581,18 +586,16 @@ main( optind++; /* check and open data device */ - data_dev_fd = open_device(argv[optind], &is_data_dev_file); + open_device(&ddev, argv[optind]); + /* check and open log device */ if (mdrestore.external_log) - /* check and open log device */ - log_dev_fd = open_device(logdev, &is_log_dev_file); + open_device(&logdev, logdev_path); - mdrestore.mdrops->restore(&headers, src_f, data_dev_fd, - is_data_dev_file, log_dev_fd, is_log_dev_file); + mdrestore.mdrops->restore(&headers, src_f, &ddev, &logdev); - close(data_dev_fd); - if (mdrestore.external_log) - close(log_dev_fd); + close_device(&ddev); + close_device(&logdev); if (src_f != stdin) fclose(src_f); From patchwork Thu Dec 19 19:45:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13915646 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E0F5E1B4F0D for ; Thu, 19 Dec 2024 19:45:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734637502; cv=none; b=OZkuUjWVKGPtkKdxlk3IqBjw7lJDZveBr3uhWrnUowcMY+zFvJNikrVPIieSAOD1W+mx/VVCqe3E64cZ/UU6gPmPx0XcqdDAWiL5+OXiFVm8k5AHd66+Shmelf65m8XhjDu6FQ5RF67TWOK9643XekWIFt9fUV4HbOSGUgq0yww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734637502; c=relaxed/simple; bh=zuZpHkqboysASAemrWVpwKx/+YapZ8jcK6MSaSAzO2o=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QXn+uGXDog8njLCLcN8V2BnRvLCI6hLKbVUyJ2CdSFZKX/2hEDWRBM+nVCOMIC5eoVGHdGy0cKaJ0gHl0dFqulKuFPG4JkUhmJM3WrKOK5FpkUzkI44SVkVzc0O5p77lzBnrU9JP1T+jaqF5FRpwXZZx0RwxU6+brOE7VL9FxxI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dLKQj/Ii; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dLKQj/Ii" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 84BBEC4CECE; Thu, 19 Dec 2024 19:45:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734637501; bh=zuZpHkqboysASAemrWVpwKx/+YapZ8jcK6MSaSAzO2o=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=dLKQj/Iiq4OlbfN28OJLHxi94yec6pLWYuA8N3IF7UYXh3nTeA2OY22fD4kCfTfmn RuN52ObuNZMzylukexI0AzKXkDXDhWdEkU4q+/1GlV2N7XofcmgUR2pi+uJSKw69Xb NLYRSJ/qlXSYgvYWSy+XSSEprPht1KKv6O+Kjk3kVDUHX6qax22B6xYlj9ioKeCmFf 6N69SdqObFaDGRWEac9dkvQjde5/iJp+0Y8d124+mMqpgdGU1whLmE8jGZryWLPDnJ BfhHb5ANKAU8byZTVlKmB+pnb9ZqgA8E0IvObSqV8/0yyWyStBQ3o4OdvecpNLkQic rxQOVhh/Qvbxw== Date: Thu, 19 Dec 2024 11:45:01 -0800 Subject: [PATCH 3/3] xfs_mdrestore: restore rt group superblocks to realtime device From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <173463582943.1574879.4367794239821092582.stgit@frogsfrogsfrogs> In-Reply-To: <173463582894.1574879.10113776916850781634.stgit@frogsfrogsfrogs> References: <173463582894.1574879.10113776916850781634.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Support restoring realtime device metadata to the realtime device, if the dumped filesystem had one. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- man/man8/xfs_mdrestore.8 | 10 ++++++++++ mdrestore/xfs_mdrestore.c | 47 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/man/man8/xfs_mdrestore.8 b/man/man8/xfs_mdrestore.8 index f60e7b56ebf0d1..6f6e14e96c6a5c 100644 --- a/man/man8/xfs_mdrestore.8 +++ b/man/man8/xfs_mdrestore.8 @@ -8,6 +8,9 @@ .SH SYNOPSIS ] [ .B \-l .I logdev +] [ +.B \-r +.I rtdev ] .I source .I target @@ -17,6 +20,9 @@ .SH SYNOPSIS [ .B \-l .I logdev +] [ +.B \-r +.I rtdev ] .I source .br @@ -61,6 +67,10 @@ .SH OPTIONS In such a scenario, the user has to provide a device to which the log device contents from the metadump file are copied. .TP +.BI \-r " rtdev" +Restore realtime device metadata to this device. +This is only required for a metadump in v2 format. +.TP .B \-V Prints the version number and exits. .SH DIAGNOSTICS diff --git a/mdrestore/xfs_mdrestore.c b/mdrestore/xfs_mdrestore.c index c5584fec68813e..d5014981b15a68 100644 --- a/mdrestore/xfs_mdrestore.c +++ b/mdrestore/xfs_mdrestore.c @@ -28,7 +28,8 @@ struct mdrestore_ops { void (*show_info)(union mdrestore_headers *header, const char *md_file); void (*restore)(union mdrestore_headers *header, FILE *md_fp, const struct mdrestore_dev *ddev, - const struct mdrestore_dev *logdev); + const struct mdrestore_dev *logdev, + const struct mdrestore_dev *rtdev); }; static struct mdrestore { @@ -37,6 +38,7 @@ static struct mdrestore { bool show_info; bool progress_since_warning; bool external_log; + bool realtime_data; } mdrestore; static void @@ -212,7 +214,8 @@ restore_v1( union mdrestore_headers *h, FILE *md_fp, const struct mdrestore_dev *ddev, - const struct mdrestore_dev *logdev) + const struct mdrestore_dev *logdev, + const struct mdrestore_dev *rtdev) { struct xfs_metablock *metablock; /* header + index + blocks */ __be64 *block_index; @@ -336,8 +339,9 @@ read_header_v2( if (!mdrestore.external_log && (compat & XFS_MD2_COMPAT_EXTERNALLOG)) fatal("External Log device is required\n"); - if (h->v2.xmh_incompat_flags & cpu_to_be32(XFS_MD2_INCOMPAT_RTDEVICE)) - fatal("Realtime device not yet supported\n"); + if ((h->v2.xmh_incompat_flags & cpu_to_be32(XFS_MD2_INCOMPAT_RTDEVICE)) && + !mdrestore.realtime_data) + fatal("Realtime device is required\n"); } static void @@ -346,14 +350,17 @@ show_info_v2( const char *md_file) { uint32_t compat_flags; + uint32_t incompat_flags; compat_flags = be32_to_cpu(h->v2.xmh_compat_flags); + incompat_flags = be32_to_cpu(h->v2.xmh_incompat_flags); - printf("%s: %sobfuscated, %s log, external log contents are %sdumped, %s metadata blocks,\n", + printf("%s: %sobfuscated, %s log, external log contents are %sdumped, rt device contents are %sdumped, %s metadata blocks,\n", md_file, compat_flags & XFS_MD2_COMPAT_OBFUSCATED ? "":"not ", compat_flags & XFS_MD2_COMPAT_DIRTYLOG ? "dirty":"clean", compat_flags & XFS_MD2_COMPAT_EXTERNALLOG ? "":"not ", + incompat_flags & XFS_MD2_INCOMPAT_RTDEVICE ? "":"not ", compat_flags & XFS_MD2_COMPAT_FULLBLOCKS ? "full":"zeroed"); } @@ -390,7 +397,8 @@ restore_v2( union mdrestore_headers *h, FILE *md_fp, const struct mdrestore_dev *ddev, - const struct mdrestore_dev *logdev) + const struct mdrestore_dev *logdev, + const struct mdrestore_dev *rtdev) { struct xfs_sb sb; struct xfs_meta_extent xme; @@ -431,6 +439,11 @@ restore_v2( verify_device_size(logdev, sb.sb_logblocks, sb.sb_blocksize); } + if (sb.sb_rblocks > 0) { + ASSERT(mdrestore.realtime_data == true); + verify_device_size(rtdev, sb.sb_rblocks, sb.sb_blocksize); + } + if (pwrite(ddev->fd, block_buffer, len, 0) < 0) fatal("error writing primary superblock: %s\n", strerror(errno)); @@ -459,6 +472,10 @@ restore_v2( device = "log"; fd = logdev->fd; break; + case XME_ADDR_RT_DEVICE: + device = "rt"; + fd = rtdev->fd; + break; default: fatal("Invalid device found in metadump\n"); break; @@ -488,7 +505,7 @@ static struct mdrestore_ops mdrestore_ops_v2 = { static void usage(void) { - fprintf(stderr, "Usage: %s [-V] [-g] [-i] [-l logdev] source target\n", + fprintf(stderr, "Usage: %s [-V] [-g] [-i] [-l logdev] [-r rtdev] source target\n", progname); exit(1); } @@ -501,18 +518,21 @@ main( union mdrestore_headers headers; DEFINE_MDRESTORE_DEV(ddev); DEFINE_MDRESTORE_DEV(logdev); + DEFINE_MDRESTORE_DEV(rtdev); FILE *src_f; char *logdev_path = NULL; + char *rtdev_path = NULL; int c; mdrestore.show_progress = false; mdrestore.show_info = false; mdrestore.progress_since_warning = false; mdrestore.external_log = false; + mdrestore.realtime_data = false; progname = basename(argv[0]); - while ((c = getopt(argc, argv, "gil:V")) != EOF) { + while ((c = getopt(argc, argv, "gil:r:V")) != EOF) { switch (c) { case 'g': mdrestore.show_progress = true; @@ -524,6 +544,10 @@ main( logdev_path = optarg; mdrestore.external_log = true; break; + case 'r': + rtdev_path = optarg; + mdrestore.realtime_data = true; + break; case 'V': printf("%s version %s\n", progname, VERSION); exit(0); @@ -592,10 +616,15 @@ main( if (mdrestore.external_log) open_device(&logdev, logdev_path); - mdrestore.mdrops->restore(&headers, src_f, &ddev, &logdev); + /* check and open realtime device */ + if (mdrestore.realtime_data) + open_device(&rtdev, rtdev_path); + + mdrestore.mdrops->restore(&headers, src_f, &ddev, &logdev, &rtdev); close_device(&ddev); close_device(&logdev); + close_device(&rtdev); if (src_f != stdin) fclose(src_f);