Skip to content

Commit ea3f7c1

Browse files
Don Bradyallanjude
authored andcommitted
Extend import_progress kstat with a notes field
Detail the import progress of log spacemaps as they can take a very long time. Also grab the spa_note() messages to, as they provide insight into what is happening Sponsored-By: OpenDrives Inc. Sponsored-By: Klara Inc. Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Don Brady <[email protected]> Co-authored-by: Allan Jude <[email protected]> Closes #15539
1 parent 6f32335 commit ea3f7c1

File tree

6 files changed

+256
-10
lines changed

6 files changed

+256
-10
lines changed

include/sys/spa.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,10 @@ extern int spa_import_progress_set_max_txg(uint64_t pool_guid,
966966
uint64_t max_txg);
967967
extern int spa_import_progress_set_state(uint64_t pool_guid,
968968
spa_load_state_t spa_load_state);
969+
extern void spa_import_progress_set_notes(spa_t *spa,
970+
const char *fmt, ...) __printflike(2, 3);
971+
extern void spa_import_progress_set_notes_nolog(spa_t *spa,
972+
const char *fmt, ...) __printflike(2, 3);
969973

970974
/* Pool configuration locks */
971975
extern int spa_config_tryenter(spa_t *spa, int locks, const void *tag,

module/zfs/spa.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3324,6 +3324,7 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type)
33243324
spa->spa_load_state = state;
33253325
(void) spa_import_progress_set_state(spa_guid(spa),
33263326
spa_load_state(spa));
3327+
spa_import_progress_set_notes(spa, "spa_load()");
33273328

33283329
gethrestime(&spa->spa_loaded_ts);
33293330
error = spa_load_impl(spa, type, &ereport);
@@ -3552,7 +3553,7 @@ spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
35523553
uint64_t mmp_config = ub->ub_mmp_config;
35533554
uint16_t mmp_seq = MMP_SEQ_VALID(ub) ? MMP_SEQ(ub) : 0;
35543555
uint64_t import_delay;
3555-
hrtime_t import_expire;
3556+
hrtime_t import_expire, now;
35563557
nvlist_t *mmp_label = NULL;
35573558
vdev_t *rvd = spa->spa_root_vdev;
35583559
kcondvar_t cv;
@@ -3590,7 +3591,17 @@ spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
35903591

35913592
import_expire = gethrtime() + import_delay;
35923593

3593-
while (gethrtime() < import_expire) {
3594+
spa_import_progress_set_notes(spa, "Checking MMP activity, waiting "
3595+
"%llu ms", (u_longlong_t)NSEC2MSEC(import_delay));
3596+
3597+
int interations = 0;
3598+
while ((now = gethrtime()) < import_expire) {
3599+
if (interations++ % 30 == 0) {
3600+
spa_import_progress_set_notes(spa, "Checking MMP "
3601+
"activity, %llu ms remaining",
3602+
(u_longlong_t)NSEC2MSEC(import_expire - now));
3603+
}
3604+
35943605
(void) spa_import_progress_set_mmp_check(spa_guid(spa),
35953606
NSEC2SEC(import_expire - gethrtime()));
35963607

@@ -5204,6 +5215,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52045215
/*
52055216
* Retrieve the checkpoint txg if the pool has a checkpoint.
52065217
*/
5218+
spa_import_progress_set_notes(spa, "Loading checkpoint txg");
52075219
error = spa_ld_read_checkpoint_txg(spa);
52085220
if (error != 0)
52095221
return (error);
@@ -5216,6 +5228,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52165228
* initiated. Otherwise we could be reading from indirect vdevs before
52175229
* we have loaded their mappings.
52185230
*/
5231+
spa_import_progress_set_notes(spa, "Loading indirect vdev metadata");
52195232
error = spa_ld_open_indirect_vdev_metadata(spa);
52205233
if (error != 0)
52215234
return (error);
@@ -5224,6 +5237,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52245237
* Retrieve the full list of active features from the MOS and check if
52255238
* they are all supported.
52265239
*/
5240+
spa_import_progress_set_notes(spa, "Checking feature flags");
52275241
error = spa_ld_check_features(spa, &missing_feat_write);
52285242
if (error != 0)
52295243
return (error);
@@ -5232,13 +5246,15 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52325246
* Load several special directories from the MOS needed by the dsl_pool
52335247
* layer.
52345248
*/
5249+
spa_import_progress_set_notes(spa, "Loading special MOS directories");
52355250
error = spa_ld_load_special_directories(spa);
52365251
if (error != 0)
52375252
return (error);
52385253

52395254
/*
52405255
* Retrieve pool properties from the MOS.
52415256
*/
5257+
spa_import_progress_set_notes(spa, "Loading properties");
52425258
error = spa_ld_get_props(spa);
52435259
if (error != 0)
52445260
return (error);
@@ -5247,6 +5263,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52475263
* Retrieve the list of auxiliary devices - cache devices and spares -
52485264
* and open them.
52495265
*/
5266+
spa_import_progress_set_notes(spa, "Loading AUX vdevs");
52505267
error = spa_ld_open_aux_vdevs(spa, type);
52515268
if (error != 0)
52525269
return (error);
@@ -5255,14 +5272,17 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52555272
* Load the metadata for all vdevs. Also check if unopenable devices
52565273
* should be autoreplaced.
52575274
*/
5275+
spa_import_progress_set_notes(spa, "Loading vdev metadata");
52585276
error = spa_ld_load_vdev_metadata(spa);
52595277
if (error != 0)
52605278
return (error);
52615279

5280+
spa_import_progress_set_notes(spa, "Loading dedup tables");
52625281
error = spa_ld_load_dedup_tables(spa);
52635282
if (error != 0)
52645283
return (error);
52655284

5285+
spa_import_progress_set_notes(spa, "Loading BRT");
52665286
error = spa_ld_load_brt(spa);
52675287
if (error != 0)
52685288
return (error);
@@ -5271,6 +5291,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52715291
* Verify the logs now to make sure we don't have any unexpected errors
52725292
* when we claim log blocks later.
52735293
*/
5294+
spa_import_progress_set_notes(spa, "Verifying Log Devices");
52745295
error = spa_ld_verify_logs(spa, type, ereport);
52755296
if (error != 0)
52765297
return (error);
@@ -5292,6 +5313,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
52925313
* state. When performing an extreme rewind, we verify the whole pool,
52935314
* which can take a very long time.
52945315
*/
5316+
spa_import_progress_set_notes(spa, "Verifying pool data");
52955317
error = spa_ld_verify_pool_data(spa);
52965318
if (error != 0)
52975319
return (error);
@@ -5301,13 +5323,15 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
53015323
* we write anything to the pool because we'd need to update the space
53025324
* accounting using the deflated sizes.
53035325
*/
5326+
spa_import_progress_set_notes(spa, "Calculating deflated space");
53045327
spa_update_dspace(spa);
53055328

53065329
/*
53075330
* We have now retrieved all the information we needed to open the
53085331
* pool. If we are importing the pool in read-write mode, a few
53095332
* additional steps must be performed to finish the import.
53105333
*/
5334+
spa_import_progress_set_notes(spa, "Starting import");
53115335
if (spa_writeable(spa) && (spa->spa_load_state == SPA_LOAD_RECOVER ||
53125336
spa->spa_load_max_txg == UINT64_MAX)) {
53135337
uint64_t config_cache_txg = spa->spa_config_txg;
@@ -5324,6 +5348,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
53245348
(u_longlong_t)spa->spa_uberblock.ub_checkpoint_txg);
53255349
}
53265350

5351+
spa_import_progress_set_notes(spa, "Claiming ZIL blocks");
53275352
/*
53285353
* Traverse the ZIL and claim all blocks.
53295354
*/
@@ -5343,13 +5368,15 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
53435368
* will have been set for us by ZIL traversal operations
53445369
* performed above.
53455370
*/
5371+
spa_import_progress_set_notes(spa, "Syncing ZIL claims");
53465372
txg_wait_synced(spa->spa_dsl_pool, spa->spa_claim_max_txg);
53475373

53485374
/*
53495375
* Check if we need to request an update of the config. On the
53505376
* next sync, we would update the config stored in vdev labels
53515377
* and the cachefile (by default /etc/zfs/zpool.cache).
53525378
*/
5379+
spa_import_progress_set_notes(spa, "Updating configs");
53535380
spa_ld_check_for_config_update(spa, config_cache_txg,
53545381
update_config_cache);
53555382

@@ -5358,6 +5385,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
53585385
* Then check all DTLs to see if anything needs resilvering.
53595386
* The resilver will be deferred if a rebuild was started.
53605387
*/
5388+
spa_import_progress_set_notes(spa, "Starting resilvers");
53615389
if (vdev_rebuild_active(spa->spa_root_vdev)) {
53625390
vdev_rebuild_restart(spa);
53635391
} else if (!dsl_scan_resilvering(spa->spa_dsl_pool) &&
@@ -5371,6 +5399,8 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
53715399
*/
53725400
spa_history_log_version(spa, "open", NULL);
53735401

5402+
spa_import_progress_set_notes(spa,
5403+
"Restarting device removals");
53745404
spa_restart_removal(spa);
53755405
spa_spawn_aux_threads(spa);
53765406

@@ -5383,19 +5413,26 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
53835413
* auxiliary threads above (from which the livelist
53845414
* deletion zthr is part of).
53855415
*/
5416+
spa_import_progress_set_notes(spa,
5417+
"Cleaning up inconsistent objsets");
53865418
(void) dmu_objset_find(spa_name(spa),
53875419
dsl_destroy_inconsistent, NULL, DS_FIND_CHILDREN);
53885420

53895421
/*
53905422
* Clean up any stale temporary dataset userrefs.
53915423
*/
5424+
spa_import_progress_set_notes(spa,
5425+
"Cleaning up temporary userrefs");
53925426
dsl_pool_clean_tmp_userrefs(spa->spa_dsl_pool);
53935427

53945428
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
5429+
spa_import_progress_set_notes(spa, "Restarting initialize");
53955430
vdev_initialize_restart(spa->spa_root_vdev);
5431+
spa_import_progress_set_notes(spa, "Restarting TRIM");
53965432
vdev_trim_restart(spa->spa_root_vdev);
53975433
vdev_autotrim_restart(spa);
53985434
spa_config_exit(spa, SCL_CONFIG, FTAG);
5435+
spa_import_progress_set_notes(spa, "Finished importing");
53995436
}
54005437

54015438
spa_import_progress_remove(spa_guid(spa));

module/zfs/spa_log_spacemap.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ spa_ld_log_sm_data(spa_t *spa)
11531153

11541154
uint_t pn = 0;
11551155
uint64_t ps = 0;
1156+
uint64_t nsm = 0;
11561157
psls = sls = avl_first(&spa->spa_sm_logs_by_txg);
11571158
while (sls != NULL) {
11581159
/* Prefetch log spacemaps up to 16 TXGs or MBs ahead. */
@@ -1185,6 +1186,10 @@ spa_ld_log_sm_data(spa_t *spa)
11851186
summary_add_data(spa, sls->sls_txg,
11861187
sls->sls_mscount, 0, sls->sls_nblocks);
11871188

1189+
spa_import_progress_set_notes_nolog(spa,
1190+
"Read %llu of %lu log space maps", (u_longlong_t)nsm,
1191+
avl_numnodes(&spa->spa_sm_logs_by_txg));
1192+
11881193
struct spa_ld_log_sm_arg vla = {
11891194
.slls_spa = spa,
11901195
.slls_txg = sls->sls_txg
@@ -1200,6 +1205,7 @@ spa_ld_log_sm_data(spa_t *spa)
12001205

12011206
pn--;
12021207
ps -= space_map_length(sls->sls_sm);
1208+
nsm++;
12031209
space_map_close(sls->sls_sm);
12041210
sls->sls_sm = NULL;
12051211
sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls);
@@ -1210,11 +1216,11 @@ spa_ld_log_sm_data(spa_t *spa)
12101216

12111217
hrtime_t read_logs_endtime = gethrtime();
12121218
spa_load_note(spa,
1213-
"read %llu log space maps (%llu total blocks - blksz = %llu bytes) "
1214-
"in %lld ms", (u_longlong_t)avl_numnodes(&spa->spa_sm_logs_by_txg),
1219+
"Read %lu log space maps (%llu total blocks - blksz = %llu bytes) "
1220+
"in %lld ms", avl_numnodes(&spa->spa_sm_logs_by_txg),
12151221
(u_longlong_t)spa_log_sm_nblocks(spa),
12161222
(u_longlong_t)zfs_log_sm_blksz,
1217-
(longlong_t)((read_logs_endtime - read_logs_starttime) / 1000000));
1223+
(longlong_t)NSEC2MSEC(read_logs_endtime - read_logs_starttime));
12181224

12191225
out:
12201226
if (error != 0) {

module/zfs/spa_misc.c

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ spa_load_note(spa_t *spa, const char *fmt, ...)
417417

418418
zfs_dbgmsg("spa_load(%s, config %s): %s", spa->spa_name,
419419
spa->spa_trust_config ? "trusted" : "untrusted", buf);
420+
421+
spa_import_progress_set_notes_nolog(spa, "%s", buf);
420422
}
421423

422424
/*
@@ -2172,6 +2174,7 @@ typedef struct spa_import_progress {
21722174
uint64_t pool_guid; /* unique id for updates */
21732175
char *pool_name;
21742176
spa_load_state_t spa_load_state;
2177+
char *spa_load_notes;
21752178
uint64_t mmp_sec_remaining; /* MMP activity check */
21762179
uint64_t spa_load_max_txg; /* rewind txg */
21772180
procfs_list_node_t smh_node;
@@ -2182,9 +2185,9 @@ spa_history_list_t *spa_import_progress_list = NULL;
21822185
static int
21832186
spa_import_progress_show_header(struct seq_file *f)
21842187
{
2185-
seq_printf(f, "%-20s %-14s %-14s %-12s %s\n", "pool_guid",
2188+
seq_printf(f, "%-20s %-14s %-14s %-12s %-16s %s\n", "pool_guid",
21862189
"load_state", "multihost_secs", "max_txg",
2187-
"pool_name");
2190+
"pool_name", "notes");
21882191
return (0);
21892192
}
21902193

@@ -2193,11 +2196,12 @@ spa_import_progress_show(struct seq_file *f, void *data)
21932196
{
21942197
spa_import_progress_t *sip = (spa_import_progress_t *)data;
21952198

2196-
seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %s\n",
2199+
seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %-16s %s\n",
21972200
(u_longlong_t)sip->pool_guid, (u_longlong_t)sip->spa_load_state,
21982201
(u_longlong_t)sip->mmp_sec_remaining,
21992202
(u_longlong_t)sip->spa_load_max_txg,
2200-
(sip->pool_name ? sip->pool_name : "-"));
2203+
(sip->pool_name ? sip->pool_name : "-"),
2204+
(sip->spa_load_notes ? sip->spa_load_notes : "-"));
22012205

22022206
return (0);
22032207
}
@@ -2211,6 +2215,8 @@ spa_import_progress_truncate(spa_history_list_t *shl, unsigned int size)
22112215
sip = list_remove_head(&shl->procfs_list.pl_list);
22122216
if (sip->pool_name)
22132217
spa_strfree(sip->pool_name);
2218+
if (sip->spa_load_notes)
2219+
kmem_strfree(sip->spa_load_notes);
22142220
kmem_free(sip, sizeof (spa_import_progress_t));
22152221
shl->size--;
22162222
}
@@ -2266,6 +2272,10 @@ spa_import_progress_set_state(uint64_t pool_guid,
22662272
sip = list_prev(&shl->procfs_list.pl_list, sip)) {
22672273
if (sip->pool_guid == pool_guid) {
22682274
sip->spa_load_state = load_state;
2275+
if (sip->spa_load_notes != NULL) {
2276+
kmem_strfree(sip->spa_load_notes);
2277+
sip->spa_load_notes = NULL;
2278+
}
22692279
error = 0;
22702280
break;
22712281
}
@@ -2275,6 +2285,59 @@ spa_import_progress_set_state(uint64_t pool_guid,
22752285
return (error);
22762286
}
22772287

2288+
static void
2289+
spa_import_progress_set_notes_impl(spa_t *spa, boolean_t log_dbgmsg,
2290+
const char *fmt, va_list adx)
2291+
{
2292+
spa_history_list_t *shl = spa_import_progress_list;
2293+
spa_import_progress_t *sip;
2294+
uint64_t pool_guid = spa_guid(spa);
2295+
2296+
if (shl->size == 0)
2297+
return;
2298+
2299+
char *notes = kmem_vasprintf(fmt, adx);
2300+
2301+
mutex_enter(&shl->procfs_list.pl_lock);
2302+
for (sip = list_tail(&shl->procfs_list.pl_list); sip != NULL;
2303+
sip = list_prev(&shl->procfs_list.pl_list, sip)) {
2304+
if (sip->pool_guid == pool_guid) {
2305+
if (sip->spa_load_notes != NULL) {
2306+
kmem_strfree(sip->spa_load_notes);
2307+
sip->spa_load_notes = NULL;
2308+
}
2309+
sip->spa_load_notes = notes;
2310+
if (log_dbgmsg)
2311+
zfs_dbgmsg("'%s' %s", sip->pool_name, notes);
2312+
notes = NULL;
2313+
break;
2314+
}
2315+
}
2316+
mutex_exit(&shl->procfs_list.pl_lock);
2317+
if (notes != NULL)
2318+
kmem_strfree(notes);
2319+
}
2320+
2321+
void
2322+
spa_import_progress_set_notes(spa_t *spa, const char *fmt, ...)
2323+
{
2324+
va_list adx;
2325+
2326+
va_start(adx, fmt);
2327+
spa_import_progress_set_notes_impl(spa, B_TRUE, fmt, adx);
2328+
va_end(adx);
2329+
}
2330+
2331+
void
2332+
spa_import_progress_set_notes_nolog(spa_t *spa, const char *fmt, ...)
2333+
{
2334+
va_list adx;
2335+
2336+
va_start(adx, fmt);
2337+
spa_import_progress_set_notes_impl(spa, B_FALSE, fmt, adx);
2338+
va_end(adx);
2339+
}
2340+
22782341
int
22792342
spa_import_progress_set_max_txg(uint64_t pool_guid, uint64_t load_max_txg)
22802343
{
@@ -2343,6 +2406,7 @@ spa_import_progress_add(spa_t *spa)
23432406
poolname = spa_name(spa);
23442407
sip->pool_name = spa_strdup(poolname);
23452408
sip->spa_load_state = spa_load_state(spa);
2409+
sip->spa_load_notes = NULL;
23462410

23472411
mutex_enter(&shl->procfs_list.pl_lock);
23482412
procfs_list_add(&shl->procfs_list, sip);
@@ -2362,6 +2426,8 @@ spa_import_progress_remove(uint64_t pool_guid)
23622426
if (sip->pool_guid == pool_guid) {
23632427
if (sip->pool_name)
23642428
spa_strfree(sip->pool_name);
2429+
if (sip->spa_load_notes)
2430+
spa_strfree(sip->spa_load_notes);
23652431
list_remove(&shl->procfs_list.pl_list, sip);
23662432
shl->size--;
23672433
kmem_free(sip, sizeof (spa_import_progress_t));

0 commit comments

Comments
 (0)