block/partitions/ibm.c

Source file repositories/reference/linux-study-clean/block/partitions/ibm.c

File Facts

System
Linux kernel
Corpus path
block/partitions/ibm.c
Extension
.c
Size
10433 bytes
Lines
408
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: implementation source
Status
source implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dasd_vollabel {
	char *type;
	int idx;
};

static struct dasd_vollabel dasd_vollabels[] = {
	[DASD_VOLLBL_TYPE_VOL1] = {
		.type = "VOL1",
		.idx = DASD_VOLLBL_TYPE_VOL1,
	},
	[DASD_VOLLBL_TYPE_LNX1] = {
		.type = "LNX1",
		.idx = DASD_VOLLBL_TYPE_LNX1,
	},
	[DASD_VOLLBL_TYPE_CMS1] = {
		.type = "CMS1",
		.idx = DASD_VOLLBL_TYPE_CMS1,
	},
};

static int get_label_by_type(const char *type)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(dasd_vollabels); i++) {
		if (!memcmp(type, dasd_vollabels[i].type, DASD_VOL_TYPE_LEN))
			return dasd_vollabels[i].idx;
	}

	return -1;
}

static int find_label(struct parsed_partitions *state,
		      dasd_information2_t *info,
		      struct hd_geometry *geo,
		      int blocksize,
		      sector_t *labelsect,
		      char name[],
		      char type[],
		      union label_t *label)
{
	sector_t testsect[3];
	int i, testcount;
	Sector sect;
	void *data;

	/* There a three places where we may find a valid label:
	 * - on an ECKD disk it's block 2
	 * - on an FBA disk it's block 1
	 * - on an CMS formatted FBA disk it is sector 1, even if the block size
	 *   is larger than 512 bytes (possible if the DIAG discipline is used)
	 * If we have a valid info structure, then we know exactly which case we
	 * have, otherwise we just search through all possebilities.
	 */
	if (info) {
		if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) ||
		    (info->cu_type == 0x3880 && info->dev_type == 0x3370))
			testsect[0] = info->label_block;
		else
			testsect[0] = info->label_block * (blocksize >> 9);
		testcount = 1;
	} else {
		testsect[0] = 1;
		testsect[1] = (blocksize >> 9);
		testsect[2] = 2 * (blocksize >> 9);
		testcount = 3;
	}
	for (i = 0; i < testcount; ++i) {
		data = read_part_sector(state, testsect[i], &sect);
		if (data == NULL)
			continue;
		memcpy(label, data, sizeof(*label));
		memcpy(type, data, DASD_VOL_TYPE_LEN);
		EBCASC(type, DASD_VOL_TYPE_LEN);
		put_dev_sector(sect);
		switch (get_label_by_type(type)) {
		case DASD_VOLLBL_TYPE_VOL1:
			memcpy(name, label->vol.volid, DASD_VOL_ID_LEN);
			EBCASC(name, DASD_VOL_ID_LEN);
			*labelsect = testsect[i];
			return 1;
		case DASD_VOLLBL_TYPE_LNX1:
		case DASD_VOLLBL_TYPE_CMS1:
			memcpy(name, label->lnx.volid, DASD_VOL_ID_LEN);
			EBCASC(name, DASD_VOL_ID_LEN);
			*labelsect = testsect[i];
			return 1;
		default:
			break;
		}

Annotation

Implementation Notes