xfs
[Top] [All Lists]

[PATCH 2/2] xfs_spaceman: Accounting for AGFL blocks

To: <xfs@xxxxxxxxxxx>
Subject: [PATCH 2/2] xfs_spaceman: Accounting for AGFL blocks
From: Dhruvesh Rathore <adrscube@xxxxxxxxx>
Date: Fri, 16 Jan 2015 17:40:40 +0530
Delivered-to: xfs@xxxxxxxxxxx
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:from:date:subject:to; bh=zfmb7WrfMFK6VsD7bTLlgNtRIo8bzq8wI2nu2sYXuhY=; b=GBv7FHrJvtRiADPLfwPi5rO5k3JRcmluj7xYRQ+O4dJ6/+iD+tN0uWfFy3j5nUyRwn nuBg16TXrwu5uCAt1I01AG7dljfxoQIX+jBm/xnLhonClqW+v4UaezzdeHZZsJkN7CTA wb+J/Js0fw230jv4y7cpMrYLXAH5dc73Z8Cb3F9aZBOQy64OkrOqw4/WTmTmjRH6ncCE X45tTJPMIjhD105iW3g/N6OUBzdc8tV59HpS9grjAXg9xCdZcr83iMJGPoqySwRLaWlM TnrtlovIyDvvioGZTo5ef0/h1NWPtOMXUedWGNM3hgmnA5YGwIrZZYRoc0AvF3pvWYPA Dl2g==
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

------------------------------------------------------------------------------------------------

<Prev in Thread] Current Thread [Next in Thread>