.. SPDX-License-Identifier: GPL-2.0

=================================================================
XFS AF (Allocation Field) Mount Options
=================================================================

Overview
========

The AF (Allocation Field) mount options allow users to define specific
Allocation Group (AG) ranges for XFS block allocation. This feature
enables prioritized allocation from different regions of the filesystem
by dividing the AG space into multiple allocation fields.

Mount Options
=============

- **af1** - Offset from tail (end) for the primary allocation field boundary
- **af2** - Offset from tail for the secondary allocation field boundary

Both options take an unsigned integer value representing the number of AGs
to exclude from the corresponding search phase, counted from the end of
the AG list.

Syntax
======

.. code-block:: bash

    mount -t xfs -o af1=<value1>,af2=<value2> <device> <mountpoint>

Constraints
===========

The mount options must satisfy the following constraint::

    0 <= af2 <= af1 < agcount

Where ``agcount`` is the total number of allocation groups in the filesystem.

Failure to meet this constraint will result in a mount failure with an
error message indicating the constraint violation.

How AF Works
============

When AF options are specified, XFS divides the AG space into allocation
fields using the following formula::

    next_af = agcount - m_af[i]

The allocation proceeds in two phases, searching from the "outside"
(lower AG numbers) toward the "inside" (higher AG numbers).

AG Layout Diagram
-----------------

For a filesystem with ``agcount=100`` and mount options ``af1=20,af2=10``::

    AG Number:  0 ............... 79 80 ........ 89 90 ....... 99
                |                 |  |          |  |         |
                |<----- AF1 ----->|  |<- AF2 -->|  |<- AF3 ->|
                |   (Phase 1)     |  |(Phase 2) |  |(Phase 3)|
                |                 |  |          |  |         |

    Calculation (from tail):
    - AF1 boundary = agcount - af1 = 100 - 20 = 80
    - AF2 boundary = agcount - af2 = 100 - 10 = 90
    - AF3 boundary = agcount (always search to end for phase 3)

    Search order: AF1 -> AF2 -> AF3 (outer to inner)

Phase Diagram
-------------

The AF parameters (af1, af2) are offsets counted from the **tail** (end) of the AG list.

**Phase 1 (Primary Search - AF1):**

.. code-block:: text

    AG:      0        40        80        90        99
             |         |         |         |         |
    Range:   [=========AF1=========]                 |
             ^                     ^                 |
             |                     |                 |
           curr_af=0          next_af=80      agcount=100

    af1 = 20 means: exclude last 20 AGs from phase 1
    Search AGs 0 to 79 (80 AGs)

**Phase 2 (Secondary Search - AF2):**

.. code-block:: text

    AG:      0        40        80        90        99
             |         |         |         |         |
    Range:                         [==AF2==]         |
                                   ^       ^         |
                                   |       |         |
                              curr_af=80 next_af=90 agcount=100

    af2 = 10 means: exclude last 10 AGs from phase 2
    Search AGs 80 to 89 (10 AGs)

**Phase 3 (Tertiary Search - AF3, if af2 > 0):**

.. code-block:: text

    AG:      0        40        80        90        99
             |         |         |         |         |
    Range:                                   [==AF3==]
                                             ^       ^
                                             |       |
                                        curr_af=90 agcount=100

    Search AGs 90 to 99 (10 AGs) - the remaining space

General Case Diagram
--------------------

The relationship between af1, af2, and agcount (offsets from tail)::

    0         (agcount-af1)   (agcount-af2)   agcount
    |               |               |            |
    |<---- AF1 ---->|<---- AF2 ---->|<--- AF3 --->|
    |  (Phase 1)    |   (Phase 2)   |  (Phase 3) |
    |               |               |            |

    Search order: AF1 -> AF2 -> AF3 (outside to inside)

    Constraint: 0 <= af2 <= af1 < agcount

.. important::
    - **af1** is the offset from tail for phase 1 boundary (outer boundary)
    - **af2** is the offset from tail for phase 2 boundary (inner boundary)
    - When **af2 = 0**, there is no AF3; Phase 2 searches to the end
    - When **af2 > 0**, AF3 automatically covers the remaining space

The allocation proceeds in two phases:

1. **First Phase (af1)**: Searches for free space in the range
   ``[0, agcount - af1)``, i.e., from AG 0 to AG (agcount - af1 - 1).

2. **Second Phase (af2)**: If the first phase fails to find suitable
   space, searches in the range ``[agcount - af1, agcount - af2)``,
   i.e., from AG (agcount - af1) to AG (agcount - af2 - 1).

This allows the filesystem to prioritize allocation in the outer AGs
first, then fall back to inner AGs if needed. The reserved region (when
af2 > 0) can be used for special purposes or left unused.

Examples
========

Example 1: Basic AF Configuration (Three Phases)
------------------------------------------------

For a filesystem with 100 AGs (agcount=100)::

    mount -t xfs -o af1=20,af2=10 /dev/sda1 /mnt

.. code-block:: text

    AG:      0 .............. 79 80 ....... 89 90 ....... 99
             |                |  |         |  |         |
             |<- Phase 1 (80)->|  |<-P2(10)->|  |<-P3(10)->|
             |                |  |         |  |         |
             |                |  |         |  |         |

    Boundaries (calculated from tail):
    - af1=20: Exclude last 20 AGs from phase 1 → boundary at AG 80
    - af2=10: Exclude last 10 AGs from phase 2 → boundary at AG 90

    Calculation:
    - agcount - af1 = 100 - 20 = 80
    - agcount - af2 = 100 - 10 = 90

Allocation behavior (outside-in):

- **Phase 1 (AF1)**: Search AGs 0-79 (range [0, 80))
- **Phase 2 (AF2)**: If Phase 1 fails, search AGs 80-89 (range [80, 90))
- **Phase 3 (AF3)**: If Phase 2 fails, search AGs 90-99 (range [90, 100))

Example 2: Two-Phase Configuration (No AF3)
-------------------------------------------

To use only two allocation fields (no phase 3), set af2=0::

    mount -t xfs -o af1=30,af2=0 /dev/sda1 /mnt

.. code-block:: text

    AG:      0 .............. 69 70 ....... 99
             |                |  |         |
             |<- Phase 1 (70)->|  |<-P2(30)->|
             |   (outer)       |  | (inner) |
             |                |  |         |

    Boundaries (calculated from tail):
    - af1=30: Exclude last 30 AGs from phase 1 → boundary at AG 70
    - af2=0: No exclusion for phase 2 → search to end

    Calculation:
    - agcount - af1 = 100 - 30 = 70
    - agcount - af2 = 100 - 0 = 100 (end of filesystem)

Allocation behavior (outside-in):

- **Phase 1 (AF1)**: Search AGs 0-69 (range [0, 70))
- **Phase 2 (AF2)**: If Phase 1 fails, search AGs 70-99 (range [70, 100))

Example 3: Invalid Configuration (Will Fail)
--------------------------------------------

The following will fail to mount because af1 < af2 (boundaries would overlap)::

    mount -t xfs -o af1=10,af2=20 /dev/sda1 /mnt

.. code-block:: text

    INVALID: af1(10) < af2(20) violates constraint 0 <= af2 <= af1 < agcount

    If allowed, this would result in reversed boundaries:
    - af1=10: boundary at AG 90 (exclude last 10)
    - af2=20: boundary at AG 80 (exclude last 20)

    AG:      0 .............. 79 80 ....... 89 90 ....... 99
             |                |  |         |  |         |
             |<- AF2 boundary |  |<- AF1 boundary |     |
             |                |  |         |  |         |

    This would cause AF1 range [0,90) to overlap with AF2 range [90,80),
    which is invalid.

Error message::

    AF layout: af1(10) must be >= af2(20)

Use Cases
=========

1. **Performance Optimization**: Direct allocations to specific AG regions
   that may have better performance characteristics (e.g., outer tracks
   on spinning disks).

2. **Storage Tiering**: Prioritize allocation on faster media by
   configuring AF boundaries to match underlying storage topology.

3. **Fragmentation Control**: Limit allocation to specific AG ranges to
   reduce fragmentation in critical regions.

Default Behavior
================

When AF options are not specified (default, af1=0, af2=0), XFS searches
the entire AG space in a single phase without boundaries.

Notes
=====

- The AF feature is specific to KYLIN kernel builds and may not be
  available in mainline kernels.

- AF boundaries are applied during block allocation for data extents.
  Metadata allocation may not be affected.

- Changes to AF options require remounting the filesystem.

See Also
========

- ``Documentation/filesystems/xfs.rst`` - General XFS documentation
- ``xfs(5)`` - XFS filesystem manual page
