drivers/block/null_blk/main.c

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

File Facts

System
Linux kernel
Corpus path
drivers/block/null_blk/main.c
Extension
.c
Size
57744 bytes
Lines
2224
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 null_mq_ops = {
	.queue_rq       = null_queue_rq,
	.queue_rqs	= null_queue_rqs,
	.complete	= null_complete_rq,
	.timeout	= null_timeout_rq,
	.poll		= null_poll,
	.map_queues	= null_map_queues,
	.init_hctx	= null_init_hctx,
};

static void null_del_dev(struct nullb *nullb)
{
	struct nullb_device *dev;

	if (!nullb)
		return;

	dev = nullb->dev;

	ida_free(&nullb_indexes, nullb->index);

	list_del_init(&nullb->list);

	del_gendisk(nullb->disk);

	if (test_bit(NULLB_DEV_FL_THROTTLED, &nullb->dev->flags)) {
		hrtimer_cancel(&nullb->bw_timer);
		atomic_long_set(&nullb->cur_bytes, LONG_MAX);
		blk_mq_start_stopped_hw_queues(nullb->q, true);
	}

	put_disk(nullb->disk);
	if (nullb->tag_set == &nullb->__tag_set)
		blk_mq_free_tag_set(nullb->tag_set);
	kfree(nullb->queues);
	if (null_cache_active(nullb))
		null_free_device_storage(nullb->dev, true);
	kfree(nullb);
	dev->nullb = NULL;
}

static void null_config_discard(struct nullb *nullb, struct queue_limits *lim)
{
	if (nullb->dev->discard == false)
		return;

	if (!nullb->dev->memory_backed) {
		nullb->dev->discard = false;
		pr_info("discard option is ignored without memory backing\n");
		return;
	}

	if (nullb->dev->zoned) {
		nullb->dev->discard = false;
		pr_info("discard option is ignored in zoned mode\n");
		return;
	}

	lim->max_hw_discard_sectors = UINT_MAX >> 9;
}

static const struct block_device_operations null_ops = {
	.owner		= THIS_MODULE,
	.report_zones	= null_report_zones,
};

static int setup_queues(struct nullb *nullb)
{
	int nqueues = nr_cpu_ids;

	if (g_poll_queues)
		nqueues += g_poll_queues;

	nullb->queues = kzalloc_objs(struct nullb_queue, nqueues);
	if (!nullb->queues)
		return -ENOMEM;

	return 0;
}

static int null_init_tag_set(struct blk_mq_tag_set *set, int poll_queues)
{
	set->ops = &null_mq_ops;
	set->cmd_size = sizeof(struct nullb_cmd);
	set->timeout = 5 * HZ;
	set->nr_maps = 1;
	if (poll_queues) {
		set->nr_hw_queues += poll_queues;
		set->nr_maps += 2;
	}

Annotation

Implementation Notes