All of lore.kernel.org
 help / color / mirror / Atom feed
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
> 


  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 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.