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

📄 fsys_zfs.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * Copyright 2008 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. *//* * All files in the zfs directory are derived from the OpenSolaris * zfs grub files.  All files in the zfs-include directory were * included without changes. *//* * The zfs plug-in routines for GRUB are: * * zfs_mount() - locates a valid uberblock of the root pool and reads *		in its MOS at the memory address MOS. * * zfs_open() - locates a plain file object by following the MOS *		and places its dnode at the memory address DNODE. * * zfs_read() - read in the data blocks pointed by the DNODE. * * ZFS_SCRATCH is used as a working area. * * (memory addr)   MOS      DNODE	ZFS_SCRATCH *		    |         |          | *	    +-------V---------V----------V---------------+ *   memory |       | dnode   | dnode    |  scratch      | *	    |       | 512B    | 512B     |  area         | *	    +--------------------------------------------+ */#include <stdio.h>#include <strings.h>/* From "shared.h" */#include "mb_info.h"/* Boot signature related defines for the findroot command */#define	BOOTSIGN_DIR	"/boot/grub/bootsign"#define	BOOTSIGN_BACKUP	"/etc/bootsign"/* Maybe redirect memory requests through grub_scratch_mem. */#define	RAW_ADDR(x) (x)#define	RAW_SEG(x) (x)/* ZFS will use the top 4 Meg of physical memory (below 4Gig) for sratch */#define	ZFS_SCRATCH_SIZE 0x400000#define	MIN(x, y) ((x) < (y) ? (x) : (y))/* End from shared.h */#include "fsys_zfs.h"/* cache for a file block of the currently zfs_open()-ed file */#define	file_buf zfs_ba->zfs_file_buf#define	file_start zfs_ba->zfs_file_start#define	file_end zfs_ba->zfs_file_end/* cache for a dnode block */#define	dnode_buf zfs_ba->zfs_dnode_buf#define	dnode_mdn zfs_ba->zfs_dnode_mdn#define	dnode_start zfs_ba->zfs_dnode_start#define	dnode_end zfs_ba->zfs_dnode_end#define	stackbase zfs_ba->zfs_stackbasedecomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] ={	{"noop", 0},	{"on", lzjb_decompress}, 	/* ZIO_COMPRESS_ON */	{"off", 0},	{"lzjb", lzjb_decompress}	/* ZIO_COMPRESS_LZJB */};/* From disk_io.c *//* ZFS root filesystem for booting */#define	current_bootpath zfs_ba->zfs_current_bootpath#define	current_rootpool zfs_ba->zfs_current_rootpool#define	current_bootfs zfs_ba->zfs_current_bootfs#define	current_bootfs_obj zfs_ba->zfs_current_bootfs_obj#define	is_zfs_mount (*fsig_int1(ffi))/* End from disk_io.c */#define	is_zfs_open zfs_ba->zfs_open/* * Our own version of bcmp(). */static intzfs_bcmp(const void *s1, const void *s2, size_t n){	const unsigned char *ps1 = s1;	const unsigned char *ps2 = s2;	if (s1 != s2 && n != 0) {		do {			if (*ps1++ != *ps2++)				return (1);		} while (--n != 0);	}	return (0);}/* * Our own version of log2().  Same thing as highbit()-1. */static intzfs_log2(uint64_t num){	int i = 0;	while (num > 1) {		i++;		num = num >> 1;	}	return (i);}/* Checksum Functions */static voidzio_checksum_off(const void *buf, uint64_t size, zio_cksum_t *zcp){	ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0);}/* Checksum Table and Values */zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {	{{NULL,			NULL},			0, 0,	"inherit"},	{{NULL,			NULL},			0, 0,	"on"},	{{zio_checksum_off,	zio_checksum_off},	0, 0,	"off"},	{{zio_checksum_SHA256,	zio_checksum_SHA256},	1, 1,	"label"},	{{zio_checksum_SHA256,	zio_checksum_SHA256},	1, 1,	"gang_header"},	{{fletcher_2_native,	fletcher_2_byteswap},	0, 1,	"zilog"},	{{fletcher_2_native,	fletcher_2_byteswap},	0, 0,	"fletcher2"},	{{fletcher_4_native,	fletcher_4_byteswap},	1, 0,	"fletcher4"},	{{zio_checksum_SHA256,	zio_checksum_SHA256},	1, 0,	"SHA256"}};/* * zio_checksum_verify: Provides support for checksum verification. * * Fletcher2, Fletcher4, and SHA256 are supported. * * Return: * 	-1 = Failure *	 0 = Success */static intzio_checksum_verify(blkptr_t *bp, char *data, int size){	zio_cksum_t zc = bp->blk_cksum;	uint32_t checksum = BP_IS_GANG(bp) ? ZIO_CHECKSUM_GANG_HEADER :	    BP_GET_CHECKSUM(bp);	int byteswap = BP_SHOULD_BYTESWAP(bp);	zio_block_tail_t *zbt = (zio_block_tail_t *)(data + size) - 1;	zio_checksum_info_t *ci = &zio_checksum_table[checksum];	zio_cksum_t actual_cksum, expected_cksum;	/* byteswap is not supported */	if (byteswap)		return (-1);	if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL)		return (-1);	if (ci->ci_zbt) {		if (checksum == ZIO_CHECKSUM_GANG_HEADER) {			/*			 * 'gang blocks' is not supported.			 */			return (-1);		}		if (zbt->zbt_magic == BSWAP_64(ZBT_MAGIC)) {			/* byte swapping is not supported */			return (-1);		} else {			expected_cksum = zbt->zbt_cksum;			zbt->zbt_cksum = zc;			ci->ci_func[0](data, size, &actual_cksum);			zbt->zbt_cksum = expected_cksum;		}		zc = expected_cksum;	} else {		if (BP_IS_GANG(bp))			return (-1);		ci->ci_func[byteswap](data, size, &actual_cksum);	}	if ((actual_cksum.zc_word[0] - zc.zc_word[0]) |	    (actual_cksum.zc_word[1] - zc.zc_word[1]) |	    (actual_cksum.zc_word[2] - zc.zc_word[2]) |	    (actual_cksum.zc_word[3] - zc.zc_word[3]))		return (-1);	return (0);}/* * vdev_label_offset takes "offset" (the offset within a vdev_label) and * returns its physical disk offset (starting from the beginning of the vdev). * * Input: *	psize	: Physical size of this vdev *      l	: Label Number (0-3) *	offset	: The offset with a vdev_label in which we want the physical *		  address * Return: * 	Success : physical disk offset * 	Failure : errnum = ERR_BAD_ARGUMENT, return value is meaningless */static uint64_tvdev_label_offset(fsi_file_t *ffi, uint64_t psize, int l, uint64_t offset){	/* XXX Need to add back label support! */	if (l >= VDEV_LABELS/2 || offset > sizeof (vdev_label_t)) {		errnum = ERR_BAD_ARGUMENT;		return (0);	}	return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?	    0 : psize - VDEV_LABELS * sizeof (vdev_label_t)));}/* * vdev_uberblock_compare takes two uberblock structures and returns an integer * indicating the more recent of the two. * 	Return Value = 1 if ub2 is more recent * 	Return Value = -1 if ub1 is more recent * The most recent uberblock is determined using its transaction number and * timestamp.  The uberblock with the highest transaction number is * considered "newer".  If the transaction numbers of the two blocks match, the * timestamps are compared to determine the "newer" of the two. */static intvdev_uberblock_compare(uberblock_t *ub1, uberblock_t *ub2){	if (ub1->ub_txg < ub2->ub_txg)		return (-1);	if (ub1->ub_txg > ub2->ub_txg)		return (1);	if (ub1->ub_timestamp < ub2->ub_timestamp)		return (-1);	if (ub1->ub_timestamp > ub2->ub_timestamp)		return (1);	return (0);}/* * Three pieces of information are needed to verify an uberblock: the magic * number, the version number, and the checksum. * * Currently Implemented: version number, magic number * Need to Implement: checksum * * Return: *     0 - Success *    -1 - Failure */static intuberblock_verify(uberblock_phys_t *ub, int offset){	uberblock_t *uber = &ub->ubp_uberblock;	blkptr_t bp;	BP_ZERO(&bp);	BP_SET_CHECKSUM(&bp, ZIO_CHECKSUM_LABEL);	BP_SET_BYTEORDER(&bp, ZFS_HOST_BYTEORDER);	ZIO_SET_CHECKSUM(&bp.blk_cksum, offset, 0, 0, 0);	if (zio_checksum_verify(&bp, (char *)ub, UBERBLOCK_SIZE) != 0)		return (-1);	if (uber->ub_magic == UBERBLOCK_MAGIC &&	    uber->ub_version >= SPA_VERSION_1 &&	    uber->ub_version <= SPA_VERSION)		return (0);	return (-1);}/* * Find the best uberblock. * Return: *    Success - Pointer to the best uberblock. *    Failure - NULL */static uberblock_phys_t *find_bestub(fsi_file_t *ffi, uberblock_phys_t *ub_array, int label){	uberblock_phys_t *ubbest = NULL;	int i, offset;	for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++) {		offset = vdev_label_offset(ffi, 0, label,		    VDEV_UBERBLOCK_OFFSET(i));		if (errnum == ERR_BAD_ARGUMENT)			return (NULL);		if (uberblock_verify(&ub_array[i], offset) == 0) {			if (ubbest == NULL) {				ubbest = &ub_array[i];			} else if (vdev_uberblock_compare(			    &(ub_array[i].ubp_uberblock),			    &(ubbest->ubp_uberblock)) > 0) {				ubbest = &ub_array[i];			}		}	}	return (ubbest);}/* * Read in a block and put its uncompressed data in buf. * * Return: *	0 - success *	errnum - failure */static intzio_read(fsi_file_t *ffi, blkptr_t *bp, void *buf, char *stack){	uint64_t offset, sector;	int psize, lsize;	int i, comp, cksum;	psize = BP_GET_PSIZE(bp);	lsize = BP_GET_LSIZE(bp);	comp = BP_GET_COMPRESS(bp);	cksum = BP_GET_CHECKSUM(bp);	if ((unsigned int)comp >= ZIO_COMPRESS_FUNCTIONS ||	    (comp != ZIO_COMPRESS_OFF &&	    decomp_table[comp].decomp_func == NULL))		return (ERR_FSYS_CORRUPT);	/* pick a good dva from the block pointer */	for (i = 0; i < SPA_DVAS_PER_BP; i++) {		if (bp->blk_dva[i].dva_word[0] == 0 &&		    bp->blk_dva[i].dva_word[1] == 0)			continue;		/* read in a block */		offset = DVA_GET_OFFSET(&bp->blk_dva[i]);		sector =  DVA_OFFSET_TO_PHYS_SECTOR(offset);		if (comp != ZIO_COMPRESS_OFF) {			if (devread(ffi, sector, 0, psize, stack) == 0)				continue;			if (zio_checksum_verify(bp, stack, psize) != 0)				continue;			decomp_table[comp].decomp_func(stack, buf, psize,			    lsize);		} else {			if (devread(ffi, sector, 0, psize, buf) == 0)				continue;			if (zio_checksum_verify(bp, buf, psize) != 0)				continue;		}		return (0);	}	return (ERR_FSYS_CORRUPT);}/* * Get the block from a block id. * push the block onto the stack. * * Return: * 	0 - success * 	errnum - failure */static intdmu_read(fsi_file_t *ffi, dnode_phys_t *dn, uint64_t blkid, void *buf,    char *stack){	int idx, level;	blkptr_t *bp_array = dn->dn_blkptr;	int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;	blkptr_t *bp, *tmpbuf;	bp = (blkptr_t *)stack;	stack += sizeof (blkptr_t);	tmpbuf = (blkptr_t *)stack;	stack += 1<<dn->dn_indblkshift;	for (level = dn->dn_nlevels - 1; level >= 0; level--) {		idx = (blkid >> (epbs * level)) & ((1<<epbs)-1);		*bp = bp_array[idx];		if (level == 0)			tmpbuf = buf;		if (BP_IS_HOLE(bp)) {			grub_memset(buf, 0,			    dn->dn_datablkszsec << SPA_MINBLOCKSHIFT);			break;		} else if ((errnum = zio_read(ffi, bp, tmpbuf, stack))) {			return (errnum);		}		bp_array = tmpbuf;	}	return (0);}/* * mzap_lookup: Looks up property described by "name" and returns the value * in "value". * * Return: *	0 - success *	errnum - failure */static intmzap_lookup(mzap_phys_t *zapobj, int objsize, char *name,	uint64_t *value){	int i, chunks;	mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;	chunks = objsize/MZAP_ENT_LEN - 1;	for (i = 0; i < chunks; i++) {		if (strcmp(mzap_ent[i].mze_name, name) == 0) {			*value = mzap_ent[i].mze_value;			return (0);		}	}	return (ERR_FSYS_CORRUPT);}static uint64_tzap_hash(fsi_file_t *ffi, uint64_t salt, const char *name){	static uint64_t table[256];	const uint8_t *cp;	uint8_t c;	uint64_t crc = salt;	if (table[128] == 0) {		uint64_t *ct;		int i, j;		for (i = 0; i < 256; i++) {			for (ct = table + i, *ct = i, j = 8; j > 0; j--)				*ct = (*ct >> 1) ^ (-(*ct & 1) &				    ZFS_CRC64_POLY);		}	}	if (crc == 0 || table[128] != ZFS_CRC64_POLY) {		errnum = ERR_FSYS_CORRUPT;		return (0);	}	for (cp = (const uint8_t *)name; (c = *cp) != '\0'; cp++)		crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF];

⌨️ 快捷键说明

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