.. | .. |
---|
11 | 11 | #include <linux/f2fs_fs.h> |
---|
12 | 12 | #include <linux/seq_file.h> |
---|
13 | 13 | #include <linux/unicode.h> |
---|
| 14 | +#include <linux/ioprio.h> |
---|
| 15 | +#include <linux/sysfs.h> |
---|
14 | 16 | |
---|
15 | 17 | #include "f2fs.h" |
---|
16 | 18 | #include "segment.h" |
---|
.. | .. |
---|
27 | 29 | NM_INFO, /* struct f2fs_nm_info */ |
---|
28 | 30 | F2FS_SBI, /* struct f2fs_sb_info */ |
---|
29 | 31 | #ifdef CONFIG_F2FS_STAT_FS |
---|
30 | | - STAT_INFO, /* struct f2fs_stat_info */ |
---|
| 32 | + STAT_INFO, /* struct f2fs_stat_info */ |
---|
31 | 33 | #endif |
---|
32 | 34 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
---|
33 | 35 | FAULT_INFO_RATE, /* struct f2fs_fault_info */ |
---|
34 | 36 | FAULT_INFO_TYPE, /* struct f2fs_fault_info */ |
---|
35 | 37 | #endif |
---|
36 | 38 | RESERVED_BLOCKS, /* struct f2fs_sb_info */ |
---|
| 39 | + CPRC_INFO, /* struct ckpt_req_control */ |
---|
| 40 | + ATGC_INFO, /* struct atgc_management */ |
---|
37 | 41 | }; |
---|
38 | 42 | |
---|
39 | 43 | struct f2fs_attr { |
---|
.. | .. |
---|
70 | 74 | else if (struct_type == STAT_INFO) |
---|
71 | 75 | return (unsigned char *)F2FS_STAT(sbi); |
---|
72 | 76 | #endif |
---|
| 77 | + else if (struct_type == CPRC_INFO) |
---|
| 78 | + return (unsigned char *)&sbi->cprc_info; |
---|
| 79 | + else if (struct_type == ATGC_INFO) |
---|
| 80 | + return (unsigned char *)&sbi->am; |
---|
73 | 81 | return NULL; |
---|
74 | 82 | } |
---|
75 | 83 | |
---|
.. | .. |
---|
87 | 95 | (unsigned long long)(free_segments(sbi))); |
---|
88 | 96 | } |
---|
89 | 97 | |
---|
| 98 | +static ssize_t ovp_segments_show(struct f2fs_attr *a, |
---|
| 99 | + struct f2fs_sb_info *sbi, char *buf) |
---|
| 100 | +{ |
---|
| 101 | + return sprintf(buf, "%llu\n", |
---|
| 102 | + (unsigned long long)(overprovision_segments(sbi))); |
---|
| 103 | +} |
---|
| 104 | + |
---|
90 | 105 | static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a, |
---|
91 | 106 | struct f2fs_sb_info *sbi, char *buf) |
---|
92 | 107 | { |
---|
93 | | - struct super_block *sb = sbi->sb; |
---|
94 | | - |
---|
95 | | - if (!sb->s_bdev->bd_part) |
---|
96 | | - return sprintf(buf, "0\n"); |
---|
97 | | - |
---|
98 | 108 | return sprintf(buf, "%llu\n", |
---|
99 | 109 | (unsigned long long)(sbi->kbytes_written + |
---|
100 | | - BD_PART_WRITTEN(sbi))); |
---|
| 110 | + ((f2fs_get_sectors_written(sbi) - |
---|
| 111 | + sbi->sectors_written_start) >> 1))); |
---|
| 112 | +} |
---|
| 113 | + |
---|
| 114 | +static ssize_t sb_status_show(struct f2fs_attr *a, |
---|
| 115 | + struct f2fs_sb_info *sbi, char *buf) |
---|
| 116 | +{ |
---|
| 117 | + return sprintf(buf, "%lx\n", sbi->s_flag); |
---|
| 118 | +} |
---|
| 119 | + |
---|
| 120 | +static ssize_t pending_discard_show(struct f2fs_attr *a, |
---|
| 121 | + struct f2fs_sb_info *sbi, char *buf) |
---|
| 122 | +{ |
---|
| 123 | + if (!SM_I(sbi)->dcc_info) |
---|
| 124 | + return -EINVAL; |
---|
| 125 | + return sprintf(buf, "%llu\n", (unsigned long long)atomic_read( |
---|
| 126 | + &SM_I(sbi)->dcc_info->discard_cmd_cnt)); |
---|
101 | 127 | } |
---|
102 | 128 | |
---|
103 | 129 | static ssize_t features_show(struct f2fs_attr *a, |
---|
104 | 130 | struct f2fs_sb_info *sbi, char *buf) |
---|
105 | 131 | { |
---|
106 | | - struct super_block *sb = sbi->sb; |
---|
107 | 132 | int len = 0; |
---|
108 | | - |
---|
109 | | - if (!sb->s_bdev->bd_part) |
---|
110 | | - return sprintf(buf, "0\n"); |
---|
111 | 133 | |
---|
112 | 134 | if (f2fs_sb_has_encrypt(sbi)) |
---|
113 | 135 | len += scnprintf(buf, PAGE_SIZE - len, "%s", |
---|
.. | .. |
---|
145 | 167 | if (f2fs_sb_has_casefold(sbi)) |
---|
146 | 168 | len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", |
---|
147 | 169 | len ? ", " : "", "casefold"); |
---|
| 170 | + if (f2fs_sb_has_readonly(sbi)) |
---|
| 171 | + len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", |
---|
| 172 | + len ? ", " : "", "readonly"); |
---|
148 | 173 | if (f2fs_sb_has_compression(sbi)) |
---|
149 | 174 | len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s", |
---|
150 | 175 | len ? ", " : "", "compression"); |
---|
.. | .. |
---|
225 | 250 | } |
---|
226 | 251 | #endif |
---|
227 | 252 | |
---|
| 253 | +static ssize_t main_blkaddr_show(struct f2fs_attr *a, |
---|
| 254 | + struct f2fs_sb_info *sbi, char *buf) |
---|
| 255 | +{ |
---|
| 256 | + return snprintf(buf, PAGE_SIZE, "%llu\n", |
---|
| 257 | + (unsigned long long)MAIN_BLKADDR(sbi)); |
---|
| 258 | +} |
---|
| 259 | + |
---|
228 | 260 | static ssize_t f2fs_sbi_show(struct f2fs_attr *a, |
---|
229 | 261 | struct f2fs_sb_info *sbi, char *buf) |
---|
230 | 262 | { |
---|
.. | .. |
---|
254 | 286 | len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n", |
---|
255 | 287 | extlist[i]); |
---|
256 | 288 | return len; |
---|
| 289 | + } |
---|
| 290 | + |
---|
| 291 | + if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { |
---|
| 292 | + struct ckpt_req_control *cprc = &sbi->cprc_info; |
---|
| 293 | + int len = 0; |
---|
| 294 | + int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio); |
---|
| 295 | + int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio); |
---|
| 296 | + |
---|
| 297 | + if (class == IOPRIO_CLASS_RT) |
---|
| 298 | + len += scnprintf(buf + len, PAGE_SIZE - len, "rt,"); |
---|
| 299 | + else if (class == IOPRIO_CLASS_BE) |
---|
| 300 | + len += scnprintf(buf + len, PAGE_SIZE - len, "be,"); |
---|
| 301 | + else |
---|
| 302 | + return -EINVAL; |
---|
| 303 | + |
---|
| 304 | + len += scnprintf(buf + len, PAGE_SIZE - len, "%d\n", data); |
---|
| 305 | + return len; |
---|
| 306 | + } |
---|
| 307 | + |
---|
| 308 | +#ifdef CONFIG_F2FS_FS_COMPRESSION |
---|
| 309 | + if (!strcmp(a->attr.name, "compr_written_block")) |
---|
| 310 | + return sysfs_emit(buf, "%llu\n", sbi->compr_written_block); |
---|
| 311 | + |
---|
| 312 | + if (!strcmp(a->attr.name, "compr_saved_block")) |
---|
| 313 | + return sysfs_emit(buf, "%llu\n", sbi->compr_saved_block); |
---|
| 314 | + |
---|
| 315 | + if (!strcmp(a->attr.name, "compr_new_inode")) |
---|
| 316 | + return sysfs_emit(buf, "%u\n", sbi->compr_new_inode); |
---|
| 317 | +#endif |
---|
| 318 | + |
---|
| 319 | + if (!strcmp(a->attr.name, "gc_segment_mode")) |
---|
| 320 | + return sysfs_emit(buf, "%u\n", sbi->gc_segment_mode); |
---|
| 321 | + |
---|
| 322 | + if (!strcmp(a->attr.name, "gc_reclaimed_segments")) { |
---|
| 323 | + return sysfs_emit(buf, "%u\n", |
---|
| 324 | + sbi->gc_reclaimed_segs[sbi->gc_segment_mode]); |
---|
257 | 325 | } |
---|
258 | 326 | |
---|
259 | 327 | ui = (unsigned int *)(ptr + a->offset); |
---|
.. | .. |
---|
295 | 363 | if (strlen(name) >= F2FS_EXTENSION_LEN) |
---|
296 | 364 | return -EINVAL; |
---|
297 | 365 | |
---|
298 | | - down_write(&sbi->sb_lock); |
---|
| 366 | + f2fs_down_write(&sbi->sb_lock); |
---|
299 | 367 | |
---|
300 | 368 | ret = f2fs_update_extension_list(sbi, name, hot, set); |
---|
301 | 369 | if (ret) |
---|
.. | .. |
---|
305 | 373 | if (ret) |
---|
306 | 374 | f2fs_update_extension_list(sbi, name, hot, !set); |
---|
307 | 375 | out: |
---|
308 | | - up_write(&sbi->sb_lock); |
---|
| 376 | + f2fs_up_write(&sbi->sb_lock); |
---|
309 | 377 | return ret ? ret : count; |
---|
| 378 | + } |
---|
| 379 | + |
---|
| 380 | + if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { |
---|
| 381 | + const char *name = strim((char *)buf); |
---|
| 382 | + struct ckpt_req_control *cprc = &sbi->cprc_info; |
---|
| 383 | + int class; |
---|
| 384 | + long data; |
---|
| 385 | + int ret; |
---|
| 386 | + |
---|
| 387 | + if (!strncmp(name, "rt,", 3)) |
---|
| 388 | + class = IOPRIO_CLASS_RT; |
---|
| 389 | + else if (!strncmp(name, "be,", 3)) |
---|
| 390 | + class = IOPRIO_CLASS_BE; |
---|
| 391 | + else |
---|
| 392 | + return -EINVAL; |
---|
| 393 | + |
---|
| 394 | + name += 3; |
---|
| 395 | + ret = kstrtol(name, 10, &data); |
---|
| 396 | + if (ret) |
---|
| 397 | + return ret; |
---|
| 398 | + if (data >= IOPRIO_BE_NR || data < 0) |
---|
| 399 | + return -EINVAL; |
---|
| 400 | + |
---|
| 401 | + cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, data); |
---|
| 402 | + if (test_opt(sbi, MERGE_CHECKPOINT)) { |
---|
| 403 | + ret = set_task_ioprio(cprc->f2fs_issue_ckpt, |
---|
| 404 | + cprc->ckpt_thread_ioprio); |
---|
| 405 | + if (ret) |
---|
| 406 | + return ret; |
---|
| 407 | + } |
---|
| 408 | + |
---|
| 409 | + return count; |
---|
310 | 410 | } |
---|
311 | 411 | |
---|
312 | 412 | ui = (unsigned int *)(ptr + a->offset); |
---|
.. | .. |
---|
323 | 423 | if (a->struct_type == RESERVED_BLOCKS) { |
---|
324 | 424 | spin_lock(&sbi->stat_lock); |
---|
325 | 425 | if (t > (unsigned long)(sbi->user_block_count - |
---|
326 | | - F2FS_OPTION(sbi).root_reserved_blocks)) { |
---|
| 426 | + F2FS_OPTION(sbi).root_reserved_blocks - |
---|
| 427 | + sbi->blocks_per_seg * |
---|
| 428 | + SM_I(sbi)->additional_reserved_segments)) { |
---|
327 | 429 | spin_unlock(&sbi->stat_lock); |
---|
328 | 430 | return -EINVAL; |
---|
329 | 431 | } |
---|
.. | .. |
---|
352 | 454 | return -EINVAL; |
---|
353 | 455 | |
---|
354 | 456 | if (!strcmp(a->attr.name, "gc_urgent")) { |
---|
355 | | - if (t >= 1) { |
---|
356 | | - sbi->gc_mode = GC_URGENT; |
---|
| 457 | + if (t == 0) { |
---|
| 458 | + sbi->gc_mode = GC_NORMAL; |
---|
| 459 | + } else if (t == 1) { |
---|
| 460 | + sbi->gc_mode = GC_URGENT_HIGH; |
---|
357 | 461 | if (sbi->gc_thread) { |
---|
358 | 462 | sbi->gc_thread->gc_wake = 1; |
---|
359 | 463 | wake_up_interruptible_all( |
---|
360 | 464 | &sbi->gc_thread->gc_wait_queue_head); |
---|
361 | 465 | wake_up_discard_thread(sbi, true); |
---|
362 | 466 | } |
---|
| 467 | + } else if (t == 2) { |
---|
| 468 | + sbi->gc_mode = GC_URGENT_LOW; |
---|
| 469 | + } else if (t == 3) { |
---|
| 470 | + sbi->gc_mode = GC_URGENT_MID; |
---|
| 471 | + if (sbi->gc_thread) { |
---|
| 472 | + sbi->gc_thread->gc_wake = 1; |
---|
| 473 | + wake_up_interruptible_all( |
---|
| 474 | + &sbi->gc_thread->gc_wait_queue_head); |
---|
| 475 | + } |
---|
363 | 476 | } else { |
---|
364 | | - sbi->gc_mode = GC_NORMAL; |
---|
| 477 | + return -EINVAL; |
---|
365 | 478 | } |
---|
366 | 479 | return count; |
---|
367 | 480 | } |
---|
368 | 481 | if (!strcmp(a->attr.name, "gc_idle")) { |
---|
369 | | - if (t == GC_IDLE_CB) |
---|
| 482 | + if (t == GC_IDLE_CB) { |
---|
370 | 483 | sbi->gc_mode = GC_IDLE_CB; |
---|
371 | | - else if (t == GC_IDLE_GREEDY) |
---|
| 484 | + } else if (t == GC_IDLE_GREEDY) { |
---|
372 | 485 | sbi->gc_mode = GC_IDLE_GREEDY; |
---|
373 | | - else |
---|
| 486 | + } else if (t == GC_IDLE_AT) { |
---|
| 487 | + if (!sbi->am.atgc_enabled) |
---|
| 488 | + return -EINVAL; |
---|
| 489 | + sbi->gc_mode = GC_IDLE_AT; |
---|
| 490 | + } else { |
---|
374 | 491 | sbi->gc_mode = GC_NORMAL; |
---|
| 492 | + } |
---|
375 | 493 | return count; |
---|
376 | 494 | } |
---|
377 | 495 | |
---|
.. | .. |
---|
385 | 503 | if (!strcmp(a->attr.name, "iostat_period_ms")) { |
---|
386 | 504 | if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS) |
---|
387 | 505 | return -EINVAL; |
---|
388 | | - spin_lock(&sbi->iostat_lock); |
---|
| 506 | + spin_lock_irq(&sbi->iostat_lock); |
---|
389 | 507 | sbi->iostat_period_ms = (unsigned int)t; |
---|
390 | | - spin_unlock(&sbi->iostat_lock); |
---|
| 508 | + spin_unlock_irq(&sbi->iostat_lock); |
---|
| 509 | + return count; |
---|
| 510 | + } |
---|
| 511 | + |
---|
| 512 | +#ifdef CONFIG_F2FS_FS_COMPRESSION |
---|
| 513 | + if (!strcmp(a->attr.name, "compr_written_block") || |
---|
| 514 | + !strcmp(a->attr.name, "compr_saved_block")) { |
---|
| 515 | + if (t != 0) |
---|
| 516 | + return -EINVAL; |
---|
| 517 | + sbi->compr_written_block = 0; |
---|
| 518 | + sbi->compr_saved_block = 0; |
---|
| 519 | + return count; |
---|
| 520 | + } |
---|
| 521 | + |
---|
| 522 | + if (!strcmp(a->attr.name, "compr_new_inode")) { |
---|
| 523 | + if (t != 0) |
---|
| 524 | + return -EINVAL; |
---|
| 525 | + sbi->compr_new_inode = 0; |
---|
| 526 | + return count; |
---|
| 527 | + } |
---|
| 528 | +#endif |
---|
| 529 | + |
---|
| 530 | + if (!strcmp(a->attr.name, "atgc_candidate_ratio")) { |
---|
| 531 | + if (t > 100) |
---|
| 532 | + return -EINVAL; |
---|
| 533 | + sbi->am.candidate_ratio = t; |
---|
| 534 | + return count; |
---|
| 535 | + } |
---|
| 536 | + |
---|
| 537 | + if (!strcmp(a->attr.name, "atgc_age_weight")) { |
---|
| 538 | + if (t > 100) |
---|
| 539 | + return -EINVAL; |
---|
| 540 | + sbi->am.age_weight = t; |
---|
| 541 | + return count; |
---|
| 542 | + } |
---|
| 543 | + |
---|
| 544 | + if (!strcmp(a->attr.name, "gc_segment_mode")) { |
---|
| 545 | + if (t < MAX_GC_MODE) |
---|
| 546 | + sbi->gc_segment_mode = t; |
---|
| 547 | + else |
---|
| 548 | + return -EINVAL; |
---|
| 549 | + return count; |
---|
| 550 | + } |
---|
| 551 | + |
---|
| 552 | + if (!strcmp(a->attr.name, "gc_reclaimed_segments")) { |
---|
| 553 | + if (t != 0) |
---|
| 554 | + return -EINVAL; |
---|
| 555 | + sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0; |
---|
| 556 | + return count; |
---|
| 557 | + } |
---|
| 558 | + |
---|
| 559 | + if (!strcmp(a->attr.name, "hot_data_age_threshold")) { |
---|
| 560 | + if (t == 0 || t >= sbi->warm_data_age_threshold) |
---|
| 561 | + return -EINVAL; |
---|
| 562 | + if (t == *ui) |
---|
| 563 | + return count; |
---|
| 564 | + *ui = (unsigned int)t; |
---|
| 565 | + return count; |
---|
| 566 | + } |
---|
| 567 | + |
---|
| 568 | + if (!strcmp(a->attr.name, "warm_data_age_threshold")) { |
---|
| 569 | + if (t == 0 || t <= sbi->hot_data_age_threshold) |
---|
| 570 | + return -EINVAL; |
---|
| 571 | + if (t == *ui) |
---|
| 572 | + return count; |
---|
| 573 | + *ui = (unsigned int)t; |
---|
| 574 | + return count; |
---|
| 575 | + } |
---|
| 576 | + |
---|
| 577 | + if (!strcmp(a->attr.name, "last_age_weight")) { |
---|
| 578 | + if (t > 100) |
---|
| 579 | + return -EINVAL; |
---|
| 580 | + if (t == *ui) |
---|
| 581 | + return count; |
---|
| 582 | + *ui = (unsigned int)t; |
---|
391 | 583 | return count; |
---|
392 | 584 | } |
---|
393 | 585 | |
---|
.. | .. |
---|
442 | 634 | complete(&sbi->s_kobj_unregister); |
---|
443 | 635 | } |
---|
444 | 636 | |
---|
445 | | -enum feat_id { |
---|
446 | | - FEAT_CRYPTO = 0, |
---|
447 | | - FEAT_BLKZONED, |
---|
448 | | - FEAT_ATOMIC_WRITE, |
---|
449 | | - FEAT_EXTRA_ATTR, |
---|
450 | | - FEAT_PROJECT_QUOTA, |
---|
451 | | - FEAT_INODE_CHECKSUM, |
---|
452 | | - FEAT_FLEXIBLE_INLINE_XATTR, |
---|
453 | | - FEAT_QUOTA_INO, |
---|
454 | | - FEAT_INODE_CRTIME, |
---|
455 | | - FEAT_LOST_FOUND, |
---|
456 | | - FEAT_VERITY, |
---|
457 | | - FEAT_SB_CHECKSUM, |
---|
458 | | - FEAT_CASEFOLD, |
---|
459 | | - FEAT_COMPRESSION, |
---|
460 | | - FEAT_TEST_DUMMY_ENCRYPTION_V2, |
---|
461 | | -}; |
---|
462 | | - |
---|
| 637 | +/* |
---|
| 638 | + * Note that there are three feature list entries: |
---|
| 639 | + * 1) /sys/fs/f2fs/features |
---|
| 640 | + * : shows runtime features supported by in-kernel f2fs along with Kconfig. |
---|
| 641 | + * - ref. F2FS_FEATURE_RO_ATTR() |
---|
| 642 | + * |
---|
| 643 | + * 2) /sys/fs/f2fs/$s_id/features <deprecated> |
---|
| 644 | + * : shows on-disk features enabled by mkfs.f2fs, used for old kernels. This |
---|
| 645 | + * won't add new feature anymore, and thus, users should check entries in 3) |
---|
| 646 | + * instead of this 2). |
---|
| 647 | + * |
---|
| 648 | + * 3) /sys/fs/f2fs/$s_id/feature_list |
---|
| 649 | + * : shows on-disk features enabled by mkfs.f2fs per instance, which follows |
---|
| 650 | + * sysfs entry rule where each entry should expose single value. |
---|
| 651 | + * This list covers old feature list provided by 2) and beyond. Therefore, |
---|
| 652 | + * please add new on-disk feature in this list only. |
---|
| 653 | + * - ref. F2FS_SB_FEATURE_RO_ATTR() |
---|
| 654 | + */ |
---|
463 | 655 | static ssize_t f2fs_feature_show(struct f2fs_attr *a, |
---|
464 | 656 | struct f2fs_sb_info *sbi, char *buf) |
---|
465 | 657 | { |
---|
466 | | - switch (a->id) { |
---|
467 | | - case FEAT_CRYPTO: |
---|
468 | | - case FEAT_BLKZONED: |
---|
469 | | - case FEAT_ATOMIC_WRITE: |
---|
470 | | - case FEAT_EXTRA_ATTR: |
---|
471 | | - case FEAT_PROJECT_QUOTA: |
---|
472 | | - case FEAT_INODE_CHECKSUM: |
---|
473 | | - case FEAT_FLEXIBLE_INLINE_XATTR: |
---|
474 | | - case FEAT_QUOTA_INO: |
---|
475 | | - case FEAT_INODE_CRTIME: |
---|
476 | | - case FEAT_LOST_FOUND: |
---|
477 | | - case FEAT_VERITY: |
---|
478 | | - case FEAT_SB_CHECKSUM: |
---|
479 | | - case FEAT_CASEFOLD: |
---|
480 | | - case FEAT_COMPRESSION: |
---|
481 | | - case FEAT_TEST_DUMMY_ENCRYPTION_V2: |
---|
| 658 | + return sprintf(buf, "supported\n"); |
---|
| 659 | +} |
---|
| 660 | + |
---|
| 661 | +#define F2FS_FEATURE_RO_ATTR(_name) \ |
---|
| 662 | +static struct f2fs_attr f2fs_attr_##_name = { \ |
---|
| 663 | + .attr = {.name = __stringify(_name), .mode = 0444 }, \ |
---|
| 664 | + .show = f2fs_feature_show, \ |
---|
| 665 | +} |
---|
| 666 | + |
---|
| 667 | +static ssize_t f2fs_sb_feature_show(struct f2fs_attr *a, |
---|
| 668 | + struct f2fs_sb_info *sbi, char *buf) |
---|
| 669 | +{ |
---|
| 670 | + if (F2FS_HAS_FEATURE(sbi, a->id)) |
---|
482 | 671 | return sprintf(buf, "supported\n"); |
---|
483 | | - } |
---|
484 | | - return 0; |
---|
| 672 | + return sprintf(buf, "unsupported\n"); |
---|
| 673 | +} |
---|
| 674 | + |
---|
| 675 | +#define F2FS_SB_FEATURE_RO_ATTR(_name, _feat) \ |
---|
| 676 | +static struct f2fs_attr f2fs_attr_sb_##_name = { \ |
---|
| 677 | + .attr = {.name = __stringify(_name), .mode = 0444 }, \ |
---|
| 678 | + .show = f2fs_sb_feature_show, \ |
---|
| 679 | + .id = F2FS_FEATURE_##_feat, \ |
---|
485 | 680 | } |
---|
486 | 681 | |
---|
487 | 682 | #define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \ |
---|
.. | .. |
---|
501 | 696 | #define F2FS_GENERAL_RO_ATTR(name) \ |
---|
502 | 697 | static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL) |
---|
503 | 698 | |
---|
504 | | -#define F2FS_FEATURE_RO_ATTR(_name, _id) \ |
---|
505 | | -static struct f2fs_attr f2fs_attr_##_name = { \ |
---|
506 | | - .attr = {.name = __stringify(_name), .mode = 0444 }, \ |
---|
507 | | - .show = f2fs_feature_show, \ |
---|
508 | | - .id = _id, \ |
---|
509 | | -} |
---|
510 | | - |
---|
511 | 699 | #define F2FS_STAT_ATTR(_struct_type, _struct_name, _name, _elname) \ |
---|
512 | 700 | static struct f2fs_attr f2fs_attr_##_name = { \ |
---|
513 | 701 | .attr = {.name = __stringify(_name), .mode = 0444 }, \ |
---|
.. | .. |
---|
524 | 712 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode); |
---|
525 | 713 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode); |
---|
526 | 714 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); |
---|
527 | | -F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, main_blkaddr, main_blkaddr); |
---|
528 | 715 | F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards); |
---|
529 | 716 | F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity); |
---|
530 | 717 | F2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, reserved_blocks, reserved_blocks); |
---|
.. | .. |
---|
551 | 738 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); |
---|
552 | 739 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_period_ms, iostat_period_ms); |
---|
553 | 740 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra); |
---|
| 741 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_io_bytes, max_io_bytes); |
---|
554 | 742 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold); |
---|
555 | 743 | F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list); |
---|
556 | 744 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
---|
.. | .. |
---|
559 | 747 | #endif |
---|
560 | 748 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag); |
---|
561 | 749 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, node_io_flag, node_io_flag); |
---|
| 750 | +F2FS_RW_ATTR(CPRC_INFO, ckpt_req_control, ckpt_thread_ioprio, ckpt_thread_ioprio); |
---|
562 | 751 | F2FS_GENERAL_RO_ATTR(dirty_segments); |
---|
563 | 752 | F2FS_GENERAL_RO_ATTR(free_segments); |
---|
| 753 | +F2FS_GENERAL_RO_ATTR(ovp_segments); |
---|
564 | 754 | F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes); |
---|
565 | 755 | F2FS_GENERAL_RO_ATTR(features); |
---|
566 | 756 | F2FS_GENERAL_RO_ATTR(current_reserved_blocks); |
---|
567 | 757 | F2FS_GENERAL_RO_ATTR(unusable); |
---|
568 | 758 | F2FS_GENERAL_RO_ATTR(encoding); |
---|
569 | 759 | F2FS_GENERAL_RO_ATTR(mounted_time_sec); |
---|
| 760 | +F2FS_GENERAL_RO_ATTR(main_blkaddr); |
---|
| 761 | +F2FS_GENERAL_RO_ATTR(pending_discard); |
---|
570 | 762 | #ifdef CONFIG_F2FS_STAT_FS |
---|
571 | 763 | F2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, cp_foreground_calls, cp_count); |
---|
572 | 764 | F2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, cp_background_calls, bg_cp_count); |
---|
.. | .. |
---|
578 | 770 | #endif |
---|
579 | 771 | |
---|
580 | 772 | #ifdef CONFIG_FS_ENCRYPTION |
---|
581 | | -F2FS_FEATURE_RO_ATTR(encryption, FEAT_CRYPTO); |
---|
582 | | -F2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2, FEAT_TEST_DUMMY_ENCRYPTION_V2); |
---|
| 773 | +F2FS_FEATURE_RO_ATTR(encryption); |
---|
| 774 | +F2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2); |
---|
| 775 | +#ifdef CONFIG_UNICODE |
---|
| 776 | +F2FS_FEATURE_RO_ATTR(encrypted_casefold); |
---|
583 | 777 | #endif |
---|
| 778 | +#endif /* CONFIG_FS_ENCRYPTION */ |
---|
584 | 779 | #ifdef CONFIG_BLK_DEV_ZONED |
---|
585 | | -F2FS_FEATURE_RO_ATTR(block_zoned, FEAT_BLKZONED); |
---|
| 780 | +F2FS_FEATURE_RO_ATTR(block_zoned); |
---|
586 | 781 | #endif |
---|
587 | | -F2FS_FEATURE_RO_ATTR(atomic_write, FEAT_ATOMIC_WRITE); |
---|
588 | | -F2FS_FEATURE_RO_ATTR(extra_attr, FEAT_EXTRA_ATTR); |
---|
589 | | -F2FS_FEATURE_RO_ATTR(project_quota, FEAT_PROJECT_QUOTA); |
---|
590 | | -F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM); |
---|
591 | | -F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); |
---|
592 | | -F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); |
---|
593 | | -F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); |
---|
594 | | -F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); |
---|
| 782 | +F2FS_FEATURE_RO_ATTR(atomic_write); |
---|
| 783 | +F2FS_FEATURE_RO_ATTR(extra_attr); |
---|
| 784 | +F2FS_FEATURE_RO_ATTR(project_quota); |
---|
| 785 | +F2FS_FEATURE_RO_ATTR(inode_checksum); |
---|
| 786 | +F2FS_FEATURE_RO_ATTR(flexible_inline_xattr); |
---|
| 787 | +F2FS_FEATURE_RO_ATTR(quota_ino); |
---|
| 788 | +F2FS_FEATURE_RO_ATTR(inode_crtime); |
---|
| 789 | +F2FS_FEATURE_RO_ATTR(lost_found); |
---|
595 | 790 | #ifdef CONFIG_FS_VERITY |
---|
596 | | -F2FS_FEATURE_RO_ATTR(verity, FEAT_VERITY); |
---|
| 791 | +F2FS_FEATURE_RO_ATTR(verity); |
---|
597 | 792 | #endif |
---|
598 | | -F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM); |
---|
599 | | -F2FS_FEATURE_RO_ATTR(casefold, FEAT_CASEFOLD); |
---|
| 793 | +F2FS_FEATURE_RO_ATTR(sb_checksum); |
---|
| 794 | +#ifdef CONFIG_UNICODE |
---|
| 795 | +F2FS_FEATURE_RO_ATTR(casefold); |
---|
| 796 | +#endif |
---|
| 797 | +F2FS_FEATURE_RO_ATTR(readonly); |
---|
600 | 798 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
---|
601 | | -F2FS_FEATURE_RO_ATTR(compression, FEAT_COMPRESSION); |
---|
| 799 | +F2FS_FEATURE_RO_ATTR(compression); |
---|
| 800 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block); |
---|
| 801 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block); |
---|
| 802 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_new_inode, compr_new_inode); |
---|
602 | 803 | #endif |
---|
| 804 | +F2FS_FEATURE_RO_ATTR(pin_file); |
---|
| 805 | + |
---|
| 806 | +/* For ATGC */ |
---|
| 807 | +F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_ratio, candidate_ratio); |
---|
| 808 | +F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_count, max_candidate_count); |
---|
| 809 | +F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_weight, age_weight); |
---|
| 810 | +F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_threshold, age_threshold); |
---|
| 811 | + |
---|
| 812 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_segment_mode, gc_segment_mode); |
---|
| 813 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_reclaimed_segments, gc_reclaimed_segs); |
---|
| 814 | + |
---|
| 815 | +/* For block age extent cache */ |
---|
| 816 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, hot_data_age_threshold, hot_data_age_threshold); |
---|
| 817 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, warm_data_age_threshold, warm_data_age_threshold); |
---|
| 818 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, last_age_weight, last_age_weight); |
---|
603 | 819 | |
---|
604 | 820 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) |
---|
605 | 821 | static struct attribute *f2fs_attrs[] = { |
---|
.. | .. |
---|
613 | 829 | ATTR_LIST(main_blkaddr), |
---|
614 | 830 | ATTR_LIST(max_small_discards), |
---|
615 | 831 | ATTR_LIST(discard_granularity), |
---|
| 832 | + ATTR_LIST(pending_discard), |
---|
616 | 833 | ATTR_LIST(batched_trim_sections), |
---|
617 | 834 | ATTR_LIST(ipu_policy), |
---|
618 | 835 | ATTR_LIST(min_ipu_util), |
---|
.. | .. |
---|
634 | 851 | ATTR_LIST(iostat_enable), |
---|
635 | 852 | ATTR_LIST(iostat_period_ms), |
---|
636 | 853 | ATTR_LIST(readdir_ra), |
---|
| 854 | + ATTR_LIST(max_io_bytes), |
---|
637 | 855 | ATTR_LIST(gc_pin_file_thresh), |
---|
638 | 856 | ATTR_LIST(extension_list), |
---|
639 | 857 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
---|
.. | .. |
---|
642 | 860 | #endif |
---|
643 | 861 | ATTR_LIST(data_io_flag), |
---|
644 | 862 | ATTR_LIST(node_io_flag), |
---|
| 863 | + ATTR_LIST(ckpt_thread_ioprio), |
---|
645 | 864 | ATTR_LIST(dirty_segments), |
---|
646 | 865 | ATTR_LIST(free_segments), |
---|
| 866 | + ATTR_LIST(ovp_segments), |
---|
647 | 867 | ATTR_LIST(unusable), |
---|
648 | 868 | ATTR_LIST(lifetime_write_kbytes), |
---|
649 | 869 | ATTR_LIST(features), |
---|
.. | .. |
---|
660 | 880 | ATTR_LIST(moved_blocks_background), |
---|
661 | 881 | ATTR_LIST(avg_vblocks), |
---|
662 | 882 | #endif |
---|
| 883 | +#ifdef CONFIG_F2FS_FS_COMPRESSION |
---|
| 884 | + ATTR_LIST(compr_written_block), |
---|
| 885 | + ATTR_LIST(compr_saved_block), |
---|
| 886 | + ATTR_LIST(compr_new_inode), |
---|
| 887 | +#endif |
---|
| 888 | + /* For ATGC */ |
---|
| 889 | + ATTR_LIST(atgc_candidate_ratio), |
---|
| 890 | + ATTR_LIST(atgc_candidate_count), |
---|
| 891 | + ATTR_LIST(atgc_age_weight), |
---|
| 892 | + ATTR_LIST(atgc_age_threshold), |
---|
| 893 | + ATTR_LIST(gc_segment_mode), |
---|
| 894 | + ATTR_LIST(gc_reclaimed_segments), |
---|
| 895 | + ATTR_LIST(hot_data_age_threshold), |
---|
| 896 | + ATTR_LIST(warm_data_age_threshold), |
---|
| 897 | + ATTR_LIST(last_age_weight), |
---|
663 | 898 | NULL, |
---|
664 | 899 | }; |
---|
| 900 | +ATTRIBUTE_GROUPS(f2fs); |
---|
665 | 901 | |
---|
666 | 902 | static struct attribute *f2fs_feat_attrs[] = { |
---|
667 | 903 | #ifdef CONFIG_FS_ENCRYPTION |
---|
668 | 904 | ATTR_LIST(encryption), |
---|
669 | 905 | ATTR_LIST(test_dummy_encryption_v2), |
---|
| 906 | +#ifdef CONFIG_UNICODE |
---|
| 907 | + ATTR_LIST(encrypted_casefold), |
---|
670 | 908 | #endif |
---|
| 909 | +#endif /* CONFIG_FS_ENCRYPTION */ |
---|
671 | 910 | #ifdef CONFIG_BLK_DEV_ZONED |
---|
672 | 911 | ATTR_LIST(block_zoned), |
---|
673 | 912 | #endif |
---|
.. | .. |
---|
683 | 922 | ATTR_LIST(verity), |
---|
684 | 923 | #endif |
---|
685 | 924 | ATTR_LIST(sb_checksum), |
---|
| 925 | +#ifdef CONFIG_UNICODE |
---|
686 | 926 | ATTR_LIST(casefold), |
---|
| 927 | +#endif |
---|
| 928 | + ATTR_LIST(readonly), |
---|
687 | 929 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
---|
688 | 930 | ATTR_LIST(compression), |
---|
689 | 931 | #endif |
---|
| 932 | + ATTR_LIST(pin_file), |
---|
690 | 933 | NULL, |
---|
691 | 934 | }; |
---|
| 935 | +ATTRIBUTE_GROUPS(f2fs_feat); |
---|
| 936 | + |
---|
| 937 | +F2FS_GENERAL_RO_ATTR(sb_status); |
---|
| 938 | +static struct attribute *f2fs_stat_attrs[] = { |
---|
| 939 | + ATTR_LIST(sb_status), |
---|
| 940 | + NULL, |
---|
| 941 | +}; |
---|
| 942 | +ATTRIBUTE_GROUPS(f2fs_stat); |
---|
| 943 | + |
---|
| 944 | +F2FS_SB_FEATURE_RO_ATTR(encryption, ENCRYPT); |
---|
| 945 | +F2FS_SB_FEATURE_RO_ATTR(block_zoned, BLKZONED); |
---|
| 946 | +F2FS_SB_FEATURE_RO_ATTR(extra_attr, EXTRA_ATTR); |
---|
| 947 | +F2FS_SB_FEATURE_RO_ATTR(project_quota, PRJQUOTA); |
---|
| 948 | +F2FS_SB_FEATURE_RO_ATTR(inode_checksum, INODE_CHKSUM); |
---|
| 949 | +F2FS_SB_FEATURE_RO_ATTR(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR); |
---|
| 950 | +F2FS_SB_FEATURE_RO_ATTR(quota_ino, QUOTA_INO); |
---|
| 951 | +F2FS_SB_FEATURE_RO_ATTR(inode_crtime, INODE_CRTIME); |
---|
| 952 | +F2FS_SB_FEATURE_RO_ATTR(lost_found, LOST_FOUND); |
---|
| 953 | +F2FS_SB_FEATURE_RO_ATTR(verity, VERITY); |
---|
| 954 | +F2FS_SB_FEATURE_RO_ATTR(sb_checksum, SB_CHKSUM); |
---|
| 955 | +F2FS_SB_FEATURE_RO_ATTR(casefold, CASEFOLD); |
---|
| 956 | +F2FS_SB_FEATURE_RO_ATTR(compression, COMPRESSION); |
---|
| 957 | +F2FS_SB_FEATURE_RO_ATTR(readonly, RO); |
---|
| 958 | + |
---|
| 959 | +static struct attribute *f2fs_sb_feat_attrs[] = { |
---|
| 960 | + ATTR_LIST(sb_encryption), |
---|
| 961 | + ATTR_LIST(sb_block_zoned), |
---|
| 962 | + ATTR_LIST(sb_extra_attr), |
---|
| 963 | + ATTR_LIST(sb_project_quota), |
---|
| 964 | + ATTR_LIST(sb_inode_checksum), |
---|
| 965 | + ATTR_LIST(sb_flexible_inline_xattr), |
---|
| 966 | + ATTR_LIST(sb_quota_ino), |
---|
| 967 | + ATTR_LIST(sb_inode_crtime), |
---|
| 968 | + ATTR_LIST(sb_lost_found), |
---|
| 969 | + ATTR_LIST(sb_verity), |
---|
| 970 | + ATTR_LIST(sb_sb_checksum), |
---|
| 971 | + ATTR_LIST(sb_casefold), |
---|
| 972 | + ATTR_LIST(sb_compression), |
---|
| 973 | + ATTR_LIST(sb_readonly), |
---|
| 974 | + NULL, |
---|
| 975 | +}; |
---|
| 976 | +ATTRIBUTE_GROUPS(f2fs_sb_feat); |
---|
692 | 977 | |
---|
693 | 978 | static const struct sysfs_ops f2fs_attr_ops = { |
---|
694 | 979 | .show = f2fs_attr_show, |
---|
.. | .. |
---|
696 | 981 | }; |
---|
697 | 982 | |
---|
698 | 983 | static struct kobj_type f2fs_sb_ktype = { |
---|
699 | | - .default_attrs = f2fs_attrs, |
---|
| 984 | + .default_groups = f2fs_groups, |
---|
700 | 985 | .sysfs_ops = &f2fs_attr_ops, |
---|
701 | 986 | .release = f2fs_sb_release, |
---|
702 | 987 | }; |
---|
.. | .. |
---|
706 | 991 | }; |
---|
707 | 992 | |
---|
708 | 993 | static struct kset f2fs_kset = { |
---|
709 | | - .kobj = {.ktype = &f2fs_ktype}, |
---|
| 994 | + .kobj = {.ktype = &f2fs_ktype}, |
---|
710 | 995 | }; |
---|
711 | 996 | |
---|
712 | 997 | static struct kobj_type f2fs_feat_ktype = { |
---|
713 | | - .default_attrs = f2fs_feat_attrs, |
---|
| 998 | + .default_groups = f2fs_feat_groups, |
---|
714 | 999 | .sysfs_ops = &f2fs_attr_ops, |
---|
715 | 1000 | }; |
---|
716 | 1001 | |
---|
717 | 1002 | static struct kobject f2fs_feat = { |
---|
718 | 1003 | .kset = &f2fs_kset, |
---|
| 1004 | +}; |
---|
| 1005 | + |
---|
| 1006 | +static ssize_t f2fs_stat_attr_show(struct kobject *kobj, |
---|
| 1007 | + struct attribute *attr, char *buf) |
---|
| 1008 | +{ |
---|
| 1009 | + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, |
---|
| 1010 | + s_stat_kobj); |
---|
| 1011 | + struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); |
---|
| 1012 | + |
---|
| 1013 | + return a->show ? a->show(a, sbi, buf) : 0; |
---|
| 1014 | +} |
---|
| 1015 | + |
---|
| 1016 | +static ssize_t f2fs_stat_attr_store(struct kobject *kobj, struct attribute *attr, |
---|
| 1017 | + const char *buf, size_t len) |
---|
| 1018 | +{ |
---|
| 1019 | + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, |
---|
| 1020 | + s_stat_kobj); |
---|
| 1021 | + struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); |
---|
| 1022 | + |
---|
| 1023 | + return a->store ? a->store(a, sbi, buf, len) : 0; |
---|
| 1024 | +} |
---|
| 1025 | + |
---|
| 1026 | +static void f2fs_stat_kobj_release(struct kobject *kobj) |
---|
| 1027 | +{ |
---|
| 1028 | + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, |
---|
| 1029 | + s_stat_kobj); |
---|
| 1030 | + complete(&sbi->s_stat_kobj_unregister); |
---|
| 1031 | +} |
---|
| 1032 | + |
---|
| 1033 | +static const struct sysfs_ops f2fs_stat_attr_ops = { |
---|
| 1034 | + .show = f2fs_stat_attr_show, |
---|
| 1035 | + .store = f2fs_stat_attr_store, |
---|
| 1036 | +}; |
---|
| 1037 | + |
---|
| 1038 | +static struct kobj_type f2fs_stat_ktype = { |
---|
| 1039 | + .default_groups = f2fs_stat_groups, |
---|
| 1040 | + .sysfs_ops = &f2fs_stat_attr_ops, |
---|
| 1041 | + .release = f2fs_stat_kobj_release, |
---|
| 1042 | +}; |
---|
| 1043 | + |
---|
| 1044 | +static ssize_t f2fs_sb_feat_attr_show(struct kobject *kobj, |
---|
| 1045 | + struct attribute *attr, char *buf) |
---|
| 1046 | +{ |
---|
| 1047 | + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, |
---|
| 1048 | + s_feature_list_kobj); |
---|
| 1049 | + struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); |
---|
| 1050 | + |
---|
| 1051 | + return a->show ? a->show(a, sbi, buf) : 0; |
---|
| 1052 | +} |
---|
| 1053 | + |
---|
| 1054 | +static void f2fs_feature_list_kobj_release(struct kobject *kobj) |
---|
| 1055 | +{ |
---|
| 1056 | + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, |
---|
| 1057 | + s_feature_list_kobj); |
---|
| 1058 | + complete(&sbi->s_feature_list_kobj_unregister); |
---|
| 1059 | +} |
---|
| 1060 | + |
---|
| 1061 | +static const struct sysfs_ops f2fs_feature_list_attr_ops = { |
---|
| 1062 | + .show = f2fs_sb_feat_attr_show, |
---|
| 1063 | +}; |
---|
| 1064 | + |
---|
| 1065 | +static struct kobj_type f2fs_feature_list_ktype = { |
---|
| 1066 | + .default_groups = f2fs_sb_feat_groups, |
---|
| 1067 | + .sysfs_ops = &f2fs_feature_list_attr_ops, |
---|
| 1068 | + .release = f2fs_feature_list_kobj_release, |
---|
719 | 1069 | }; |
---|
720 | 1070 | |
---|
721 | 1071 | static int __maybe_unused segment_info_seq_show(struct seq_file *seq, |
---|
.. | .. |
---|
924 | 1274 | init_completion(&sbi->s_kobj_unregister); |
---|
925 | 1275 | err = kobject_init_and_add(&sbi->s_kobj, &f2fs_sb_ktype, NULL, |
---|
926 | 1276 | "%s", sb->s_id); |
---|
927 | | - if (err) { |
---|
928 | | - kobject_put(&sbi->s_kobj); |
---|
929 | | - wait_for_completion(&sbi->s_kobj_unregister); |
---|
930 | | - return err; |
---|
931 | | - } |
---|
| 1277 | + if (err) |
---|
| 1278 | + goto put_sb_kobj; |
---|
| 1279 | + |
---|
| 1280 | + sbi->s_stat_kobj.kset = &f2fs_kset; |
---|
| 1281 | + init_completion(&sbi->s_stat_kobj_unregister); |
---|
| 1282 | + err = kobject_init_and_add(&sbi->s_stat_kobj, &f2fs_stat_ktype, |
---|
| 1283 | + &sbi->s_kobj, "stat"); |
---|
| 1284 | + if (err) |
---|
| 1285 | + goto put_stat_kobj; |
---|
| 1286 | + |
---|
| 1287 | + sbi->s_feature_list_kobj.kset = &f2fs_kset; |
---|
| 1288 | + init_completion(&sbi->s_feature_list_kobj_unregister); |
---|
| 1289 | + err = kobject_init_and_add(&sbi->s_feature_list_kobj, |
---|
| 1290 | + &f2fs_feature_list_ktype, |
---|
| 1291 | + &sbi->s_kobj, "feature_list"); |
---|
| 1292 | + if (err) |
---|
| 1293 | + goto put_feature_list_kobj; |
---|
932 | 1294 | |
---|
933 | 1295 | if (f2fs_proc_root) |
---|
934 | 1296 | sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); |
---|
.. | .. |
---|
944 | 1306 | victim_bits_seq_show, sb); |
---|
945 | 1307 | } |
---|
946 | 1308 | return 0; |
---|
| 1309 | +put_feature_list_kobj: |
---|
| 1310 | + kobject_put(&sbi->s_feature_list_kobj); |
---|
| 1311 | + wait_for_completion(&sbi->s_feature_list_kobj_unregister); |
---|
| 1312 | +put_stat_kobj: |
---|
| 1313 | + kobject_put(&sbi->s_stat_kobj); |
---|
| 1314 | + wait_for_completion(&sbi->s_stat_kobj_unregister); |
---|
| 1315 | +put_sb_kobj: |
---|
| 1316 | + kobject_put(&sbi->s_kobj); |
---|
| 1317 | + wait_for_completion(&sbi->s_kobj_unregister); |
---|
| 1318 | + return err; |
---|
947 | 1319 | } |
---|
948 | 1320 | |
---|
949 | 1321 | void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) |
---|
.. | .. |
---|
955 | 1327 | remove_proc_entry("victim_bits", sbi->s_proc); |
---|
956 | 1328 | remove_proc_entry(sbi->sb->s_id, f2fs_proc_root); |
---|
957 | 1329 | } |
---|
| 1330 | + |
---|
| 1331 | + kobject_del(&sbi->s_stat_kobj); |
---|
| 1332 | + kobject_put(&sbi->s_stat_kobj); |
---|
| 1333 | + wait_for_completion(&sbi->s_stat_kobj_unregister); |
---|
| 1334 | + kobject_del(&sbi->s_feature_list_kobj); |
---|
| 1335 | + kobject_put(&sbi->s_feature_list_kobj); |
---|
| 1336 | + wait_for_completion(&sbi->s_feature_list_kobj_unregister); |
---|
| 1337 | + |
---|
958 | 1338 | kobject_del(&sbi->s_kobj); |
---|
959 | 1339 | kobject_put(&sbi->s_kobj); |
---|
960 | 1340 | wait_for_completion(&sbi->s_kobj_unregister); |
---|