The AG Free List is located in the 4th sector of each AG and is known as the AGFL. It is an array of AG relative block pointers for reserved space for growing the free space B+trees. This space cannot be used for general user data including inodes, data, directories and extended attributes.
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 as the free space fragments, additional blocks will be reserved from the AG and added to the free list array.
As the free list array is located within a single sector, a typical device will have space for 128 elements in the array (512 bytes per sector, 4 bytes per AG relative block pointer). The actual size can be determined by using the XFS_AGFL_SIZE
macro.
Active elements in the array are specified by the AGF's (
Section 3.2.1, “AG Free Space Block”)
agf_flfirst
,
agf_fllast
and
agf_flcount
values. The array is managed as a circular list.
The presence of these reserved block guarantees that the free space B+trees can be updated if any blocks are freed by extent changes in a full AG.
xfs_db Examples:
These examples are derived from an AG that has been deliberately fragmented.
The AGF:
xfs_db> agf <ag#>
xfs_db> p
magicnum = 0x58414746
versionnum = 1
seqno = 0
length = 3923122
bnoroot = 7
cntroot = 83343
bnolevel = 2
cntlevel = 2
flfirst = 22
fllast = 27
flcount = 6
freeblks = 3654234
longest = 3384327
btreeblks = 0
In the AGFL, the active elements are from 22 to 27 inclusive which are obtained from the flfirst
and fllast
values from the agf
in the previous example:
xfs_db> agfl 0
xfs_db> p
bno[0-127] = 0:4 1:5 2:6 3:7 4:83342 5:83343 6:83344 7:83345 8:83346 9:83347
10:4 11:5 12:80205 13:80780 14:81496 15:81766 16:83346 17:4 18:5
19:80205 20:82449 21:81496 22:81766 23:82455 24:80780 25:5
26:80205 27:83344
The free space B+tree sorted by block offset, the root block is from the AGF's bnoroot
value:
xfs_db> fsblock 7
xfs_db> type bnobt
xfs_db> p
magic = 0x41425442
level = 1
numrecs = 4
leftsib = null
rightsib = null
keys[1-4] = [startblock,blockcount]
1:[12,16] 2:[184586,3] 3:[225579,1] 4:[511629,1]
ptrs[1-4] = 1:2 2:83347 3:6 4:4
Blocks 2, 83347, 6 and 4 contain the leaves for the free space B+tree by starting block. Block 2 would contain offsets 16 up to but not including 184586 while block 4 would have all offsets from 511629 to the end of the AG.
The free space B+tree sorted by block count, the root block is from the AGF's cntroot
value:
xfs_db> fsblock 83343
xfs_db> type cntbt
xfs_db> p
magic = 0x41425443
level = 1
numrecs = 4
leftsib = null
rightsib = null
keys[1-4] = [blockcount,startblock]
1:[1,81496] 2:[1,511729] 3:[3,191875] 4:[6,184595]
ptrs[1-4] = 1:3 2:83345 3:83342 4:83346
The leaf in block 3, in this example, would only contain single block counts. The offsets are sorted in ascending order if the block count is the same.
Inspecting the leaf in block 83346, we can see the largest block at the end:
xfs_db> fsblock 83346
xfs_db> type cntbt
xfs_db> p
magic = 0x41425443
level = 0
numrecs = 344
leftsib = 83342
rightsib = null
recs[1-344] = [startblock,blockcount]
1:[184595,6] 2:[187573,6] 3:[187776,6]
...
342:[513712,755] 343:[230317,258229] 344:[538795,3384327]
The longest block count must be the same as the AGF's longest
value.