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

📄 fsys_zfs.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
		return (1);	nvlist += 4;	*out = nvlist;	return (0);}static char *nvlist_array(char *nvlist, int index){	int i, encode_size;	for (i = 0; i < index; i++) {		/* skip the header, nvl_version, and nvl_nvflag */		nvlist = nvlist + 4 * 2;		while ((encode_size = BSWAP_32(*(uint32_t *)nvlist)))			nvlist += encode_size; /* goto the next nvpair */		nvlist = nvlist + 4 * 2; /* skip the ending 2 zeros - 8 bytes */	}	return (nvlist);}static intnvlist_lookup_value(char *nvlist, char *name, void *val, int valtype,    int *nelmp){	int name_len, type, slen, encode_size;	char *nvpair, *nvp_name, *strval = val;	uint64_t *intval = val;	/* skip the header, nvl_version, and nvl_nvflag */	nvlist = nvlist + 4 * 2;	/*	 * Loop thru the nvpair list	 * The XDR representation of an integer is in big-endian byte order.	 */	while ((encode_size = BSWAP_32(*(uint32_t *)nvlist)))  {		nvpair = nvlist + 4 * 2; /* skip the encode/decode size */		name_len = BSWAP_32(*(uint32_t *)nvpair);		nvpair += 4;		nvp_name = nvpair;		nvpair = nvpair + ((name_len + 3) & ~3); /* align */		type = BSWAP_32(*(uint32_t *)nvpair);		nvpair += 4;		if (((strncmp(nvp_name, name, name_len) == 0) &&		    type == valtype)) {			int nelm;			if (((nelm = BSWAP_32(*(uint32_t *)nvpair)) < 1))				return (1);			nvpair += 4;			switch (valtype) {			case DATA_TYPE_STRING:				slen = BSWAP_32(*(uint32_t *)nvpair);				nvpair += 4;				grub_memmove(strval, nvpair, slen);				strval[slen] = '\0';				return (0);			case DATA_TYPE_UINT64:				*intval = BSWAP_64(*(uint64_t *)nvpair);				return (0);			case DATA_TYPE_NVLIST:				*(void **)val = (void *)nvpair;				return (0);			case DATA_TYPE_NVLIST_ARRAY:				*(void **)val = (void *)nvpair;				if (nelmp)					*nelmp = nelm;				return (0);			}		}		nvlist += encode_size; /* goto the next nvpair */	}	return (1);}/* * Check if this vdev is online and is in a good state. */static intvdev_validate(char *nv){	uint64_t ival;	if (nvlist_lookup_value(nv, ZPOOL_CONFIG_OFFLINE, &ival,	    DATA_TYPE_UINT64, NULL) == 0 ||	    nvlist_lookup_value(nv, ZPOOL_CONFIG_FAULTED, &ival,	    DATA_TYPE_UINT64, NULL) == 0 ||	    nvlist_lookup_value(nv, ZPOOL_CONFIG_DEGRADED, &ival,	    DATA_TYPE_UINT64, NULL) == 0 ||	    nvlist_lookup_value(nv, ZPOOL_CONFIG_REMOVED, &ival,	    DATA_TYPE_UINT64, NULL) == 0)		return (ERR_DEV_VALUES);	return (0);}/* * Get a list of valid vdev pathname from the boot device. * The caller should already allocate MAXNAMELEN memory for bootpath. */static intvdev_get_bootpath(char *nv, char *bootpath){	char type[16];	bootpath[0] = '\0';	if (nvlist_lookup_value(nv, ZPOOL_CONFIG_TYPE, &type, DATA_TYPE_STRING,	    NULL))		return (ERR_FSYS_CORRUPT);	if (strcmp(type, VDEV_TYPE_DISK) == 0) {		if (vdev_validate(nv) != 0 ||		    nvlist_lookup_value(nv, ZPOOL_CONFIG_PHYS_PATH, bootpath,		    DATA_TYPE_STRING, NULL) != 0)			return (ERR_NO_BOOTPATH);	} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {		int nelm, i;		char *child;		if (nvlist_lookup_value(nv, ZPOOL_CONFIG_CHILDREN, &child,		    DATA_TYPE_NVLIST_ARRAY, &nelm))			return (ERR_FSYS_CORRUPT);		for (i = 0; i < nelm; i++) {			char tmp_path[MAXNAMELEN];			char *child_i;			child_i = nvlist_array(child, i);			if (vdev_validate(child_i) != 0)				continue;			if (nvlist_lookup_value(child_i, ZPOOL_CONFIG_PHYS_PATH,			    tmp_path, DATA_TYPE_STRING, NULL) != 0)				return (ERR_NO_BOOTPATH);			if ((strlen(bootpath) + strlen(tmp_path)) > MAXNAMELEN)				return (ERR_WONT_FIT);			if (strlen(bootpath) == 0)				sprintf(bootpath, "%s", tmp_path);			else				sprintf(bootpath, "%s %s", bootpath, tmp_path);		}	}	return (strlen(bootpath) > 0 ? 0 : ERR_NO_BOOTPATH);}/* * Check the disk label information and retrieve needed vdev name-value pairs. * * Return: *	0 - success *	ERR_* - failure */static intcheck_pool_label(fsi_file_t *ffi, int label, char *stack){	vdev_phys_t *vdev;	uint64_t sector, pool_state, txg = 0;	char *nvlist, *nv;	zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;	sector = (label * sizeof (vdev_label_t) + VDEV_SKIP_SIZE +	    VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT;	/* Read in the vdev name-value pair list (112K). */	if (devread(ffi, sector, 0, VDEV_PHYS_SIZE, stack) == 0)		return (ERR_READ);	vdev = (vdev_phys_t *)stack;	if (nvlist_unpack(vdev->vp_nvlist, &nvlist))		return (ERR_FSYS_CORRUPT);	if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_POOL_STATE, &pool_state,	    DATA_TYPE_UINT64, NULL))		return (ERR_FSYS_CORRUPT);	if (pool_state == POOL_STATE_DESTROYED)		return (ERR_FILESYSTEM_NOT_FOUND);	if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_POOL_NAME,	    current_rootpool, DATA_TYPE_STRING, NULL))		return (ERR_FSYS_CORRUPT);	if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_POOL_TXG, &txg,	    DATA_TYPE_UINT64, NULL))		return (ERR_FSYS_CORRUPT);	/* not an active device */	if (txg == 0)		return (ERR_NO_BOOTPATH);	if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_VDEV_TREE, &nv,	    DATA_TYPE_NVLIST, NULL))		return (ERR_FSYS_CORRUPT);	if (vdev_get_bootpath(nv, current_bootpath))		return (ERR_NO_BOOTPATH);	return (0);}/* * zfs_mount() locates a valid uberblock of the root pool and read in its MOS * to the memory address MOS. * * Return: *	1 - success *	0 - failure */static intzfs_mount(fsi_file_t *ffi, const char *options){	char *stack;	int label = 0;	uberblock_phys_t *ub_array, *ubbest = NULL;	objset_phys_t *osp;	zfs_bootarea_t *zfs_ba;	/* if zfs is already mounted, don't do it again */	if (is_zfs_mount == 1)		return (1);	/* get much bigger data block for zfs */	if (((zfs_ba = malloc(sizeof (zfs_bootarea_t))) == NULL)) {		return (1);	}	bzero(zfs_ba, sizeof (zfs_bootarea_t));	/* replace small data area in fsi with big one */	free(ffi->ff_fsi->f_data);	ffi->ff_fsi->f_data = (void *)zfs_ba;	/* If an boot filesystem is passed in, set it to current_bootfs */	if (options != NULL) {		if (strlen(options) < MAXNAMELEN) {			strcpy(current_bootfs, options);		}	}	stackbase = ZFS_SCRATCH;	stack = stackbase;	ub_array = (uberblock_phys_t *)stack;	stack += VDEV_UBERBLOCK_RING;	osp = (objset_phys_t *)stack;	stack += sizeof (objset_phys_t);	/* XXX add back labels support? */	for (label = 0; ubbest == NULL && label < (VDEV_LABELS/2); label++) {		uint64_t sector = (label * sizeof (vdev_label_t) +		    VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE +		    VDEV_PHYS_SIZE) >> SPA_MINBLOCKSHIFT;		/* Read in the uberblock ring (128K). */		if (devread(ffi, sector, 0, VDEV_UBERBLOCK_RING,		    (char *)ub_array) == 0)			continue;		if ((ubbest = find_bestub(ffi, ub_array, label)) != NULL &&		    zio_read(ffi, &ubbest->ubp_uberblock.ub_rootbp, osp, stack)		    == 0) {			VERIFY_OS_TYPE(osp, DMU_OST_META);			/* Got the MOS. Save it at the memory addr MOS. */			grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE);			if (check_pool_label(ffi, label, stack))				return (0);			/*			 * Copy fsi->f_data to ffi->ff_data since			 * fsig_mount copies from ff_data to f_data			 * overwriting fsi->f_data.			 */			bcopy(zfs_ba, fsig_file_buf(ffi), FSYS_BUFLEN);			is_zfs_mount = 1;			return (1);		}	}	return (0);}/* * zfs_open() locates a file in the rootpool by following the * MOS and places the dnode of the file in the memory address DNODE. * * Return: *	1 - success *	0 - failure */static intzfs_open(fsi_file_t *ffi, char *filename){	char *stack;	dnode_phys_t *mdn;	char *bootstring;	zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;	file_buf = NULL;	stackbase = ZFS_SCRATCH;	stack = stackbase;	mdn = (dnode_phys_t *)stack;	stack += sizeof (dnode_phys_t);	dnode_mdn = NULL;	dnode_buf = (dnode_phys_t *)stack;	stack += 1<<DNODE_BLOCK_SHIFT;	/*	 * menu.lst is placed at the root pool filesystem level,	 * do not goto 'current_bootfs'.	 */	if (is_top_dataset_file(filename)) {		if ((errnum = get_objset_mdn(ffi, MOS, NULL, NULL, mdn, stack)))			return (0);		current_bootfs_obj = 0;	} else {		if (current_bootfs[0] == '\0') {			/* Get the default root filesystem object number */			if ((errnum = get_default_bootfsobj(ffi, MOS,			    &current_bootfs_obj, stack)))				return (0);			if ((errnum = get_objset_mdn(ffi, MOS, NULL,			    &current_bootfs_obj, mdn, stack)))				return (0);		} else {			if ((errnum = get_objset_mdn(ffi, MOS,			    current_bootfs, &current_bootfs_obj, mdn, stack)))				return (0);		}		/*		 * Put zfs rootpool and boot obj number into bootstring.		 */		if (is_zfs_open == 0) {			char temp[25];		/* needs to hold long long */			int alloc_size;			char zfs_bootstr[] = "zfs-bootfs=";			char zfs_bootpath[] = ",bootpath='";			snprintf(temp, sizeof(temp), "%llu", (unsigned long long)			    current_bootfs_obj);			alloc_size = strlen(zfs_bootstr) +			    strlen(current_rootpool) +			    strlen(temp) + strlen(zfs_bootpath) +			    strlen(current_bootpath) + 3;			bootstring = fsi_bootstring_alloc(ffi->ff_fsi,			    alloc_size);			if (bootstring != NULL) {				strcpy(bootstring, zfs_bootstr);				strcat(bootstring, current_rootpool);				strcat(bootstring, "/");				strcat(bootstring, temp);				strcat(bootstring, zfs_bootpath);				strcat(bootstring, current_bootpath);				strcat(bootstring, "'");				is_zfs_open = 1;			}		}	}	if (dnode_get_path(ffi, mdn, filename, DNODE, stack)) {		errnum = ERR_FILE_NOT_FOUND;		return (0);	}	/* get the file size and set the file position to 0 */	filemax = ((znode_phys_t *)DN_BONUS(DNODE))->zp_size;	filepos = 0;	dnode_buf = NULL;	return (1);}/* * zfs_read reads in the data blocks pointed by the DNODE. * * Return: *	len - the length successfully read in to the buffer *	0   - failure */static intzfs_read(fsi_file_t *ffi, char *buf, int len){	char *stack;	int blksz, length, movesize;	zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;	if (file_buf == NULL) {		file_buf = stackbase;		stackbase += SPA_MAXBLOCKSIZE;		file_start = file_end = 0;	}	stack = stackbase;	/*	 * If offset is in memory, move it into the buffer provided and return.	 */	if (filepos >= file_start && filepos+len <= file_end) {		grub_memmove(buf, file_buf + filepos - file_start, len);		filepos += len;		return (len);	}	blksz = DNODE->dn_datablkszsec << SPA_MINBLOCKSHIFT;	/*	 * Entire Dnode is too big to fit into the space available.  We	 * will need to read it in chunks.  This could be optimized to	 * read in as large a chunk as there is space available, but for	 * now, this only reads in one data block at a time.	 */	length = len;	while (length) {		/*		 * Find requested blkid and the offset within that block.		 */		uint64_t blkid = filepos / blksz;		if ((errnum = dmu_read(ffi, DNODE, blkid, file_buf, stack)))			return (0);		file_start = blkid * blksz;		file_end = file_start + blksz;		movesize = MIN(length, file_end - filepos);		grub_memmove(buf, file_buf + filepos - file_start,		    movesize);		buf += movesize;		length -= movesize;		filepos += movesize;	}	return (len);}/* * No-Op */intzfs_embed(int *start_sector, int needed_sectors){	return (1);}fsi_plugin_ops_t *fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name){	static fsig_plugin_ops_t ops = {		FSIMAGE_PLUGIN_VERSION,		.fpo_mount = zfs_mount,		.fpo_dir = zfs_open,		.fpo_read = zfs_read	};	*name = "zfs";	return (fsig_init(fp, &ops));}

⌨️ 快捷键说明

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