⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldm.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * The last_vblkd_seq can be before the end of the vmdb, just make sure	 * it is not out of bounds.	 */	if ((vm->vblk_size * vm->last_vblk_seq) > (toc->bitmap1_size << 9)) {		ldm_crit ("VMDB exceeds allowed size specified by TOCBLOCK.  "				"Database is corrupt.  Aborting.");		goto out;	}	result = true;out:	put_dev_sector (sect);	return result;}/** * ldm_validate_partition_table - Determine whether bdev might be a dynamic disk * @bdev:  Device holding the LDM Database * * This function provides a weak test to decide whether the device is a dynamic * disk or not.  It looks for an MS-DOS-style partition table containing at * least one partition of type 0x42 (formerly SFS, now used by Windows for * dynamic disks). * * N.B.  The only possible error can come from the read_dev_sector and that is *       only likely to happen if the underlying device is strange.  If that IS *       the case we should return zero to let someone else try. * * Return:  'true'   @bdev is a dynamic disk *          'false'  @bdev is not a dynamic disk, or an error occurred */static bool ldm_validate_partition_table (struct block_device *bdev){	Sector sect;	u8 *data;	struct partition *p;	int i;	bool result = false;	BUG_ON (!bdev);	data = read_dev_sector (bdev, 0, &sect);	if (!data) {		ldm_crit ("Disk read failed.");		return false;	}	if (*(__le16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))		goto out;	p = (struct partition*)(data + 0x01BE);	for (i = 0; i < 4; i++, p++)		if (SYS_IND (p) == LDM_PARTITION) {			result = true;			break;		}	if (result)		ldm_debug ("Found W2K dynamic disk partition type.");out:	put_dev_sector (sect);	return result;}/** * ldm_get_disk_objid - Search a linked list of vblk's for a given Disk Id * @ldb:  Cache of the database structures * * The LDM Database contains a list of all partitions on all dynamic disks. * The primary PRIVHEAD, at the beginning of the physical disk, tells us * the GUID of this disk.  This function searches for the GUID in a linked * list of vblk's. * * Return:  Pointer, A matching vblk was found *          NULL,    No match, or an error */static struct vblk * ldm_get_disk_objid (const struct ldmdb *ldb){	struct list_head *item;	BUG_ON (!ldb);	list_for_each (item, &ldb->v_disk) {		struct vblk *v = list_entry (item, struct vblk, list);		if (!memcmp (v->vblk.disk.disk_id, ldb->ph.disk_id, GUID_SIZE))			return v;	}	return NULL;}/** * ldm_create_data_partitions - Create data partitions for this device * @pp:   List of the partitions parsed so far * @ldb:  Cache of the database structures * * The database contains ALL the partitions for ALL disk groups, so we need to * filter out this specific disk. Using the disk's object id, we can find all * the partitions in the database that belong to this disk. * * Add each partition in our database, to the parsed_partitions structure. * * N.B.  This function creates the partitions in the order it finds partition *       objects in the linked list. * * Return:  'true'   Partition created *          'false'  Error, probably a range checking problem */static bool ldm_create_data_partitions (struct parsed_partitions *pp,					const struct ldmdb *ldb){	struct list_head *item;	struct vblk *vb;	struct vblk *disk;	struct vblk_part *part;	int part_num = 1;	BUG_ON (!pp || !ldb);	disk = ldm_get_disk_objid (ldb);	if (!disk) {		ldm_crit ("Can't find the ID of this disk in the database.");		return false;	}	printk (" [LDM]");	/* Create the data partitions */	list_for_each (item, &ldb->v_part) {		vb = list_entry (item, struct vblk, list);		part = &vb->vblk.part;		if (part->disk_id != disk->obj_id)			continue;		put_partition (pp, part_num, ldb->ph.logical_disk_start +				part->start, part->size);		part_num++;	}	printk ("\n");	return true;}/** * ldm_relative - Calculate the next relative offset * @buffer:  Block of data being worked on * @buflen:  Size of the block of data * @base:    Size of the previous fixed width fields * @offset:  Cumulative size of the previous variable-width fields * * Because many of the VBLK fields are variable-width, it's necessary * to calculate each offset based on the previous one and the length * of the field it pointed to. * * Return:  -1 Error, the calculated offset exceeded the size of the buffer *           n OK, a range-checked offset into buffer */static int ldm_relative(const u8 *buffer, int buflen, int base, int offset){	base += offset;	if (!buffer || offset < 0 || base > buflen) {		if (!buffer)			ldm_error("!buffer");		if (offset < 0)			ldm_error("offset (%d) < 0", offset);		if (base > buflen)			ldm_error("base (%d) > buflen (%d)", base, buflen);		return -1;	}	if (base + buffer[base] >= buflen) {		ldm_error("base (%d) + buffer[base] (%d) >= buflen (%d)", base,				buffer[base], buflen);		return -1;	}	return buffer[base] + offset + 1;}/** * ldm_get_vnum - Convert a variable-width, big endian number, into cpu order * @block:  Pointer to the variable-width number to convert * * Large numbers in the LDM Database are often stored in a packed format.  Each * number is prefixed by a one byte width marker.  All numbers in the database * are stored in big-endian byte order.  This function reads one of these * numbers and returns the result * * N.B.  This function DOES NOT perform any range checking, though the most *       it will read is eight bytes. * * Return:  n A number *          0 Zero, or an error occurred */static u64 ldm_get_vnum (const u8 *block){	u64 tmp = 0;	u8 length;	BUG_ON (!block);	length = *block++;	if (length && length <= 8)		while (length--)			tmp = (tmp << 8) | *block++;	else		ldm_error ("Illegal length %d.", length);	return tmp;}/** * ldm_get_vstr - Read a length-prefixed string into a buffer * @block:   Pointer to the length marker * @buffer:  Location to copy string to * @buflen:  Size of the output buffer * * Many of the strings in the LDM Database are not NULL terminated.  Instead * they are prefixed by a one byte length marker.  This function copies one of * these strings into a buffer. * * N.B.  This function DOES NOT perform any range checking on the input. *       If the buffer is too small, the output will be truncated. * * Return:  0, Error and @buffer contents are undefined *          n, String length in characters (excluding NULL) *          buflen-1, String was truncated. */static int ldm_get_vstr (const u8 *block, u8 *buffer, int buflen){	int length;	BUG_ON (!block || !buffer);	length = block[0];	if (length >= buflen) {		ldm_error ("Truncating string %d -> %d.", length, buflen);		length = buflen - 1;	}	memcpy (buffer, block + 1, length);	buffer[length] = 0;	return length;}/** * ldm_parse_cmp3 - Read a raw VBLK Component object into a vblk structure * @buffer:  Block of data being worked on * @buflen:  Size of the block of data * @vb:      In-memory vblk in which to return information * * Read a raw VBLK Component object (version 3) into a vblk structure. * * Return:  'true'   @vb contains a Component VBLK *          'false'  @vb contents are not defined */static bool ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb){	int r_objid, r_name, r_vstate, r_child, r_parent, r_stripe, r_cols, len;	struct vblk_comp *comp;	BUG_ON (!buffer || !vb);	r_objid  = ldm_relative (buffer, buflen, 0x18, 0);	r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);	r_vstate = ldm_relative (buffer, buflen, 0x18, r_name);	r_child  = ldm_relative (buffer, buflen, 0x1D, r_vstate);	r_parent = ldm_relative (buffer, buflen, 0x2D, r_child);	if (buffer[0x12] & VBLK_FLAG_COMP_STRIPE) {		r_stripe = ldm_relative (buffer, buflen, 0x2E, r_parent);		r_cols   = ldm_relative (buffer, buflen, 0x2E, r_stripe);		len = r_cols;	} else {		r_stripe = 0;		r_cols   = 0;		len = r_parent;	}	if (len < 0)		return false;	len += VBLK_SIZE_CMP3;	if (len != BE32 (buffer + 0x14))		return false;	comp = &vb->vblk.comp;	ldm_get_vstr (buffer + 0x18 + r_name, comp->state,		sizeof (comp->state));	comp->type      = buffer[0x18 + r_vstate];	comp->children  = ldm_get_vnum (buffer + 0x1D + r_vstate);	comp->parent_id = ldm_get_vnum (buffer + 0x2D + r_child);	comp->chunksize = r_stripe ? ldm_get_vnum (buffer+r_parent+0x2E) : 0;	return true;}/** * ldm_parse_dgr3 - Read a raw VBLK Disk Group object into a vblk structure * @buffer:  Block of data being worked on * @buflen:  Size of the block of data * @vb:      In-memory vblk in which to return information * * Read a raw VBLK Disk Group object (version 3) into a vblk structure. * * Return:  'true'   @vb contains a Disk Group VBLK *          'false'  @vb contents are not defined */static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb){	int r_objid, r_name, r_diskid, r_id1, r_id2, len;	struct vblk_dgrp *dgrp;	BUG_ON (!buffer || !vb);	r_objid  = ldm_relative (buffer, buflen, 0x18, 0);	r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);	r_diskid = ldm_relative (buffer, buflen, 0x18, r_name);	if (buffer[0x12] & VBLK_FLAG_DGR3_IDS) {		r_id1 = ldm_relative (buffer, buflen, 0x24, r_diskid);		r_id2 = ldm_relative (buffer, buflen, 0x24, r_id1);		len = r_id2;	} else {		r_id1 = 0;		r_id2 = 0;		len = r_diskid;	}	if (len < 0)		return false;	len += VBLK_SIZE_DGR3;	if (len != BE32 (buffer + 0x14))		return false;	dgrp = &vb->vblk.dgrp;	ldm_get_vstr (buffer + 0x18 + r_name, dgrp->disk_id,		sizeof (dgrp->disk_id));	return true;}/** * ldm_parse_dgr4 - Read a raw VBLK Disk Group object into a vblk structure * @buffer:  Block of data being worked on * @buflen:  Size of the block of data * @vb:      In-memory vblk in which to return information * * Read a raw VBLK Disk Group object (version 4) into a vblk structure. * * Return:  'true'   @vb contains a Disk Group VBLK *          'false'  @vb contents are not defined */static bool ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb){	char buf[64];	int r_objid, r_name, r_id1, r_id2, len;	struct vblk_dgrp *dgrp;	BUG_ON (!buffer || !vb);	r_objid  = ldm_relative (buffer, buflen, 0x18, 0);	r_name   = ldm_relative (buffer, buflen, 0x18, r_objid);	if (buffer[0x12] & VBLK_FLAG_DGR4_IDS) {		r_id1 = ldm_relative (buffer, buflen, 0x44, r_name);		r_id2 = ldm_relative (buffer, buflen, 0x44, r_id1);		len = r_id2;	} else {		r_id1 = 0;		r_id2 = 0;		len = r_name;	}	if (len < 0)		return false;	len += VBLK_SIZE_DGR4;	if (len != BE32 (buffer + 0x14))		return false;	dgrp = &vb->vblk.dgrp;	ldm_get_vstr (buffer + 0x18 + r_objid, buf, sizeof (buf));	return true;}/** * ldm_parse_dsk3 - Read a raw VBLK Disk object into a vblk structure * @buffer:  Block of data being worked on * @buflen:  Size of the block of data * @vb:      In-memory vblk in which to return information * * Read a raw VBLK Disk object (version 3) into a vblk structure. * * Return:  'true'   @vb contains a Disk VBLK *          'false'  @vb contents are not defined */static bool ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb){	int r_objid, r_name, r_diskid, r_altname, len;	struct vblk_disk *disk;	BUG_ON (!buffer || !vb);	r_objid   = ldm_relative (buffer, buflen, 0x18, 0);	r_name    = ldm_relative (buffer, buflen, 0x18, r_objid);	r_diskid  = ldm_relative (buffer, buflen, 0x18, r_name);	r_altname = ldm_relative (buffer, buflen, 0x18, r_diskid);	len = r_altname;	if (len < 0)		return false;	len += VBLK_SIZE_DSK3;	if (len != BE32 (buffer + 0x14))		return false;	disk = &vb->vblk.disk;	ldm_get_vstr (buffer + 0x18 + r_diskid, disk->alt_name,		sizeof (disk->alt_name));	if (!ldm_parse_guid (buffer + 0x19 + r_name, disk->disk_id))		return false;	return true;}/** * ldm_parse_dsk4 - Read a raw VBLK Disk object into a vblk structure * @buffer:  Block of data being worked on * @buflen:  Size of the block of data * @vb:      In-memory vblk in which to return information * * Read a raw VBLK Disk object (version 4) into a vblk structure. * * Return:  'true'   @vb contains a Disk VBLK *          'false'  @vb contents are not defined */static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb){	int r_objid, r_name, len;	struct vblk_disk *disk;	BUG_ON (!buffer || !vb);	r_objid = ldm_relative (buffer, buflen, 0x18, 0);	r_name  = ldm_relative (buffer, buflen, 0x18, r_objid);	len     = r_name;	if (len < 0)		return false;	len += VBLK_SIZE_DSK4;	if (len != BE32 (buffer + 0x14))		return false;	disk = &vb->vblk.disk;	memcpy (disk->disk_id, buffer + 0x18 + r_name, GUID_SIZE);	return true;}/** * ldm_parse_prt3 - Read a raw VBLK Partition object into a vblk structure * @buffer:  Block of data being worked on * @buflen:  Size of the block of data * @vb:      In-memory vblk in which to return information * * Read a raw VBLK Partition object (version 3) into a vblk structure. * * Return:  'true'   @vb contains a Partition VBLK *          'false'  @vb contents are not defined */static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb){	int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len;	struct vblk_part *part;	BUG_ON(!buffer || !vb);	r_objid = ldm_relative(buffer, buflen, 0x18, 0);	if (r_objid < 0) {		ldm_error("r_objid %d < 0", r_objid);		return false;	}	r_name = ldm_relative(buffer, buflen, 0x18, r_objid);	if (r_name < 0) {		ldm_error("r_name %d < 0", r_name);		return false;	}	r_size = ldm_relative(buffer, buflen, 0x34, r_name);	if (r_size < 0) {		ldm_error("r_size %d < 0", r_size);		return false;	}	r_parent = ldm_relative(buffer, buflen, 0x34, r_size);	if (r_parent < 0) {		ldm_error("r_parent %d < 0", r_parent);		return false;	}	r_diskid = ldm_relative(buffer, buflen, 0x34, r_parent);	if (r_diskid < 0) {		ldm_error("r_diskid %d < 0", r_diskid);		return false;	}	if (buffer[0x12] & VBLK_FLAG_PART_INDEX) {		r_index = ldm_relative(buffer, buflen, 0x34, r_diskid);		if (r_index < 0) {			ldm_error("r_index %d < 0", r_index);			return false;		}		len = r_index;	} else {		r_index = 0;		len = r_diskid;	}	if (len < 0) {		ldm_error("len %d < 0", len);		return false;	}	len += VBLK_SIZE_PRT3;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -