diff options
author | Alan Somers <[email protected]> | 2021-01-13 10:00:12 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2021-01-21 11:24:35 -0800 |
commit | e50b5217e7a85f1466edf88d5f3ea5aed0c2fd22 (patch) | |
tree | 5578d5f1e38f37a700900ea1f1c63181e736089e /lib/libzutil/zutil_import.c | |
parent | ec40ce84058628ca943d5fe5328d8a1df8198616 (diff) |
libzutil: optimize zpool_read_label with AIO
Read all labels in parallel instead of sequentially.
Originally committed as
https://cgit.freebsd.org/src/commit/?id=b49e9abcf44cafaf5cfad7029c9a6adbb28346e8
Obtained from: FreeBSD
Sponsored by: Spectra Logic, Axcient
Reviewed-by: Jorgen Lundman <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Alek Pinchuk <[email protected]>
Signed-off-by: Alan Somers <[email protected]>
Closes #11467
Diffstat (limited to 'lib/libzutil/zutil_import.c')
-rw-r--r-- | lib/libzutil/zutil_import.c | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/lib/libzutil/zutil_import.c b/lib/libzutil/zutil_import.c index bf914d37c..823f093f4 100644 --- a/lib/libzutil/zutil_import.c +++ b/lib/libzutil/zutil_import.c @@ -46,6 +46,7 @@ * using our derived config, and record the results. */ +#include <aio.h> #include <ctype.h> #include <dirent.h> #include <errno.h> @@ -887,11 +888,12 @@ int zpool_read_label(int fd, nvlist_t **config, int *num_labels) { struct stat64 statbuf; - int l, count = 0; - vdev_phys_t *label; + struct aiocb aiocbs[VDEV_LABELS]; + struct aiocb *aiocbps[VDEV_LABELS]; + vdev_phys_t *labels; nvlist_t *expected_config = NULL; uint64_t expected_guid = 0, size; - int error; + int error, l, count = 0; *config = NULL; @@ -899,20 +901,51 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels) return (0); size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); - error = posix_memalign((void **)&label, PAGESIZE, sizeof (*label)); + error = posix_memalign((void **)&labels, PAGESIZE, + VDEV_LABELS * sizeof (*labels)); if (error) return (-1); + memset(aiocbs, 0, sizeof (aiocbs)); for (l = 0; l < VDEV_LABELS; l++) { - uint64_t state, guid, txg; off_t offset = label_offset(size, l) + VDEV_SKIP_SIZE; - if (pread64(fd, label, sizeof (vdev_phys_t), - offset) != sizeof (vdev_phys_t)) + aiocbs[l].aio_fildes = fd; + aiocbs[l].aio_offset = offset; + aiocbs[l].aio_buf = &labels[l]; + aiocbs[l].aio_nbytes = sizeof (vdev_phys_t); + aiocbs[l].aio_lio_opcode = LIO_READ; + aiocbps[l] = &aiocbs[l]; + } + + if (lio_listio(LIO_WAIT, aiocbps, VDEV_LABELS, NULL) != 0) { + int saved_errno = errno; + + if (errno == EAGAIN || errno == EINTR || errno == EIO) { + /* + * A portion of the requests may have been submitted. + * Clean them up. + */ + for (l = 0; l < VDEV_LABELS; l++) { + errno = 0; + int r = aio_error(&aiocbs[l]); + if (r != EINVAL) + (void) aio_return(&aiocbs[l]); + } + } + free(labels); + errno = saved_errno; + return (-1); + } + + for (l = 0; l < VDEV_LABELS; l++) { + uint64_t state, guid, txg; + + if (aio_return(&aiocbs[l]) != sizeof (vdev_phys_t)) continue; - if (nvlist_unpack(label->vp_nvlist, - sizeof (label->vp_nvlist), config, 0) != 0) + if (nvlist_unpack(labels[l].vp_nvlist, + sizeof (labels[l].vp_nvlist), config, 0) != 0) continue; if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_GUID, @@ -949,7 +982,7 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels) if (num_labels != NULL) *num_labels = count; - free(label); + free(labels); *config = expected_config; return (0); |