Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/lib/libzutil/zutil_import.c
Show All 40 Lines | |||||
* | * | ||||
* Duplicate entries matching this same tuple will be discarded. Once we have | * Duplicate entries matching this same tuple will be discarded. Once we have | ||||
* examined every device, we pick the best label txg config for each toplevel | * examined every device, we pick the best label txg config for each toplevel | ||||
* vdev. We then arrange these toplevel vdevs into a complete pool config, and | * vdev. We then arrange these toplevel vdevs into a complete pool config, and | ||||
* update any paths that have changed. Finally, we attempt to import the pool | * update any paths that have changed. Finally, we attempt to import the pool | ||||
* using our derived config, and record the results. | * using our derived config, and record the results. | ||||
*/ | */ | ||||
#include <aio.h> | |||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <dirent.h> | #include <dirent.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <libintl.h> | #include <libintl.h> | ||||
#include <libgen.h> | #include <libgen.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
▲ Show 20 Lines • Show All 825 Lines • ▼ Show 20 Lines | |||||
* Given a file descriptor, read the label information and return an nvlist | * Given a file descriptor, read the label information and return an nvlist | ||||
* describing the configuration, if there is one. The number of valid | * describing the configuration, if there is one. The number of valid | ||||
* labels found will be returned in num_labels when non-NULL. | * labels found will be returned in num_labels when non-NULL. | ||||
*/ | */ | ||||
int | int | ||||
zpool_read_label(int fd, nvlist_t **config, int *num_labels) | zpool_read_label(int fd, nvlist_t **config, int *num_labels) | ||||
{ | { | ||||
struct stat64 statbuf; | struct stat64 statbuf; | ||||
int l, count = 0; | struct aiocb aiocbs[VDEV_LABELS]; | ||||
vdev_label_t *label; | struct aiocb *aiocbps[VDEV_LABELS]; | ||||
vdev_phys_t *labels; | |||||
nvlist_t *expected_config = NULL; | nvlist_t *expected_config = NULL; | ||||
uint64_t expected_guid = 0, size; | uint64_t expected_guid = 0, size; | ||||
int error; | int error, l, count = 0; | ||||
*config = NULL; | *config = NULL; | ||||
if (fstat64_blk(fd, &statbuf) == -1) | if (fstat64_blk(fd, &statbuf) == -1) | ||||
return (0); | return (0); | ||||
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); | 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) | if (error) | ||||
return (-1); | return (-1); | ||||
memset(aiocbs, 0, sizeof (aiocbs)); | |||||
for (l = 0; l < VDEV_LABELS; l++) { | for (l = 0; l < VDEV_LABELS; l++) { | ||||
off_t offset = label_offset(size, l) + VDEV_SKIP_SIZE; | |||||
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; | uint64_t state, guid, txg; | ||||
if (pread64(fd, label, sizeof (vdev_label_t), | if (aio_return(&aiocbs[l]) != sizeof (vdev_phys_t)) | ||||
label_offset(size, l)) != sizeof (vdev_label_t)) | |||||
continue; | continue; | ||||
if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, | if (nvlist_unpack(labels[l].vp_nvlist, | ||||
sizeof (label->vl_vdev_phys.vp_nvlist), config, 0) != 0) | sizeof (labels[l].vp_nvlist), config, 0) != 0) | ||||
continue; | continue; | ||||
if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_GUID, | if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_GUID, | ||||
&guid) != 0 || guid == 0) { | &guid) != 0 || guid == 0) { | ||||
nvlist_free(*config); | nvlist_free(*config); | ||||
continue; | continue; | ||||
} | } | ||||
Show All 20 Lines | if (expected_guid) { | ||||
expected_guid = guid; | expected_guid = guid; | ||||
count++; | count++; | ||||
} | } | ||||
} | } | ||||
if (num_labels != NULL) | if (num_labels != NULL) | ||||
*num_labels = count; | *num_labels = count; | ||||
free(label); | free(labels); | ||||
*config = expected_config; | *config = expected_config; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Sorted by full path and then vdev guid to allow for multiple entries with | * Sorted by full path and then vdev guid to allow for multiple entries with | ||||
* the same full path name. This is required because it's possible to | * the same full path name. This is required because it's possible to | ||||
▲ Show 20 Lines • Show All 629 Lines • Show Last 20 Lines |