drivers/block/zloop.c

Source file repositories/reference/linux-study-clean/drivers/block/zloop.c

File Facts

System
Linux kernel
Corpus path
drivers/block/zloop.c
Extension
.c
Size
42519 bytes
Lines
1773
Domain
Driver Families
Bucket
drivers/block
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct blk_mq_ops zloop_mq_ops = {
	.queue_rq       = zloop_queue_rq,
	.complete	= zloop_complete_rq,
};

static int zloop_open(struct gendisk *disk, blk_mode_t mode)
{
	struct zloop_device *zlo = disk->private_data;
	int ret;

	ret = mutex_lock_killable(&zloop_ctl_mutex);
	if (ret)
		return ret;

	if (zlo->state != Zlo_live)
		ret = -ENXIO;
	mutex_unlock(&zloop_ctl_mutex);
	return ret;
}

static int zloop_report_zones(struct gendisk *disk, sector_t sector,
		unsigned int nr_zones, struct blk_report_zones_args *args)
{
	struct zloop_device *zlo = disk->private_data;
	struct blk_zone blkz = {};
	unsigned int first, i;
	int ret;

	first = disk_zone_no(disk, sector);
	if (first >= zlo->nr_zones)
		return 0;
	nr_zones = min(nr_zones, zlo->nr_zones - first);

	for (i = 0; i < nr_zones; i++) {
		unsigned int zone_no = first + i;
		struct zloop_zone *zone = &zlo->zones[zone_no];

		mutex_lock(&zone->lock);

		if (test_and_clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags)) {
			ret = zloop_update_seq_zone(zlo, zone_no);
			if (ret) {
				mutex_unlock(&zone->lock);
				return ret;
			}
		}

		blkz.start = zone->start;
		blkz.len = zlo->zone_size;
		spin_lock(&zone->wp_lock);
		blkz.wp = zone->wp;
		spin_unlock(&zone->wp_lock);
		blkz.cond = zone->cond;
		if (test_bit(ZLOOP_ZONE_CONV, &zone->flags)) {
			blkz.type = BLK_ZONE_TYPE_CONVENTIONAL;
			blkz.capacity = zlo->zone_size;
		} else {
			blkz.type = BLK_ZONE_TYPE_SEQWRITE_REQ;
			blkz.capacity = zlo->zone_capacity;
		}

		mutex_unlock(&zone->lock);

		ret = disk_report_zone(disk, &blkz, i, args);
		if (ret)
			return ret;
	}

	return nr_zones;
}

static void zloop_free_disk(struct gendisk *disk)
{
	struct zloop_device *zlo = disk->private_data;
	unsigned int i;

	blk_mq_free_tag_set(&zlo->tag_set);

	for (i = 0; i < zlo->nr_zones; i++) {
		struct zloop_zone *zone = &zlo->zones[i];

		mapping_set_gfp_mask(zone->file->f_mapping,
				zone->old_gfp_mask);
		fput(zone->file);
	}

	fput(zlo->data_dir);
	destroy_workqueue(zlo->workqueue);
	kfree(zlo->base_dir);
	kvfree(zlo);

Annotation

Implementation Notes