From: Bill O'Donnell <bodonnel@redhat.com>
To: "Darrick J. Wong" <djwong@kernel.org>
Cc: Dave Chinner <david@fromorbit.com>,
Eric Sandeen <sandeen@redhat.com>,
xfs <linux-xfs@vger.kernel.org>,
shrikanth hegde <sshegde@linux.vnet.ibm.com>,
Ritesh Harjani <ritesh.list@gmail.com>
Subject: Re: [PATCH 1/2] xfs_db: dump unlinked buckets
Date: Thu, 31 Aug 2023 15:01:08 -0500 [thread overview]
Message-ID: <ZPDxhOTVrt27rZXU@redhat.com> (raw)
In-Reply-To: <20230830232509.GK28186@frogsfrogsfrogs>
On Wed, Aug 30, 2023 at 04:25:09PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
>
> Create a new command to dump the resource usage of files in the unlinked
> buckets.
>
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Bill O'Donnell <bodonnel@redhat.com>
> ---
> db/Makefile | 2
> db/command.c | 1
> db/command.h | 1
> db/iunlink.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++
> libxfs/libxfs_api_defs.h | 1
> man/man8/xfs_db.8 | 19 ++++
> 6 files changed, 227 insertions(+), 1 deletion(-)
> create mode 100644 db/iunlink.c
>
> diff --git a/db/Makefile b/db/Makefile
> index 2f95f670..d00801ab 100644
> --- a/db/Makefile
> +++ b/db/Makefile
> @@ -14,7 +14,7 @@ HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \
> io.h logformat.h malloc.h metadump.h output.h print.h quit.h sb.h \
> sig.h strvec.h text.h type.h write.h attrset.h symlink.h fsmap.h \
> fuzz.h obfuscate.h
> -CFILES = $(HFILES:.h=.c) btdump.c btheight.c convert.c info.c namei.c \
> +CFILES = $(HFILES:.h=.c) btdump.c btheight.c convert.c info.c iunlink.c namei.c \
> timelimit.c
> LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh
>
> diff --git a/db/command.c b/db/command.c
> index 02f778b9..b4021c86 100644
> --- a/db/command.c
> +++ b/db/command.c
> @@ -127,6 +127,7 @@ init_commands(void)
> info_init();
> inode_init();
> input_init();
> + iunlink_init();
> logres_init();
> logformat_init();
> io_init();
> diff --git a/db/command.h b/db/command.h
> index 498983ff..a89e7150 100644
> --- a/db/command.h
> +++ b/db/command.h
> @@ -34,3 +34,4 @@ extern void info_init(void);
> extern void btheight_init(void);
> extern void timelimit_init(void);
> extern void namei_init(void);
> +extern void iunlink_init(void);
> diff --git a/db/iunlink.c b/db/iunlink.c
> new file mode 100644
> index 00000000..303b5daf
> --- /dev/null
> +++ b/db/iunlink.c
> @@ -0,0 +1,204 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2022-2023 Oracle. All Rights Reserved.
> + * Author: Darrick J. Wong <djwong@kernel.org>
> + */
> +#include "libxfs.h"
> +#include "command.h"
> +#include "output.h"
> +#include "init.h"
> +
> +static xfs_filblks_t
> +count_rtblocks(
> + struct xfs_inode *ip)
> +{
> + struct xfs_iext_cursor icur;
> + struct xfs_bmbt_irec got;
> + xfs_filblks_t count = 0;
> + struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
> + int error;
> +
> + error = -libxfs_iread_extents(NULL, ip, XFS_DATA_FORK);
> + if (error) {
> + dbprintf(
> +_("could not read AG %u agino %u extents, err=%d\n"),
> + XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
> + XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
> + error);
> + return 0;
> + }
> +
> + for_each_xfs_iext(ifp, &icur, &got)
> + if (!isnullstartblock(got.br_startblock))
> + count += got.br_blockcount;
> + return count;
> +}
> +
> +static xfs_agino_t
> +get_next_unlinked(
> + xfs_agnumber_t agno,
> + xfs_agino_t agino,
> + bool verbose)
> +{
> + struct xfs_buf *ino_bp;
> + struct xfs_dinode *dip;
> + struct xfs_inode *ip;
> + xfs_ino_t ino;
> + xfs_agino_t ret;
> + int error;
> +
> + ino = XFS_AGINO_TO_INO(mp, agno, agino);
> + error = -libxfs_iget(mp, NULL, ino, 0, &ip);
> + if (error)
> + goto bad;
> +
> + if (verbose) {
> + xfs_filblks_t blocks, rtblks = 0;
> +
> + if (XFS_IS_REALTIME_INODE(ip))
> + rtblks = count_rtblocks(ip);
> + blocks = ip->i_nblocks - rtblks;
> +
> + dbprintf(_(" blocks %llu rtblocks %llu\n"),
> + blocks, rtblks);
> + } else {
> + dbprintf("\n");
> + }
> +
> + error = -libxfs_imap_to_bp(mp, NULL, &ip->i_imap, &ino_bp);
> + if (error)
> + goto bad;
> +
> + dip = xfs_buf_offset(ino_bp, ip->i_imap.im_boffset);
> + ret = be32_to_cpu(dip->di_next_unlinked);
> + libxfs_buf_relse(ino_bp);
> +
> + return ret;
> +bad:
> + dbprintf(_("AG %u agino %u: %s\n"), agno, agino, strerror(error));
> + return NULLAGINO;
> +}
> +
> +static void
> +dump_unlinked_bucket(
> + xfs_agnumber_t agno,
> + struct xfs_buf *agi_bp,
> + unsigned int bucket,
> + bool quiet,
> + bool verbose)
> +{
> + struct xfs_agi *agi = agi_bp->b_addr;
> + xfs_agino_t agino;
> + unsigned int i = 0;
> +
> + agino = be32_to_cpu(agi->agi_unlinked[bucket]);
> + if (agino != NULLAGINO)
> + dbprintf(_("AG %u bucket %u agino %u"), agno, bucket, agino);
> + else if (!quiet && agino == NULLAGINO)
> + dbprintf(_("AG %u bucket %u agino NULL\n"), agno, bucket);
> +
> + while (agino != NULLAGINO) {
> + agino = get_next_unlinked(agno, agino, verbose);
> + if (agino != NULLAGINO)
> + dbprintf(_(" [%u] agino %u"), i++, agino);
> + else if (!quiet && agino == NULLAGINO)
> + dbprintf(_(" [%u] agino NULL\n"), i++);
> + }
> +}
> +
> +static void
> +dump_unlinked(
> + struct xfs_perag *pag,
> + unsigned int bucket,
> + bool quiet,
> + bool verbose)
> +{
> + struct xfs_buf *agi_bp;
> + xfs_agnumber_t agno = pag->pag_agno;
> + int error;
> +
> + error = -libxfs_ialloc_read_agi(pag, NULL, &agi_bp);
> + if (error) {
> + dbprintf(_("AGI %u: %s\n"), agno, strerror(errno));
> + return;
> + }
> +
> + if (bucket != -1U) {
> + dump_unlinked_bucket(agno, agi_bp, bucket, quiet, verbose);
> + goto relse;
> + }
> +
> + for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
> + dump_unlinked_bucket(agno, agi_bp, bucket, quiet, verbose);
> + }
> +
> +relse:
> + libxfs_buf_relse(agi_bp);
> +}
> +
> +static int
> +dump_iunlinked_f(
> + int argc,
> + char **argv)
> +{
> + struct xfs_perag *pag;
> + xfs_agnumber_t agno = NULLAGNUMBER;
> + unsigned int bucket = -1U;
> + bool quiet = false;
> + bool verbose = false;
> + int c;
> +
> + while ((c = getopt(argc, argv, "a:b:qv")) != EOF) {
> + switch (c) {
> + case 'a':
> + agno = atoi(optarg);
> + if (agno >= mp->m_sb.sb_agcount) {
> + dbprintf(_("Unknown AG %u, agcount is %u.\n"),
> + agno, mp->m_sb.sb_agcount);
> + return 0;
> + }
> + break;
> + case 'b':
> + bucket = atoi(optarg);
> + if (bucket >= XFS_AGI_UNLINKED_BUCKETS) {
> + dbprintf(_("Unknown bucket %u, max is 63.\n"),
> + bucket);
> + return 0;
> + }
> + break;
> + case 'q':
> + quiet = true;
> + break;
> + case 'v':
> + verbose = true;
> + break;
> + default:
> + dbprintf(_("Bad option for dump_iunlinked command.\n"));
> + return 0;
> + }
> + }
> +
> + if (agno != NULLAGNUMBER) {
> + struct xfs_perag *pag = libxfs_perag_get(mp, agno);
> +
> + dump_unlinked(pag, bucket, quiet, verbose);
> + libxfs_perag_put(pag);
> + return 0;
> + }
> +
> + for_each_perag(mp, agno, pag)
> + dump_unlinked(pag, bucket, quiet, verbose);
> +
> + return 0;
> +}
> +
> +static const cmdinfo_t dump_iunlinked_cmd =
> + { "dump_iunlinked", NULL, dump_iunlinked_f, 0, -1, 0,
> + N_("[-a agno] [-b bucket] [-q] [-v]"),
> + N_("dump chain of unlinked inode buckets"), NULL };
> +
> +void
> +iunlink_init(void)
> +{
> + add_command(&dump_iunlinked_cmd);
> +}
> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> index 026aa510..ddba5c7c 100644
> --- a/libxfs/libxfs_api_defs.h
> +++ b/libxfs/libxfs_api_defs.h
> @@ -125,6 +125,7 @@
> #define xfs_idestroy_fork libxfs_idestroy_fork
> #define xfs_iext_lookup_extent libxfs_iext_lookup_extent
> #define xfs_ifork_zap_attr libxfs_ifork_zap_attr
> +#define xfs_imap_to_bp libxfs_imap_to_bp
> #define xfs_initialize_perag libxfs_initialize_perag
> #define xfs_initialize_perag_data libxfs_initialize_perag_data
> #define xfs_init_local_fork libxfs_init_local_fork
> diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
> index 60dcdc52..2d6d0da4 100644
> --- a/man/man8/xfs_db.8
> +++ b/man/man8/xfs_db.8
> @@ -579,6 +579,25 @@ print the current debug option bits. These are for the use of the implementor.
> .BI "dquot [" \-g | \-p | \-u ] " id"
> Set current address to a group, project or user quota block for the given ID. Defaults to user quota.
> .TP
> +.BI "dump_iunlinked [-a " agno " ] [-b " bucket " ] [-q] [-v]"
> +Dump the contents of unlinked buckets.
> +
> +Options include:
> +.RS 1.0i
> +.TP 0.4i
> +.B \-a
> +Print only this AG's unlinked buckets.
> +.TP 0.4i
> +.B \-b
> +Print only this bucket within each AGI.
> +.TP 0.4i
> +.B \-q
> +Only print the essentials.
> +.TP 0.4i
> +.B \-v
> +Print resource usage of each file on the unlinked lists.
> +.RE
> +.TP
> .BI "echo [" arg "] ..."
> Echo the arguments to the output.
> .TP
>
next prev parent reply other threads:[~2023-08-31 20:02 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-30 15:26 [PATCH v2] xfs: load uncached unlinked inodes into memory on demand Darrick J. Wong
2023-08-30 22:29 ` Dave Chinner
2023-08-30 23:25 ` [PATCH 1/2] xfs_db: dump unlinked buckets Darrick J. Wong
2023-08-31 20:01 ` Bill O'Donnell [this message]
2023-08-30 23:25 ` [PATCH 2/2] xfs_db: create unlinked inodes Darrick J. Wong
2023-08-31 20:02 ` Bill O'Donnell
2023-08-30 23:26 ` [RFC PATCH] fstests: test unlinked inode list repair on demand Darrick J. Wong
2023-08-31 12:39 ` [PATCH v2] xfs: load uncached unlinked inodes into memory " Ritesh Harjani
2023-08-31 20:39 ` Eric Sandeen
2023-08-31 22:44 ` Darrick J. Wong
2023-08-31 17:43 ` Eric Sandeen
2023-08-31 18:10 ` Bill O'Donnell
2023-08-31 20:18 ` Bill O'Donnell
2023-09-01 14:31 ` Bill O'Donnell
-- strict thread matches above, loose matches on Subject: below --
2023-09-25 21:59 [PATCHSET 0/2] xfsprogs: reload the last iunlink item Darrick J. Wong
2023-09-25 21:59 ` [PATCH 1/2] xfs_db: dump unlinked buckets 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=ZPDxhOTVrt27rZXU@redhat.com \
--to=bodonnel@redhat.com \
--cc=david@fromorbit.com \
--cc=djwong@kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=ritesh.list@gmail.com \
--cc=sandeen@redhat.com \
--cc=sshegde@linux.vnet.ibm.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox