[Top] [All Lists]

[PATCH 4/4] xfs: obey minleft values during extent allocation correctly.

To: xfs@xxxxxxxxxxx
Subject: [PATCH 4/4] xfs: obey minleft values during extent allocation correctly.
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Thu, 21 Apr 2011 14:29:04 +1000
In-reply-to: <1303360144-10632-1-git-send-email-david@xxxxxxxxxxxxx>
References: <1303360144-10632-1-git-send-email-david@xxxxxxxxxxxxx>
From: Dave Chinner <dchinner@xxxxxxxxxx>

When allocating an extent that is long enough to consume the
remaining free space in an AG, we need to ensure that the allocation
leaves enough space in the AG for any subsequent bmap btree blocks
that are needed to track the new extent. These have to be allocated
in the same AG as we only reserve enough blocks in an allocation
transaction for modification of the freespace trees in a single AG.

xfs_alloc_fix_minleft() has been considering blocks on the AGFL as
free blocks available for extent and bmbt block allocation, which is
not correct - blocks on the AGFL are there exclusively for the use
of the free space btrees. As a result, when minleft is less than the
number of blocks on the AGFL, xfs_alloc_fix_minleft() does not trim
the given extent to leave minleft blocks available for bmbt
allocation, and hence we can fail allocation during bmbt record

A further problem is that bmbt block allocation doesn't set the
total number of blocks correctly for the allocation, thereby
allowing it to allocate a block from the AGFL before failing on the
second block in xfs_alloc_fix_freelist(). The total needs to be set
so that it skips AGs that only have the minimum reserved
amount of AGFL blocks free in them.

Similarly, xfs_inobt_alloc_block() needs to set args->total as well.

Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
 fs/xfs/xfs_alloc.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 27d64d7..8946464 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -280,7 +280,6 @@ xfs_alloc_fix_minleft(
                return 1;
        agf = XFS_BUF_TO_AGF(args->agbp);
        diff = be32_to_cpu(agf->agf_freeblks)
-               + be32_to_cpu(agf->agf_flcount)
                - args->len - args->minleft;
        if (diff >= 0)
                return 1;

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