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

📄 fsys_zfs.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * Only use 28 bits, since we need 4 bits in the cookie for the	 * collision differentiator.  We MUST use the high bits, since	 * those are the onces that we first pay attention to when	 * chosing the bucket.	 */	crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);	return (crc);}/* * Only to be used on 8-bit arrays. * array_len is actual len in bytes (not encoded le_value_length). * buf is null-terminated. */static intzap_leaf_array_equal(zap_leaf_phys_t *l, int blksft, int chunk,    int array_len, const char *buf){	int bseen = 0;	while (bseen < array_len) {		struct zap_leaf_array *la =		    &ZAP_LEAF_CHUNK(l, blksft, chunk).l_array;		int toread = MIN(array_len - bseen, ZAP_LEAF_ARRAY_BYTES);		if (chunk >= ZAP_LEAF_NUMCHUNKS(blksft))			return (0);		if (zfs_bcmp(la->la_array, buf + bseen, toread) != 0)			break;		chunk = la->la_next;		bseen += toread;	}	return (bseen == array_len);}/* * Given a zap_leaf_phys_t, walk thru the zap leaf chunks to get the * value for the property "name". * * Return: *	0 - success *	errnum - failure */static intzap_leaf_lookup(zap_leaf_phys_t *l, int blksft, uint64_t h,    const char *name, uint64_t *value){	uint16_t chunk;	struct zap_leaf_entry *le;	/* Verify if this is a valid leaf block */	if (l->l_hdr.lh_block_type != ZBT_LEAF)		return (ERR_FSYS_CORRUPT);	if (l->l_hdr.lh_magic != ZAP_LEAF_MAGIC)		return (ERR_FSYS_CORRUPT);	for (chunk = l->l_hash[LEAF_HASH(blksft, h)];	    chunk != CHAIN_END; chunk = le->le_next) {		if (chunk >= ZAP_LEAF_NUMCHUNKS(blksft))			return (ERR_FSYS_CORRUPT);		le = ZAP_LEAF_ENTRY(l, blksft, chunk);		/* Verify the chunk entry */		if (le->le_type != ZAP_CHUNK_ENTRY)			return (ERR_FSYS_CORRUPT);		if (le->le_hash != h)			continue;		if (zap_leaf_array_equal(l, blksft, le->le_name_chunk,		    le->le_name_length, name)) {			struct zap_leaf_array *la;			uint8_t *ip;			if (le->le_int_size != 8 || le->le_value_length != 1)				return (ERR_FSYS_CORRUPT);			/* get the uint64_t property value */			la = &ZAP_LEAF_CHUNK(l, blksft,			    le->le_value_chunk).l_array;			ip = la->la_array;			*value = (uint64_t)ip[0] << 56 | (uint64_t)ip[1] << 48 |			    (uint64_t)ip[2] << 40 | (uint64_t)ip[3] << 32 |			    (uint64_t)ip[4] << 24 | (uint64_t)ip[5] << 16 |			    (uint64_t)ip[6] << 8 | (uint64_t)ip[7];			return (0);		}	}	return (ERR_FSYS_CORRUPT);}/* * Fat ZAP lookup * * Return: *	0 - success *	errnum - failure */static intfzap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, zap_phys_t *zap,    char *name, uint64_t *value, char *stack){	zap_leaf_phys_t *l;	uint64_t hash, idx, blkid;	int blksft = zfs_log2(zap_dnode->dn_datablkszsec << DNODE_SHIFT);	/* Verify if this is a fat zap header block */	if (zap->zap_magic != (uint64_t)ZAP_MAGIC)		return (ERR_FSYS_CORRUPT);	hash = zap_hash(ffi, zap->zap_salt, name);	if (errnum)		return (errnum);	/* get block id from index */	if (zap->zap_ptrtbl.zt_numblks != 0) {		/* external pointer tables not supported */		return (ERR_FSYS_CORRUPT);	}	idx = ZAP_HASH_IDX(hash, zap->zap_ptrtbl.zt_shift);	blkid = ((uint64_t *)zap)[idx + (1<<(blksft-3-1))];	/* Get the leaf block */	l = (zap_leaf_phys_t *)stack;	stack += 1<<blksft;	if ((errnum = dmu_read(ffi, zap_dnode, blkid, l, stack)))		return (errnum);	return (zap_leaf_lookup(l, blksft, hash, name, value));}/* * Read in the data of a zap object and find the value for a matching * property name. * * Return: *	0 - success *	errnum - failure */static intzap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, char *name,    uint64_t *val, char *stack){	uint64_t block_type;	int size;	void *zapbuf;	/* Read in the first block of the zap object data. */	zapbuf = stack;	size = zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;	stack += size;	if ((errnum = dmu_read(ffi, zap_dnode, 0, zapbuf, stack)))		return (errnum);	block_type = *((uint64_t *)zapbuf);	if (block_type == ZBT_MICRO) {		return (mzap_lookup(zapbuf, size, name, val));	} else if (block_type == ZBT_HEADER) {		/* this is a fat zap */		return (fzap_lookup(ffi, zap_dnode, zapbuf, name,		    val, stack));	}	return (ERR_FSYS_CORRUPT);}/* * Get the dnode of an object number from the metadnode of an object set. * * Input *	mdn - metadnode to get the object dnode *	objnum - object number for the object dnode *	buf - data buffer that holds the returning dnode *	stack - scratch area * * Return: *	0 - success *	errnum - failure */static intdnode_get(fsi_file_t *ffi, dnode_phys_t *mdn, uint64_t objnum,    uint8_t type, dnode_phys_t *buf, char *stack){	uint64_t blkid, blksz; /* the block id this object dnode is in */	int epbs; /* shift of number of dnodes in a block */	int idx; /* index within a block */	dnode_phys_t *dnbuf;	zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;	blksz = mdn->dn_datablkszsec << SPA_MINBLOCKSHIFT;	epbs = zfs_log2(blksz) - DNODE_SHIFT;	blkid = objnum >> epbs;	idx = objnum & ((1<<epbs)-1);	if (dnode_buf != NULL && dnode_mdn == mdn &&	    objnum >= dnode_start && objnum < dnode_end) {		grub_memmove(buf, &dnode_buf[idx], DNODE_SIZE);		VERIFY_DN_TYPE(buf, type);		return (0);	}	if (dnode_buf && blksz == 1<<DNODE_BLOCK_SHIFT) {		dnbuf = dnode_buf;		dnode_mdn = mdn;		dnode_start = blkid << epbs;		dnode_end = (blkid + 1) << epbs;	} else {		dnbuf = (dnode_phys_t *)stack;		stack += blksz;	}	if ((errnum = dmu_read(ffi, mdn, blkid, (char *)dnbuf, stack)))		return (errnum);	grub_memmove(buf, &dnbuf[idx], DNODE_SIZE);	VERIFY_DN_TYPE(buf, type);	return (0);}/* * Check if this is a special file that resides at the top * dataset of the pool. Currently this is the GRUB menu, * boot signature and boot signature backup. * str starts with '/'. */static intis_top_dataset_file(char *str){	char *tptr;	if (((tptr = strstr(str, "menu.lst"))) &&	    (tptr[8] == '\0' || tptr[8] == ' ') &&	    *(tptr-1) == '/')		return (1);	if (strncmp(str, BOOTSIGN_DIR"/",	    strlen(BOOTSIGN_DIR) + 1) == 0)		return (1);	if (strcmp(str, BOOTSIGN_BACKUP) == 0)		return (1);	return (0);}/* * Get the file dnode for a given file name where mdn is the meta dnode * for this ZFS object set. When found, place the file dnode in dn. * The 'path' argument will be mangled. * * Return: *	0 - success *	errnum - failure */static intdnode_get_path(fsi_file_t *ffi, dnode_phys_t *mdn, char *path,    dnode_phys_t *dn, char *stack){	uint64_t objnum, version;	char *cname, ch;	if ((errnum = dnode_get(ffi, mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,	    dn, stack)))		return (errnum);	if ((errnum = zap_lookup(ffi, dn, ZPL_VERSION_STR, &version, stack)))		return (errnum);	if (version > ZPL_VERSION)		return (-1);	if ((errnum = zap_lookup(ffi, dn, ZFS_ROOT_OBJ, &objnum, stack)))		return (errnum);	if ((errnum = dnode_get(ffi, mdn, objnum, DMU_OT_DIRECTORY_CONTENTS,	    dn, stack)))		return (errnum);	/* skip leading slashes */	while (*path == '/')		path++;	while (*path && !isspace((uint8_t)*path)) {		/* get the next component name */		cname = path;		while (*path && !isspace((uint8_t)*path) && *path != '/')			path++;		ch = *path;		*path = 0;   /* ensure null termination */		if ((errnum = zap_lookup(ffi, dn, cname, &objnum, stack)))			return (errnum);		objnum = ZFS_DIRENT_OBJ(objnum);		if ((errnum = dnode_get(ffi, mdn, objnum, 0, dn, stack)))			return (errnum);		*path = ch;		while (*path == '/')			path++;	}	/* We found the dnode for this file. Verify if it is a plain file. */	VERIFY_DN_TYPE(dn, DMU_OT_PLAIN_FILE_CONTENTS);	return (0);}/* * Get the default 'bootfs' property value from the rootpool. * * Return: *	0 - success *	errnum -failure */static intget_default_bootfsobj(fsi_file_t *ffi, dnode_phys_t *mosmdn,    uint64_t *obj, char *stack){	uint64_t objnum = 0;	dnode_phys_t *dn = (dnode_phys_t *)stack;	stack += DNODE_SIZE;	if ((errnum = dnode_get(ffi, mosmdn, DMU_POOL_DIRECTORY_OBJECT,	    DMU_OT_OBJECT_DIRECTORY, dn, stack)))		return (errnum);	/*	 * find the object number for 'pool_props', and get the dnode	 * of the 'pool_props'.	 */	if (zap_lookup(ffi, dn, DMU_POOL_PROPS, &objnum, stack))		return (ERR_FILESYSTEM_NOT_FOUND);	if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_POOL_PROPS, dn,	    stack)))		return (errnum);	if (zap_lookup(ffi, dn, ZPOOL_PROP_BOOTFS, &objnum, stack))		return (ERR_FILESYSTEM_NOT_FOUND);	if (!objnum)		return (ERR_FILESYSTEM_NOT_FOUND);	*obj = objnum;	return (0);}/* * Given a MOS metadnode, get the metadnode of a given filesystem name (fsname), * e.g. pool/rootfs, or a given object number (obj), e.g. the object number * of pool/rootfs. * * If no fsname and no obj are given, return the DSL_DIR metadnode. * If fsname is given, return its metadnode and its matching object number. * If only obj is given, return the metadnode for this object number. * * Return: *	0 - success *	errnum - failure */static intget_objset_mdn(fsi_file_t *ffi, dnode_phys_t *mosmdn, char *fsname,    uint64_t *obj, dnode_phys_t *mdn, char *stack){	uint64_t objnum, headobj;	char *cname, ch;	blkptr_t *bp;	objset_phys_t *osp;	if (fsname == NULL && obj) {		headobj = *obj;		goto skip;	}	if ((errnum = dnode_get(ffi, mosmdn, DMU_POOL_DIRECTORY_OBJECT,	    DMU_OT_OBJECT_DIRECTORY, mdn, stack)))		return (errnum);	if ((errnum = zap_lookup(ffi, mdn, DMU_POOL_ROOT_DATASET, &objnum,	    stack)))		return (errnum);	if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_DSL_DIR, mdn,	    stack)))		return (errnum);	if (fsname == NULL) {		headobj =		    ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;		goto skip;	}	/* take out the pool name */	while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/')		fsname++;	while (*fsname && !isspace((uint8_t)*fsname)) {		uint64_t childobj;		while (*fsname == '/')			fsname++;		cname = fsname;		while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/')			fsname++;		ch = *fsname;		*fsname = 0;		childobj =		    ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_child_dir_zapobj;		if ((errnum = dnode_get(ffi, mosmdn, childobj,		    DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack)))			return (errnum);		if (zap_lookup(ffi, mdn, cname, &objnum, stack))			return (ERR_FILESYSTEM_NOT_FOUND);		if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_DSL_DIR,		    mdn, stack)))			return (errnum);		*fsname = ch;	}	headobj = ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;	if (obj)		*obj = headobj;skip:	if ((errnum = dnode_get(ffi, mosmdn, headobj, DMU_OT_DSL_DATASET, mdn,	    stack)))		return (errnum);	/* TODO: Add snapshot support here - for fsname=snapshot-name */	bp = &((dsl_dataset_phys_t *)DN_BONUS(mdn))->ds_bp;	osp = (objset_phys_t *)stack;	stack += sizeof (objset_phys_t);	if ((errnum = zio_read(ffi, bp, osp, stack)))		return (errnum);	grub_memmove((char *)mdn, (char *)&osp->os_meta_dnode, DNODE_SIZE);	return (0);}/* * For a given XDR packed nvlist, verify the first 4 bytes and move on. * * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : * *      encoding method/host endian     (4 bytes) *      nvl_version                     (4 bytes) *      nvl_nvflag                      (4 bytes) *	encoded nvpairs: *		encoded size of the nvpair      (4 bytes) *		decoded size of the nvpair      (4 bytes) *		name string size                (4 bytes) *		name string data                (sizeof(NV_ALIGN4(string)) *		data type                       (4 bytes) *		# of elements in the nvpair     (4 bytes) *		data *      2 zero's for the last nvpair *		(end of the entire list)	(8 bytes) * * Return: *	0 - success *	1 - failure */static intnvlist_unpack(char *nvlist, char **out){	/* Verify if the 1st and 2nd byte in the nvlist are valid. */	if (nvlist[0] != NV_ENCODE_XDR || nvlist[1] != HOST_ENDIAN)

⌨️ 快捷键说明

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