Changeset View
Changeset View
Standalone View
Standalone View
cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c
Show All 36 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 <devid.h> | #include <devid.h> | ||||
#include <dirent.h> | #include <dirent.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <libintl.h> | #include <libintl.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
▲ Show 20 Lines • Show All 861 Lines • ▼ Show 20 Lines | zpool_read_label(int fd, nvlist_t **config) | ||||
*config = NULL; | *config = NULL; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
/* | /* | ||||
* 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. | * describing the configuration, if there is one. | ||||
* returns the number of valid labels found | * returns the number of valid labels found | ||||
* If a label is found, returns it via config. The caller is responsible for | |||||
* freeing it. | |||||
*/ | */ | ||||
int | int | ||||
zpool_read_all_labels(int fd, nvlist_t **config) | zpool_read_all_labels(int fd, nvlist_t **config) | ||||
{ | { | ||||
struct stat64 statbuf; | struct stat64 statbuf; | ||||
struct aiocb aiocbs[VDEV_LABELS]; | |||||
struct aiocb *aiocbps[VDEV_LABELS]; | |||||
int l; | int l; | ||||
vdev_label_t *label; | vdev_label_t *labels; | ||||
uint64_t state, txg, size; | uint64_t state, txg, size; | ||||
int nlabels = 0; | int nlabels = 0; | ||||
*config = NULL; | *config = NULL; | ||||
if (fstat64(fd, &statbuf) == -1) | if (fstat64(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); | ||||
if ((label = malloc(sizeof (vdev_label_t))) == NULL) | if ((labels = calloc(VDEV_LABELS, sizeof (vdev_label_t))) == NULL) | ||||
return (0); | return (0); | ||||
memset(aiocbs, 0, sizeof(aiocbs)); | |||||
for (l = 0; l < VDEV_LABELS; l++) { | for (l = 0; l < VDEV_LABELS; l++) { | ||||
aiocbs[l].aio_fildes = fd; | |||||
aiocbs[l].aio_offset = label_offset(size, l); | |||||
aiocbs[l].aio_buf = &labels[l]; | |||||
aiocbs[l].aio_nbytes = sizeof(vdev_label_t); | |||||
aiocbs[l].aio_lio_opcode = LIO_READ; | |||||
aiocbps[l] = &aiocbs[l]; | |||||
} | |||||
if (lio_listio(LIO_WAIT, aiocbps, VDEV_LABELS, NULL) != 0) { | |||||
if (errno == EAGAIN || errno == EINTR || errno == EIO) { | |||||
for (l = 0; l < VDEV_LABELS; l++) { | |||||
errno = 0; | |||||
int r = aio_error(&aiocbs[l]); | |||||
if (r != EINVAL) | |||||
(void)aio_return(&aiocbs[l]); | |||||
} | |||||
} | |||||
return (0); | |||||
} | |||||
for (l = 0; l < VDEV_LABELS; l++) { | |||||
nvlist_t *temp = NULL; | nvlist_t *temp = NULL; | ||||
/* TODO: use aio_read so we can read al 4 labels in parallel */ | if (aio_return(&aiocbs[l]) != sizeof(vdev_label_t)) | ||||
if (pread64(fd, label, sizeof (vdev_label_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].vl_vdev_phys.vp_nvlist, | ||||
sizeof (label->vl_vdev_phys.vp_nvlist), &temp, 0) != 0) | sizeof (labels[l].vl_vdev_phys.vp_nvlist), &temp, 0) != 0) | ||||
continue; | continue; | ||||
if (nvlist_lookup_uint64(temp, ZPOOL_CONFIG_POOL_STATE, | if (nvlist_lookup_uint64(temp, ZPOOL_CONFIG_POOL_STATE, | ||||
&state) != 0 || state > POOL_STATE_L2CACHE) { | &state) != 0 || state > POOL_STATE_L2CACHE) { | ||||
nvlist_free(temp); | nvlist_free(temp); | ||||
temp = NULL; | temp = NULL; | ||||
continue; | continue; | ||||
} | } | ||||
if (state != POOL_STATE_SPARE && state != POOL_STATE_L2CACHE && | if (state != POOL_STATE_SPARE && state != POOL_STATE_L2CACHE && | ||||
(nvlist_lookup_uint64(temp, ZPOOL_CONFIG_POOL_TXG, | (nvlist_lookup_uint64(temp, ZPOOL_CONFIG_POOL_TXG, | ||||
&txg) != 0 || txg == 0)) { | &txg) != 0 || txg == 0)) { | ||||
nvlist_free(temp); | nvlist_free(temp); | ||||
temp = NULL; | temp = NULL; | ||||
continue; | continue; | ||||
} | } | ||||
if (temp) | if (temp) | ||||
*config = temp; | *config = temp; | ||||
nlabels++; | nlabels++; | ||||
} | } | ||||
free(label); | free(labels); | ||||
return (nlabels); | return (nlabels); | ||||
} | } | ||||
typedef struct rdsk_node { | typedef struct rdsk_node { | ||||
char *rn_name; | char *rn_name; | ||||
int rn_dfd; | int rn_dfd; | ||||
libzfs_handle_t *rn_hdl; | libzfs_handle_t *rn_hdl; | ||||
nvlist_t *rn_config; | nvlist_t *rn_config; | ||||
▲ Show 20 Lines • Show All 828 Lines • Show Last 20 Lines |