3 files changed, 192 insertions(+), 97 deletions(-)
tools/libfsimage/common/fsimage_grub.h | 1
tools/libfsimage/zfs/fsys_zfs.c | 276 ++++++++++++++++++++++----------
tools/libfsimage/zfs/zfs-include/zfs.h | 12 -
# HG changeset patch
# User Jody Belka <dev@xxxxxxxx>
# Date 1232022187 0
# Branch zfs14
# Node ID 74b7416dc04c4bf734c4e8df7d64b2630da6ef0b
# Parent 10a8fae412c5e1b1cd24e58f94f780f180b84ab8
Port over the latest zfs code from opensolaris-grub to libfsimage
The existing libfsimage zfs code is rather old now, and can't read
versions of zfs now in general use. Port over the current code from
the opensolaris-patched grub, so that pygrub can be used again for
booting solaris/zfs based domains.
Signed-off-by: Jody Belka <dev@xxxxxxxx>
diff -r 10a8fae412c5 -r 74b7416dc04c tools/libfsimage/common/fsimage_grub.h
--- a/tools/libfsimage/common/fsimage_grub.h Wed Jan 14 13:43:17 2009 +0000
+++ b/tools/libfsimage/common/fsimage_grub.h Thu Jan 15 12:23:07 2009 +0000
@@ -78,6 +78,7 @@
#define ERR_DEV_VALUES 1
#define ERR_WONT_FIT 1
#define ERR_READ 1
+#define ERR_NEWER_VERSION 1
fsi_plugin_ops_t *fsig_init(fsi_plugin_t *, fsig_plugin_ops_t *);
diff -r 10a8fae412c5 -r 74b7416dc04c tools/libfsimage/zfs/fsys_zfs.c
--- a/tools/libfsimage/zfs/fsys_zfs.c Wed Jan 14 13:43:17 2009 +0000
+++ b/tools/libfsimage/zfs/fsys_zfs.c Thu Jan 15 12:23:07 2009 +0000
@@ -85,11 +85,15 @@
decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] =
{
- {"noop", 0},
+ {"inherit", 0}, /* ZIO_COMPRESS_INHERIT */
{"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */
- {"off", 0},
- {"lzjb", lzjb_decompress} /* ZIO_COMPRESS_LZJB */
+ {"off", 0}, /* ZIO_COMPRESS_OFF */
+ {"lzjb", lzjb_decompress}, /* ZIO_COMPRESS_LZJB */
+ {"empty", 0} /* ZIO_COMPRESS_EMPTY */
};
+
+static int zio_read_data(fsi_file_t *ffi, blkptr_t *bp, void *buf, char
*stack);
+
/* From disk_io.c */
/* ZFS root filesystem for booting */
@@ -170,8 +174,7 @@
zio_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);
+ uint32_t checksum = 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];
@@ -185,27 +188,13 @@
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;
- }
+ 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);
}
@@ -298,7 +287,7 @@
return (-1);
if (uber->ub_magic == UBERBLOCK_MAGIC &&
- uber->ub_version >= SPA_VERSION_1 &&
+ uber->ub_version > 0 &&
uber->ub_version <= SPA_VERSION)
return (0);
@@ -337,7 +326,93 @@
}
/*
- * Read in a block and put its uncompressed data in buf.
+ * Read a block of data based on the gang block address dva,
+ * and put its data in buf.
+ *
+ * Return:
+ * 0 - success
+ * 1 - failure
+ */
+static int
+zio_read_gang(fsi_file_t *ffi, blkptr_t *bp, dva_t *dva, void *buf, char
*stack)
+{
+ zio_gbh_phys_t *zio_gb;
+ uint64_t offset, sector;
+ blkptr_t tmpbp;
+ int i;
+
+ zio_gb = (zio_gbh_phys_t *)stack;
+ stack += SPA_GANGBLOCKSIZE;
+ offset = DVA_GET_OFFSET(dva);
+ sector = DVA_OFFSET_TO_PHYS_SECTOR(offset);
+
+ /* read in the gang block header */
+ if (devread(ffi, sector, 0, SPA_GANGBLOCKSIZE, (char *)zio_gb) == 0) {
+ return (1);
+ }
+
+ /* self checksuming the gang block header */
+ BP_ZERO(&tmpbp);
+ BP_SET_CHECKSUM(&tmpbp, ZIO_CHECKSUM_GANG_HEADER);
+ BP_SET_BYTEORDER(&tmpbp, ZFS_HOST_BYTEORDER);
+ ZIO_SET_CHECKSUM(&tmpbp.blk_cksum, DVA_GET_VDEV(dva),
+ DVA_GET_OFFSET(dva), bp->blk_birth, 0);
+ if (zio_checksum_verify(&tmpbp, (char *)zio_gb, SPA_GANGBLOCKSIZE)) {
+ return (1);
+ }
+
+ for (i = 0; i < SPA_GBH_NBLKPTRS; i++) {
+ if (zio_gb->zg_blkptr[i].blk_birth == 0)
+ continue;
+
+ if (zio_read_data(ffi, &zio_gb->zg_blkptr[i], buf, stack))
+ return (1);
+ buf += BP_GET_PSIZE(&zio_gb->zg_blkptr[i]);
+ }
+
+ return (0);
+}
+
+/*
+ * Read in a block of raw data to buf.
+ *
+ * Return:
+ * 0 - success
+ * 1 - failure
+ */
+static int
+zio_read_data(fsi_file_t *ffi, blkptr_t *bp, void *buf, char *stack)
+{
+ int i, psize;
+
+ psize = BP_GET_PSIZE(bp);
+
+ /* pick a good dva from the block pointer */
+ for (i = 0; i < SPA_DVAS_PER_BP; i++) {
+ uint64_t offset, sector;
+
+ if (bp->blk_dva[i].dva_word[0] == 0 &&
+ bp->blk_dva[i].dva_word[1] == 0)
+ continue;
+
+ if (DVA_GET_GANG(&bp->blk_dva[i])) {
+ if (zio_read_gang(ffi, bp, &bp->blk_dva[i], buf, stack)
== 0)
+ return (0);
+ } else {
+ /* read in a data block */
+ offset = DVA_GET_OFFSET(&bp->blk_dva[i]);
+ sector = DVA_OFFSET_TO_PHYS_SECTOR(offset);
+ if (devread(ffi, sector, 0, psize, buf))
+ return (0);
+ }
+ }
+
+ return (1);
+}
+
+/*
+ * Read in a block of data, verify its checksum, decompress if needed,
+ * and put the uncompressed data in buf.
*
* Return:
* 0 - success
@@ -346,49 +421,41 @@
static int
zio_read(fsi_file_t *ffi, blkptr_t *bp, void *buf, char *stack)
{
- uint64_t offset, sector;
- int psize, lsize;
- int i, comp, cksum;
+ int lsize, psize, comp;
+ char *retbuf;
+ comp = BP_GET_COMPRESS(bp);
+ lsize = BP_GET_LSIZE(bp);
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))
+ 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);
+ if ((char *)buf < stack && ((char *)buf) + lsize > stack) {
+ return (ERR_WONT_FIT);
+ }
+
+ retbuf = buf;
+ if (comp != ZIO_COMPRESS_OFF) {
+ buf = stack;
+ stack += psize;
+ }
+
+ if (zio_read_data(ffi, bp, buf, stack)) {
+ return (ERR_FSYS_CORRUPT);
+ }
+
+ if (zio_checksum_verify(bp, buf, psize) != 0) {
+ return (ERR_FSYS_CORRUPT);
+ }
+
+ if (comp != ZIO_COMPRESS_OFF)
+ decomp_table[comp].decomp_func(buf, retbuf, psize, lsize);
+
+ return (0);
}
/*
@@ -618,6 +685,8 @@
/* Get the leaf block */
l = (zap_leaf_phys_t *)stack;
stack += 1<<blksft;
+ if ((1<<blksft) < sizeof (zap_leaf_phys_t))
+ return (ERR_FSYS_CORRUPT);
if ((errnum = dmu_read(ffi, zap_dnode, blkid, l, stack)))
return (errnum);
@@ -865,6 +934,8 @@
char *cname, ch;
blkptr_t *bp;
objset_phys_t *osp;
+ int issnapshot = 0;
+ char *snapname = NULL;
if (fsname == NULL && obj) {
headobj = *obj;
@@ -905,6 +976,13 @@
ch = *fsname;
*fsname = 0;
+ snapname = cname;
+ while (*snapname && !isspace((uint8_t)*snapname) && *snapname
!= '@')
+ snapname++;
+ if (*snapname == '@') {
+ issnapshot = 1;
+ *snapname = 0;
+ }
childobj =
((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_child_dir_zapobj;
if ((errnum = dnode_get(ffi, mosmdn, childobj,
@@ -919,6 +997,8 @@
return (errnum);
*fsname = ch;
+ if (issnapshot)
+ *snapname = '@';
}
headobj = ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
if (obj)
@@ -928,8 +1008,23 @@
if ((errnum = dnode_get(ffi, mosmdn, headobj, DMU_OT_DSL_DATASET, mdn,
stack)))
return (errnum);
+ if (issnapshot) {
+ uint64_t snapobj;
- /* TODO: Add snapshot support here - for fsname=snapshot-name */
+ snapobj = ((dsl_dataset_phys_t *)DN_BONUS(mdn))->
+ ds_snapnames_zapobj;
+
+ if ((errnum = dnode_get(ffi, mosmdn, snapobj,
+ DMU_OT_DSL_DS_SNAP_MAP, mdn, stack)))
+ return (errnum);
+ if (zap_lookup(ffi, mdn, snapname + 1, &headobj, stack))
+ return (ERR_FILESYSTEM_NOT_FOUND);
+ if ((errnum = dnode_get(ffi, mosmdn, headobj,
+ DMU_OT_DSL_DATASET, mdn, stack)))
+ return (errnum);
+ if (obj)
+ *obj = headobj;
+ }
bp = &((dsl_dataset_phys_t *)DN_BONUS(mdn))->ds_bp;
osp = (objset_phys_t *)stack;
@@ -1073,8 +1168,6 @@
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);
@@ -1087,20 +1180,35 @@
* The caller should already allocate MAXNAMELEN memory for bootpath.
*/
static int
-vdev_get_bootpath(char *nv, char *bootpath)
+vdev_get_bootpath(char *nv, uint64_t inguid, 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)
+ uint64_t guid;
+
+ if (vdev_validate(nv) != 0)
return (ERR_NO_BOOTPATH);
+
+ if (nvlist_lookup_value(nv, ZPOOL_CONFIG_GUID,
+ &guid, DATA_TYPE_UINT64, NULL) != 0)
+ return (ERR_NO_BOOTPATH);
+
+ if (guid != inguid)
+ return (ERR_NO_BOOTPATH);
+
+ if (nvlist_lookup_value(nv, ZPOOL_CONFIG_PHYS_PATH,
+ bootpath, DATA_TYPE_STRING, NULL) != 0)
+ bootpath[0] = '\0';
+
+ if (strlen(bootpath) >= MAXNAMELEN)
+ return (ERR_WONT_FIT);
+
+ return (0);
} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
int nelm, i;
@@ -1111,28 +1219,15 @@
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);
+ if (vdev_get_bootpath(child_i, inguid, bootpath) == 0)
+ return (0);
}
}
- return (strlen(bootpath) > 0 ? 0 : ERR_NO_BOOTPATH);
+ return (ERR_NO_BOOTPATH);
}
/*
@@ -1148,6 +1243,8 @@
vdev_phys_t *vdev;
uint64_t sector, pool_state, txg = 0;
char *nvlist, *nv;
+ uint64_t diskguid;
+ uint64_t version;
zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;
sector = (label * sizeof (vdev_label_t) + VDEV_SKIP_SIZE +
@@ -1181,11 +1278,18 @@
if (txg == 0)
return (ERR_NO_BOOTPATH);
+ if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_VERSION, &version,
+ DATA_TYPE_UINT64, NULL))
+ return (ERR_FSYS_CORRUPT);
+ if (version > SPA_VERSION)
+ return (ERR_NEWER_VERSION);
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))
+ if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_GUID, &diskguid,
+ DATA_TYPE_UINT64, NULL))
+ return (ERR_FSYS_CORRUPT);
+ if (vdev_get_bootpath(nv, diskguid, current_bootpath))
return (ERR_NO_BOOTPATH);
return (0);
diff -r 10a8fae412c5 -r 74b7416dc04c tools/libfsimage/zfs/zfs-include/zfs.h
--- a/tools/libfsimage/zfs/zfs-include/zfs.h Wed Jan 14 13:43:17 2009 +0000
+++ b/tools/libfsimage/zfs/zfs-include/zfs.h Thu Jan 15 12:23:07 2009 +0000
@@ -28,17 +28,7 @@
/*
* On-disk version number.
*/
-#define SPA_VERSION_1 1ULL
-#define SPA_VERSION_2 2ULL
-#define SPA_VERSION_3 3ULL
-#define SPA_VERSION_4 4ULL
-#define SPA_VERSION_5 5ULL
-#define SPA_VERSION_6 6ULL
-#define SPA_VERSION_7 7ULL
-#define SPA_VERSION_8 8ULL
-#define SPA_VERSION_9 9ULL
-#define SPA_VERSION_10 10ULL
-#define SPA_VERSION SPA_VERSION_10
+#define SPA_VERSION 14ULL
/*
* The following are configuration names used in the nvlist describing a pool's
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|