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@xxxxxxxxxxx> Amey Ruikar <ameyruikar@xxxxxxxxx> Somdeep Dey <somdeepdey10@xxxxxxxxx> --- 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 ------------------------------------------------------------------------------------------------ _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs