|
25 | 25 | #include <sys/vdev_impl.h> |
26 | 26 | #include <sys/spa.h> |
27 | 27 | #include <zfs_comutil.h> |
| 28 | +#include <sys/metaslab_impl.h> |
28 | 29 |
|
29 | 30 | /* |
30 | 31 | * Keeps stats on last N reads per spa_t, disabled by default. |
@@ -303,6 +304,107 @@ spa_txg_history_init(spa_t *spa) |
303 | 304 | offsetof(spa_txg_history_t, sth_node)); |
304 | 305 | } |
305 | 306 |
|
| 307 | +typedef struct { |
| 308 | + spa_t *spa; |
| 309 | + int metaclass; |
| 310 | +} freespace_histogram_stat_t; |
| 311 | + |
| 312 | +static void * |
| 313 | +spa_frag_addr(kstat_t *ksp, loff_t n) |
| 314 | +{ |
| 315 | + if (n == 0) { |
| 316 | + freespace_histogram_stat_t *stat = ksp->ks_private; |
| 317 | + switch (stat->metaclass) { |
| 318 | + case 0: |
| 319 | + return (spa_normal_class(stat->spa)); |
| 320 | + case 1: |
| 321 | + return (spa_log_class(stat->spa)); |
| 322 | + case 2: |
| 323 | + return (spa_embedded_log_class(stat->spa)); |
| 324 | + case 3: |
| 325 | + return (spa_special_class(stat->spa)); |
| 326 | + case 4: |
| 327 | + return (spa_dedup_class(stat->spa)); |
| 328 | + case 5: |
| 329 | + return (spa_special_embedded_log_class(stat->spa)); |
| 330 | + } |
| 331 | + } |
| 332 | + return (NULL); |
| 333 | +} |
| 334 | + |
| 335 | +static int |
| 336 | +spa_frag_data(char *buf, size_t size, void *data) |
| 337 | +{ |
| 338 | + metaslab_class_t *mc = data; |
| 339 | + size_t offset = 0; |
| 340 | + snprintf(buf+offset, size-offset, "bucket count\n"); |
| 341 | + offset = strlen(buf); |
| 342 | + |
| 343 | + mutex_enter(&mc->mc_lock); |
| 344 | + for (int i = 0; i < ZFS_RANGE_TREE_HISTOGRAM_SIZE; i++) { |
| 345 | + if (mc->mc_histogram[i] > 0) { |
| 346 | + snprintf(buf + offset, size - offset, "%d %llu\n", i, |
| 347 | + (u_longlong_t)mc->mc_histogram[i]); |
| 348 | + offset = strlen(buf); |
| 349 | + } |
| 350 | + } |
| 351 | + mutex_exit(&mc->mc_lock); |
| 352 | + |
| 353 | + return (0); |
| 354 | +} |
| 355 | + |
| 356 | +static void |
| 357 | +spa_fragmentation_init(spa_t *spa) |
| 358 | +{ |
| 359 | + char *dirname; |
| 360 | + const char *statnames[] = { |
| 361 | + "class_normal_free_histogram", |
| 362 | + "class_log_free_histogram", |
| 363 | + "class_elog_free_histogram", |
| 364 | + "class_special_free_histogram", |
| 365 | + "class_dedup_free_histogram", |
| 366 | + "class_special_elog_free_histogram" |
| 367 | + }; |
| 368 | + for (int i = 0; i < 6; i++) { |
| 369 | + spa_history_kstat_t *shk = &spa->spa_stats.fragmentation[i]; |
| 370 | + kstat_t *ksp; |
| 371 | + |
| 372 | + dirname = kmem_asprintf("zfs/%s", spa_name(spa)); |
| 373 | + ksp = kstat_create(dirname, 0, statnames[i], "misc", |
| 374 | + KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL); |
| 375 | + kmem_strfree(dirname); |
| 376 | + |
| 377 | + shk->kstat = ksp; |
| 378 | + if (ksp) { |
| 379 | + freespace_histogram_stat_t *stat = kmem_zalloc( |
| 380 | + sizeof (freespace_histogram_stat_t), KM_SLEEP); |
| 381 | + stat->spa = spa; |
| 382 | + stat->metaclass = i; |
| 383 | + ksp->ks_private = stat; |
| 384 | + ksp->ks_flags |= KSTAT_FLAG_NO_HEADERS; |
| 385 | + kstat_set_raw_ops(ksp, NULL, spa_frag_data, |
| 386 | + spa_frag_addr); |
| 387 | + kstat_install(ksp); |
| 388 | + } |
| 389 | + } |
| 390 | +} |
| 391 | + |
| 392 | +static void |
| 393 | +spa_fragmentation_destroy(spa_t *spa) |
| 394 | +{ |
| 395 | + for (int i = 0; i < 6; i++) { |
| 396 | + spa_history_kstat_t *shk = &spa->spa_stats.fragmentation[i]; |
| 397 | + kstat_t *ksp = shk->kstat; |
| 398 | + if (ksp) { |
| 399 | + if (ksp->ks_private) { |
| 400 | + kmem_free(ksp->ks_private, |
| 401 | + sizeof (freespace_histogram_stat_t)); |
| 402 | + } |
| 403 | + kstat_delete(ksp); |
| 404 | + } |
| 405 | + } |
| 406 | +} |
| 407 | + |
306 | 408 | static void |
307 | 409 | spa_txg_history_destroy(spa_t *spa) |
308 | 410 | { |
@@ -1047,11 +1149,13 @@ spa_stats_init(spa_t *spa) |
1047 | 1149 | spa_state_init(spa); |
1048 | 1150 | spa_guid_init(spa); |
1049 | 1151 | spa_iostats_init(spa); |
| 1152 | + spa_fragmentation_init(spa); |
1050 | 1153 | } |
1051 | 1154 |
|
1052 | 1155 | void |
1053 | 1156 | spa_stats_destroy(spa_t *spa) |
1054 | 1157 | { |
| 1158 | + spa_fragmentation_destroy(spa); |
1055 | 1159 | spa_iostats_destroy(spa); |
1056 | 1160 | spa_health_destroy(spa); |
1057 | 1161 | spa_tx_assign_destroy(spa); |
|
0 commit comments