summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmeer Hamza <[email protected]>2024-01-04 19:02:50 +0500
committerBrian Behlendorf <[email protected]>2024-01-29 14:53:29 -0800
commit52cee9a3eb0a691ce915a6f46d23f575351d8b4d (patch)
tree949d7dfd29938d4144829fc54230f73a10a507a2
parent2006ac1f4a52419d08641324ba56ecc5d0bbaf6f (diff)
fix: Uber block label not always found for aux vdevs
When spare or l2cache (aux) vdev is added during pool creation, spa->spa_uberblock is not dumped until that point. Subsequently, the aux label is never synchronized after its initial creation, resulting in the uberblock label remaining undumped. The uberblock is crucial for lib_blkid in identifying the ZFS partition type. To address this issue, we now ensure sync of the uberblock label once if it's not dumped initially. Reviewed-by: Umer Saleem <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Ameer Hamza <[email protected]> Closes #15737
-rw-r--r--include/sys/spa_impl.h1
-rw-r--r--module/zfs/vdev_label.c31
2 files changed, 32 insertions, 0 deletions
diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
index cdf65c371..c7ecd3d0c 100644
--- a/include/sys/spa_impl.h
+++ b/include/sys/spa_impl.h
@@ -266,6 +266,7 @@ struct spa {
spa_aux_vdev_t spa_spares; /* hot spares */
spa_aux_vdev_t spa_l2cache; /* L2ARC cache devices */
+ boolean_t spa_aux_sync_uber; /* need to sync aux uber */
nvlist_t *spa_label_features; /* Features for reading MOS */
uint64_t spa_config_object; /* MOS object for pool config */
uint64_t spa_config_generation; /* config generation number */
diff --git a/module/zfs/vdev_label.c b/module/zfs/vdev_label.c
index a2e5524a8..21348f95a 100644
--- a/module/zfs/vdev_label.c
+++ b/module/zfs/vdev_label.c
@@ -1148,6 +1148,14 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
*/
VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_ASHIFT,
vd->vdev_ashift) == 0);
+
+ /*
+ * When spare or l2cache (aux) vdev is added during pool
+ * creation, spa->spa_uberblock is not written until this
+ * point. Write it on next config sync.
+ */
+ if (uberblock_verify(&spa->spa_uberblock))
+ spa->spa_aux_sync_uber = B_TRUE;
} else {
uint64_t txg = 0ULL;
@@ -1749,6 +1757,16 @@ vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
for (int v = 0; v < svdcount; v++)
vdev_uberblock_sync(zio, &good_writes, ub, svd[v], flags);
+ if (spa->spa_aux_sync_uber) {
+ for (int v = 0; v < spa->spa_spares.sav_count; v++) {
+ vdev_uberblock_sync(zio, &good_writes, ub,
+ spa->spa_spares.sav_vdevs[v], flags);
+ }
+ for (int v = 0; v < spa->spa_l2cache.sav_count; v++) {
+ vdev_uberblock_sync(zio, &good_writes, ub,
+ spa->spa_l2cache.sav_vdevs[v], flags);
+ }
+ }
(void) zio_wait(zio);
/*
@@ -1763,6 +1781,19 @@ vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
zio_flush(zio, svd[v]);
}
}
+ if (spa->spa_aux_sync_uber) {
+ spa->spa_aux_sync_uber = B_FALSE;
+ for (int v = 0; v < spa->spa_spares.sav_count; v++) {
+ if (vdev_writeable(spa->spa_spares.sav_vdevs[v])) {
+ zio_flush(zio, spa->spa_spares.sav_vdevs[v]);
+ }
+ }
+ for (int v = 0; v < spa->spa_l2cache.sav_count; v++) {
+ if (vdev_writeable(spa->spa_l2cache.sav_vdevs[v])) {
+ zio_flush(zio, spa->spa_l2cache.sav_vdevs[v]);
+ }
+ }
+ }
(void) zio_wait(zio);