summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2015-09-23 12:44:17 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-09-23 12:44:17 -0400
commitb5799018827e67867fda77c3cde10fc080606fe2 (patch)
treeebd4cc981162d55bef49b45ff86c846923411ef8
parent1f93e4a96c9109378204c147b3eec0d0e8100fde (diff)
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>
-rw-r--r--fs/ext4/Makefile2
-rw-r--r--fs/ext4/ext4.h5
-rw-r--r--fs/ext4/super.c426
-rw-r--r--fs/ext4/sysfs.c387
4 files changed, 410 insertions, 410 deletions
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 75285ea9aa05..f52cf54f0cbc 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -8,7 +8,7 @@ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
8 ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ 8 ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
9 ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ 9 ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
10 mmp.o indirect.o extents_status.o xattr.o xattr_user.o \ 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
13ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o 13ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
14ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o 14ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index fd1f28be5296..76daccf38aa3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2903,6 +2903,11 @@ extern const struct inode_operations ext4_encrypted_symlink_inode_operations;
2903extern const struct inode_operations ext4_symlink_inode_operations; 2903extern const struct inode_operations ext4_symlink_inode_operations;
2904extern const struct inode_operations ext4_fast_symlink_inode_operations; 2904extern const struct inode_operations ext4_fast_symlink_inode_operations;
2905 2905
2906/* sysfs.c */
2907extern int ext4_register_sysfs(struct super_block *sb);
2908extern int __init ext4_init_sysfs(void);
2909extern void ext4_exit_sysfs(void);
2910
2906/* block_validity */ 2911/* block_validity */
2907extern void ext4_release_system_zone(struct super_block *sb); 2912extern void ext4_release_system_zone(struct super_block *sb);
2908extern int ext4_setup_system_zone(struct super_block *sb); 2913extern int ext4_setup_system_zone(struct super_block *sb);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index a63c7b0a10cf..4a574fbeffec 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -55,10 +55,8 @@
55#include <trace/events/ext4.h> 55#include <trace/events/ext4.h>
56 56
57static struct proc_dir_entry *ext4_proc_root; 57static struct proc_dir_entry *ext4_proc_root;
58static struct kset *ext4_kset;
59static struct ext4_lazy_init *ext4_li_info; 58static struct ext4_lazy_init *ext4_li_info;
60static struct mutex ext4_li_mtx; 59static struct mutex ext4_li_mtx;
61static struct ext4_features *ext4_feat;
62static int ext4_mballoc_ready; 60static int ext4_mballoc_ready;
63static struct ratelimit_state ext4_mount_msg_ratelimit; 61static struct ratelimit_state ext4_mount_msg_ratelimit;
64 62
@@ -83,7 +81,6 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly);
83static void ext4_destroy_lazyinit_thread(void); 81static void ext4_destroy_lazyinit_thread(void);
84static void ext4_unregister_li_request(struct super_block *sb); 82static void ext4_unregister_li_request(struct super_block *sb);
85static void ext4_clear_request_list(void); 83static void ext4_clear_request_list(void);
86static int ext4_reserve_clusters(struct ext4_sb_info *, ext4_fsblk_t);
87 84
88#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) 85#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
89static struct file_system_type ext2_fs_type = { 86static struct file_system_type ext2_fs_type = {
@@ -2470,335 +2467,6 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
2470 return ret; 2467 return ret;
2471} 2468}
2472 2469
2473/* sysfs supprt */
2474
2475struct ext4_attr {
2476 struct attribute attr;
2477 ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *);
2478 ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *,
2479 const char *, size_t);
2480 union {
2481 int offset;
2482 int deprecated_val;
2483 } u;
2484};
2485
2486static int parse_strtoull(const char *buf,
2487 unsigned long long max, unsigned long long *value)
2488{
2489 int ret;
2490
2491 ret = kstrtoull(skip_spaces(buf), 0, value);
2492 if (!ret && *value > max)
2493 ret = -EINVAL;
2494 return ret;
2495}
2496
2497static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
2498 struct ext4_sb_info *sbi,
2499 char *buf)
2500{
2501 return snprintf(buf, PAGE_SIZE, "%llu\n",
2502 (s64) EXT4_C2B(sbi,
2503 percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
2504}
2505
2506static ssize_t session_write_kbytes_show(struct ext4_attr *a,
2507 struct ext4_sb_info *sbi, char *buf)
2508{
2509 struct super_block *sb = sbi->s_buddy_cache->i_sb;
2510
2511 if (!sb->s_bdev->bd_part)
2512 return snprintf(buf, PAGE_SIZE, "0\n");
2513 return snprintf(buf, PAGE_SIZE, "%lu\n",
2514 (part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
2515 sbi->s_sectors_written_start) >> 1);
2516}
2517
2518static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
2519 struct ext4_sb_info *sbi, char *buf)
2520{
2521 struct super_block *sb = sbi->s_buddy_cache->i_sb;
2522
2523 if (!sb->s_bdev->bd_part)
2524 return snprintf(buf, PAGE_SIZE, "0\n");
2525 return snprintf(buf, PAGE_SIZE, "%llu\n",
2526 (unsigned long long)(sbi->s_kbytes_written +
2527 ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
2528 EXT4_SB(sb)->s_sectors_written_start) >> 1)));
2529}
2530
2531static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
2532 struct ext4_sb_info *sbi,
2533 const char *buf, size_t count)
2534{
2535 unsigned long t;
2536 int ret;
2537
2538 ret = kstrtoul(skip_spaces(buf), 0, &t);
2539 if (ret)
2540 return ret;
2541
2542 if (t && (!is_power_of_2(t) || t > 0x40000000))
2543 return -EINVAL;
2544
2545 sbi->s_inode_readahead_blks = t;
2546 return count;
2547}
2548
2549static ssize_t sbi_ui_show(struct ext4_attr *a,
2550 struct ext4_sb_info *sbi, char *buf)
2551{
2552 unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
2553
2554 return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
2555}
2556
2557static ssize_t sbi_ui_store(struct ext4_attr *a,
2558 struct ext4_sb_info *sbi,
2559 const char *buf, size_t count)
2560{
2561 unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
2562 unsigned long t;
2563 int ret;
2564
2565 ret = kstrtoul(skip_spaces(buf), 0, &t);
2566 if (ret)
2567 return ret;
2568 *ui = t;
2569 return count;
2570}
2571
2572static ssize_t es_ui_show(struct ext4_attr *a,
2573 struct ext4_sb_info *sbi, char *buf)
2574{
2575
2576 unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) +
2577 a->u.offset);
2578
2579 return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
2580}
2581
2582static ssize_t reserved_clusters_show(struct ext4_attr *a,
2583 struct ext4_sb_info *sbi, char *buf)
2584{
2585 return snprintf(buf, PAGE_SIZE, "%llu\n",
2586 (unsigned long long) atomic64_read(&sbi->s_resv_clusters));
2587}
2588
2589static ssize_t reserved_clusters_store(struct ext4_attr *a,
2590 struct ext4_sb_info *sbi,
2591 const char *buf, size_t count)
2592{
2593 unsigned long long val;
2594 int ret;
2595
2596 if (parse_strtoull(buf, -1ULL, &val))
2597 return -EINVAL;
2598 ret = ext4_reserve_clusters(sbi, val);
2599
2600 return ret ? ret : count;
2601}
2602
2603static ssize_t trigger_test_error(struct ext4_attr *a,
2604 struct ext4_sb_info *sbi,
2605 const char *buf, size_t count)
2606{
2607 int len = count;
2608
2609 if (!capable(CAP_SYS_ADMIN))
2610 return -EPERM;
2611
2612 if (len && buf[len-1] == '\n')
2613 len--;
2614
2615 if (len)
2616 ext4_error(sbi->s_sb, "%.*s", len, buf);
2617 return count;
2618}
2619
2620static ssize_t sbi_deprecated_show(struct ext4_attr *a,
2621 struct ext4_sb_info *sbi, char *buf)
2622{
2623 return snprintf(buf, PAGE_SIZE, "%d\n", a->u.deprecated_val);
2624}
2625
2626#define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \
2627static struct ext4_attr ext4_attr_##_name = { \
2628 .attr = {.name = __stringify(_name), .mode = _mode }, \
2629 .show = _show, \
2630 .store = _store, \
2631 .u = { \
2632 .offset = offsetof(struct ext4_sb_info, _elname),\
2633 }, \
2634}
2635
2636#define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname) \
2637static struct ext4_attr ext4_attr_##_name = { \
2638 .attr = {.name = __stringify(_name), .mode = _mode }, \
2639 .show = _show, \
2640 .store = _store, \
2641 .u = { \
2642 .offset = offsetof(struct ext4_super_block, _elname), \
2643 }, \
2644}
2645
2646#define EXT4_ATTR(name, mode, show, store) \
2647static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
2648
2649#define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL)
2650#define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
2651#define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
2652
2653#define EXT4_RO_ATTR_ES_UI(name, elname) \
2654 EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname)
2655#define EXT4_RW_ATTR_SBI_UI(name, elname) \
2656 EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname)
2657
2658#define ATTR_LIST(name) &ext4_attr_##name.attr
2659#define EXT4_DEPRECATED_ATTR(_name, _val) \
2660static struct ext4_attr ext4_attr_##_name = { \
2661 .attr = {.name = __stringify(_name), .mode = 0444 }, \
2662 .show = sbi_deprecated_show, \
2663 .u = { \
2664 .deprecated_val = _val, \
2665 }, \
2666}
2667
2668EXT4_RO_ATTR(delayed_allocation_blocks);
2669EXT4_RO_ATTR(session_write_kbytes);
2670EXT4_RO_ATTR(lifetime_write_kbytes);
2671EXT4_RW_ATTR(reserved_clusters);
2672EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
2673 inode_readahead_blks_store, s_inode_readahead_blks);
2674EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
2675EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
2676EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
2677EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
2678EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
2679EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
2680EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
2681EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);
2682EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
2683EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
2684EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
2685EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
2686EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
2687EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
2688EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
2689EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
2690EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
2691EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time);
2692EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time);
2693
2694static struct attribute *ext4_attrs[] = {
2695 ATTR_LIST(delayed_allocation_blocks),
2696 ATTR_LIST(session_write_kbytes),
2697 ATTR_LIST(lifetime_write_kbytes),
2698 ATTR_LIST(reserved_clusters),
2699 ATTR_LIST(inode_readahead_blks),
2700 ATTR_LIST(inode_goal),
2701 ATTR_LIST(mb_stats),
2702 ATTR_LIST(mb_max_to_scan),
2703 ATTR_LIST(mb_min_to_scan),
2704 ATTR_LIST(mb_order2_req),
2705 ATTR_LIST(mb_stream_req),
2706 ATTR_LIST(mb_group_prealloc),
2707 ATTR_LIST(max_writeback_mb_bump),
2708 ATTR_LIST(extent_max_zeroout_kb),
2709 ATTR_LIST(trigger_fs_error),
2710 ATTR_LIST(err_ratelimit_interval_ms),
2711 ATTR_LIST(err_ratelimit_burst),
2712 ATTR_LIST(warning_ratelimit_interval_ms),
2713 ATTR_LIST(warning_ratelimit_burst),
2714 ATTR_LIST(msg_ratelimit_interval_ms),
2715 ATTR_LIST(msg_ratelimit_burst),
2716 ATTR_LIST(errors_count),
2717 ATTR_LIST(first_error_time),
2718 ATTR_LIST(last_error_time),
2719 NULL,
2720};
2721
2722/* Features this copy of ext4 supports */
2723EXT4_INFO_ATTR(lazy_itable_init);
2724EXT4_INFO_ATTR(batched_discard);
2725EXT4_INFO_ATTR(meta_bg_resize);
2726EXT4_INFO_ATTR(encryption);
2727
2728static struct attribute *ext4_feat_attrs[] = {
2729 ATTR_LIST(lazy_itable_init),
2730 ATTR_LIST(batched_discard),
2731 ATTR_LIST(meta_bg_resize),
2732 ATTR_LIST(encryption),
2733 NULL,
2734};
2735
2736static ssize_t ext4_attr_show(struct kobject *kobj,
2737 struct attribute *attr, char *buf)
2738{
2739 struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
2740 s_kobj);
2741 struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
2742
2743 return a->show ? a->show(a, sbi, buf) : 0;
2744}
2745
2746static ssize_t ext4_attr_store(struct kobject *kobj,
2747 struct attribute *attr,
2748 const char *buf, size_t len)
2749{
2750 struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
2751 s_kobj);
2752 struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
2753
2754 return a->store ? a->store(a, sbi, buf, len) : 0;
2755}
2756
2757static void ext4_sb_release(struct kobject *kobj)
2758{
2759 struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
2760 s_kobj);
2761 complete(&sbi->s_kobj_unregister);
2762}
2763
2764static const struct sysfs_ops ext4_attr_ops = {
2765 .show = ext4_attr_show,
2766 .store = ext4_attr_store,
2767};
2768
2769static struct kobj_type ext4_ktype = {
2770 .default_attrs = ext4_attrs,
2771 .sysfs_ops = &ext4_attr_ops,
2772 .release = ext4_sb_release,
2773};
2774
2775static void ext4_feat_release(struct kobject *kobj)
2776{
2777 complete(&ext4_feat->f_kobj_unregister);
2778}
2779
2780static ssize_t ext4_feat_show(struct kobject *kobj,
2781 struct attribute *attr, char *buf)
2782{
2783 return snprintf(buf, PAGE_SIZE, "supported\n");
2784}
2785
2786/*
2787 * We can not use ext4_attr_show/store because it relies on the kobject
2788 * being embedded in the ext4_sb_info structure which is definitely not
2789 * true in this case.
2790 */
2791static const struct sysfs_ops ext4_feat_ops = {
2792 .show = ext4_feat_show,
2793 .store = NULL,
2794};
2795
2796static struct kobj_type ext4_feat_ktype = {
2797 .default_attrs = ext4_feat_attrs,
2798 .sysfs_ops = &ext4_feat_ops,
2799 .release = ext4_feat_release,
2800};
2801
2802/* 2470/*
2803 * Check whether this filesystem can be mounted based on 2471 * Check whether this filesystem can be mounted based on
2804 * the features present and the RDONLY/RDWR mount requested. 2472 * the features present and the RDONLY/RDWR mount requested.
@@ -3403,10 +3071,10 @@ int ext4_calculate_overhead(struct super_block *sb)
3403 return 0; 3071 return 0;
3404} 3072}
3405 3073
3406 3074static void ext4_set_resv_clusters(struct super_block *sb)
3407static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
3408{ 3075{
3409 ext4_fsblk_t resv_clusters; 3076 ext4_fsblk_t resv_clusters;
3077 struct ext4_sb_info *sbi = EXT4_SB(sb);
3410 3078
3411 /* 3079 /*
3412 * There's no need to reserve anything when we aren't using extents. 3080 * There's no need to reserve anything when we aren't using extents.
@@ -3415,7 +3083,7 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
3415 * to keep ext2/3 backward compatibility. 3083 * to keep ext2/3 backward compatibility.
3416 */ 3084 */
3417 if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) 3085 if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
3418 return 0; 3086 return;
3419 /* 3087 /*
3420 * By default we reserve 2% or 4096 clusters, whichever is smaller. 3088 * By default we reserve 2% or 4096 clusters, whichever is smaller.
3421 * This should cover the situations where we can not afford to run 3089 * This should cover the situations where we can not afford to run
@@ -3424,26 +3092,13 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
3424 * allocation would require 1, or 2 blocks, higher numbers are 3092 * allocation would require 1, or 2 blocks, higher numbers are
3425 * very rare. 3093 * very rare.
3426 */ 3094 */
3427 resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >> 3095 resv_clusters = (ext4_blocks_count(sbi->s_es) >>
3428 EXT4_SB(sb)->s_cluster_bits; 3096 sbi->s_cluster_bits);
3429 3097
3430 do_div(resv_clusters, 50); 3098 do_div(resv_clusters, 50);
3431 resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096); 3099 resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
3432 3100
3433 return resv_clusters; 3101 atomic64_set(&sbi->s_resv_clusters, resv_clusters);
3434}
3435
3436
3437static int ext4_reserve_clusters(struct ext4_sb_info *sbi, ext4_fsblk_t count)
3438{
3439 ext4_fsblk_t clusters = ext4_blocks_count(sbi->s_es) >>
3440 sbi->s_cluster_bits;
3441
3442 if (count >= clusters)
3443 return -EINVAL;
3444
3445 atomic64_set(&sbi->s_resv_clusters, count);
3446 return 0;
3447} 3102}
3448 3103
3449static int ext4_fill_super(struct super_block *sb, void *data, int silent) 3104static int ext4_fill_super(struct super_block *sb, void *data, int silent)
@@ -4192,12 +3847,7 @@ no_journal:
4192 "available"); 3847 "available");
4193 } 3848 }
4194 3849
4195 err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb)); 3850 ext4_set_resv_clusters(sb);
4196 if (err) {
4197 ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
4198 "reserved pool", ext4_calculate_resv_clusters(sb));
4199 goto failed_mount4a;
4200 }
4201 3851
4202 err = ext4_setup_system_zone(sb); 3852 err = ext4_setup_system_zone(sb);
4203 if (err) { 3853 if (err) {
@@ -4248,10 +3898,7 @@ no_journal:
4248 if (err) 3898 if (err)
4249 goto failed_mount6; 3899 goto failed_mount6;
4250 3900
4251 sbi->s_kobj.kset = ext4_kset; 3901 err = ext4_register_sysfs(sb);
4252 init_completion(&sbi->s_kobj_unregister);
4253 err = kobject_init_and_add(&sbi->s_kobj, &ext4_ktype, NULL,
4254 "%s", sb->s_id);
4255 if (err) 3902 if (err)
4256 goto failed_mount7; 3903 goto failed_mount7;
4257 3904
@@ -5586,37 +5233,6 @@ static struct file_system_type ext4_fs_type = {
5586}; 5233};
5587MODULE_ALIAS_FS("ext4"); 5234MODULE_ALIAS_FS("ext4");
5588 5235
5589static int __init ext4_init_feat_adverts(void)
5590{
5591 struct ext4_features *ef;
5592 int ret = -ENOMEM;
5593
5594 ef = kzalloc(sizeof(struct ext4_features), GFP_KERNEL);
5595 if (!ef)
5596 goto out;
5597
5598 ef->f_kobj.kset = ext4_kset;
5599 init_completion(&ef->f_kobj_unregister);
5600 ret = kobject_init_and_add(&ef->f_kobj, &ext4_feat_ktype, NULL,
5601 "features");
5602 if (ret) {
5603 kfree(ef);
5604 goto out;
5605 }
5606
5607 ext4_feat = ef;
5608 ret = 0;
5609out:
5610 return ret;
5611}
5612
5613static void ext4_exit_feat_adverts(void)
5614{
5615 kobject_put(&ext4_feat->f_kobj);
5616 wait_for_completion(&ext4_feat->f_kobj_unregister);
5617 kfree(ext4_feat);
5618}
5619
5620/* Shared across all ext4 file systems */ 5236/* Shared across all ext4 file systems */
5621wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; 5237wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
5622struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ]; 5238struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ];
@@ -5643,21 +5259,16 @@ static int __init ext4_init_fs(void)
5643 5259
5644 err = ext4_init_pageio(); 5260 err = ext4_init_pageio();
5645 if (err) 5261 if (err)
5646 goto out7; 5262 goto out5;
5647 5263
5648 err = ext4_init_system_zone(); 5264 err = ext4_init_system_zone();
5649 if (err) 5265 if (err)
5650 goto out6; 5266 goto out4;
5651 ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
5652 if (!ext4_kset) {
5653 err = -ENOMEM;
5654 goto out5;
5655 }
5656 ext4_proc_root = proc_mkdir("fs/ext4", NULL); 5267 ext4_proc_root = proc_mkdir("fs/ext4", NULL);
5657 5268
5658 err = ext4_init_feat_adverts(); 5269 err = ext4_init_sysfs();
5659 if (err) 5270 if (err)
5660 goto out4; 5271 goto out3;
5661 5272
5662 err = ext4_init_mballoc(); 5273 err = ext4_init_mballoc();
5663 if (err) 5274 if (err)
@@ -5682,16 +5293,14 @@ out1:
5682 ext4_mballoc_ready = 0; 5293 ext4_mballoc_ready = 0;
5683 ext4_exit_mballoc(); 5294 ext4_exit_mballoc();
5684out2: 5295out2:
5685 ext4_exit_feat_adverts(); 5296 ext4_exit_sysfs();
5686out4: 5297out3:
5687 if (ext4_proc_root) 5298 if (ext4_proc_root)
5688 remove_proc_entry("fs/ext4", NULL); 5299 remove_proc_entry("fs/ext4", NULL);
5689 kset_unregister(ext4_kset);
5690out5:
5691 ext4_exit_system_zone(); 5300 ext4_exit_system_zone();
5692out6: 5301out4:
5693 ext4_exit_pageio(); 5302 ext4_exit_pageio();
5694out7: 5303out5:
5695 ext4_exit_es(); 5304 ext4_exit_es();
5696 5305
5697 return err; 5306 return err;
@@ -5706,9 +5315,8 @@ static void __exit ext4_exit_fs(void)
5706 unregister_filesystem(&ext4_fs_type); 5315 unregister_filesystem(&ext4_fs_type);
5707 destroy_inodecache(); 5316 destroy_inodecache();
5708 ext4_exit_mballoc(); 5317 ext4_exit_mballoc();
5709 ext4_exit_feat_adverts(); 5318 ext4_exit_sysfs();
5710 remove_proc_entry("fs/ext4", NULL); 5319 remove_proc_entry("fs/ext4", NULL);
5711 kset_unregister(ext4_kset);
5712 ext4_exit_system_zone(); 5320 ext4_exit_system_zone();
5713 ext4_exit_pageio(); 5321 ext4_exit_pageio();
5714 ext4_exit_es(); 5322 ext4_exit_es();
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
new file mode 100644
index 000000000000..9fdc21b9b265
--- /dev/null
+++ b/fs/ext4/sysfs.c
@@ -0,0 +1,387 @@
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
18struct 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
29static 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
40static 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
49static 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
61static 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
74static 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
92static 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
100static 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
115static 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
125static 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
132static 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
150static 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
167static 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) \
174static 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) \
184static 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) \
194static 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) \
207static 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
215EXT4_RO_ATTR(delayed_allocation_blocks);
216EXT4_RO_ATTR(session_write_kbytes);
217EXT4_RO_ATTR(lifetime_write_kbytes);
218EXT4_RW_ATTR(reserved_clusters);
219EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
220 inode_readahead_blks_store, s_inode_readahead_blks);
221EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
222EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
223EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
224EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
225EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
226EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
227EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
228EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);
229EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
230EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
231EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
232EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
233EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
234EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
235EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
236EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
237EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
238EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time);
239EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time);
240
241static 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 */
270EXT4_INFO_ATTR(lazy_itable_init);
271EXT4_INFO_ATTR(batched_discard);
272EXT4_INFO_ATTR(meta_bg_resize);
273EXT4_INFO_ATTR(encryption);
274
275static 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
283static 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
293static 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
304static 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
311static const struct sysfs_ops ext4_attr_ops = {
312 .show = ext4_attr_show,
313 .store = ext4_attr_store,
314};
315
316static struct kobj_type ext4_sb_ktype = {
317 .default_attrs = ext4_attrs,
318 .sysfs_ops = &ext4_attr_ops,
319 .release = ext4_sb_release,
320};
321
322static struct kobj_type ext4_ktype = {
323 .sysfs_ops = &ext4_attr_ops,
324};
325
326static struct kset ext4_kset = {
327 .kobj = {.ktype = &ext4_ktype},
328};
329
330static 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 */
341static const struct sysfs_ops ext4_feat_ops = {
342 .show = ext4_feat_show,
343 .store = NULL,
344};
345
346static struct kobj_type ext4_feat_ktype = {
347 .default_attrs = ext4_feat_attrs,
348 .sysfs_ops = &ext4_feat_ops,
349};
350
351static struct kobject ext4_feat = {
352 .kset = &ext4_kset,
353};
354
355int 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
365int __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
382void ext4_exit_sysfs(void)
383{
384 kobject_put(&ext4_feat);
385 kset_unregister(&ext4_kset);
386}
387