fs/xfs/xfs_zone_alloc.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/xfs_zone_alloc.c
Extension
.c
Size
37876 bytes
Lines
1440
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

struct xfs_init_zones {
	uint32_t		zone_size;
	uint32_t		zone_capacity;
	uint64_t		available;
	uint64_t		reclaimable;
};

/*
 * For sequential write required zones, we restart writing at the hardware write
 * pointer returned by xfs_validate_blk_zone().
 *
 * For conventional zones or conventional devices we have to query the rmap to
 * find the highest recorded block and set the write pointer to the block after
 * that.  In case of a power loss this misses blocks where the data I/O has
 * completed but not recorded in the rmap yet, and it also rewrites blocks if
 * the most recently written ones got deleted again before unmount, but this is
 * the best we can do without hardware support.
 */
static int
xfs_query_write_pointer(
	struct xfs_init_zones	*iz,
	struct xfs_rtgroup	*rtg,
	xfs_rgblock_t		*write_pointer)
{
	struct xfs_mount	*mp = rtg_mount(rtg);
	struct block_device	*bdev = mp->m_rtdev_targp->bt_bdev;
	sector_t		start = xfs_gbno_to_daddr(&rtg->rtg_group, 0);
	xfs_rgblock_t		highest_rgbno;
	struct blk_zone		zone = {};
	int			error;

	if (bdev_is_zoned(bdev)) {
		error = blkdev_get_zone_info(bdev, start, &zone);
		if (error)
			return error;
		if (zone.start != start) {
			xfs_warn(mp, "mismatched zone start: 0x%llx/0x%llx.",
				zone.start, start);
			return -EFSCORRUPTED;
		}

		if (!xfs_validate_blk_zone(mp, &zone, rtg_rgno(rtg),
				iz->zone_size, iz->zone_capacity,
				write_pointer))
			return -EFSCORRUPTED;

		/*
		 * Use the hardware write pointer returned by
		 * xfs_validate_blk_zone for sequential write required zones,
		 * else fall through to the rmap-based estimation below.
		 */
		if (zone.cond != BLK_ZONE_COND_NOT_WP)
			return 0;
	}

	xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
	highest_rgbno = xfs_rtrmap_highest_rgbno(rtg);
	xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP);

	if (highest_rgbno == NULLRGBLOCK)
		*write_pointer = 0;
	else
		*write_pointer = highest_rgbno + 1;
	return 0;
}

static int
xfs_init_zone(
	struct xfs_init_zones	*iz,
	struct xfs_rtgroup	*rtg,
	xfs_rgblock_t		write_pointer)
{
	struct xfs_mount	*mp = rtg_mount(rtg);
	struct xfs_zone_info	*zi = mp->m_zone_info;
	uint32_t		used = rtg_rmap(rtg)->i_used_blocks;
	int			error;

	if (write_pointer > rtg->rtg_extents) {
		xfs_warn(mp, "zone %u has invalid write pointer (0x%x).",
			 rtg_rgno(rtg), write_pointer);
		return -EFSCORRUPTED;
	}

	if (used > rtg->rtg_extents) {
		xfs_warn(mp,
"zone %u has used counter (0x%x) larger than zone capacity (0x%llx).",
			 rtg_rgno(rtg), used, rtg->rtg_extents);
		return -EFSCORRUPTED;
	}

Annotation

Implementation Notes