drivers/block/ublk_drv.c

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

File Facts

System
Linux kernel
Corpus path
drivers/block/ublk_drv.c
Extension
.c
Size
152736 bytes
Lines
5916
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 ublk_mq_ops = {
	.queue_rq       = ublk_queue_rq,
	.queue_rqs      = ublk_queue_rqs,
	.init_hctx	= ublk_init_hctx,
	.timeout	= ublk_timeout,
};

static const struct blk_mq_ops ublk_batch_mq_ops = {
	.commit_rqs	= ublk_commit_rqs,
	.queue_rq       = ublk_batch_queue_rq,
	.queue_rqs      = ublk_batch_queue_rqs,
	.init_hctx	= ublk_init_hctx,
	.timeout	= ublk_timeout,
};

static void ublk_queue_reinit(struct ublk_device *ub, struct ublk_queue *ubq)
{
	int i;

	ubq->nr_io_ready = 0;

	for (i = 0; i < ubq->q_depth; i++) {
		struct ublk_io *io = &ubq->ios[i];

		/*
		 * UBLK_IO_FLAG_CANCELED is kept for avoiding to touch
		 * io->cmd
		 */
		io->flags &= UBLK_IO_FLAG_CANCELED;
		io->cmd = NULL;
		io->buf.addr = 0;

		/*
		 * old task is PF_EXITING, put it now
		 *
		 * It could be NULL in case of closing one quiesced
		 * device.
		 */
		if (io->task) {
			put_task_struct(io->task);
			io->task = NULL;
		}

		WARN_ON_ONCE(refcount_read(&io->ref));
		WARN_ON_ONCE(io->task_registered_buffers);
	}
}

static int ublk_ch_open(struct inode *inode, struct file *filp)
{
	struct ublk_device *ub = container_of(inode->i_cdev,
			struct ublk_device, cdev);

	if (test_and_set_bit(UB_STATE_OPEN, &ub->state))
		return -EBUSY;
	filp->private_data = ub;
	ub->ublksrv_tgid = current->tgid;
	return 0;
}

static void ublk_reset_ch_dev(struct ublk_device *ub)
{
	int i;

	for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
		struct ublk_queue *ubq = ublk_get_queue(ub, i);

		/* Sync with ublk_cancel_cmd() */
		spin_lock(&ubq->cancel_lock);
		ublk_queue_reinit(ub, ubq);
		spin_unlock(&ubq->cancel_lock);
	}

	/* set to NULL, otherwise new tasks cannot mmap io_cmd_buf */
	ub->mm = NULL;
	ub->nr_queue_ready = 0;
	ub->unprivileged_daemons = false;
	ub->ublksrv_tgid = -1;
}

static struct gendisk *ublk_get_disk(struct ublk_device *ub)
{
	struct gendisk *disk;

	spin_lock(&ub->lock);
	disk = ub->ub_disk;
	if (disk)
		get_device(disk_to_dev(disk));
	spin_unlock(&ub->lock);

Annotation

Implementation Notes