drivers/block/xen-blkfront.c

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

File Facts

System
Linux kernel
Corpus path
drivers/block/xen-blkfront.c
Extension
.c
Size
72981 bytes
Lines
2643
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 blkfront_mq_ops = {
	.queue_rq = blkif_queue_rq,
	.complete = blkif_complete_rq,
};

static void blkif_set_queue_limits(const struct blkfront_info *info,
		struct queue_limits *lim)
{
	unsigned int segments = info->max_indirect_segments ? :
				BLKIF_MAX_SEGMENTS_PER_REQUEST;

	if (info->feature_discard) {
		lim->max_hw_discard_sectors = UINT_MAX;
		if (info->discard_granularity)
			lim->discard_granularity = info->discard_granularity;
		lim->discard_alignment = info->discard_alignment;
		if (info->feature_secdiscard)
			lim->max_secure_erase_sectors = UINT_MAX;
	}

	if (info->feature_flush) {
		lim->features |= BLK_FEAT_WRITE_CACHE;
		if (info->feature_fua)
			lim->features |= BLK_FEAT_FUA;
	}

	/* Hard sector size and max sectors impersonate the equiv. hardware. */
	lim->logical_block_size = info->sector_size;
	lim->physical_block_size = info->physical_sector_size;
	lim->max_hw_sectors = (segments * XEN_PAGE_SIZE) / 512;

	/* Each segment in a request is up to an aligned page in size. */
	lim->seg_boundary_mask = PAGE_SIZE - 1;
	lim->max_segment_size = PAGE_SIZE;

	/* Ensure a merged request will fit in a single I/O ring slot. */
	lim->max_segments = segments / GRANTS_PER_PSEG;

	/* Make sure buffer addresses are sector-aligned. */
	lim->dma_alignment = 511;
}

static const char *flush_info(struct blkfront_info *info)
{
	if (info->feature_flush && info->feature_fua)
		return "barrier: enabled;";
	else if (info->feature_flush)
		return "flush diskcache: enabled;";
	else
		return "barrier or flush: disabled;";
}

static void xlvbd_flush(struct blkfront_info *info)
{
	pr_info("blkfront: %s: %s %s %s %s %s %s %s\n",
		info->gd->disk_name, flush_info(info),
		"persistent grants:", info->feature_persistent ?
		"enabled;" : "disabled;", "indirect descriptors:",
		info->max_indirect_segments ? "enabled;" : "disabled;",
		"bounce buffer:", info->bounce ? "enabled" : "disabled;");
}

static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
{
	int major;
	major = BLKIF_MAJOR(vdevice);
	*minor = BLKIF_MINOR(vdevice);
	switch (major) {
		case XEN_IDE0_MAJOR:
			*offset = (*minor / 64) + EMULATED_HD_DISK_NAME_OFFSET;
			*minor = ((*minor / 64) * PARTS_PER_DISK) +
				EMULATED_HD_DISK_MINOR_OFFSET;
			break;
		case XEN_IDE1_MAJOR:
			*offset = (*minor / 64) + 2 + EMULATED_HD_DISK_NAME_OFFSET;
			*minor = (((*minor / 64) + 2) * PARTS_PER_DISK) +
				EMULATED_HD_DISK_MINOR_OFFSET;
			break;
		case XEN_SCSI_DISK0_MAJOR:
			*offset = (*minor / PARTS_PER_DISK) + EMULATED_SD_DISK_NAME_OFFSET;
			*minor = *minor + EMULATED_SD_DISK_MINOR_OFFSET;
			break;
		case XEN_SCSI_DISK1_MAJOR:
		case XEN_SCSI_DISK2_MAJOR:
		case XEN_SCSI_DISK3_MAJOR:
		case XEN_SCSI_DISK4_MAJOR:
		case XEN_SCSI_DISK5_MAJOR:
		case XEN_SCSI_DISK6_MAJOR:
		case XEN_SCSI_DISK7_MAJOR:
			*offset = (*minor / PARTS_PER_DISK) +

Annotation

Implementation Notes