Allow pool import with corrupted spare/l2arc configs

That information should not be critical for read-only imports, and
imports with zfs_recover.  Let the import proceed by just dropping
those devices and trying to recover it with small space leak.

While there, allow zdb to report errors when dumping those objects.

Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Alexander Motin <[email protected]>
Closes #18937
This commit is contained in:
Alexander Motin authored and GitHub committed 2026-08-19 17:58:58 -07:00
1 parent ec779f356c
commit a5d6788648
2 files changed
+49 -18

No files matched your search

+13 -2
View File
@@ -928,13 +928,24 @@ dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
nvlist_t *nv;
size_t nvsize = *(uint64_t *)data;
char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
int err;
VERIFY0(dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
err = dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH);
if (err != 0) {
(void) printf("got error %u from dmu_read\n", err);
umem_free(packed, nvsize);
return;
}
VERIFY0(nvlist_unpack(packed, nvsize, &nv, 0));
err = nvlist_unpack(packed, nvsize, &nv, 0);
umem_free(packed, nvsize);
if (err != 0) {
(void) printf("got error %u from nvlist_unpack\n", err);
return;
}
dump_nvlist(nv, 8);
nvlist_free(nv);
+36 -16
View File
@@ -5548,15 +5548,25 @@ spa_ld_open_aux_vdevs(spa_t *spa, spa_import_type_t type)
return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
if (error == 0 && type != SPA_IMPORT_ASSEMBLE) {
ASSERT(spa_version(spa) >= SPA_VERSION_SPARES);
if (load_nvlist(spa, spa->spa_spares.sav_object,
&spa->spa_spares.sav_config) != 0) {
spa_load_failed(spa, "error loading spares nvlist");
return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
error = load_nvlist(spa, spa->spa_spares.sav_object,
&spa->spa_spares.sav_config);
if (error != 0) {
if (!zfs_recover && spa_writeable(spa)) {
spa_load_failed(spa, "error loading spares "
"nvlist [error=%d]", error);
return (spa_vdev_err(rvd,
VDEV_AUX_CORRUPT_DATA, EIO));
}
spa_load_note(spa, "ignoring spares nvlist "
"[error=%d], no spares will be available", error);
/* Leak the object, its dnode may be unreadable. */
spa->spa_spares.sav_object = 0;
spa->spa_spares.sav_sync = B_TRUE;
} else {
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa_load_spares(spa);
spa_config_exit(spa, SCL_ALL, FTAG);
}
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa_load_spares(spa);
spa_config_exit(spa, SCL_ALL, FTAG);
} else if (error == 0) {
spa->spa_spares.sav_sync = B_TRUE;
}
@@ -5570,15 +5580,25 @@ spa_ld_open_aux_vdevs(spa_t *spa, spa_import_type_t type)
return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
if (error == 0 && type != SPA_IMPORT_ASSEMBLE) {
ASSERT(spa_version(spa) >= SPA_VERSION_L2CACHE);
if (load_nvlist(spa, spa->spa_l2cache.sav_object,
&spa->spa_l2cache.sav_config) != 0) {
spa_load_failed(spa, "error loading l2cache nvlist");
return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
error = load_nvlist(spa, spa->spa_l2cache.sav_object,
&spa->spa_l2cache.sav_config);
if (error != 0) {
if (!zfs_recover && spa_writeable(spa)) {
spa_load_failed(spa, "error loading l2cache "
"nvlist [error=%d]", error);
return (spa_vdev_err(rvd,
VDEV_AUX_CORRUPT_DATA, EIO));
}
spa_load_note(spa, "ignoring l2cache nvlist "
"[error=%d], no l2cache will be available", error);
/* Leak the object, its dnode may be unreadable. */
spa->spa_l2cache.sav_object = 0;
spa->spa_l2cache.sav_sync = B_TRUE;
} else {
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa_load_l2cache(spa);
spa_config_exit(spa, SCL_ALL, FTAG);
}
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa_load_l2cache(spa);
spa_config_exit(spa, SCL_ALL, FTAG);
} else if (error == 0) {
spa->spa_l2cache.sav_sync = B_TRUE;
}