fs/xfs/libxfs/xfs_ag_resv.c

Source file repositories/reference/linux-study-clean/fs/xfs/libxfs/xfs_ag_resv.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/libxfs/xfs_ag_resv.c
Extension
.c
Size
11981 bytes
Lines
419
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (error) {
			/*
			 * Because we didn't have per-AG reservations when the
			 * finobt feature was added we might not be able to
			 * reserve all needed blocks.  Warn and fall back to the
			 * old and potentially buggy code in that case, but
			 * ensure we do have the reservation for the refcountbt.
			 */
			ask = used = 0;

			mp->m_finobt_nores = true;

			error = xfs_refcountbt_calc_reserves(mp, tp, pag, &ask,
					&used);
			if (error)
				goto out;

			error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA,
					ask, used);
			if (error)
				goto out;
		}
		if (ask)
			has_resv = true;
	}

	/* Create the RMAPBT metadata reservation */
	if (pag->pag_rmapbt_resv.ar_asked == 0) {
		ask = used = 0;

		error = xfs_rmapbt_calc_reserves(mp, tp, pag, &ask, &used);
		if (error)
			goto out;

		error = __xfs_ag_resv_init(pag, XFS_AG_RESV_RMAPBT, ask, used);
		if (error)
			goto out;
		if (ask)
			has_resv = true;
	}

out:
	/*
	 * Initialize the pagf if we have at least one active reservation on the
	 * AG. This may have occurred already via reservation calculation, but
	 * fall back to an explicit init to ensure the in-core allocbt usage
	 * counters are initialized as soon as possible. This is important
	 * because filesystems with large perag reservations are susceptible to
	 * free space reservation problems that the allocbt counter is used to
	 * address.
	 */
	if (has_resv) {
		error2 = xfs_alloc_read_agf(pag, tp, 0, NULL);
		if (error2)
			return error2;

		/*
		 * If there isn't enough space in the AG to satisfy the
		 * reservation, let the caller know that there wasn't enough
		 * space.  Callers are responsible for deciding what to do
		 * next, since (in theory) we can stumble along with
		 * insufficient reservation if data blocks are being freed to
		 * replenish the AG's free space.
		 */
		if (!error &&
		    xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
		    xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved >
		    pag->pagf_freeblks + pag->pagf_flcount)
			error = -ENOSPC;
	}

	return error;
}

/* Allocate a block from the reservation. */
void
xfs_ag_resv_alloc_extent(
	struct xfs_perag		*pag,
	enum xfs_ag_resv_type		type,
	struct xfs_alloc_arg		*args)
{
	struct xfs_ag_resv		*resv;
	xfs_extlen_t			len;
	uint				field;

	trace_xfs_ag_resv_alloc_extent(pag, type, args->len);

	switch (type) {
	case XFS_AG_RESV_AGFL:
	case XFS_AG_RESV_METAFILE:

Annotation

Implementation Notes