// SPDX-License-Identifier: GPL-2.0
#include "misc.h"
#include "ctree.h"
#include "space-info.h"
#include "sysfs.h"
#include "volumes.h"
#include "free-space-cache.h"
#include "ordered-data.h"
#include "transaction.h"
#include "block-group.h"
/*
* HOW DOES SPACE RESERVATION WORK
*
* If you want to know about delalloc specifically, there is a separate comment
* for that with the delalloc code. This comment is about how the whole system
* works generally.
*
* BASIC CONCEPTS
*
* 1) space_info. This is the ultimate arbiter of how much space we can use.
* There's a description of the bytes_ fields with the struct declaration,
* refer to that for specifics on each field. Suffice it to say that for
* reservations we care about total_bytes - SUM(space_info->bytes_) when
* determining if there is space to make an allocation. There is a space_info
* for METADATA, SYSTEM, and DATA areas.
*
* 2) block_rsv's. These are basically buckets for every different type of
* metadata reservation we have. You can see the comment in the block_rsv
* code on the rules for each type, but generally block_rsv->reserved is how
* much space is accounted for in space_info->bytes_may_use.
*
* 3) btrfs_calc*_size. These are the worst case calculations we used based
* on the number of items we will want to modify. We have one for changing
* items, and one for inserting new items. Generally we use these helpers to
* determine the size of the block reserves, and then use the actual bytes
* values to adjust the space_info counters.
*
* MAKING RESERVATIONS, THE NORMAL CASE
*
* We call into either btrfs_reserve_data_bytes() or
* btrfs_reserve_metadata_bytes(), depending on which we're looking for, with
* num_bytes we want to reserve.
*
* ->reserve
* space_info->bytes_may_reserve += num_bytes
*
* ->extent allocation
* Call btrfs_add_reserved_bytes() which does
* space_info->bytes_may_reserve -= num_bytes
* space_info->bytes_reserved += extent_bytes
*
* ->insert reference
* Call btrfs_update_block_group() which does
* space_info->bytes_reserved -= extent_bytes
* space_info->bytes_used += extent_bytes
*
* MAKING RESERVATIONS, FLUSHING NORMALLY (non-priority)
*
* Assume we are unable to simply make the reservation because we do not have
* enough space
*
* -> __reserve_bytes
* create a reserve_ticket with ->bytes set to our reservation, add it to
* the tail of space_info->tickets, kick async flush thread
*
* ->handle_reserve_ticket
* wait on ticket->wait for ->bytes to be reduced to 0, or ->error to be set
* on the ticket.
*
* -> btrfs_async_reclaim_metadata_space/btrfs_async_reclaim_data_space
* Flushes various things attempting to free up space.
*
* -> btrfs_try_granting_tickets()
* This is called by anything that either subtracts space from
* space_info->bytes_may_use, ->bytes_pinned, etc, or adds to the
* space_info->total_bytes. This loops through the ->priority_tickets and
*