xfs
[Top] [All Lists]

[PATCH 32/58] xfs: don't update rmapbt when fixing agfl

To: david@xxxxxxxxxxxxx, darrick.wong@xxxxxxxxxx
Subject: [PATCH 32/58] xfs: don't update rmapbt when fixing agfl
From: "Darrick J. Wong" <darrick.wong@xxxxxxxxxx>
Date: Tue, 06 Oct 2015 21:58:38 -0700
Cc: linux-fsdevel@xxxxxxxxxxxxxxx, xfs@xxxxxxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <20151007045443.30457.47038.stgit@xxxxxxxxxxxxxxxx>
References: <20151007045443.30457.47038.stgit@xxxxxxxxxxxxxxxx>
User-agent: StGit/0.17.1-dirty
Allow a caller of xfs_alloc_fix_freelist to disable rmapbt updates
when fixing the AG freelist.  xfs_repair needs this during phase 5
to be able to adjust the freelist while it's reconstructing the rmap
btree; the missing entries will be added back at the very end of
phase 5 once the AGFL contents settle down.

Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
 fs/xfs/libxfs/xfs_alloc.c |   40 ++++++++++++++++++++++++++--------------
 fs/xfs/libxfs/xfs_alloc.h |    5 ++++-
 2 files changed, 30 insertions(+), 15 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index d7b9d43..be44873 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2099,26 +2099,38 @@ xfs_alloc_fix_freelist(
         * anything other than extra overhead when we need to put more blocks
         * back on the free list? Maybe we should only do this when space is
         * getting low or the AGFL is more than half full?
+        *
+        * The NOSHRINK flag prevents the AGFL from being shrunk if it's too
+        * big; the NORMAP flag prevents AGFL expand/shrink operations from
+        * updating the rmapbt.  Both flags are used in xfs_repair while we're
+        * rebuilding the rmapbt, and neither are used by the kernel.  They're
+        * both required to ensure that rmaps are correctly recorded for the
+        * regenerated AGFL, bnobt, and cntbt.  See repair/phase5.c and
+        * repair/rmap.c in xfsprogs for details.
         */
-       XFS_RMAP_AG_OWNER(&targs.oinfo, XFS_RMAP_OWN_AG);
-       while (pag->pagf_flcount > need) {
-               struct xfs_buf  *bp;
+       memset(&targs, 0, sizeof(targs));
+       if (!(flags & XFS_ALLOC_FLAG_NOSHRINK)) {
+               if (!(flags & XFS_ALLOC_FLAG_NORMAP))
+                       XFS_RMAP_AG_OWNER(&targs.oinfo, XFS_RMAP_OWN_AG);
+               while (pag->pagf_flcount > need) {
+                       struct xfs_buf  *bp;
 
-               error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
-               if (error)
-                       goto out_agbp_relse;
-               error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1,
-                                          &targs.oinfo, 1);
-               if (error)
-                       goto out_agbp_relse;
-               bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
-               xfs_trans_binval(tp, bp);
+                       error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
+                       if (error)
+                               goto out_agbp_relse;
+                       error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1,
+                                                  &targs.oinfo, 1);
+                       if (error)
+                               goto out_agbp_relse;
+                       bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
+                       xfs_trans_binval(tp, bp);
+               }
        }
 
-       memset(&targs, 0, sizeof(targs));
        targs.tp = tp;
        targs.mp = mp;
-       XFS_RMAP_AG_OWNER(&targs.oinfo, XFS_RMAP_OWN_AG);
+       if (!(flags & XFS_ALLOC_FLAG_NORMAP))
+               XFS_RMAP_AG_OWNER(&targs.oinfo, XFS_RMAP_OWN_AG);
        targs.agbp = agbp;
        targs.agno = args->agno;
        targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 67e564e..754b5dd 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -54,6 +54,9 @@ typedef unsigned int xfs_alloctype_t;
  */
 #define        XFS_ALLOC_FLAG_TRYLOCK  0x00000001  /* use trylock for buffer 
locking */
 #define        XFS_ALLOC_FLAG_FREEING  0x00000002  /* indicate caller is 
freeing extents*/
+#define        XFS_ALLOC_FLAG_NORMAP   0x00000004  /* don't modify the rmapbt 
*/
+#define        XFS_ALLOC_FLAG_NOSHRINK 0x00000008  /* don't shrink the 
freelist */
+
 
 /*
  * Argument structure for xfs_alloc routines.
@@ -86,7 +89,7 @@ typedef struct xfs_alloc_arg {
        char            isfl;           /* set if is freelist blocks - !acctg */
        char            userdata;       /* set if this is user data */
        xfs_fsblock_t   firstblock;     /* io first block allocated */
-       struct xfs_owner_info   oinfo;          /* owner of blocks being 
allocated */
+       struct xfs_owner_info   oinfo;  /* owner of blocks being allocated */
 } xfs_alloc_arg_t;
 
 /*

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