Skip to content

Commit 3d36e28

Browse files
committed
Fix "Detach spare vdev in case if resilvering does not happen"
Spare vdev should detach from the pool when a disk is reinserted. However, spare detachment depends on the completion of resilvering, and if resilver does not schedule, the spare vdev keeps attached to the pool until the next resilvering. When a zfs pool contains several disks (25+ mirror), resilvering does not always happen when a disk is reinserted. In this patch, spare vdev is manually detached from the pool when resilvering does not occur and it has been tested on both Linux and FreeBSD. Signed-off-by: Ameer Hamza <[email protected]>
1 parent 1038f87 commit 3d36e28

File tree

3 files changed

+15
-3
lines changed

3 files changed

+15
-3
lines changed

include/sys/spa.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ extern int bpobj_enqueue_free_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx);
787787
#define SPA_ASYNC_L2CACHE_REBUILD 0x800
788788
#define SPA_ASYNC_L2CACHE_TRIM 0x1000
789789
#define SPA_ASYNC_REBUILD_DONE 0x2000
790+
#define SPA_ASYNC_DETACH_SPARE 0x4000
790791

791792
/* device manipulation */
792793
extern int spa_vdev_add(spa_t *spa, nvlist_t *nvroot);

module/zfs/spa.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7058,7 +7058,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
70587058
* Detach a device from a mirror or replacing vdev.
70597059
*
70607060
* If 'replace_done' is specified, only detach if the parent
7061-
* is a replacing vdev.
7061+
* is a replacing or a spare vdev.
70627062
*/
70637063
int
70647064
spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
@@ -8281,7 +8281,8 @@ spa_async_thread(void *arg)
82818281
* If any devices are done replacing, detach them.
82828282
*/
82838283
if (tasks & SPA_ASYNC_RESILVER_DONE ||
8284-
tasks & SPA_ASYNC_REBUILD_DONE) {
8284+
tasks & SPA_ASYNC_REBUILD_DONE ||
8285+
tasks & SPA_ASYNC_DETACH_SPARE) {
82858286
spa_vdev_resilver_done(spa);
82868287
}
82878288

module/zfs/vdev.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4183,9 +4183,19 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate)
41834183

41844184
if (wasoffline ||
41854185
(oldstate < VDEV_STATE_DEGRADED &&
4186-
vd->vdev_state >= VDEV_STATE_DEGRADED))
4186+
vd->vdev_state >= VDEV_STATE_DEGRADED)) {
41874187
spa_event_notify(spa, vd, NULL, ESC_ZFS_VDEV_ONLINE);
41884188

4189+
/*
4190+
* Asynchronously detach spare vdev if resilver or
4191+
* rebuild is not required
4192+
*/
4193+
if (vd->vdev_unspare &&
4194+
!dsl_scan_resilvering(spa->spa_dsl_pool) &&
4195+
!dsl_scan_resilver_scheduled(spa->spa_dsl_pool) &&
4196+
!vdev_rebuild_active(tvd))
4197+
spa_async_request(spa, SPA_ASYNC_DETACH_SPARE);
4198+
}
41894199
return (spa_vdev_state_exit(spa, vd, 0));
41904200
}
41914201

0 commit comments

Comments
 (0)