diff options
author | Brian Behlendorf <[email protected]> | 2020-03-04 15:07:11 -0800 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-04 15:07:11 -0800 |
commit | 2288d4196821ae4b5fa375e8e519f6e83f26abad (patch) | |
tree | 49c49baf2112da27d14ea2f90e09a333d1ab99da /module | |
parent | b3212d2fa6ab8d7d8373373e8a6b8acbbf45508e (diff) |
Add trim support to zpool wait
Manual trims fall into the category of long-running pool activities
which people might want to wait synchronously for. This change adds
support to 'zpool wait' for waiting for manual trim operations to
complete. It also adds a '-w' flag to 'zpool trim' which can be used to
turn 'zpool trim' into a synchronous operation.
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Serapheim Dimitropoulos <[email protected]>
Signed-off-by: John Gallagher <[email protected]>
Closes #10071
Diffstat (limited to 'module')
-rw-r--r-- | module/zfs/spa.c | 47 | ||||
-rw-r--r-- | module/zfs/vdev_trim.c | 3 |
2 files changed, 32 insertions, 18 deletions
diff --git a/module/zfs/spa.c b/module/zfs/spa.c index a6f97eb37..72a54ebce 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -9280,28 +9280,35 @@ spa_wake_waiters(spa_t *spa) mutex_exit(&spa->spa_activities_lock); } -/* Whether the vdev or any of its descendants is initializing. */ +/* Whether the vdev or any of its descendants are being initialized/trimmed. */ static boolean_t -spa_vdev_initializing_impl(vdev_t *vd) +spa_vdev_activity_in_progress_impl(vdev_t *vd, zpool_wait_activity_t activity) { spa_t *spa = vd->vdev_spa; - boolean_t initializing; ASSERT(spa_config_held(spa, SCL_CONFIG | SCL_STATE, RW_READER)); ASSERT(MUTEX_HELD(&spa->spa_activities_lock)); + ASSERT(activity == ZPOOL_WAIT_INITIALIZE || + activity == ZPOOL_WAIT_TRIM); + + kmutex_t *lock = activity == ZPOOL_WAIT_INITIALIZE ? + &vd->vdev_initialize_lock : &vd->vdev_trim_lock; mutex_exit(&spa->spa_activities_lock); - mutex_enter(&vd->vdev_initialize_lock); + mutex_enter(lock); mutex_enter(&spa->spa_activities_lock); - initializing = (vd->vdev_initialize_state == VDEV_INITIALIZE_ACTIVE); - mutex_exit(&vd->vdev_initialize_lock); + boolean_t in_progress = (activity == ZPOOL_WAIT_INITIALIZE) ? + (vd->vdev_initialize_state == VDEV_INITIALIZE_ACTIVE) : + (vd->vdev_trim_state == VDEV_TRIM_ACTIVE); + mutex_exit(lock); - if (initializing) + if (in_progress) return (B_TRUE); for (int i = 0; i < vd->vdev_children; i++) { - if (spa_vdev_initializing_impl(vd->vdev_child[i])) + if (spa_vdev_activity_in_progress_impl(vd->vdev_child[i], + activity)) return (B_TRUE); } @@ -9310,12 +9317,13 @@ spa_vdev_initializing_impl(vdev_t *vd) /* * If use_guid is true, this checks whether the vdev specified by guid is - * being initialized. Otherwise, it checks whether any vdev in the pool is being - * initialized. The caller must hold the config lock and spa_activities_lock. + * being initialized/trimmed. Otherwise, it checks whether any vdev in the pool + * is being initialized/trimmed. The caller must hold the config lock and + * spa_activities_lock. */ static int -spa_vdev_initializing(spa_t *spa, boolean_t use_guid, uint64_t guid, - boolean_t *in_progress) +spa_vdev_activity_in_progress(spa_t *spa, boolean_t use_guid, uint64_t guid, + zpool_wait_activity_t activity, boolean_t *in_progress) { mutex_exit(&spa->spa_activities_lock); spa_config_enter(spa, SCL_CONFIG | SCL_STATE, FTAG, RW_READER); @@ -9332,7 +9340,7 @@ spa_vdev_initializing(spa_t *spa, boolean_t use_guid, uint64_t guid, vd = spa->spa_root_vdev; } - *in_progress = spa_vdev_initializing_impl(vd); + *in_progress = spa_vdev_activity_in_progress_impl(vd, activity); spa_config_exit(spa, SCL_CONFIG | SCL_STATE, FTAG); return (0); @@ -9403,7 +9411,9 @@ spa_activity_in_progress(spa_t *spa, zpool_wait_activity_t activity, spa_livelist_delete_check(spa)); break; case ZPOOL_WAIT_INITIALIZE: - error = spa_vdev_initializing(spa, use_tag, tag, in_progress); + case ZPOOL_WAIT_TRIM: + error = spa_vdev_activity_in_progress(spa, use_tag, tag, + activity, in_progress); break; case ZPOOL_WAIT_REPLACE: mutex_exit(&spa->spa_activities_lock); @@ -9443,15 +9453,16 @@ spa_wait_common(const char *pool, zpool_wait_activity_t activity, { /* * The tag is used to distinguish between instances of an activity. - * 'initialize' is the only activity that we use this for. The other - * activities can only have a single instance in progress in a pool at - * one time, making the tag unnecessary. + * 'initialize' and 'trim' are the only activities that we use this for. + * The other activities can only have a single instance in progress in a + * pool at one time, making the tag unnecessary. * * There can be multiple devices being replaced at once, but since they * all finish once resilvering finishes, we don't bother keeping track * of them individually, we just wait for them all to finish. */ - if (use_tag && activity != ZPOOL_WAIT_INITIALIZE) + if (use_tag && activity != ZPOOL_WAIT_INITIALIZE && + activity != ZPOOL_WAIT_TRIM) return (EINVAL); if (activity < 0 || activity >= ZPOOL_WAIT_NUM_ACTIVITIES) diff --git a/module/zfs/vdev_trim.c b/module/zfs/vdev_trim.c index 7dec07e3c..137ba83df 100644 --- a/module/zfs/vdev_trim.c +++ b/module/zfs/vdev_trim.c @@ -346,6 +346,9 @@ vdev_trim_change_state(vdev_t *vd, vdev_trim_state_t new_state, } dmu_tx_commit(tx); + + if (new_state != VDEV_TRIM_ACTIVE) + spa_notify_waiters(spa); } /* |