All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: cem@kernel.org, djwong@kernel.org
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 03/10] xfs_db: get and put blocks on the AGFL
Date: Sun, 31 Dec 2023 16:40:45 +9900	[thread overview]
Message-ID: <170405020364.1820796.4627927059186718750.stgit@frogsfrogsfrogs> (raw)
In-Reply-To: <170405020316.1820796.451112156000559887.stgit@frogsfrogsfrogs>

From: Darrick J. Wong <djwong@kernel.org>

Add a new xfs_db command to let people add and remove blocks from an
AGFL.  This isn't really related to rmap btree reconstruction, other
than enabling debugging code to mess around with the AGFL to exercise
various odd scenarios.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 db/agfl.c                |  297 ++++++++++++++++++++++++++++++++++++++++++++++
 libxfs/libxfs_api_defs.h |    4 +
 man/man8/xfs_db.8        |   11 ++
 3 files changed, 308 insertions(+), 4 deletions(-)


diff --git a/db/agfl.c b/db/agfl.c
index f0f3f21a64d..662b6403cb2 100644
--- a/db/agfl.c
+++ b/db/agfl.c
@@ -15,13 +15,14 @@
 #include "output.h"
 #include "init.h"
 #include "agfl.h"
+#include "libfrog/bitmap.h"
 
 static int agfl_bno_size(void *obj, int startoff);
 static int agfl_f(int argc, char **argv);
 static void agfl_help(void);
 
 static const cmdinfo_t agfl_cmd =
-	{ "agfl", NULL, agfl_f, 0, 1, 1, N_("[agno]"),
+	{ "agfl", NULL, agfl_f, 0, -1, 1, N_("[agno] [-g nr] [-p nr]"),
 	  N_("set address to agfl block"), agfl_help };
 
 const field_t	agfl_hfld[] = { {
@@ -77,10 +78,280 @@ agfl_help(void)
 " for each allocation group.  This acts as a reserved pool of space\n"
 " separate from the general filesystem freespace (not used for user data).\n"
 "\n"
+" -g quantity\tRemove this many blocks from the AGFL.\n"
+" -p quantity\tAdd this many blocks to the AGFL.\n"
+"\n"
 ));
 
 }
 
+struct dump_info {
+	struct xfs_perag	*pag;
+	bool			leak;
+};
+
+/* Return blocks freed from the AGFL to the free space btrees. */
+static int
+free_grabbed(
+	uint64_t		start,
+	uint64_t		length,
+	void			*data)
+{
+	struct dump_info	*di = data;
+	struct xfs_perag	*pag = di->pag;
+	struct xfs_mount	*mp = pag->pag_mount;
+	struct xfs_trans	*tp;
+	struct xfs_buf		*agf_bp;
+	int			error;
+
+	error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0,
+			&tp);
+	if (error)
+		return error;
+
+	error = -libxfs_alloc_read_agf(pag, tp, 0, &agf_bp);
+	if (error)
+		goto out_cancel;
+
+	error = -libxfs_free_extent(tp, pag, start, length, &XFS_RMAP_OINFO_AG,
+			XFS_AG_RESV_AGFL);
+	if (error)
+		goto out_cancel;
+
+	return -libxfs_trans_commit(tp);
+
+out_cancel:
+	libxfs_trans_cancel(tp);
+	return error;
+}
+
+/* Report blocks freed from the AGFL. */
+static int
+dump_grabbed(
+	uint64_t		start,
+	uint64_t		length,
+	void			*data)
+{
+	struct dump_info	*di = data;
+	const char		*fmt;
+
+	if (length == 1)
+		fmt = di->leak ? _("agfl %u: leaked agbno %u\n") :
+				 _("agfl %u: removed agbno %u\n");
+	else
+		fmt = di->leak ? _("agfl %u: leaked agbno %u-%u\n") :
+				 _("agfl %u: removed agbno %u-%u\n");
+
+	printf(fmt, di->pag->pag_agno, (unsigned int)start,
+			(unsigned int)(start + length - 1));
+	return 0;
+}
+
+/* Remove blocks from the AGFL. */
+static int
+agfl_get(
+	struct xfs_perag	*pag,
+	int			quantity)
+{
+	struct dump_info	di = {
+		.pag		= pag,
+		.leak		= quantity < 0,
+	};
+	struct xfs_agf		*agf;
+	struct xfs_buf		*agf_bp;
+	struct xfs_trans	*tp;
+	struct bitmap		*grabbed;
+	const unsigned int	agfl_size = libxfs_agfl_size(pag->pag_mount);
+	unsigned int		i;
+	int			error;
+
+	if (!quantity)
+		return 0;
+
+	if (di.leak)
+		quantity = -quantity;
+	quantity = min(quantity, agfl_size);
+
+	error = bitmap_alloc(&grabbed);
+	if (error)
+		goto out;
+
+	error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, quantity, 0,
+			0, &tp);
+	if (error)
+		goto out_bitmap;
+
+	error = -libxfs_alloc_read_agf(pag, tp, 0, &agf_bp);
+	if (error)
+		goto out_cancel;
+
+	agf = agf_bp->b_addr;
+	quantity = min(quantity, be32_to_cpu(agf->agf_flcount));
+
+	for (i = 0; i < quantity; i++) {
+		xfs_agblock_t	agbno;
+
+		error = -libxfs_alloc_get_freelist(pag, tp, agf_bp, &agbno, 0);
+		if (error)
+			goto out_cancel;
+
+		if (agbno == NULLAGBLOCK) {
+			error = ENOSPC;
+			goto out_cancel;
+		}
+
+		error = bitmap_set(grabbed, agbno, 1);
+		if (error)
+			goto out_cancel;
+	}
+
+	error = -libxfs_trans_commit(tp);
+	if (error)
+		goto out_bitmap;
+
+	error = bitmap_iterate(grabbed, dump_grabbed, &di);
+	if (error)
+		goto out_bitmap;
+
+	if (!di.leak) {
+		error = bitmap_iterate(grabbed, free_grabbed, &di);
+		if (error)
+			goto out_bitmap;
+	}
+
+	bitmap_free(&grabbed);
+	return 0;
+
+out_cancel:
+	libxfs_trans_cancel(tp);
+out_bitmap:
+	bitmap_free(&grabbed);
+out:
+	if (error)
+		printf(_("agfl %u: %s\n"), pag->pag_agno, strerror(error));
+	return error;
+}
+
+/* Add blocks to the AGFL. */
+static int
+agfl_put(
+	struct xfs_perag	*pag,
+	int			quantity)
+{
+	struct xfs_alloc_arg	args = {
+		.mp		= pag->pag_mount,
+		.alignment	= 1,
+		.minlen		= 1,
+		.prod		= 1,
+		.resv		= XFS_AG_RESV_AGFL,
+		.oinfo		= XFS_RMAP_OINFO_AG,
+	};
+	struct xfs_buf		*agfl_bp;
+	struct xfs_agf		*agf;
+	struct xfs_trans	*tp;
+	xfs_fsblock_t		target;
+	const unsigned int	agfl_size = libxfs_agfl_size(pag->pag_mount);
+	unsigned int		i;
+	bool			eoag = quantity < 0;
+	int			error;
+
+	if (!quantity)
+		return 0;
+
+	if (eoag)
+		quantity = -quantity;
+	quantity = min(quantity, agfl_size);
+
+	error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, quantity, 0,
+			0, &tp);
+	if (error)
+		return error;
+	args.tp = tp;
+
+	error = -libxfs_alloc_read_agf(pag, tp, 0, &args.agbp);
+	if (error)
+		goto out_cancel;
+
+	agf = args.agbp->b_addr;
+	args.maxlen = min(quantity, agfl_size - be32_to_cpu(agf->agf_flcount));
+
+	if (eoag)
+		target = XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
+				be32_to_cpu(agf->agf_length) - 1);
+	else
+		target = XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno, 0);
+
+	error = -libxfs_alloc_read_agfl(pag, tp, &agfl_bp);
+	if (error)
+		goto out_cancel;
+
+	error = -libxfs_alloc_vextent_near_bno(&args, target);
+	if (error)
+		goto out_cancel;
+
+	if (args.agbno == NULLAGBLOCK) {
+		error = ENOSPC;
+		goto out_cancel;
+	}
+
+	for (i = 0; i < args.len; i++) {
+		error = -libxfs_alloc_put_freelist(pag, tp, args.agbp,
+				agfl_bp, args.agbno + i, 0);
+		if (error)
+			goto out_cancel;
+	}
+
+	if (i == 1)
+		printf(_("agfl %u: added agbno %u\n"), pag->pag_agno,
+				args.agbno);
+	else if (i > 1)
+		printf(_("agfl %u: added agbno %u-%u\n"), pag->pag_agno,
+				args.agbno, args.agbno + i - 1);
+
+	error = -libxfs_trans_commit(tp);
+	if (error)
+		goto out;
+
+	return 0;
+
+out_cancel:
+	libxfs_trans_cancel(tp);
+out:
+	if (error)
+		printf(_("agfl %u: %s\n"), pag->pag_agno, strerror(error));
+	return error;
+}
+
+static void
+agfl_adjust(
+	struct xfs_mount	*mp,
+	xfs_agnumber_t		agno,
+	int			gblocks,
+	int			pblocks)
+{
+	struct xfs_perag	*pag;
+	int			error;
+
+	if (!expert_mode) {
+		printf(_("AGFL get/put only supported in expert mode.\n"));
+		exitcode = 1;
+		return;
+	}
+
+	pag = libxfs_perag_get(mp, agno);
+
+	error = agfl_get(pag, gblocks);
+	if (error)
+		goto out_pag;
+
+	error = agfl_put(pag, pblocks);
+
+out_pag:
+	libxfs_perag_put(pag);
+	if (error)
+		exitcode = 1;
+}
+
 static int
 agfl_f(
 	int		argc,
@@ -88,9 +359,25 @@ agfl_f(
 {
 	xfs_agnumber_t	agno;
 	char		*p;
+	int		c;
+	int		gblocks = 0, pblocks = 0;
 
-	if (argc > 1) {
-		agno = (xfs_agnumber_t)strtoul(argv[1], &p, 0);
+	while ((c = getopt(argc, argv, "g:p:")) != -1) {
+		switch (c) {
+		case 'g':
+			gblocks = atoi(optarg);
+			break;
+		case 'p':
+			pblocks = atoi(optarg);
+			break;
+		default:
+			agfl_help();
+			return 1;
+		}
+	}
+
+	if (argc > optind) {
+		agno = (xfs_agnumber_t)strtoul(argv[optind], &p, 0);
 		if (*p != '\0' || agno >= mp->m_sb.sb_agcount) {
 			dbprintf(_("bad allocation group number %s\n"), argv[1]);
 			return 0;
@@ -98,6 +385,10 @@ agfl_f(
 		cur_agno = agno;
 	} else if (cur_agno == NULLAGNUMBER)
 		cur_agno = 0;
+
+	if (gblocks || pblocks)
+		agfl_adjust(mp, cur_agno, gblocks, pblocks);
+
 	ASSERT(typtab[TYP_AGFL].typnm == TYP_AGFL);
 	set_cur(&typtab[TYP_AGFL],
 		XFS_AG_DADDR(mp, cur_agno, XFS_AGFL_DADDR(mp)),
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 4e7b3caba4b..52616086ef0 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -30,8 +30,12 @@
 #define xfs_allocbt_maxrecs		libxfs_allocbt_maxrecs
 #define xfs_allocbt_stage_cursor	libxfs_allocbt_stage_cursor
 #define xfs_alloc_fix_freelist		libxfs_alloc_fix_freelist
+#define xfs_alloc_get_freelist		libxfs_alloc_get_freelist
 #define xfs_alloc_min_freelist		libxfs_alloc_min_freelist
+#define xfs_alloc_put_freelist		libxfs_alloc_put_freelist
 #define xfs_alloc_read_agf		libxfs_alloc_read_agf
+#define xfs_alloc_read_agfl		libxfs_alloc_read_agfl
+#define xfs_alloc_vextent_near_bno	libxfs_alloc_vextent_near_bno
 #define xfs_alloc_vextent_start_ag	libxfs_alloc_vextent_start_ag
 
 #define xfs_ascii_ci_hashname		libxfs_ascii_ci_hashname
diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
index 3e80bcc57de..39461398c6a 100644
--- a/man/man8/xfs_db.8
+++ b/man/man8/xfs_db.8
@@ -182,10 +182,19 @@ Set current address to the AGF block for allocation group
 .IR agno .
 If no argument is given, use the current allocation group.
 .TP
-.BI "agfl [" agno ]
+.BI "agfl [" agno "] [\-g " " quantity" "] [\-p " quantity ]
 Set current address to the AGFL block for allocation group
 .IR agno .
 If no argument is given, use the current allocation group.
+If the
+.B -g
+option is specified with a positive quantity, remove that many blocks from the
+AGFL and put them in the free space btrees.
+If the quantity is negative, remove the blocks and leak them.
+If the
+.B -p
+option is specified, add that many blocks to the AGFL.
+If the quantity is negative, the blocks are selected from the end of the AG.
 .TP
 .BI "agi [" agno ]
 Set current address to the AGI block for allocation group


  parent reply	other threads:[~2024-01-01  0:40 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-31 18:25 [NYE PATCHRIVER 4/4] xfs: freespace defrag for online shrink Darrick J. Wong
2023-12-31 19:38 ` [PATCHSET 1/5] xfs: improve post-close eofblocks gc behavior Darrick J. Wong
2023-12-31 22:00   ` [PATCH 1/3] xfs: only free posteof blocks on first close Darrick J. Wong
2023-12-31 22:00   ` [PATCH 2/3] xfs: don't free EOF blocks on read close Darrick J. Wong
2023-12-31 22:00   ` [PATCH 3/3] xfs: Don't free EOF blocks on close when extent size hints are set Darrick J. Wong
2023-12-31 19:38 ` [PATCHSET RFC 2/5] xfs: noalloc allocation groups Darrick J. Wong
2023-12-31 22:00   ` [PATCH 1/5] xfs: track deferred ops statistics Darrick J. Wong
2023-12-31 22:01   ` [PATCH 2/5] xfs: whine to dmesg when we encounter errors Darrick J. Wong
2023-12-31 22:01   ` [PATCH 3/5] xfs: create a noalloc mode for allocation groups Darrick J. Wong
2023-12-31 22:01   ` [PATCH 4/5] xfs: enable userspace to hide an AG from allocation Darrick J. Wong
2023-12-31 22:02   ` [PATCH 5/5] xfs: apply noalloc mode to inode allocations too Darrick J. Wong
2023-12-31 19:39 ` [PATCHSET 3/5] xfs: report refcount information to userspace Darrick J. Wong
2023-12-31 22:02   ` [PATCH 1/1] xfs: export reference count " Darrick J. Wong
2023-12-31 19:39 ` [PATCHSET 4/5] xfs: defragment free space Darrick J. Wong
2023-12-31 22:02   ` [PATCH 1/2] xfs: capture the offset and length in fallocate tracepoints Darrick J. Wong
2023-12-31 22:02   ` [PATCH 2/2] xfs: add an ioctl to map free space into a file Darrick J. Wong
2023-12-31 19:39 ` [PATCHSET v2 5/5] xfs: aligned file data extent mappings Darrick J. Wong
2023-12-31 22:03   ` [PATCH 1/4] xfs: create a new inode flag to require extsize alignment of file data space Darrick J. Wong
2023-12-31 22:03   ` [PATCH 2/4] xfs: make file data allocations observe the 'forcealign' flag Darrick J. Wong
2024-01-16  9:26     ` John Garry
2023-12-31 22:03   ` [PATCH 3/4] xfs: support reflink with force align enabled Darrick J. Wong
2023-12-31 22:03   ` [PATCH 4/4] xfs: enable file data force-align feature Darrick J. Wong
2023-12-31 19:56 ` [PATCHSET RFC 1/3] xfsprogs: noalloc allocation groups Darrick J. Wong
2023-12-27 13:38   ` [PATCH 1/5] xfs: track deferred ops statistics Darrick J. Wong
2023-12-27 13:38   ` [PATCH 2/5] xfs: create a noalloc mode for allocation groups Darrick J. Wong
2023-12-27 13:38   ` [PATCH 3/5] xfs: enable userspace to hide an AG from allocation Darrick J. Wong
2023-12-27 13:39   ` [PATCH 4/5] xfs: apply noalloc mode to inode allocations too Darrick J. Wong
2023-12-27 13:39   ` [PATCH 5/5] xfs_io: enhance the aginfo command to control the noalloc flag Darrick J. Wong
2023-12-31 19:56 ` [PATCHSET 2/3] xfsprogs: report refcount information to userspace Darrick J. Wong
2023-12-27 13:39   ` [PATCH 1/2] xfs: export reference count " Darrick J. Wong
2023-12-27 13:39   ` [PATCH 2/2] xfs_io: dump reference count information Darrick J. Wong
2023-12-31 19:56 ` [PATCHSET 3/3] xfsprogs: defragment free space Darrick J. Wong
2023-12-27 13:40   ` [PATCH 01/10] xfs: add an ioctl to map free space into a file Darrick J. Wong
2023-12-27 13:40   ` [PATCH 02/10] xfs_io: support using XFS_IOC_MAP_FREESP to map free space Darrick J. Wong
2023-12-27 13:40   ` Darrick J. Wong [this message]
2023-12-27 13:41   ` [PATCH 04/10] xfs_spaceman: implement clearing " Darrick J. Wong
2023-12-27 13:41   ` [PATCH 05/10] spaceman: physically move a regular inode Darrick J. Wong
2023-12-27 13:41   ` [PATCH 06/10] spaceman: find owners of space in an AG Darrick J. Wong
2023-12-27 13:41   ` [PATCH 07/10] xfs_spaceman: wrap radix tree accesses in find_owner.c Darrick J. Wong
2023-12-27 13:42   ` [PATCH 08/10] xfs_spaceman: port relocation structure to 32-bit systems Darrick J. Wong
2023-12-27 13:42   ` [PATCH 09/10] spaceman: relocate the contents of an AG Darrick J. Wong
2023-12-27 13:42   ` [PATCH 10/10] spaceman: move inodes with hardlinks Darrick J. Wong
2023-12-31 20:02 ` [PATCHSET 1/2] fstests: functional test for refcount reporting Darrick J. Wong
2023-12-27 14:06   ` [PATCH 1/2] xfs/122: update for the getfsrefs ioctl Darrick J. Wong
2023-12-27 14:06   ` [PATCH 2/2] xfs: test output of new FSREFCOUNTS ioctl Darrick J. Wong
2023-12-31 20:02 ` [PATCHSET 2/2] fstests: defragment free space Darrick J. Wong
2023-12-27 14:06   ` [PATCH 1/2] xfs/122: update for XFS_IOC_MAP_FREESP Darrick J. Wong
2023-12-27 14:07   ` [PATCH 2/2] xfs: test clearing of free space 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=170405020364.1820796.4627927059186718750.stgit@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=cem@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.