Skip to content

Commit 4296626

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 openzfs#15539
1 parent 0ab4172 commit 4296626

File tree

6 files changed

+255
-10
lines changed

6 files changed

+255
-10
lines changed

include/sys/spa.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,10 @@ extern int spa_import_progress_set_max_txg(uint64_t pool_guid,
10041004
uint64_t max_txg);
10051005
extern int spa_import_progress_set_state(uint64_t pool_guid,
10061006
spa_load_state_t spa_load_state);
1007+
extern void spa_import_progress_set_notes(spa_t *spa,
1008+
const char *fmt, ...) __printflike(2, 3);
1009+
extern void spa_import_progress_set_notes_nolog(spa_t *spa,
1010+
const char *fmt, ...) __printflike(2, 3);
10071011

10081012
/* Pool configuration locks */
10091013
extern int spa_config_tryenter(spa_t *spa, int locks, const void *tag,

module/zfs/spa.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3331,6 +3331,7 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type)
33313331
spa->spa_load_state = state;
33323332
(void) spa_import_progress_set_state(spa_guid(spa),
33333333
spa_load_state(spa));
3334+
spa_import_progress_set_notes(spa, "spa_load()");
33343335

33353336
gethrestime(&spa->spa_loaded_ts);
33363337
error = spa_load_impl(spa, type, &ereport);
@@ -3551,7 +3552,7 @@ spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
35513552
uint64_t mmp_config = ub->ub_mmp_config;
35523553
uint16_t mmp_seq = MMP_SEQ_VALID(ub) ? MMP_SEQ(ub) : 0;
35533554
uint64_t import_delay;
3554-
hrtime_t import_expire;
3555+
hrtime_t import_expire, now;
35553556
nvlist_t *mmp_label = NULL;
35563557
vdev_t *rvd = spa->spa_root_vdev;
35573558
kcondvar_t cv;
@@ -3589,7 +3590,17 @@ spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
35893590

35903591
import_expire = gethrtime() + import_delay;
35913592

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

@@ -5188,6 +5199,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
51885199
/*
51895200
* Retrieve the checkpoint txg if the pool has a checkpoint.
51905201
*/
5202+
spa_import_progress_set_notes(spa, "Loading checkpoint txg");
51915203
error = spa_ld_read_checkpoint_txg(spa);
51925204
if (error != 0)
51935205
return (error);
@@ -5200,6 +5212,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52005212
* initiated. Otherwise we could be reading from indirect vdevs before
52015213
* we have loaded their mappings.
52025214
*/
5215+
spa_import_progress_set_notes(spa, "Loading indirect vdev metadata");
52035216
error = spa_ld_open_indirect_vdev_metadata(spa);
52045217
if (error != 0)
52055218
return (error);
@@ -5208,6 +5221,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52085221
* Retrieve the full list of active features from the MOS and check if
52095222
* they are all supported.
52105223
*/
5224+
spa_import_progress_set_notes(spa, "Checking feature flags");
52115225
error = spa_ld_check_features(spa, &missing_feat_write);
52125226
if (error != 0)
52135227
return (error);
@@ -5216,13 +5230,15 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52165230
* Load several special directories from the MOS needed by the dsl_pool
52175231
* layer.
52185232
*/
5233+
spa_import_progress_set_notes(spa, "Loading special MOS directories");
52195234
error = spa_ld_load_special_directories(spa);
52205235
if (error != 0)
52215236
return (error);
52225237

52235238
/*
52245239
* Retrieve pool properties from the MOS.
52255240
*/
5241+
spa_import_progress_set_notes(spa, "Loading properties");
52265242
error = spa_ld_get_props(spa);
52275243
if (error != 0)
52285244
return (error);
@@ -5231,6 +5247,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52315247
* Retrieve the list of auxiliary devices - cache devices and spares -
52325248
* and open them.
52335249
*/
5250+
spa_import_progress_set_notes(spa, "Loading AUX vdevs");
52345251
error = spa_ld_open_aux_vdevs(spa, type);
52355252
if (error != 0)
52365253
return (error);
@@ -5239,10 +5256,12 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52395256
* Load the metadata for all vdevs. Also check if unopenable devices
52405257
* should be autoreplaced.
52415258
*/
5259+
spa_import_progress_set_notes(spa, "Loading vdev metadata");
52425260
error = spa_ld_load_vdev_metadata(spa);
52435261
if (error != 0)
52445262
return (error);
52455263

5264+
spa_import_progress_set_notes(spa, "Loading dedup tables");
52465265
error = spa_ld_load_dedup_tables(spa);
52475266
if (error != 0)
52485267
return (error);
@@ -5251,6 +5270,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52515270
* Verify the logs now to make sure we don't have any unexpected errors
52525271
* when we claim log blocks later.
52535272
*/
5273+
spa_import_progress_set_notes(spa, "Verifying Log Devices");
52545274
error = spa_ld_verify_logs(spa, type, ereport);
52555275
if (error != 0)
52565276
return (error);
@@ -5272,6 +5292,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52725292
* state. When performing an extreme rewind, we verify the whole pool,
52735293
* which can take a very long time.
52745294
*/
5295+
spa_import_progress_set_notes(spa, "Verifying pool data");
52755296
error = spa_ld_verify_pool_data(spa);
52765297
if (error != 0)
52775298
return (error);
@@ -5281,13 +5302,15 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
52815302
* we write anything to the pool because we'd need to update the space
52825303
* accounting using the deflated sizes.
52835304
*/
5305+
spa_import_progress_set_notes(spa, "Calculating deflated space");
52845306
spa_update_dspace(spa);
52855307

52865308
/*
52875309
* We have now retrieved all the information we needed to open the
52885310
* pool. If we are importing the pool in read-write mode, a few
52895311
* additional steps must be performed to finish the import.
52905312
*/
5313+
spa_import_progress_set_notes(spa, "Starting import");
52915314
if (spa_writeable(spa) && (spa->spa_load_state == SPA_LOAD_RECOVER ||
52925315
spa->spa_load_max_txg == UINT64_MAX)) {
52935316
uint64_t config_cache_txg = spa->spa_config_txg;
@@ -5304,6 +5327,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
53045327
(u_longlong_t)spa->spa_uberblock.ub_checkpoint_txg);
53055328
}
53065329

5330+
spa_import_progress_set_notes(spa, "Claiming ZIL blocks");
53075331
/*
53085332
* Traverse the ZIL and claim all blocks.
53095333
*/
@@ -5323,13 +5347,15 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
53235347
* will have been set for us by ZIL traversal operations
53245348
* performed above.
53255349
*/
5350+
spa_import_progress_set_notes(spa, "Syncing ZIL claims");
53265351
txg_wait_synced(spa->spa_dsl_pool, spa->spa_claim_max_txg);
53275352

53285353
/*
53295354
* Check if we need to request an update of the config. On the
53305355
* next sync, we would update the config stored in vdev labels
53315356
* and the cachefile (by default /etc/zfs/zpool.cache).
53325357
*/
5358+
spa_import_progress_set_notes(spa, "Updating configs");
53335359
spa_ld_check_for_config_update(spa, config_cache_txg,
53345360
update_config_cache);
53355361

@@ -5338,6 +5364,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
53385364
* Then check all DTLs to see if anything needs resilvering.
53395365
* The resilver will be deferred if a rebuild was started.
53405366
*/
5367+
spa_import_progress_set_notes(spa, "Starting resilvers");
53415368
if (vdev_rebuild_active(spa->spa_root_vdev)) {
53425369
vdev_rebuild_restart(spa);
53435370
} else if (!dsl_scan_resilvering(spa->spa_dsl_pool) &&
@@ -5351,6 +5378,8 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
53515378
*/
53525379
spa_history_log_version(spa, "open", NULL);
53535380

5381+
spa_import_progress_set_notes(spa,
5382+
"Restarting device removals");
53545383
spa_restart_removal(spa);
53555384
spa_spawn_aux_threads(spa);
53565385

@@ -5363,19 +5392,26 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
53635392
* auxiliary threads above (from which the livelist
53645393
* deletion zthr is part of).
53655394
*/
5395+
spa_import_progress_set_notes(spa,
5396+
"Cleaning up inconsistent objsets");
53665397
(void) dmu_objset_find(spa_name(spa),
53675398
dsl_destroy_inconsistent, NULL, DS_FIND_CHILDREN);
53685399

53695400
/*
53705401
* Clean up any stale temporary dataset userrefs.
53715402
*/
5403+
spa_import_progress_set_notes(spa,
5404+
"Cleaning up temporary userrefs");
53725405
dsl_pool_clean_tmp_userrefs(spa->spa_dsl_pool);
53735406

53745407
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
5408+
spa_import_progress_set_notes(spa, "Restarting initialize");
53755409
vdev_initialize_restart(spa->spa_root_vdev);
5410+
spa_import_progress_set_notes(spa, "Restarting TRIM");
53765411
vdev_trim_restart(spa->spa_root_vdev);
53775412
vdev_autotrim_restart(spa);
53785413
spa_config_exit(spa, SCL_CONFIG, FTAG);
5414+
spa_import_progress_set_notes(spa, "Finished importing");
53795415
}
53805416

53815417
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
@@ -1155,6 +1155,7 @@ spa_ld_log_sm_data(spa_t *spa)
11551155

11561156
uint_t pn = 0;
11571157
uint64_t ps = 0;
1158+
uint64_t nsm = 0;
11581159
psls = sls = avl_first(&spa->spa_sm_logs_by_txg);
11591160
while (sls != NULL) {
11601161
/* Prefetch log spacemaps up to 16 TXGs or MBs ahead. */
@@ -1187,6 +1188,10 @@ spa_ld_log_sm_data(spa_t *spa)
11871188
summary_add_data(spa, sls->sls_txg,
11881189
sls->sls_mscount, 0, sls->sls_nblocks);
11891190

1191+
spa_import_progress_set_notes_nolog(spa,
1192+
"Read %llu of %lu log space maps", (u_longlong_t)nsm,
1193+
avl_numnodes(&spa->spa_sm_logs_by_txg));
1194+
11901195
struct spa_ld_log_sm_arg vla = {
11911196
.slls_spa = spa,
11921197
.slls_txg = sls->sls_txg
@@ -1202,6 +1207,7 @@ spa_ld_log_sm_data(spa_t *spa)
12021207

12031208
pn--;
12041209
ps -= space_map_length(sls->sls_sm);
1210+
nsm++;
12051211
space_map_close(sls->sls_sm);
12061212
sls->sls_sm = NULL;
12071213
sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls);
@@ -1212,11 +1218,11 @@ spa_ld_log_sm_data(spa_t *spa)
12121218

12131219
hrtime_t read_logs_endtime = gethrtime();
12141220
spa_load_note(spa,
1215-
"read %llu log space maps (%llu total blocks - blksz = %llu bytes) "
1216-
"in %lld ms", (u_longlong_t)avl_numnodes(&spa->spa_sm_logs_by_txg),
1221+
"Read %lu log space maps (%llu total blocks - blksz = %llu bytes) "
1222+
"in %lld ms", avl_numnodes(&spa->spa_sm_logs_by_txg),
12171223
(u_longlong_t)spa_log_sm_nblocks(spa),
12181224
(u_longlong_t)zfs_log_sm_blksz,
1219-
(longlong_t)((read_logs_endtime - read_logs_starttime) / 1000000));
1225+
(longlong_t)NSEC2MSEC(read_logs_endtime - read_logs_starttime));
12201226

12211227
out:
12221228
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
/*
@@ -2215,6 +2217,7 @@ typedef struct spa_import_progress {
22152217
uint64_t pool_guid; /* unique id for updates */
22162218
char *pool_name;
22172219
spa_load_state_t spa_load_state;
2220+
char *spa_load_notes;
22182221
uint64_t mmp_sec_remaining; /* MMP activity check */
22192222
uint64_t spa_load_max_txg; /* rewind txg */
22202223
procfs_list_node_t smh_node;
@@ -2225,9 +2228,9 @@ spa_history_list_t *spa_import_progress_list = NULL;
22252228
static int
22262229
spa_import_progress_show_header(struct seq_file *f)
22272230
{
2228-
seq_printf(f, "%-20s %-14s %-14s %-12s %s\n", "pool_guid",
2231+
seq_printf(f, "%-20s %-14s %-14s %-12s %-16s %s\n", "pool_guid",
22292232
"load_state", "multihost_secs", "max_txg",
2230-
"pool_name");
2233+
"pool_name", "notes");
22312234
return (0);
22322235
}
22332236

@@ -2236,11 +2239,12 @@ spa_import_progress_show(struct seq_file *f, void *data)
22362239
{
22372240
spa_import_progress_t *sip = (spa_import_progress_t *)data;
22382241

2239-
seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %s\n",
2242+
seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %-16s %s\n",
22402243
(u_longlong_t)sip->pool_guid, (u_longlong_t)sip->spa_load_state,
22412244
(u_longlong_t)sip->mmp_sec_remaining,
22422245
(u_longlong_t)sip->spa_load_max_txg,
2243-
(sip->pool_name ? sip->pool_name : "-"));
2246+
(sip->pool_name ? sip->pool_name : "-"),
2247+
(sip->spa_load_notes ? sip->spa_load_notes : "-"));
22442248

22452249
return (0);
22462250
}
@@ -2254,6 +2258,8 @@ spa_import_progress_truncate(spa_history_list_t *shl, unsigned int size)
22542258
sip = list_remove_head(&shl->procfs_list.pl_list);
22552259
if (sip->pool_name)
22562260
spa_strfree(sip->pool_name);
2261+
if (sip->spa_load_notes)
2262+
kmem_strfree(sip->spa_load_notes);
22572263
kmem_free(sip, sizeof (spa_import_progress_t));
22582264
shl->size--;
22592265
}
@@ -2309,6 +2315,10 @@ spa_import_progress_set_state(uint64_t pool_guid,
23092315
sip = list_prev(&shl->procfs_list.pl_list, sip)) {
23102316
if (sip->pool_guid == pool_guid) {
23112317
sip->spa_load_state = load_state;
2318+
if (sip->spa_load_notes != NULL) {
2319+
kmem_strfree(sip->spa_load_notes);
2320+
sip->spa_load_notes = NULL;
2321+
}
23122322
error = 0;
23132323
break;
23142324
}
@@ -2318,6 +2328,59 @@ spa_import_progress_set_state(uint64_t pool_guid,
23182328
return (error);
23192329
}
23202330

2331+
static void
2332+
spa_import_progress_set_notes_impl(spa_t *spa, boolean_t log_dbgmsg,
2333+
const char *fmt, va_list adx)
2334+
{
2335+
spa_history_list_t *shl = spa_import_progress_list;
2336+
spa_import_progress_t *sip;
2337+
uint64_t pool_guid = spa_guid(spa);
2338+
2339+
if (shl->size == 0)
2340+
return;
2341+
2342+
char *notes = kmem_vasprintf(fmt, adx);
2343+
2344+
mutex_enter(&shl->procfs_list.pl_lock);
2345+
for (sip = list_tail(&shl->procfs_list.pl_list); sip != NULL;
2346+
sip = list_prev(&shl->procfs_list.pl_list, sip)) {
2347+
if (sip->pool_guid == pool_guid) {
2348+
if (sip->spa_load_notes != NULL) {
2349+
kmem_strfree(sip->spa_load_notes);
2350+
sip->spa_load_notes = NULL;
2351+
}
2352+
sip->spa_load_notes = notes;
2353+
if (log_dbgmsg)
2354+
zfs_dbgmsg("'%s' %s", sip->pool_name, notes);
2355+
notes = NULL;
2356+
break;
2357+
}
2358+
}
2359+
mutex_exit(&shl->procfs_list.pl_lock);
2360+
if (notes != NULL)
2361+
kmem_strfree(notes);
2362+
}
2363+
2364+
void
2365+
spa_import_progress_set_notes(spa_t *spa, const char *fmt, ...)
2366+
{
2367+
va_list adx;
2368+
2369+
va_start(adx, fmt);
2370+
spa_import_progress_set_notes_impl(spa, B_TRUE, fmt, adx);
2371+
va_end(adx);
2372+
}
2373+
2374+
void
2375+
spa_import_progress_set_notes_nolog(spa_t *spa, const char *fmt, ...)
2376+
{
2377+
va_list adx;
2378+
2379+
va_start(adx, fmt);
2380+
spa_import_progress_set_notes_impl(spa, B_FALSE, fmt, adx);
2381+
va_end(adx);
2382+
}
2383+
23212384
int
23222385
spa_import_progress_set_max_txg(uint64_t pool_guid, uint64_t load_max_txg)
23232386
{
@@ -2386,6 +2449,7 @@ spa_import_progress_add(spa_t *spa)
23862449
poolname = spa_name(spa);
23872450
sip->pool_name = spa_strdup(poolname);
23882451
sip->spa_load_state = spa_load_state(spa);
2452+
sip->spa_load_notes = NULL;
23892453

23902454
mutex_enter(&shl->procfs_list.pl_lock);
23912455
procfs_list_add(&shl->procfs_list, sip);
@@ -2405,6 +2469,8 @@ spa_import_progress_remove(uint64_t pool_guid)
24052469
if (sip->pool_guid == pool_guid) {
24062470
if (sip->pool_name)
24072471
spa_strfree(sip->pool_name);
2472+
if (sip->spa_load_notes)
2473+
spa_strfree(sip->spa_load_notes);
24082474
list_remove(&shl->procfs_list.pl_list, sip);
24092475
shl->size--;
24102476
kmem_free(sip, sizeof (spa_import_progress_t));

0 commit comments

Comments
 (0)