Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ext4: move sysfs code from super.c to fs/ext4/sysfs.c

Also statically allocate the ext4_kset and ext4_feat objects, since we
only need exactly one of each, and it's simpler and less code if we
drop the dynamic allocation and deallocation when it's not needed.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>

+410 -410
+1 -1
fs/ext4/Makefile
··· 8 8 ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ 9 9 ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ 10 10 mmp.o indirect.o extents_status.o xattr.o xattr_user.o \ 11 - xattr_trusted.o inline.o readpage.o 11 + xattr_trusted.o inline.o readpage.o sysfs.o 12 12 13 13 ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o 14 14 ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
+5
fs/ext4/ext4.h
··· 2903 2903 extern const struct inode_operations ext4_symlink_inode_operations; 2904 2904 extern const struct inode_operations ext4_fast_symlink_inode_operations; 2905 2905 2906 + /* sysfs.c */ 2907 + extern int ext4_register_sysfs(struct super_block *sb); 2908 + extern int __init ext4_init_sysfs(void); 2909 + extern void ext4_exit_sysfs(void); 2910 + 2906 2911 /* block_validity */ 2907 2912 extern void ext4_release_system_zone(struct super_block *sb); 2908 2913 extern int ext4_setup_system_zone(struct super_block *sb);
+17 -409
fs/ext4/super.c
··· 55 55 #include <trace/events/ext4.h> 56 56 57 57 static struct proc_dir_entry *ext4_proc_root; 58 - static struct kset *ext4_kset; 59 58 static struct ext4_lazy_init *ext4_li_info; 60 59 static struct mutex ext4_li_mtx; 61 - static struct ext4_features *ext4_feat; 62 60 static int ext4_mballoc_ready; 63 61 static struct ratelimit_state ext4_mount_msg_ratelimit; 64 62 ··· 81 83 static void ext4_destroy_lazyinit_thread(void); 82 84 static void ext4_unregister_li_request(struct super_block *sb); 83 85 static void ext4_clear_request_list(void); 84 - static int ext4_reserve_clusters(struct ext4_sb_info *, ext4_fsblk_t); 85 86 86 87 #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) 87 88 static struct file_system_type ext2_fs_type = { ··· 2467 2470 return ret; 2468 2471 } 2469 2472 2470 - /* sysfs supprt */ 2471 - 2472 - struct ext4_attr { 2473 - struct attribute attr; 2474 - ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *); 2475 - ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, 2476 - const char *, size_t); 2477 - union { 2478 - int offset; 2479 - int deprecated_val; 2480 - } u; 2481 - }; 2482 - 2483 - static int parse_strtoull(const char *buf, 2484 - unsigned long long max, unsigned long long *value) 2485 - { 2486 - int ret; 2487 - 2488 - ret = kstrtoull(skip_spaces(buf), 0, value); 2489 - if (!ret && *value > max) 2490 - ret = -EINVAL; 2491 - return ret; 2492 - } 2493 - 2494 - static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a, 2495 - struct ext4_sb_info *sbi, 2496 - char *buf) 2497 - { 2498 - return snprintf(buf, PAGE_SIZE, "%llu\n", 2499 - (s64) EXT4_C2B(sbi, 2500 - percpu_counter_sum(&sbi->s_dirtyclusters_counter))); 2501 - } 2502 - 2503 - static ssize_t session_write_kbytes_show(struct ext4_attr *a, 2504 - struct ext4_sb_info *sbi, char *buf) 2505 - { 2506 - struct super_block *sb = sbi->s_buddy_cache->i_sb; 2507 - 2508 - if (!sb->s_bdev->bd_part) 2509 - return snprintf(buf, PAGE_SIZE, "0\n"); 2510 - return snprintf(buf, PAGE_SIZE, "%lu\n", 2511 - (part_stat_read(sb->s_bdev->bd_part, sectors[1]) - 2512 - sbi->s_sectors_written_start) >> 1); 2513 - } 2514 - 2515 - static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, 2516 - struct ext4_sb_info *sbi, char *buf) 2517 - { 2518 - struct super_block *sb = sbi->s_buddy_cache->i_sb; 2519 - 2520 - if (!sb->s_bdev->bd_part) 2521 - return snprintf(buf, PAGE_SIZE, "0\n"); 2522 - return snprintf(buf, PAGE_SIZE, "%llu\n", 2523 - (unsigned long long)(sbi->s_kbytes_written + 2524 - ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - 2525 - EXT4_SB(sb)->s_sectors_written_start) >> 1))); 2526 - } 2527 - 2528 - static ssize_t inode_readahead_blks_store(struct ext4_attr *a, 2529 - struct ext4_sb_info *sbi, 2530 - const char *buf, size_t count) 2531 - { 2532 - unsigned long t; 2533 - int ret; 2534 - 2535 - ret = kstrtoul(skip_spaces(buf), 0, &t); 2536 - if (ret) 2537 - return ret; 2538 - 2539 - if (t && (!is_power_of_2(t) || t > 0x40000000)) 2540 - return -EINVAL; 2541 - 2542 - sbi->s_inode_readahead_blks = t; 2543 - return count; 2544 - } 2545 - 2546 - static ssize_t sbi_ui_show(struct ext4_attr *a, 2547 - struct ext4_sb_info *sbi, char *buf) 2548 - { 2549 - unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset); 2550 - 2551 - return snprintf(buf, PAGE_SIZE, "%u\n", *ui); 2552 - } 2553 - 2554 - static ssize_t sbi_ui_store(struct ext4_attr *a, 2555 - struct ext4_sb_info *sbi, 2556 - const char *buf, size_t count) 2557 - { 2558 - unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset); 2559 - unsigned long t; 2560 - int ret; 2561 - 2562 - ret = kstrtoul(skip_spaces(buf), 0, &t); 2563 - if (ret) 2564 - return ret; 2565 - *ui = t; 2566 - return count; 2567 - } 2568 - 2569 - static ssize_t es_ui_show(struct ext4_attr *a, 2570 - struct ext4_sb_info *sbi, char *buf) 2571 - { 2572 - 2573 - unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) + 2574 - a->u.offset); 2575 - 2576 - return snprintf(buf, PAGE_SIZE, "%u\n", *ui); 2577 - } 2578 - 2579 - static ssize_t reserved_clusters_show(struct ext4_attr *a, 2580 - struct ext4_sb_info *sbi, char *buf) 2581 - { 2582 - return snprintf(buf, PAGE_SIZE, "%llu\n", 2583 - (unsigned long long) atomic64_read(&sbi->s_resv_clusters)); 2584 - } 2585 - 2586 - static ssize_t reserved_clusters_store(struct ext4_attr *a, 2587 - struct ext4_sb_info *sbi, 2588 - const char *buf, size_t count) 2589 - { 2590 - unsigned long long val; 2591 - int ret; 2592 - 2593 - if (parse_strtoull(buf, -1ULL, &val)) 2594 - return -EINVAL; 2595 - ret = ext4_reserve_clusters(sbi, val); 2596 - 2597 - return ret ? ret : count; 2598 - } 2599 - 2600 - static ssize_t trigger_test_error(struct ext4_attr *a, 2601 - struct ext4_sb_info *sbi, 2602 - const char *buf, size_t count) 2603 - { 2604 - int len = count; 2605 - 2606 - if (!capable(CAP_SYS_ADMIN)) 2607 - return -EPERM; 2608 - 2609 - if (len && buf[len-1] == '\n') 2610 - len--; 2611 - 2612 - if (len) 2613 - ext4_error(sbi->s_sb, "%.*s", len, buf); 2614 - return count; 2615 - } 2616 - 2617 - static ssize_t sbi_deprecated_show(struct ext4_attr *a, 2618 - struct ext4_sb_info *sbi, char *buf) 2619 - { 2620 - return snprintf(buf, PAGE_SIZE, "%d\n", a->u.deprecated_val); 2621 - } 2622 - 2623 - #define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \ 2624 - static struct ext4_attr ext4_attr_##_name = { \ 2625 - .attr = {.name = __stringify(_name), .mode = _mode }, \ 2626 - .show = _show, \ 2627 - .store = _store, \ 2628 - .u = { \ 2629 - .offset = offsetof(struct ext4_sb_info, _elname),\ 2630 - }, \ 2631 - } 2632 - 2633 - #define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname) \ 2634 - static struct ext4_attr ext4_attr_##_name = { \ 2635 - .attr = {.name = __stringify(_name), .mode = _mode }, \ 2636 - .show = _show, \ 2637 - .store = _store, \ 2638 - .u = { \ 2639 - .offset = offsetof(struct ext4_super_block, _elname), \ 2640 - }, \ 2641 - } 2642 - 2643 - #define EXT4_ATTR(name, mode, show, store) \ 2644 - static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) 2645 - 2646 - #define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL) 2647 - #define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL) 2648 - #define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store) 2649 - 2650 - #define EXT4_RO_ATTR_ES_UI(name, elname) \ 2651 - EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname) 2652 - #define EXT4_RW_ATTR_SBI_UI(name, elname) \ 2653 - EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname) 2654 - 2655 - #define ATTR_LIST(name) &ext4_attr_##name.attr 2656 - #define EXT4_DEPRECATED_ATTR(_name, _val) \ 2657 - static struct ext4_attr ext4_attr_##_name = { \ 2658 - .attr = {.name = __stringify(_name), .mode = 0444 }, \ 2659 - .show = sbi_deprecated_show, \ 2660 - .u = { \ 2661 - .deprecated_val = _val, \ 2662 - }, \ 2663 - } 2664 - 2665 - EXT4_RO_ATTR(delayed_allocation_blocks); 2666 - EXT4_RO_ATTR(session_write_kbytes); 2667 - EXT4_RO_ATTR(lifetime_write_kbytes); 2668 - EXT4_RW_ATTR(reserved_clusters); 2669 - EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, 2670 - inode_readahead_blks_store, s_inode_readahead_blks); 2671 - EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); 2672 - EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); 2673 - EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); 2674 - EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); 2675 - EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); 2676 - EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); 2677 - EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); 2678 - EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128); 2679 - EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb); 2680 - EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error); 2681 - EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); 2682 - EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); 2683 - EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); 2684 - EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); 2685 - EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); 2686 - EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); 2687 - EXT4_RO_ATTR_ES_UI(errors_count, s_error_count); 2688 - EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time); 2689 - EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time); 2690 - 2691 - static struct attribute *ext4_attrs[] = { 2692 - ATTR_LIST(delayed_allocation_blocks), 2693 - ATTR_LIST(session_write_kbytes), 2694 - ATTR_LIST(lifetime_write_kbytes), 2695 - ATTR_LIST(reserved_clusters), 2696 - ATTR_LIST(inode_readahead_blks), 2697 - ATTR_LIST(inode_goal), 2698 - ATTR_LIST(mb_stats), 2699 - ATTR_LIST(mb_max_to_scan), 2700 - ATTR_LIST(mb_min_to_scan), 2701 - ATTR_LIST(mb_order2_req), 2702 - ATTR_LIST(mb_stream_req), 2703 - ATTR_LIST(mb_group_prealloc), 2704 - ATTR_LIST(max_writeback_mb_bump), 2705 - ATTR_LIST(extent_max_zeroout_kb), 2706 - ATTR_LIST(trigger_fs_error), 2707 - ATTR_LIST(err_ratelimit_interval_ms), 2708 - ATTR_LIST(err_ratelimit_burst), 2709 - ATTR_LIST(warning_ratelimit_interval_ms), 2710 - ATTR_LIST(warning_ratelimit_burst), 2711 - ATTR_LIST(msg_ratelimit_interval_ms), 2712 - ATTR_LIST(msg_ratelimit_burst), 2713 - ATTR_LIST(errors_count), 2714 - ATTR_LIST(first_error_time), 2715 - ATTR_LIST(last_error_time), 2716 - NULL, 2717 - }; 2718 - 2719 - /* Features this copy of ext4 supports */ 2720 - EXT4_INFO_ATTR(lazy_itable_init); 2721 - EXT4_INFO_ATTR(batched_discard); 2722 - EXT4_INFO_ATTR(meta_bg_resize); 2723 - EXT4_INFO_ATTR(encryption); 2724 - 2725 - static struct attribute *ext4_feat_attrs[] = { 2726 - ATTR_LIST(lazy_itable_init), 2727 - ATTR_LIST(batched_discard), 2728 - ATTR_LIST(meta_bg_resize), 2729 - ATTR_LIST(encryption), 2730 - NULL, 2731 - }; 2732 - 2733 - static ssize_t ext4_attr_show(struct kobject *kobj, 2734 - struct attribute *attr, char *buf) 2735 - { 2736 - struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 2737 - s_kobj); 2738 - struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); 2739 - 2740 - return a->show ? a->show(a, sbi, buf) : 0; 2741 - } 2742 - 2743 - static ssize_t ext4_attr_store(struct kobject *kobj, 2744 - struct attribute *attr, 2745 - const char *buf, size_t len) 2746 - { 2747 - struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 2748 - s_kobj); 2749 - struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); 2750 - 2751 - return a->store ? a->store(a, sbi, buf, len) : 0; 2752 - } 2753 - 2754 - static void ext4_sb_release(struct kobject *kobj) 2755 - { 2756 - struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 2757 - s_kobj); 2758 - complete(&sbi->s_kobj_unregister); 2759 - } 2760 - 2761 - static const struct sysfs_ops ext4_attr_ops = { 2762 - .show = ext4_attr_show, 2763 - .store = ext4_attr_store, 2764 - }; 2765 - 2766 - static struct kobj_type ext4_ktype = { 2767 - .default_attrs = ext4_attrs, 2768 - .sysfs_ops = &ext4_attr_ops, 2769 - .release = ext4_sb_release, 2770 - }; 2771 - 2772 - static void ext4_feat_release(struct kobject *kobj) 2773 - { 2774 - complete(&ext4_feat->f_kobj_unregister); 2775 - } 2776 - 2777 - static ssize_t ext4_feat_show(struct kobject *kobj, 2778 - struct attribute *attr, char *buf) 2779 - { 2780 - return snprintf(buf, PAGE_SIZE, "supported\n"); 2781 - } 2782 - 2783 - /* 2784 - * We can not use ext4_attr_show/store because it relies on the kobject 2785 - * being embedded in the ext4_sb_info structure which is definitely not 2786 - * true in this case. 2787 - */ 2788 - static const struct sysfs_ops ext4_feat_ops = { 2789 - .show = ext4_feat_show, 2790 - .store = NULL, 2791 - }; 2792 - 2793 - static struct kobj_type ext4_feat_ktype = { 2794 - .default_attrs = ext4_feat_attrs, 2795 - .sysfs_ops = &ext4_feat_ops, 2796 - .release = ext4_feat_release, 2797 - }; 2798 - 2799 2473 /* 2800 2474 * Check whether this filesystem can be mounted based on 2801 2475 * the features present and the RDONLY/RDWR mount requested. ··· 3071 3403 return 0; 3072 3404 } 3073 3405 3074 - 3075 - static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb) 3406 + static void ext4_set_resv_clusters(struct super_block *sb) 3076 3407 { 3077 3408 ext4_fsblk_t resv_clusters; 3409 + struct ext4_sb_info *sbi = EXT4_SB(sb); 3078 3410 3079 3411 /* 3080 3412 * There's no need to reserve anything when we aren't using extents. ··· 3083 3415 * to keep ext2/3 backward compatibility. 3084 3416 */ 3085 3417 if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) 3086 - return 0; 3418 + return; 3087 3419 /* 3088 3420 * By default we reserve 2% or 4096 clusters, whichever is smaller. 3089 3421 * This should cover the situations where we can not afford to run ··· 3092 3424 * allocation would require 1, or 2 blocks, higher numbers are 3093 3425 * very rare. 3094 3426 */ 3095 - resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >> 3096 - EXT4_SB(sb)->s_cluster_bits; 3427 + resv_clusters = (ext4_blocks_count(sbi->s_es) >> 3428 + sbi->s_cluster_bits); 3097 3429 3098 3430 do_div(resv_clusters, 50); 3099 3431 resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096); 3100 3432 3101 - return resv_clusters; 3102 - } 3103 - 3104 - 3105 - static int ext4_reserve_clusters(struct ext4_sb_info *sbi, ext4_fsblk_t count) 3106 - { 3107 - ext4_fsblk_t clusters = ext4_blocks_count(sbi->s_es) >> 3108 - sbi->s_cluster_bits; 3109 - 3110 - if (count >= clusters) 3111 - return -EINVAL; 3112 - 3113 - atomic64_set(&sbi->s_resv_clusters, count); 3114 - return 0; 3433 + atomic64_set(&sbi->s_resv_clusters, resv_clusters); 3115 3434 } 3116 3435 3117 3436 static int ext4_fill_super(struct super_block *sb, void *data, int silent) ··· 3847 4192 "available"); 3848 4193 } 3849 4194 3850 - err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb)); 3851 - if (err) { 3852 - ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for " 3853 - "reserved pool", ext4_calculate_resv_clusters(sb)); 3854 - goto failed_mount4a; 3855 - } 4195 + ext4_set_resv_clusters(sb); 3856 4196 3857 4197 err = ext4_setup_system_zone(sb); 3858 4198 if (err) { ··· 3898 4248 if (err) 3899 4249 goto failed_mount6; 3900 4250 3901 - sbi->s_kobj.kset = ext4_kset; 3902 - init_completion(&sbi->s_kobj_unregister); 3903 - err = kobject_init_and_add(&sbi->s_kobj, &ext4_ktype, NULL, 3904 - "%s", sb->s_id); 4251 + err = ext4_register_sysfs(sb); 3905 4252 if (err) 3906 4253 goto failed_mount7; 3907 4254 ··· 5233 5586 }; 5234 5587 MODULE_ALIAS_FS("ext4"); 5235 5588 5236 - static int __init ext4_init_feat_adverts(void) 5237 - { 5238 - struct ext4_features *ef; 5239 - int ret = -ENOMEM; 5240 - 5241 - ef = kzalloc(sizeof(struct ext4_features), GFP_KERNEL); 5242 - if (!ef) 5243 - goto out; 5244 - 5245 - ef->f_kobj.kset = ext4_kset; 5246 - init_completion(&ef->f_kobj_unregister); 5247 - ret = kobject_init_and_add(&ef->f_kobj, &ext4_feat_ktype, NULL, 5248 - "features"); 5249 - if (ret) { 5250 - kfree(ef); 5251 - goto out; 5252 - } 5253 - 5254 - ext4_feat = ef; 5255 - ret = 0; 5256 - out: 5257 - return ret; 5258 - } 5259 - 5260 - static void ext4_exit_feat_adverts(void) 5261 - { 5262 - kobject_put(&ext4_feat->f_kobj); 5263 - wait_for_completion(&ext4_feat->f_kobj_unregister); 5264 - kfree(ext4_feat); 5265 - } 5266 - 5267 5589 /* Shared across all ext4 file systems */ 5268 5590 wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; 5269 5591 struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ]; ··· 5259 5643 5260 5644 err = ext4_init_pageio(); 5261 5645 if (err) 5262 - goto out7; 5646 + goto out5; 5263 5647 5264 5648 err = ext4_init_system_zone(); 5265 5649 if (err) 5266 - goto out6; 5267 - ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj); 5268 - if (!ext4_kset) { 5269 - err = -ENOMEM; 5270 - goto out5; 5271 - } 5650 + goto out4; 5272 5651 ext4_proc_root = proc_mkdir("fs/ext4", NULL); 5273 5652 5274 - err = ext4_init_feat_adverts(); 5653 + err = ext4_init_sysfs(); 5275 5654 if (err) 5276 - goto out4; 5655 + goto out3; 5277 5656 5278 5657 err = ext4_init_mballoc(); 5279 5658 if (err) ··· 5293 5682 ext4_mballoc_ready = 0; 5294 5683 ext4_exit_mballoc(); 5295 5684 out2: 5296 - ext4_exit_feat_adverts(); 5297 - out4: 5685 + ext4_exit_sysfs(); 5686 + out3: 5298 5687 if (ext4_proc_root) 5299 5688 remove_proc_entry("fs/ext4", NULL); 5300 - kset_unregister(ext4_kset); 5301 - out5: 5302 5689 ext4_exit_system_zone(); 5303 - out6: 5690 + out4: 5304 5691 ext4_exit_pageio(); 5305 - out7: 5692 + out5: 5306 5693 ext4_exit_es(); 5307 5694 5308 5695 return err; ··· 5315 5706 unregister_filesystem(&ext4_fs_type); 5316 5707 destroy_inodecache(); 5317 5708 ext4_exit_mballoc(); 5318 - ext4_exit_feat_adverts(); 5709 + ext4_exit_sysfs(); 5319 5710 remove_proc_entry("fs/ext4", NULL); 5320 - kset_unregister(ext4_kset); 5321 5711 ext4_exit_system_zone(); 5322 5712 ext4_exit_pageio(); 5323 5713 ext4_exit_es();
+387
fs/ext4/sysfs.c
··· 1 + /* 2 + * linux/fs/ext4/sysfs.c 3 + * 4 + * Copyright (C) 1992, 1993, 1994, 1995 5 + * Remy Card (card@masi.ibp.fr) 6 + * Theodore Ts'o (tytso@mit.edu) 7 + * 8 + */ 9 + 10 + #include <linux/time.h> 11 + #include <linux/fs.h> 12 + #include <linux/seq_file.h> 13 + #include <linux/proc_fs.h> 14 + 15 + #include "ext4.h" 16 + #include "ext4_jbd2.h" 17 + 18 + struct ext4_attr { 19 + struct attribute attr; 20 + ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *); 21 + ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, 22 + const char *, size_t); 23 + union { 24 + int offset; 25 + int deprecated_val; 26 + } u; 27 + }; 28 + 29 + static int parse_strtoull(const char *buf, 30 + unsigned long long max, unsigned long long *value) 31 + { 32 + int ret; 33 + 34 + ret = kstrtoull(skip_spaces(buf), 0, value); 35 + if (!ret && *value > max) 36 + ret = -EINVAL; 37 + return ret; 38 + } 39 + 40 + static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a, 41 + struct ext4_sb_info *sbi, 42 + char *buf) 43 + { 44 + return snprintf(buf, PAGE_SIZE, "%llu\n", 45 + (s64) EXT4_C2B(sbi, 46 + percpu_counter_sum(&sbi->s_dirtyclusters_counter))); 47 + } 48 + 49 + static ssize_t session_write_kbytes_show(struct ext4_attr *a, 50 + struct ext4_sb_info *sbi, char *buf) 51 + { 52 + struct super_block *sb = sbi->s_buddy_cache->i_sb; 53 + 54 + if (!sb->s_bdev->bd_part) 55 + return snprintf(buf, PAGE_SIZE, "0\n"); 56 + return snprintf(buf, PAGE_SIZE, "%lu\n", 57 + (part_stat_read(sb->s_bdev->bd_part, sectors[1]) - 58 + sbi->s_sectors_written_start) >> 1); 59 + } 60 + 61 + static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, 62 + struct ext4_sb_info *sbi, char *buf) 63 + { 64 + struct super_block *sb = sbi->s_buddy_cache->i_sb; 65 + 66 + if (!sb->s_bdev->bd_part) 67 + return snprintf(buf, PAGE_SIZE, "0\n"); 68 + return snprintf(buf, PAGE_SIZE, "%llu\n", 69 + (unsigned long long)(sbi->s_kbytes_written + 70 + ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - 71 + EXT4_SB(sb)->s_sectors_written_start) >> 1))); 72 + } 73 + 74 + static ssize_t inode_readahead_blks_store(struct ext4_attr *a, 75 + struct ext4_sb_info *sbi, 76 + const char *buf, size_t count) 77 + { 78 + unsigned long t; 79 + int ret; 80 + 81 + ret = kstrtoul(skip_spaces(buf), 0, &t); 82 + if (ret) 83 + return ret; 84 + 85 + if (t && (!is_power_of_2(t) || t > 0x40000000)) 86 + return -EINVAL; 87 + 88 + sbi->s_inode_readahead_blks = t; 89 + return count; 90 + } 91 + 92 + static ssize_t sbi_ui_show(struct ext4_attr *a, 93 + struct ext4_sb_info *sbi, char *buf) 94 + { 95 + unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset); 96 + 97 + return snprintf(buf, PAGE_SIZE, "%u\n", *ui); 98 + } 99 + 100 + static ssize_t sbi_ui_store(struct ext4_attr *a, 101 + struct ext4_sb_info *sbi, 102 + const char *buf, size_t count) 103 + { 104 + unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset); 105 + unsigned long t; 106 + int ret; 107 + 108 + ret = kstrtoul(skip_spaces(buf), 0, &t); 109 + if (ret) 110 + return ret; 111 + *ui = t; 112 + return count; 113 + } 114 + 115 + static ssize_t es_ui_show(struct ext4_attr *a, 116 + struct ext4_sb_info *sbi, char *buf) 117 + { 118 + 119 + unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) + 120 + a->u.offset); 121 + 122 + return snprintf(buf, PAGE_SIZE, "%u\n", *ui); 123 + } 124 + 125 + static ssize_t reserved_clusters_show(struct ext4_attr *a, 126 + struct ext4_sb_info *sbi, char *buf) 127 + { 128 + return snprintf(buf, PAGE_SIZE, "%llu\n", 129 + (unsigned long long) atomic64_read(&sbi->s_resv_clusters)); 130 + } 131 + 132 + static ssize_t reserved_clusters_store(struct ext4_attr *a, 133 + struct ext4_sb_info *sbi, 134 + const char *buf, size_t count) 135 + { 136 + unsigned long long val; 137 + ext4_fsblk_t clusters = (ext4_blocks_count(sbi->s_es) >> 138 + sbi->s_cluster_bits); 139 + 140 + if (parse_strtoull(buf, -1ULL, &val)) 141 + return -EINVAL; 142 + 143 + if (val >= clusters) 144 + return -EINVAL; 145 + 146 + atomic64_set(&sbi->s_resv_clusters, val); 147 + return count; 148 + } 149 + 150 + static ssize_t trigger_test_error(struct ext4_attr *a, 151 + struct ext4_sb_info *sbi, 152 + const char *buf, size_t count) 153 + { 154 + int len = count; 155 + 156 + if (!capable(CAP_SYS_ADMIN)) 157 + return -EPERM; 158 + 159 + if (len && buf[len-1] == '\n') 160 + len--; 161 + 162 + if (len) 163 + ext4_error(sbi->s_sb, "%.*s", len, buf); 164 + return count; 165 + } 166 + 167 + static ssize_t sbi_deprecated_show(struct ext4_attr *a, 168 + struct ext4_sb_info *sbi, char *buf) 169 + { 170 + return snprintf(buf, PAGE_SIZE, "%d\n", a->u.deprecated_val); 171 + } 172 + 173 + #define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \ 174 + static struct ext4_attr ext4_attr_##_name = { \ 175 + .attr = {.name = __stringify(_name), .mode = _mode }, \ 176 + .show = _show, \ 177 + .store = _store, \ 178 + .u = { \ 179 + .offset = offsetof(struct ext4_sb_info, _elname),\ 180 + }, \ 181 + } 182 + 183 + #define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname) \ 184 + static struct ext4_attr ext4_attr_##_name = { \ 185 + .attr = {.name = __stringify(_name), .mode = _mode }, \ 186 + .show = _show, \ 187 + .store = _store, \ 188 + .u = { \ 189 + .offset = offsetof(struct ext4_super_block, _elname), \ 190 + }, \ 191 + } 192 + 193 + #define EXT4_ATTR(name, mode, show, store) \ 194 + static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) 195 + 196 + #define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL) 197 + #define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL) 198 + #define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store) 199 + 200 + #define EXT4_RO_ATTR_ES_UI(name, elname) \ 201 + EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname) 202 + #define EXT4_RW_ATTR_SBI_UI(name, elname) \ 203 + EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname) 204 + 205 + #define ATTR_LIST(name) &ext4_attr_##name.attr 206 + #define EXT4_DEPRECATED_ATTR(_name, _val) \ 207 + static struct ext4_attr ext4_attr_##_name = { \ 208 + .attr = {.name = __stringify(_name), .mode = 0444 }, \ 209 + .show = sbi_deprecated_show, \ 210 + .u = { \ 211 + .deprecated_val = _val, \ 212 + }, \ 213 + } 214 + 215 + EXT4_RO_ATTR(delayed_allocation_blocks); 216 + EXT4_RO_ATTR(session_write_kbytes); 217 + EXT4_RO_ATTR(lifetime_write_kbytes); 218 + EXT4_RW_ATTR(reserved_clusters); 219 + EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, 220 + inode_readahead_blks_store, s_inode_readahead_blks); 221 + EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); 222 + EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); 223 + EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); 224 + EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); 225 + EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); 226 + EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); 227 + EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); 228 + EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128); 229 + EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb); 230 + EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error); 231 + EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); 232 + EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); 233 + EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); 234 + EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); 235 + EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); 236 + EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); 237 + EXT4_RO_ATTR_ES_UI(errors_count, s_error_count); 238 + EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time); 239 + EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time); 240 + 241 + static struct attribute *ext4_attrs[] = { 242 + ATTR_LIST(delayed_allocation_blocks), 243 + ATTR_LIST(session_write_kbytes), 244 + ATTR_LIST(lifetime_write_kbytes), 245 + ATTR_LIST(reserved_clusters), 246 + ATTR_LIST(inode_readahead_blks), 247 + ATTR_LIST(inode_goal), 248 + ATTR_LIST(mb_stats), 249 + ATTR_LIST(mb_max_to_scan), 250 + ATTR_LIST(mb_min_to_scan), 251 + ATTR_LIST(mb_order2_req), 252 + ATTR_LIST(mb_stream_req), 253 + ATTR_LIST(mb_group_prealloc), 254 + ATTR_LIST(max_writeback_mb_bump), 255 + ATTR_LIST(extent_max_zeroout_kb), 256 + ATTR_LIST(trigger_fs_error), 257 + ATTR_LIST(err_ratelimit_interval_ms), 258 + ATTR_LIST(err_ratelimit_burst), 259 + ATTR_LIST(warning_ratelimit_interval_ms), 260 + ATTR_LIST(warning_ratelimit_burst), 261 + ATTR_LIST(msg_ratelimit_interval_ms), 262 + ATTR_LIST(msg_ratelimit_burst), 263 + ATTR_LIST(errors_count), 264 + ATTR_LIST(first_error_time), 265 + ATTR_LIST(last_error_time), 266 + NULL, 267 + }; 268 + 269 + /* Features this copy of ext4 supports */ 270 + EXT4_INFO_ATTR(lazy_itable_init); 271 + EXT4_INFO_ATTR(batched_discard); 272 + EXT4_INFO_ATTR(meta_bg_resize); 273 + EXT4_INFO_ATTR(encryption); 274 + 275 + static struct attribute *ext4_feat_attrs[] = { 276 + ATTR_LIST(lazy_itable_init), 277 + ATTR_LIST(batched_discard), 278 + ATTR_LIST(meta_bg_resize), 279 + ATTR_LIST(encryption), 280 + NULL, 281 + }; 282 + 283 + static ssize_t ext4_attr_show(struct kobject *kobj, 284 + struct attribute *attr, char *buf) 285 + { 286 + struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 287 + s_kobj); 288 + struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); 289 + 290 + return a->show ? a->show(a, sbi, buf) : 0; 291 + } 292 + 293 + static ssize_t ext4_attr_store(struct kobject *kobj, 294 + struct attribute *attr, 295 + const char *buf, size_t len) 296 + { 297 + struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 298 + s_kobj); 299 + struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); 300 + 301 + return a->store ? a->store(a, sbi, buf, len) : 0; 302 + } 303 + 304 + static void ext4_sb_release(struct kobject *kobj) 305 + { 306 + struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 307 + s_kobj); 308 + complete(&sbi->s_kobj_unregister); 309 + } 310 + 311 + static const struct sysfs_ops ext4_attr_ops = { 312 + .show = ext4_attr_show, 313 + .store = ext4_attr_store, 314 + }; 315 + 316 + static struct kobj_type ext4_sb_ktype = { 317 + .default_attrs = ext4_attrs, 318 + .sysfs_ops = &ext4_attr_ops, 319 + .release = ext4_sb_release, 320 + }; 321 + 322 + static struct kobj_type ext4_ktype = { 323 + .sysfs_ops = &ext4_attr_ops, 324 + }; 325 + 326 + static struct kset ext4_kset = { 327 + .kobj = {.ktype = &ext4_ktype}, 328 + }; 329 + 330 + static ssize_t ext4_feat_show(struct kobject *kobj, 331 + struct attribute *attr, char *buf) 332 + { 333 + return snprintf(buf, PAGE_SIZE, "supported\n"); 334 + } 335 + 336 + /* 337 + * We can not use ext4_attr_show/store because it relies on the kobject 338 + * being embedded in the ext4_sb_info structure which is definitely not 339 + * true in this case. 340 + */ 341 + static const struct sysfs_ops ext4_feat_ops = { 342 + .show = ext4_feat_show, 343 + .store = NULL, 344 + }; 345 + 346 + static struct kobj_type ext4_feat_ktype = { 347 + .default_attrs = ext4_feat_attrs, 348 + .sysfs_ops = &ext4_feat_ops, 349 + }; 350 + 351 + static struct kobject ext4_feat = { 352 + .kset = &ext4_kset, 353 + }; 354 + 355 + int ext4_register_sysfs(struct super_block *sb) 356 + { 357 + struct ext4_sb_info *sbi = EXT4_SB(sb); 358 + 359 + sbi->s_kobj.kset = &ext4_kset; 360 + init_completion(&sbi->s_kobj_unregister); 361 + return kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL, 362 + "%s", sb->s_id); 363 + } 364 + 365 + int __init ext4_init_sysfs(void) 366 + { 367 + int ret; 368 + 369 + kobject_set_name(&ext4_kset.kobj, "ext4"); 370 + ext4_kset.kobj.parent = fs_kobj; 371 + ret = kset_register(&ext4_kset); 372 + if (ret) 373 + return ret; 374 + 375 + ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype, 376 + NULL, "features"); 377 + if (ret) 378 + kset_unregister(&ext4_kset); 379 + return ret; 380 + } 381 + 382 + void ext4_exit_sysfs(void) 383 + { 384 + kobject_put(&ext4_feat); 385 + kset_unregister(&ext4_kset); 386 + } 387 +