diff options
Diffstat (limited to 'tools/libfsimage/zfs/fsys_zfs.c')
-rw-r--r-- | tools/libfsimage/zfs/fsys_zfs.c | 758 |
1 files changed, 425 insertions, 333 deletions
diff --git a/tools/libfsimage/zfs/fsys_zfs.c b/tools/libfsimage/zfs/fsys_zfs.c index f398632c98..6b4b183087 100644 --- a/tools/libfsimage/zfs/fsys_zfs.c +++ b/tools/libfsimage/zfs/fsys_zfs.c @@ -17,17 +17,11 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 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 @@ -48,59 +42,37 @@ * +--------------------------------------------+ */ -#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 */ +#ifdef FSYS_ZFS +#include "shared.h" +#include "filesys.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 +static void *file_buf = NULL; +static uint64_t file_start = 0; +static uint64_t file_end = 0; /* 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 +static dnode_phys_t *dnode_buf = NULL; +static dnode_phys_t *dnode_mdn = NULL; +static uint64_t dnode_start = 0; +static uint64_t dnode_end = 0; -#define stackbase zfs_ba->zfs_stackbase +static uint64_t pool_guid = 0; +static uberblock_t current_uberblock; +static char *stackbase; 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 */ }; -/* 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 +static int zio_read_data(blkptr_t *bp, void *buf, char *stack); /* * Our own version of bcmp(). @@ -108,8 +80,8 @@ decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = static int zfs_bcmp(const void *s1, const void *s2, size_t n) { - const unsigned char *ps1 = s1; - const unsigned char *ps2 = s2; + const uchar_t *ps1 = s1; + const uchar_t *ps2 = s2; if (s1 != s2 && n != 0) { do { @@ -146,15 +118,16 @@ zio_checksum_off(const void *buf, uint64_t size, zio_cksum_t *zcp) /* 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"} + { { 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" }, + { { NULL, NULL }, 0, 0, "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" }, + { { NULL, NULL }, 0, 0, "zilog2" } }; /* @@ -170,10 +143,9 @@ static int 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_eck_t *zec = (zio_eck_t *)(data + size) - 1; zio_checksum_info_t *ci = &zio_checksum_table[checksum]; zio_cksum_t actual_cksum, expected_cksum; @@ -184,28 +156,14 @@ zio_checksum_verify(blkptr_t *bp, char *data, int size) 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; - } + if (ci->ci_eck) { + expected_cksum = zec->zec_cksum; + zec->zec_cksum = zc; + ci->ci_func[0](data, size, &actual_cksum); + zec->zec_cksum = expected_cksum; zc = expected_cksum; } else { - if (BP_IS_GANG(bp)) - return (-1); ci->ci_func[byteswap](data, size, &actual_cksum); } @@ -219,30 +177,14 @@ zio_checksum_verify(blkptr_t *bp, char *data, int size) } /* - * 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 + * vdev_label_start returns the physical disk offset (in bytes) of + * label "l". */ static uint64_t -vdev_label_offset(fsi_file_t *ffi, uint64_t psize, int l, uint64_t offset) +vdev_label_start(uint64_t psize, int l) { - /* 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 ? + return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? 0 : psize - VDEV_LABELS * sizeof (vdev_label_t))); - } /* @@ -283,7 +225,7 @@ vdev_uberblock_compare(uberblock_t *ub1, uberblock_t *ub2) * -1 - Failure */ static int -uberblock_verify(uberblock_phys_t *ub, int offset) +uberblock_verify(uberblock_phys_t *ub, uint64_t offset) { uberblock_t *uber = &ub->ubp_uberblock; @@ -297,7 +239,8 @@ uberblock_verify(uberblock_phys_t *ub, int offset) if (zio_checksum_verify(&bp, (char *)ub, UBERBLOCK_SIZE) != 0) return (-1); - if (uber->ub_magic == UBERBLOCK_MAGIC && uber->ub_version > 0) + if (uber->ub_magic == UBERBLOCK_MAGIC && + uber->ub_version > 0 && uber->ub_version <= SPA_VERSION) return (0); return (-1); @@ -310,16 +253,15 @@ uberblock_verify(uberblock_phys_t *ub, int offset) * Failure - NULL */ static uberblock_phys_t * -find_bestub(fsi_file_t *ffi, uberblock_phys_t *ub_array, int label) +find_bestub(uberblock_phys_t *ub_array, uint64_t sector) { uberblock_phys_t *ubbest = NULL; - int i, offset; + uint64_t offset; + int i; 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); + offset = (sector << SPA_MINBLOCKSHIFT) + + VDEV_UBERBLOCK_OFFSET(i); if (uberblock_verify(&ub_array[i], offset) == 0) { if (ubbest == NULL) { ubbest = &ub_array[i]; @@ -335,58 +277,142 @@ find_bestub(fsi_file_t *ffi, uberblock_phys_t *ub_array, int label) } /* - * 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 - * errnum - failure + * 1 - failure */ static int -zio_read(fsi_file_t *ffi, blkptr_t *bp, void *buf, char *stack) +zio_read_gang(blkptr_t *bp, dva_t *dva, void *buf, char *stack) { + zio_gbh_phys_t *zio_gb; uint64_t offset, sector; - int psize, lsize; - int i, comp, cksum; + blkptr_t tmpbp; + int i; - psize = BP_GET_PSIZE(bp); - lsize = BP_GET_LSIZE(bp); - comp = BP_GET_COMPRESS(bp); - cksum = BP_GET_CHECKSUM(bp); + zio_gb = (zio_gbh_phys_t *)stack; + stack += SPA_GANGBLOCKSIZE; + offset = DVA_GET_OFFSET(dva); + sector = DVA_OFFSET_TO_PHYS_SECTOR(offset); - if ((unsigned int)comp >= ZIO_COMPRESS_FUNCTIONS || - (comp != ZIO_COMPRESS_OFF && - decomp_table[comp].decomp_func == NULL)) - return (ERR_FSYS_CORRUPT); + /* read in the gang block header */ + if (devread(sector, 0, SPA_GANGBLOCKSIZE, (char *)zio_gb) == 0) { + grub_printf("failed to read in a gang block header\n"); + 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)) { + grub_printf("failed to checksum a gang block header\n"); + return (1); + } + + for (i = 0; i < SPA_GBH_NBLKPTRS; i++) { + if (zio_gb->zg_blkptr[i].blk_birth == 0) + continue; + + if (zio_read_data(&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(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; - /* 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); + if (DVA_GET_GANG(&bp->blk_dva[i])) { + if (zio_read_gang(bp, &bp->blk_dva[i], buf, stack) == 0) + return (0); } else { - if (devread(ffi, sector, 0, psize, buf) == 0) - continue; - if (zio_checksum_verify(bp, buf, psize) != 0) - continue; + /* read in a data block */ + offset = DVA_GET_OFFSET(&bp->blk_dva[i]); + sector = DVA_OFFSET_TO_PHYS_SECTOR(offset); + if (devread(sector, 0, psize, buf)) + return (0); } - return (0); } - return (ERR_FSYS_CORRUPT); + return (1); +} + +/* + * Read in a block of data, verify its checksum, decompress if needed, + * and put the uncompressed data in buf. + * + * Return: + * 0 - success + * errnum - failure + */ +static int +zio_read(blkptr_t *bp, void *buf, char *stack) +{ + int lsize, psize, comp; + char *retbuf; + + comp = BP_GET_COMPRESS(bp); + lsize = BP_GET_LSIZE(bp); + psize = BP_GET_PSIZE(bp); + + if ((unsigned int)comp >= ZIO_COMPRESS_FUNCTIONS || + (comp != ZIO_COMPRESS_OFF && + decomp_table[comp].decomp_func == NULL)) { + grub_printf("compression algorithm not supported\n"); + return (ERR_FSYS_CORRUPT); + } + + if ((char *)buf < stack && ((char *)buf) + lsize > stack) { + grub_printf("not enough memory allocated\n"); + return (ERR_WONT_FIT); + } + + retbuf = buf; + if (comp != ZIO_COMPRESS_OFF) { + buf = stack; + stack += psize; + } + + if (zio_read_data(bp, buf, stack)) { + grub_printf("zio_read_data failed\n"); + return (ERR_FSYS_CORRUPT); + } + + if (zio_checksum_verify(bp, buf, psize) != 0) { + grub_printf("checksum verification failed\n"); + return (ERR_FSYS_CORRUPT); + } + + if (comp != ZIO_COMPRESS_OFF) + decomp_table[comp].decomp_func(buf, retbuf, psize, lsize); + + return (0); } /* @@ -398,8 +424,7 @@ zio_read(fsi_file_t *ffi, blkptr_t *bp, void *buf, char *stack) * errnum - failure */ static int -dmu_read(fsi_file_t *ffi, dnode_phys_t *dn, uint64_t blkid, void *buf, - char *stack) +dmu_read(dnode_phys_t *dn, uint64_t blkid, void *buf, char *stack) { int idx, level; blkptr_t *bp_array = dn->dn_blkptr; @@ -421,9 +446,10 @@ dmu_read(fsi_file_t *ffi, dnode_phys_t *dn, uint64_t blkid, void *buf, grub_memset(buf, 0, dn->dn_datablkszsec << SPA_MINBLOCKSHIFT); break; - } else if ((errnum = zio_read(ffi, bp, tmpbuf, stack))) { + } else if ((errnum = zio_read(bp, tmpbuf, stack))) { return (errnum); } + bp_array = tmpbuf; } @@ -447,7 +473,7 @@ mzap_lookup(mzap_phys_t *zapobj, int objsize, char *name, chunks = objsize/MZAP_ENT_LEN - 1; for (i = 0; i < chunks; i++) { - if (strcmp(mzap_ent[i].mze_name, name) == 0) { + if (grub_strcmp(mzap_ent[i].mze_name, name) == 0) { *value = mzap_ent[i].mze_value; return (0); } @@ -457,7 +483,7 @@ mzap_lookup(mzap_phys_t *zapobj, int objsize, char *name, } static uint64_t -zap_hash(fsi_file_t *ffi, uint64_t salt, const char *name) +zap_hash(uint64_t salt, const char *name) { static uint64_t table[256]; const uint8_t *cp; @@ -488,7 +514,7 @@ zap_hash(fsi_file_t *ffi, uint64_t salt, const char *name) * those are the onces that we first pay attention to when * chosing the bucket. */ - crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1); + crc &= ~((1ULL << (64 - 28)) - 1); return (crc); } @@ -590,7 +616,7 @@ zap_leaf_lookup(zap_leaf_phys_t *l, int blksft, uint64_t h, * errnum - failure */ static int -fzap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, zap_phys_t *zap, +fzap_lookup(dnode_phys_t *zap_dnode, zap_phys_t *zap, char *name, uint64_t *value, char *stack) { zap_leaf_phys_t *l; @@ -598,10 +624,11 @@ fzap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, zap_phys_t *zap, 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) + if (zap->zap_magic != (uint64_t)ZAP_MAGIC || + zap->zap_flags != 0) return (ERR_FSYS_CORRUPT); - hash = zap_hash(ffi, zap->zap_salt, name); + hash = zap_hash(zap->zap_salt, name); if (errnum) return (errnum); @@ -616,7 +643,9 @@ fzap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, zap_phys_t *zap, /* Get the leaf block */ l = (zap_leaf_phys_t *)stack; stack += 1<<blksft; - if ((errnum = dmu_read(ffi, zap_dnode, blkid, l, stack))) + if ((1<<blksft) < sizeof (zap_leaf_phys_t)) + return (ERR_FSYS_CORRUPT); + if ((errnum = dmu_read(zap_dnode, blkid, l, stack))) return (errnum); return (zap_leaf_lookup(l, blksft, hash, name, value)); @@ -631,8 +660,7 @@ fzap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, zap_phys_t *zap, * errnum - failure */ static int -zap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, char *name, - uint64_t *val, char *stack) +zap_lookup(dnode_phys_t *zap_dnode, char *name, uint64_t *val, char *stack) { uint64_t block_type; int size; @@ -642,7 +670,8 @@ zap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, char *name, zapbuf = stack; size = zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT; stack += size; - if ((errnum = dmu_read(ffi, zap_dnode, 0, zapbuf, stack))) + + if ((errnum = dmu_read(zap_dnode, 0, zapbuf, stack))) return (errnum); block_type = *((uint64_t *)zapbuf); @@ -651,7 +680,7 @@ zap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, char *name, 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, + return (fzap_lookup(zap_dnode, zapbuf, name, val, stack)); } @@ -672,14 +701,13 @@ zap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, char *name, * errnum - failure */ static int -dnode_get(fsi_file_t *ffi, dnode_phys_t *mdn, uint64_t objnum, - uint8_t type, dnode_phys_t *buf, char *stack) +dnode_get(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; @@ -703,7 +731,7 @@ dnode_get(fsi_file_t *ffi, dnode_phys_t *mdn, uint64_t objnum, stack += blksz; } - if ((errnum = dmu_read(ffi, mdn, blkid, (char *)dnbuf, stack))) + if ((errnum = dmu_read(mdn, blkid, (char *)dnbuf, stack))) return (errnum); grub_memmove(buf, &dnbuf[idx], DNODE_SIZE); @@ -723,16 +751,16 @@ is_top_dataset_file(char *str) { char *tptr; - if (((tptr = strstr(str, "menu.lst"))) && + if ((tptr = grub_strstr(str, "menu.lst")) && (tptr[8] == '\0' || tptr[8] == ' ') && *(tptr-1) == '/') return (1); - if (strncmp(str, BOOTSIGN_DIR"/", - strlen(BOOTSIGN_DIR) + 1) == 0) + if (grub_strncmp(str, BOOTSIGN_DIR"/", + grub_strlen(BOOTSIGN_DIR) + 1) == 0) return (1); - if (strcmp(str, BOOTSIGN_BACKUP) == 0) + if (grub_strcmp(str, BOOTSIGN_BACKUP) == 0) return (1); return (0); @@ -748,23 +776,25 @@ is_top_dataset_file(char *str) * errnum - failure */ static int -dnode_get_path(fsi_file_t *ffi, dnode_phys_t *mdn, char *path, - dnode_phys_t *dn, char *stack) +dnode_get_path(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, + if ((errnum = dnode_get(mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, dn, stack))) return (errnum); - if ((errnum = zap_lookup(ffi, dn, ZPL_VERSION_STR, &version, stack))) + if ((errnum = zap_lookup(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))) + if ((errnum = zap_lookup(dn, ZFS_ROOT_OBJ, &objnum, stack))) return (errnum); - if ((errnum = dnode_get(ffi, mdn, objnum, DMU_OT_DIRECTORY_CONTENTS, + if ((errnum = dnode_get(mdn, objnum, DMU_OT_DIRECTORY_CONTENTS, dn, stack))) return (errnum); @@ -772,20 +802,20 @@ dnode_get_path(fsi_file_t *ffi, dnode_phys_t *mdn, char *path, while (*path == '/') path++; - while (*path && !isspace((uint8_t)*path)) { + while (*path && !isspace(*path)) { /* get the next component name */ cname = path; - while (*path && !isspace((uint8_t)*path) && *path != '/') + while (*path && !isspace(*path) && *path != '/') path++; ch = *path; *path = 0; /* ensure null termination */ - if ((errnum = zap_lookup(ffi, dn, cname, &objnum, stack))) + if ((errnum = zap_lookup(dn, cname, &objnum, stack))) return (errnum); objnum = ZFS_DIRENT_OBJ(objnum); - if ((errnum = dnode_get(ffi, mdn, objnum, 0, dn, stack))) + if ((errnum = dnode_get(mdn, objnum, 0, dn, stack))) return (errnum); *path = ch; @@ -807,14 +837,13 @@ dnode_get_path(fsi_file_t *ffi, dnode_phys_t *mdn, char *path, * errnum -failure */ static int -get_default_bootfsobj(fsi_file_t *ffi, dnode_phys_t *mosmdn, - uint64_t *obj, char *stack) +get_default_bootfsobj(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, + if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT, DMU_OT_OBJECT_DIRECTORY, dn, stack))) return (errnum); @@ -822,20 +851,18 @@ get_default_bootfsobj(fsi_file_t *ffi, dnode_phys_t *mosmdn, * 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)) + if (zap_lookup(dn, DMU_POOL_PROPS, &objnum, stack)) return (ERR_FILESYSTEM_NOT_FOUND); - if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_POOL_PROPS, dn, - stack))) + if ((errnum = dnode_get(mosmdn, objnum, DMU_OT_POOL_PROPS, dn, stack))) return (errnum); - if (zap_lookup(ffi, dn, ZPOOL_PROP_BOOTFS, &objnum, stack)) + if (zap_lookup(dn, ZPOOL_PROP_BOOTFS, &objnum, stack)) return (ERR_FILESYSTEM_NOT_FOUND); if (!objnum) return (ERR_FILESYSTEM_NOT_FOUND); - *obj = objnum; return (0); } @@ -854,29 +881,30 @@ get_default_bootfsobj(fsi_file_t *ffi, dnode_phys_t *mosmdn, * errnum - failure */ static int -get_objset_mdn(fsi_file_t *ffi, dnode_phys_t *mosmdn, char *fsname, - uint64_t *obj, dnode_phys_t *mdn, char *stack) +get_objset_mdn(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; + int issnapshot = 0; + char *snapname = NULL; if (fsname == NULL && obj) { headobj = *obj; goto skip; } - if ((errnum = dnode_get(ffi, mosmdn, DMU_POOL_DIRECTORY_OBJECT, + if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT, DMU_OT_OBJECT_DIRECTORY, mdn, stack))) return (errnum); - if ((errnum = zap_lookup(ffi, mdn, DMU_POOL_ROOT_DATASET, &objnum, + if ((errnum = zap_lookup(mdn, DMU_POOL_ROOT_DATASET, &objnum, stack))) return (errnum); - if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_DSL_DIR, mdn, - stack))) + if ((errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR, mdn, stack))) return (errnum); if (fsname == NULL) { @@ -886,51 +914,74 @@ get_objset_mdn(fsi_file_t *ffi, dnode_phys_t *mosmdn, char *fsname, } /* take out the pool name */ - while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/') + while (*fsname && !isspace(*fsname) && *fsname != '/') fsname++; - while (*fsname && !isspace((uint8_t)*fsname)) { + while (*fsname && !isspace(*fsname)) { uint64_t childobj; while (*fsname == '/') fsname++; cname = fsname; - while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/') + while (*fsname && !isspace(*fsname) && *fsname != '/') fsname++; ch = *fsname; *fsname = 0; + snapname = cname; + while (*snapname && !isspace(*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, + if ((errnum = dnode_get(mosmdn, childobj, DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack))) return (errnum); - if (zap_lookup(ffi, mdn, cname, &objnum, stack)) + if (zap_lookup(mdn, cname, &objnum, stack)) return (ERR_FILESYSTEM_NOT_FOUND); - if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_DSL_DIR, + if ((errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR, mdn, stack))) return (errnum); *fsname = ch; + if (issnapshot) + *snapname = '@'; } 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))) + if ((errnum = dnode_get(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(mosmdn, snapobj, + DMU_OT_DSL_DS_SNAP_MAP, mdn, stack))) + return (errnum); + if (zap_lookup(mdn, snapname + 1, &headobj, stack)) + return (ERR_FILESYSTEM_NOT_FOUND); + if ((errnum = dnode_get(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; stack += sizeof (objset_phys_t); - if ((errnum = zio_read(ffi, bp, osp, stack))) + if ((errnum = zio_read(bp, osp, stack))) return (errnum); grub_memmove((char *)mdn, (char *)&osp->os_meta_dnode, DNODE_SIZE); @@ -1019,11 +1070,11 @@ nvlist_lookup_value(char *nvlist, char *name, void *val, int valtype, type = BSWAP_32(*(uint32_t *)nvpair); nvpair += 4; - if (((strncmp(nvp_name, name, name_len) == 0) && - type == valtype)) { + if ((grub_strncmp(nvp_name, name, name_len) == 0) && + type == valtype) { int nelm; - if (((nelm = BSWAP_32(*(uint32_t *)nvpair)) < 1)) + if ((nelm = BSWAP_32(*(uint32_t *)nvpair)) < 1) return (1); nvpair += 4; @@ -1069,8 +1120,6 @@ vdev_validate(char *nv) 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); @@ -1079,26 +1128,58 @@ vdev_validate(char *nv) } /* - * Get a list of valid vdev pathname from the boot device. - * The caller should already allocate MAXNAMELEN memory for bootpath. + * Get a valid vdev pathname/devid from the boot device. + * The caller should already allocate MAXPATHLEN memory for bootpath and devid. */ static int -vdev_get_bootpath(char *nv, char *bootpath) +vdev_get_bootpath(char *nv, uint64_t inguid, char *devid, char *bootpath, + int is_spare) { 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); - } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) { + if (guid != inguid) + return (ERR_NO_BOOTPATH); + + /* for a spare vdev, pick the disk labeled with "is_spare" */ + if (is_spare) { + uint64_t spare = 0; + (void) nvlist_lookup_value(nv, ZPOOL_CONFIG_IS_SPARE, + &spare, DATA_TYPE_UINT64, NULL); + if (!spare) + return (ERR_NO_BOOTPATH); + } + + if (nvlist_lookup_value(nv, ZPOOL_CONFIG_PHYS_PATH, + bootpath, DATA_TYPE_STRING, NULL) != 0) + bootpath[0] = '\0'; + + if (nvlist_lookup_value(nv, ZPOOL_CONFIG_DEVID, + devid, DATA_TYPE_STRING, NULL) != 0) + devid[0] = '\0'; + + if (strlen(bootpath) >= MAXPATHLEN || + strlen(devid) >= MAXPATHLEN) + return (ERR_WONT_FIT); + + return (0); + + } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 || + strcmp(type, VDEV_TYPE_REPLACING) == 0 || + (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) { int nelm, i; char *child; @@ -1107,28 +1188,16 @@ vdev_get_bootpath(char *nv, char *bootpath) 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, devid, + bootpath, is_spare) == 0) + return (0); } } - return (strlen(bootpath) > 0 ? 0 : ERR_NO_BOOTPATH); + return (ERR_NO_BOOTPATH); } /* @@ -1138,22 +1207,24 @@ vdev_get_bootpath(char *nv, char *bootpath) * 0 - success * ERR_* - failure */ -static int -check_pool_label(fsi_file_t *ffi, int label, char *stack) +int +check_pool_label(uint64_t sector, char *stack, char *outdevid, + char *outpath, uint64_t *outguid) { vdev_phys_t *vdev; - uint64_t sector, pool_state, txg = 0; + uint64_t pool_state, txg = 0; char *nvlist, *nv; - zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data; + uint64_t diskguid; + uint64_t version; - sector = (label * sizeof (vdev_label_t) + VDEV_SKIP_SIZE + - VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT; + sector += (VDEV_SKIP_SIZE >> SPA_MINBLOCKSHIFT); /* Read in the vdev name-value pair list (112K). */ - if (devread(ffi, sector, 0, VDEV_PHYS_SIZE, stack) == 0) + if (devread(sector, 0, VDEV_PHYS_SIZE, stack) == 0) return (ERR_READ); vdev = (vdev_phys_t *)stack; + stack += sizeof (vdev_phys_t); if (nvlist_unpack(vdev->vp_nvlist, &nvlist)) return (ERR_FSYS_CORRUPT); @@ -1177,13 +1248,22 @@ check_pool_label(fsi_file_t *ffi, int label, char *stack) 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, outdevid, outpath, 0)) return (ERR_NO_BOOTPATH); - + if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_POOL_GUID, outguid, + DATA_TYPE_UINT64, NULL)) + return (ERR_FSYS_CORRUPT); return (0); } @@ -1195,34 +1275,23 @@ check_pool_label(fsi_file_t *ffi, int label, char *stack) * 1 - success * 0 - failure */ -static int -zfs_mount(fsi_file_t *ffi, const char *options) +int +zfs_mount(void) { char *stack; int label = 0; - uberblock_phys_t *ub_array, *ubbest = NULL; + uberblock_phys_t *ub_array, *ubbest; 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); - } + char tmp_bootpath[MAXNAMELEN]; + char tmp_devid[MAXNAMELEN]; + uint64_t tmp_guid; + uint64_t adjpl = (uint64_t)part_length << SPA_MINBLOCKSHIFT; + int err = errnum; /* preserve previous errnum state */ + + /* if it's our first time here, zero the best uberblock out */ + if (best_drive == 0 && best_part == 0 && find_best_root) { + grub_memset(¤t_uberblock, 0, sizeof (uberblock_t)); + pool_guid = 0; } stackbase = ZFS_SCRATCH; @@ -1232,43 +1301,71 @@ zfs_mount(fsi_file_t *ffi, const char *options) osp = (objset_phys_t *)stack; stack += sizeof (objset_phys_t); + adjpl = P2ALIGN(adjpl, (uint64_t)sizeof (vdev_label_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; + for (label = 0; label < VDEV_LABELS; label++) { + uint64_t sector; + + /* + * some eltorito stacks don't give us a size and + * we end up setting the size to MAXUINT, further + * some of these devices stop working once a single + * read past the end has been issued. Checking + * for a maximum part_length and skipping the backup + * labels at the end of the slice/partition/device + * avoids breaking down on such devices. + */ + if (part_length == MAXUINT && label == 2) + break; + + sector = vdev_label_start(adjpl, + label) >> SPA_MINBLOCKSHIFT; /* Read in the uberblock ring (128K). */ - if (devread(ffi, sector, 0, VDEV_UBERBLOCK_RING, + if (devread(sector + + ((VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >> + SPA_MINBLOCKSHIFT), 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) + if ((ubbest = find_bestub(ub_array, sector)) != NULL && + zio_read(&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); + if (check_pool_label(sector, stack, tmp_devid, + tmp_bootpath, &tmp_guid)) + continue; + if (pool_guid == 0) + pool_guid = tmp_guid; - /* - * 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); + if (find_best_root && ((pool_guid != tmp_guid) || + vdev_uberblock_compare(&ubbest->ubp_uberblock, + &(current_uberblock)) <= 0)) + continue; + /* Got the MOS. Save it at the memory addr MOS. */ + grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE); + grub_memmove(¤t_uberblock, + &ubbest->ubp_uberblock, sizeof (uberblock_t)); + grub_memmove(current_bootpath, tmp_bootpath, + MAXNAMELEN); + grub_memmove(current_devid, tmp_devid, + grub_strlen(tmp_devid)); is_zfs_mount = 1; return (1); } } + /* + * While some fs impls. (tftp) rely on setting and keeping + * global errnums set, others won't reset it and will break + * when issuing rawreads. The goal here is to simply not + * have zfs mount attempts impact the previous state. + */ + errnum = err; return (0); } @@ -1280,13 +1377,11 @@ zfs_mount(fsi_file_t *ffi, const char *options) * 1 - success * 0 - failure */ -static int -zfs_open(fsi_file_t *ffi, char *filename) +int +zfs_open(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; @@ -1304,62 +1399,72 @@ zfs_open(fsi_file_t *ffi, char *filename) * do not goto 'current_bootfs'. */ if (is_top_dataset_file(filename)) { - if ((errnum = get_objset_mdn(ffi, MOS, NULL, NULL, mdn, stack))) + if ((errnum = get_objset_mdn(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, + if ((errnum = get_default_bootfsobj(MOS, ¤t_bootfs_obj, stack))) return (0); - if ((errnum = get_objset_mdn(ffi, MOS, NULL, + + if ((errnum = get_objset_mdn(MOS, NULL, ¤t_bootfs_obj, mdn, stack))) return (0); } else { - if ((errnum = get_objset_mdn(ffi, MOS, - current_bootfs, ¤t_bootfs_obj, mdn, stack))) + if ((errnum = get_objset_mdn(MOS, current_bootfs, + ¤t_bootfs_obj, mdn, stack))) { + grub_memset(current_bootfs, 0, MAXNAMELEN); 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)) { + if (dnode_get_path(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; + + /* + * For DMU_OT_SA we will need to locate the SIZE attribute + * attribute, which could be either in the bonus buffer + * or the "spill" block. + */ + if (DNODE->dn_bonustype == DMU_OT_SA) { + sa_hdr_phys_t *sahdrp; + int hdrsize; + + if (DNODE->dn_bonuslen != 0) { + sahdrp = (sa_hdr_phys_t *)DN_BONUS(DNODE); + } else { + if (DNODE->dn_flags & DNODE_FLAG_SPILL_BLKPTR) { + blkptr_t *bp = &DNODE->dn_spill; + void *buf; + + buf = (void *)stack; + stack += BP_GET_LSIZE(bp); + + /* reset errnum to rawread() failure */ + errnum = 0; + if (zio_read(bp, buf, stack) != 0) { + return (0); + } + sahdrp = buf; + } else { + errnum = ERR_FSYS_CORRUPT; + return (0); + } + } + hdrsize = SA_HDR_SIZE(sahdrp); + filemax = *(uint64_t *)((char *)sahdrp + hdrsize + + SA_SIZE_OFFSET); + } else { + filemax = ((znode_phys_t *)DN_BONUS(DNODE))->zp_size; + } filepos = 0; dnode_buf = NULL; @@ -1373,12 +1478,11 @@ zfs_open(fsi_file_t *ffi, char *filename) * len - the length successfully read in to the buffer * 0 - failure */ -static int -zfs_read(fsi_file_t *ffi, char *buf, int len) +int +zfs_read(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; @@ -1411,7 +1515,7 @@ zfs_read(fsi_file_t *ffi, char *buf, int len) */ uint64_t blkid = filepos / blksz; - if ((errnum = dmu_read(ffi, DNODE, blkid, file_buf, stack))) + if ((errnum = dmu_read(DNODE, blkid, file_buf, stack))) return (0); file_start = blkid * blksz; @@ -1438,16 +1542,4 @@ zfs_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)); -} +#endif /* FSYS_ZFS */ |