loader: rewrite zfs vdev initialization

In some cases the pool discovery will get stuck in infinite loop while setting
up the vdev children.

To fix, we split the vdev setup into two parts, first we create vdevs based on
configuration we do get from pool label, then, we process pool config from MOS
and update the pool config if needed.

Testing done: confirm previously hung loader is not hung any more.

MFC after:	1 week
This commit is contained in:
Toomas Soome 2019-12-15 21:52:40 +00:00
parent 686bcb5c14
commit 3c2db0ef43
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=355786
3 changed files with 451 additions and 268 deletions

File diff suppressed because it is too large Load Diff

View File

@ -760,6 +760,7 @@ typedef enum {
#define ZPOOL_CONFIG_IS_LOG "is_log"
#define ZPOOL_CONFIG_TIMESTAMP "timestamp" /* not stored on disk */
#define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read"
#define ZPOOL_CONFIG_VDEV_CHILDREN "vdev_children"
/*
* The persistent vdev state is stored as separate values rather than a single
@ -1173,6 +1174,8 @@ typedef enum dmu_objset_type {
DMU_OST_NUMTYPES
} dmu_objset_type_t;
#define ZAP_MAXVALUELEN (1024 * 8)
/*
* header for all bonus and spill buffers.
* The header has a fixed portion with a variable number
@ -1755,13 +1758,13 @@ typedef struct vdev {
int v_ashift; /* offset to block shift */
int v_nparity; /* # parity for raidz */
struct vdev *v_top; /* parent vdev */
int v_nchildren; /* # children */
size_t v_nchildren; /* # children */
vdev_state_t v_state; /* current state */
vdev_phys_read_t *v_phys_read; /* read from raw leaf vdev */
vdev_read_t *v_read; /* read from vdev */
void *v_read_priv; /* private data for read function */
boolean_t v_islog;
struct spa *spa; /* link to spa */
struct spa *v_spa; /* link to spa */
/*
* Values stored in the config for an indirect or removing vdev.
*/
@ -1780,11 +1783,10 @@ typedef struct spa {
uint64_t spa_guid; /* pool guid */
uint64_t spa_txg; /* most recent transaction */
struct uberblock spa_uberblock; /* best uberblock so far */
vdev_list_t spa_vdevs; /* list of all toplevel vdevs */
vdev_t *spa_root_vdev; /* toplevel vdev container */
objset_phys_t spa_mos; /* MOS for this pool */
zio_cksum_salt_t spa_cksum_salt; /* secret salt for cksum */
void *spa_cksum_tmpls[ZIO_CHECKSUM_FUNCTIONS];
int spa_inited; /* initialized */
boolean_t spa_with_log; /* this pool has log */
} spa_t;

View File

@ -1637,8 +1637,11 @@ vdev_raidz_read(vdev_t *vd, const blkptr_t *bp, void *data,
* any errors.
*/
if (total_errors <= rm->rm_firstdatacol - parity_untried) {
int rv;
if (data_errors == 0) {
if (raidz_checksum_verify(vd->spa, bp, data, bytes) == 0) {
rv = raidz_checksum_verify(vd->v_spa, bp, data, bytes);
if (rv == 0) {
/*
* If we read parity information (unnecessarily
* as it happens since no reconstruction was
@ -1683,7 +1686,8 @@ vdev_raidz_read(vdev_t *vd, const blkptr_t *bp, void *data,
code = vdev_raidz_reconstruct(rm, tgts, n);
if (raidz_checksum_verify(vd->spa, bp, data, bytes) == 0) {
rv = raidz_checksum_verify(vd->v_spa, bp, data, bytes);
if (rv == 0) {
/*
* If we read more parity disks than were used
* for reconstruction, confirm that the other
@ -1757,7 +1761,7 @@ vdev_raidz_read(vdev_t *vd, const blkptr_t *bp, void *data,
if (total_errors > rm->rm_firstdatacol) {
error = EIO;
} else if (total_errors < rm->rm_firstdatacol &&
(code = vdev_raidz_combrec(vd->spa, rm, bp, data, offset, bytes,
(code = vdev_raidz_combrec(vd->v_spa, rm, bp, data, offset, bytes,
total_errors, data_errors)) != 0) {
/*
* If we didn't use all the available parity for the