diff options
Diffstat (limited to 'libblkid/zfs.c')
-rw-r--r-- | libblkid/zfs.c | 226 |
1 files changed, 0 insertions, 226 deletions
diff --git a/libblkid/zfs.c b/libblkid/zfs.c deleted file mode 100644 index b96c5df45..000000000 --- a/libblkid/zfs.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2009-2010 by Andreas Dilger <adilger@sun.com> - * - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> -#include <inttypes.h> - -#include "superblocks.h" - -#define VDEV_LABEL_UBERBLOCK (128 * 1024ULL) -#define VDEV_LABEL_NVPAIR ( 16 * 1024ULL) -#define VDEV_LABEL_SIZE (256 * 1024ULL) - -/* #include <sys/uberblock_impl.h> */ -#define UBERBLOCK_MAGIC 0x00bab10c /* oo-ba-bloc! */ -struct zfs_uberblock { - uint64_t ub_magic; /* UBERBLOCK_MAGIC */ - uint64_t ub_version; /* SPA_VERSION */ - uint64_t ub_txg; /* txg of last sync */ - uint64_t ub_guid_sum; /* sum of all vdev guids */ - uint64_t ub_timestamp; /* UTC time of last sync */ - char ub_rootbp; /* MOS objset_phys_t */ -} __attribute__((packed)); - -#define ZFS_TRIES 64 -#define ZFS_WANT 4 - -#define DATA_TYPE_UINT64 8 -#define DATA_TYPE_STRING 9 - -struct nvpair { - uint32_t nvp_size; - uint32_t nvp_unkown; - uint32_t nvp_namelen; - char nvp_name[0]; /* aligned to 4 bytes */ - /* aligned ptr array for string arrays */ - /* aligned array of data for value */ -}; - -struct nvstring { - uint32_t nvs_type; - uint32_t nvs_elem; - uint32_t nvs_strlen; - unsigned char nvs_string[0]; -}; - -struct nvuint64 { - uint32_t nvu_type; - uint32_t nvu_elem; - uint64_t nvu_value; -}; - -struct nvlist { - uint32_t nvl_unknown[3]; - struct nvpair nvl_nvpair; -}; - -#define nvdebug(fmt, ...) do { } while(0) -/*#define nvdebug(fmt, a...) printf(fmt, ##a)*/ - -static void zfs_extract_guid_name(blkid_probe pr, loff_t offset) -{ - struct nvlist *nvl; - struct nvpair *nvp; - size_t left = 4096; - int found = 0; - - offset = (offset & ~(VDEV_LABEL_SIZE - 1)) + VDEV_LABEL_NVPAIR; - - /* Note that we currently assume that the desired fields are within - * the first 4k (left) of the nvlist. This is true for all pools - * I've seen, and simplifies this code somewhat, because we don't - * have to handle an nvpair crossing a buffer boundary. */ - nvl = (struct nvlist *)blkid_probe_get_buffer(pr, offset, left); - if (nvl == NULL) - return; - - nvdebug("zfs_extract: nvlist offset %llu\n", offset); - - nvp = &nvl->nvl_nvpair; - while (left > sizeof(*nvp) && nvp->nvp_size != 0 && found < 3) { - int avail; /* tracks that name/value data fits in nvp_size */ - int namesize; - - nvp->nvp_size = be32_to_cpu(nvp->nvp_size); - nvp->nvp_namelen = be32_to_cpu(nvp->nvp_namelen); - avail = nvp->nvp_size - nvp->nvp_namelen - sizeof(*nvp); - - nvdebug("left %zd nvp_size %u\n", left, nvp->nvp_size); - if (left < nvp->nvp_size || avail < 0) - break; - - namesize = (nvp->nvp_namelen + 3) & ~3; - - nvdebug("nvlist: size %u, namelen %u, name %*s\n", - nvp->nvp_size, nvp->nvp_namelen, nvp->nvp_namelen, - nvp->nvp_name); - if (strncmp(nvp->nvp_name, "name", nvp->nvp_namelen) == 0) { - struct nvstring *nvs = (void *)(nvp->nvp_name+namesize); - - nvs->nvs_type = be32_to_cpu(nvs->nvs_type); - nvs->nvs_strlen = be32_to_cpu(nvs->nvs_strlen); - avail -= nvs->nvs_strlen + sizeof(*nvs); - nvdebug("nvstring: type %u string %*s\n", nvs->nvs_type, - nvs->nvs_strlen, nvs->nvs_string); - if (nvs->nvs_type == DATA_TYPE_STRING && avail >= 0) - blkid_probe_set_label(pr, nvs->nvs_string, - nvs->nvs_strlen); - found++; - } else if (strncmp(nvp->nvp_name, "guid", - nvp->nvp_namelen) == 0) { - struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize); - uint64_t nvu_value; - - memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value)); - nvu->nvu_type = be32_to_cpu(nvu->nvu_type); - nvu_value = be64_to_cpu(nvu_value); - avail -= sizeof(*nvu); - nvdebug("nvuint64: type %u value %"PRIu64"\n", - nvu->nvu_type, nvu_value); - if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0) - blkid_probe_sprintf_value(pr, "UUID_SUB", - "%"PRIu64, nvu_value); - found++; - } else if (strncmp(nvp->nvp_name, "pool_guid", - nvp->nvp_namelen) == 0) { - struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize); - uint64_t nvu_value; - - memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value)); - nvu->nvu_type = be32_to_cpu(nvu->nvu_type); - nvu_value = be64_to_cpu(nvu_value); - avail -= sizeof(*nvu); - nvdebug("nvuint64: type %u value %"PRIu64"\n", - nvu->nvu_type, nvu_value); - if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0) - blkid_probe_sprintf_uuid(pr, (unsigned char *) - &nvu_value, - sizeof(nvu_value), - "%"PRIu64, nvu_value); - found++; - } - if (left > nvp->nvp_size) - left -= nvp->nvp_size; - else - left = 0; - nvp = (struct nvpair *)((char *)nvp + nvp->nvp_size); - } -} - -#define zdebug(fmt, ...) do {} while(0) -/*#define zdebug(fmt, a...) printf(fmt, ##a)*/ - -/* ZFS has 128x1kB host-endian root blocks, stored in 2 areas at the start - * of the disk, and 2 areas at the end of the disk. Check only some of them... - * #4 (@ 132kB) is the first one written on a new filesystem. */ -static int probe_zfs(blkid_probe pr, - const struct blkid_idmag *mag __attribute__((__unused__))) -{ - uint64_t swab_magic = swab64(UBERBLOCK_MAGIC); - struct zfs_uberblock *ub; - int swab_endian; - loff_t offset; - int tried; - int found; - - zdebug("probe_zfs\n"); - /* Look for at least 4 uberblocks to ensure a positive match */ - for (tried = found = 0, offset = VDEV_LABEL_UBERBLOCK; - tried < ZFS_TRIES && found < ZFS_WANT; - tried++, offset += 4096) { - /* also try the second uberblock copy */ - if (tried == (ZFS_TRIES / 2)) - offset = VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK; - - ub = (struct zfs_uberblock *) - blkid_probe_get_buffer(pr, offset, - sizeof(struct zfs_uberblock)); - if (ub == NULL) - return -1; - - if (ub->ub_magic == UBERBLOCK_MAGIC) - found++; - - if ((swab_endian = (ub->ub_magic == swab_magic))) - found++; - - zdebug("probe_zfs: found %s-endian uberblock at %llu\n", - swab_endian ? "big" : "little", offset >> 10); - } - - if (found < 4) - return -1; - - /* If we found the 4th uberblock, then we will have exited from the - * scanning loop immediately, and ub will be a valid uberblock. */ - blkid_probe_sprintf_version(pr, "%" PRIu64, swab_endian ? - swab64(ub->ub_version) : ub->ub_version); - - zfs_extract_guid_name(pr, offset); - - if (blkid_probe_set_magic(pr, offset, - sizeof(ub->ub_magic), - (unsigned char *) &ub->ub_magic)) - return -1; - - return 0; -} - -const struct blkid_idinfo zfs_idinfo = -{ - .name = "zfs_member", - .usage = BLKID_USAGE_RAID, - .probefunc = probe_zfs, - .minsz = 64 * 1024 * 1024, - .magics = BLKID_NONE_MAGIC -}; - |