diff --git a/SOURCES/0109-zfs-make-less-syscalls.patch b/SOURCES/0109-zfs-make-less-syscalls.patch new file mode 100644 index 00000000..ac770532 --- /dev/null +++ b/SOURCES/0109-zfs-make-less-syscalls.patch @@ -0,0 +1,153 @@ +From 8646f60d1b421b48b43405fa286548a0bf3f5da4 Mon Sep 17 00:00:00 2001 +From: Michal Humpula +Date: Sat, 28 Feb 2015 21:19:42 +0100 +Subject: [PATCH 109/116] zfs: make less syscalls + +Upstream: https://github.com/karelzak/util-linux/commit/e44a4c7ac9522c03b76d8b62ce88b443771fdb0b +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1392661 +Signed-off-by: Karel Zak +--- + libblkid/src/superblocks/zfs.c | 95 ++++++++++++++++++++++++++---------------- + 1 file changed, 58 insertions(+), 37 deletions(-) + +diff --git a/libblkid/src/superblocks/zfs.c b/libblkid/src/superblocks/zfs.c +index 4a64a03..9b5601e 100644 +--- a/libblkid/src/superblocks/zfs.c ++++ b/libblkid/src/superblocks/zfs.c +@@ -20,6 +20,7 @@ + #define VDEV_LABEL_NVPAIR ( 16 * 1024ULL) + #define VDEV_LABEL_SIZE (256 * 1024ULL) + #define UBERBLOCK_SIZE 1024ULL ++#define UBERBLOCKS_COUNT 128 + + /* #include */ + #define UBERBLOCK_MAGIC 0x00bab10c /* oo-ba-bloc! */ +@@ -32,7 +33,6 @@ struct zfs_uberblock { + char ub_rootbp; /* MOS objset_phys_t */ + } __attribute__((packed)); + +-#define ZFS_TRIES 512 + #define ZFS_WANT 4 + + #define DATA_TYPE_UINT64 8 +@@ -163,61 +163,82 @@ static void zfs_extract_guid_name(blkid_probe pr, loff_t offset) + #define zdebug(fmt, ...) do {} while(0) + /*#define zdebug(fmt, a...) fprintf(stderr, fmt, ##a)*/ + +-/* ZFS has 128x1kB host-endian root blocks, stored in 2 areas (labels) +- * at the start of the disk, and 2 areas at the end of the disk. +- */ ++static int find_uberblocks(const void *label, loff_t *ub_offset, int *swap_endian) ++{ ++ uint64_t swab_magic = swab64(UBERBLOCK_MAGIC); ++ struct zfs_uberblock *ub; ++ int i, found = 0; ++ loff_t offset = VDEV_LABEL_UBERBLOCK; ++ ++ for (i = 0; i < UBERBLOCKS_COUNT; i++, offset += UBERBLOCK_SIZE) { ++ ub = (struct zfs_uberblock *)(label + offset); ++ ++ if (ub->ub_magic == UBERBLOCK_MAGIC) { ++ *ub_offset = offset; ++ *swap_endian = 0; ++ found++; ++ zdebug("probe_zfs: found little-endian uberblock at %llu\n", offset >> 10); ++ } ++ ++ if (ub->ub_magic == swab_magic) { ++ *ub_offset = offset; ++ *swap_endian = 1; ++ found++; ++ zdebug("probe_zfs: found big-endian uberblock at %llu\n", offset >> 10); ++ } ++ } ++ ++ return found; ++} ++ ++/* 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) + { + uint64_t swab_magic = swab64(UBERBLOCK_MAGIC); ++ int swab_endian = 0; + struct zfs_uberblock *ub; +- int swab_endian; + loff_t offset, ub_offset = 0; +- int tried; +- int found; ++ int label_no, found = 0, found_in_label; ++ void *label; + loff_t blk_align = (pr->size % (256 * 1024ULL)); + + zdebug("probe_zfs\n"); +- /* Look for at least 4 uberblocks to ensure a positive match. +- Begin with Label 0 (L0) at the start of the block device. */ +- for (tried = found = 0, offset = VDEV_LABEL_UBERBLOCK; +- found < ZFS_WANT && tried < ZFS_TRIES; +- tried++, offset += UBERBLOCK_SIZE) +- { +- /* Leave L0 to try other labels */ +- switch(tried) { +- case 128: // jump to L1, just after L0 +- offset = VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK; ++ /* Look for at least 4 uberblocks to ensure a positive match */ ++ for (label_no = 0; label_no < 4; label_no++) { ++ switch(label_no) { ++ case 0: // jump to L0 ++ offset = 0; + break; +- case 256: // jump to L2 near the far end of the block device +- offset = pr->size - 2 * VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK - blk_align; +- zdebug("probe_zfs: l2 offset %llu\n", offset >> 10); ++ case 1: // jump to L1 ++ offset = VDEV_LABEL_SIZE; + break; +- case 384: // jump to L3 at the furthest end of the block device +- offset = pr->size - VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK - blk_align; +- zdebug("probe_zfs: l3 offset %llu\n", offset >> 10); ++ case 2: // jump to L2 ++ offset = pr->size - 2 * VDEV_LABEL_SIZE - blk_align; ++ break; ++ case 3: // jump to L3 ++ offset = pr->size - VDEV_LABEL_SIZE - blk_align; + break; + } + +- ub = (struct zfs_uberblock *) +- blkid_probe_get_buffer(pr, offset, +- sizeof(struct zfs_uberblock)); +- if (ub == NULL) ++ label = blkid_probe_get_buffer(pr, offset, VDEV_LABEL_SIZE); ++ if (label == NULL) + return errno ? -errno : 1; + +- if (ub->ub_magic == UBERBLOCK_MAGIC) { +- ub_offset = offset; +- found++; +- zdebug("probe_zfs: found little-endian uberblock at %llu\n", offset >> 10); +- } ++ found_in_label = find_uberblocks(label, &ub_offset, &swab_endian); + +- if ((swab_endian = (ub->ub_magic == swab_magic))) { +- ub_offset = offset; +- found++; +- zdebug("probe_zfs: found big-endian uberblock at %llu\n", offset >> 10); ++ if (found_in_label > 0) { ++ found+= found_in_label; ++ ub = (struct zfs_uberblock *)(label + ub_offset); ++ ub_offset += offset; ++ ++ if (found >= ZFS_WANT) ++ break; + } + } + +- if (found < 4) ++ if (found < ZFS_WANT) + return 1; + + /* If we found the 4th uberblock, then we will have exited from the +-- +2.9.3