[PATCH 2/2] xfs_spaceman: Accounting for AGFL blocks
Dhruvesh Rathore
adrscube at gmail.com
Fri Jan 16 06:10:40 CST 2015
Here is the original discussion that Dave wrote for xfs_spaceman:
http://oss.sgi.com/archives/xfs/2012-10/msg00363.html
These patches were not posted and were just forward ported to a current
3.18-rc7+ for-next XFS tree and were pushed to the fiemapfs branch in Dave's
kernel tree at:
git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git
The original xfs_spaceman tool that Dave wrote is here:
http://oss.sgi.com/archives/xfs/2012-10/msg00366.html
Dave just updated it to the 3.2.2 code base and pushed it to the
spaceman branch in this tree:
git://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git
This xfs_spaceman utility previously failed to account for AGFL blocks.
Old output (Before changes).
$ sudo xfs_spaceman -c "freesp" /media/xfs
from to extents blocks pct
1024 2047 1 1262 0.04
4096 8191 1 5126 0.15
8192 16383 3 35344 1.05
32768 65535 1 43989 1.31
262144 524287 3 1334894 39.78
524288 967428 2 1934840 57.66
As you can see the AGFL blocks were unaccounted (4 per AG, and there
were 4 AGs in this filesystem).
This patch is concerned with adding a new function which will walk the free
extents in AGFL and account for these AGFL blocks, while file system scanning.
New output (After implementing this patch).
$ uname -a
Linux dhruv-MacBookAir 3.18.0-rc7+ #3 SMP Thu Dec 25 15:29:59 IST 2014 x86_64 x86_64 x86_64 GNU/Linux
$ sudo xfs_spaceman -V
xfs_spaceman version 3.2.2
$ sudo xfs_spaceman -c "freesp" /media/xfs
from to extents blocks pct
1 1 16 16 0.00
1024 2047 1 1262 0.04
4096 8191 1 5126 0.15
8192 16383 3 35344 1.05
32768 65535 1 43989 1.31
262144 524287 3 1334894 39.78
524288 967428 2 1934840 57.66
Please do comment.
Signed-off-by:
Dhruvesh Rathore <dhruvesh_r at outlook.com>
Amey Ruikar <ameyruikar at yahoo.com>
Somdeep Dey <somdeepdey10 at gmail.com>
---
linux-xfs/fs/xfs/libxfs/xfs_alloc.c | 81 +++
1 file changed, 81 insertions(+)
-------------------------------------------------------------------------------------------
--- a/linux-xfs/fs/xfs/libxfs/xfs_alloc.c 2015-01-08 19:34:52.927862215 +0530
+++ b/linux-xfs/fs/xfs/libxfs/xfs_alloc.c 2015-01-09 14:25:23.853599350 +0530
@@ -2697,6 +2697,83 @@
}
+
+/*
+ * Walk the free extents in the AGFL (AG Free List) of each AG, and dump
+ * them all into the fieinfo.
+ *
+ * With a freshly made filesystem, 4 blocks are reserved immediately after
+ * the free space B+tree root blocks (blocks 4 to 7). As they are used up
+ * additional blocks are reserved from the AG and added to the free list
+ * array. A typical device will have space for 128 elements in the array.
+ * The actual size can be determined using XFS_AGFL_SIZE macro. The array
+ * is maintained as a circular list and active elements are pointed by
+ * AGF's agf_flfirst, agf_fllast and agf_flcount values.
+ */
+static int
+xfs_alloc_agfl_freespace_map(
+ struct xfs_buf **agbp, /* buffer for a.g. freelist header */
+ struct xfs_btree_cur *cur,
+ struct fiemap_extent_info *fieinfo,
+ xfs_agblock_t sagbno,
+ xfs_agblock_t eagbno)
+{
+ xfs_agf_t *agf; /* a.g. freespace structure */
+ xfs_buf_t *agflbp; /* buffer for a.g. freelist structure */
+ __be32 *agfl_bno; /* Reference to freelist block */
+ int j;
+ int index;
+ int error = 0;
+
+ agf = XFS_BUF_TO_AGF(*agbp);
+ error = xfs_alloc_read_agfl(cur->bc_mp, NULL, be32_to_cpu(agf->agf_seqno),
+ &agflbp);
+ if (error)
+ return error;
+
+ agfl_bno = XFS_BUF_TO_AGFL_BNO(cur->bc_mp, agflbp);
+
+ index = be32_to_cpu(agf->agf_flfirst);
+
+ for(j=1 ; j<=be32_to_cpu(agf->agf_flcount); j++)
+ {
+ xfs_agblock_t fbno;
+ xfs_extlen_t flen;
+ xfs_daddr_t dbno;
+ xfs_fileoff_t dlen;
+ int flags = 0;
+
+ /* Relative AG block number */
+ fbno = be32_to_cpu(agfl_bno[index]);
+ /* Each entry in the AGFL is a single entry i.e length is 1 block */
+ flen = 1;
+
+ /*
+ * AGFL is maintained as a circular list. Following is needed
+ * to handle array wrapping correctly.
+ */
+ if( index == ( (XFS_AGFL_SIZE(cur->bc_mp))-1 ) )
+ index = 0; /* First index of AGFL */
+ else
+ index++; /* Next index in AGFL */
+
+ /*
+ * Use daddr format for all range/len calculations as that is
+ * the format the range/len variables are supplied in by
+ * userspace.
+ */
+ dbno = XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno, fbno);
+ dlen = XFS_FSB_TO_BB(cur->bc_mp, flen);
+ error = -fiemap_fill_next_extent(fieinfo, BBTOB(dbno),
+ BBTOB(dbno), BBTOB(dlen), flags);
+ if (error)
+ break;
+ }
+ xfs_buf_relse(agflbp); /* Release the buffer */
+ return error;
+
+}
+
/*
* Map the freespace from the requested range in the requested order.
*
@@ -2802,6 +2879,10 @@
}
XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+ /* Account for the free blocks in AGFL */
+ error = xfs_alloc_agfl_freespace_map(&agbp, cur, fieinfo, sagno,
+ agno == eagno ? eagbno : NULLAGBLOCK);
+
if (!bycnt) {
/*
* if we are doing a bno ordered lookup, we can just
------------------------------------------------------------------------------------------------
More information about the xfs
mailing list