fs/zonefs/super.c

Source file repositories/reference/linux-study-clean/fs/zonefs/super.c

File Facts

System
Linux kernel
Corpus path
fs/zonefs/super.c
Extension
.c
Size
38406 bytes
Lines
1477
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: operation-table or driver-model contract
Status
pattern 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

const struct file_operations zonefs_dir_operations = {
	.llseek		= generic_file_llseek,
	.read		= generic_read_dir,
	.iterate_shared	= zonefs_readdir,
};

struct zonefs_zone_data {
	struct super_block	*sb;
	unsigned int		nr_zones[ZONEFS_ZTYPE_MAX];
	sector_t		cnv_zone_start;
	struct blk_zone		*zones;
};

static int zonefs_get_zone_info_cb(struct blk_zone *zone, unsigned int idx,
				   void *data)
{
	struct zonefs_zone_data *zd = data;
	struct super_block *sb = zd->sb;
	struct zonefs_sb_info *sbi = ZONEFS_SB(sb);

	/*
	 * We do not care about the first zone: it contains the super block
	 * and not exposed as a file.
	 */
	if (!idx)
		return 0;

	/*
	 * Count the number of zones that will be exposed as files.
	 * For sequential zones, we always have as many files as zones.
	 * FOr conventional zones, the number of files depends on if we have
	 * conventional zones aggregation enabled.
	 */
	switch (zone->type) {
	case BLK_ZONE_TYPE_CONVENTIONAL:
		if (sbi->s_features & ZONEFS_F_AGGRCNV) {
			/* One file per set of contiguous conventional zones */
			if (!(sbi->s_zgroup[ZONEFS_ZTYPE_CNV].g_nr_zones) ||
			    zone->start != zd->cnv_zone_start)
				sbi->s_zgroup[ZONEFS_ZTYPE_CNV].g_nr_zones++;
			zd->cnv_zone_start = zone->start + zone->len;
		} else {
			/* One file per zone */
			sbi->s_zgroup[ZONEFS_ZTYPE_CNV].g_nr_zones++;
		}
		break;
	case BLK_ZONE_TYPE_SEQWRITE_REQ:
	case BLK_ZONE_TYPE_SEQWRITE_PREF:
		sbi->s_zgroup[ZONEFS_ZTYPE_SEQ].g_nr_zones++;
		break;
	default:
		zonefs_err(zd->sb, "Unsupported zone type 0x%x\n",
			   zone->type);
		return -EIO;
	}

	memcpy(&zd->zones[idx], zone, sizeof(struct blk_zone));

	return 0;
}

static int zonefs_get_zone_info(struct zonefs_zone_data *zd)
{
	struct block_device *bdev = zd->sb->s_bdev;
	int ret;

	zd->zones = kvzalloc_objs(struct blk_zone, bdev_nr_zones(bdev));
	if (!zd->zones)
		return -ENOMEM;

	/* Get zones information from the device */
	ret = blkdev_report_zones(bdev, 0, BLK_ALL_ZONES,
				  zonefs_get_zone_info_cb, zd);
	if (ret < 0) {
		zonefs_err(zd->sb, "Zone report failed %d\n", ret);
		return ret;
	}

	if (ret != bdev_nr_zones(bdev)) {
		zonefs_err(zd->sb, "Invalid zone report (%d/%u zones)\n",
			   ret, bdev_nr_zones(bdev));
		return -EIO;
	}

	return 0;
}

static inline void zonefs_free_zone_info(struct zonefs_zone_data *zd)
{
	kvfree(zd->zones);

Annotation

Implementation Notes