linux/fs/ext4/sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  linux/fs/ext4/sysfs.c
   4 *
   5 * Copyright (C) 1992, 1993, 1994, 1995
   6 * Remy Card (card@masi.ibp.fr)
   7 * Theodore Ts'o (tytso@mit.edu)
   8 *
   9 */
  10
  11#include <linux/time.h>
  12#include <linux/fs.h>
  13#include <linux/seq_file.h>
  14#include <linux/slab.h>
  15#include <linux/proc_fs.h>
  16
  17#include "ext4.h"
  18#include "ext4_jbd2.h"
  19
  20typedef enum {
  21        attr_noop,
  22        attr_delayed_allocation_blocks,
  23        attr_session_write_kbytes,
  24        attr_lifetime_write_kbytes,
  25        attr_reserved_clusters,
  26        attr_inode_readahead,
  27        attr_trigger_test_error,
  28        attr_first_error_time,
  29        attr_last_error_time,
  30        attr_feature,
  31        attr_pointer_ui,
  32        attr_pointer_atomic,
  33        attr_journal_task,
  34} attr_id_t;
  35
  36typedef enum {
  37        ptr_explicit,
  38        ptr_ext4_sb_info_offset,
  39        ptr_ext4_super_block_offset,
  40} attr_ptr_t;
  41
  42static const char proc_dirname[] = "fs/ext4";
  43static struct proc_dir_entry *ext4_proc_root;
  44
  45struct ext4_attr {
  46        struct attribute attr;
  47        short attr_id;
  48        short attr_ptr;
  49        union {
  50                int offset;
  51                void *explicit_ptr;
  52        } u;
  53};
  54
  55static ssize_t session_write_kbytes_show(struct ext4_sb_info *sbi, char *buf)
  56{
  57        struct super_block *sb = sbi->s_buddy_cache->i_sb;
  58
  59        if (!sb->s_bdev->bd_part)
  60                return snprintf(buf, PAGE_SIZE, "0\n");
  61        return snprintf(buf, PAGE_SIZE, "%lu\n",
  62                        (part_stat_read(sb->s_bdev->bd_part,
  63                                        sectors[STAT_WRITE]) -
  64                         sbi->s_sectors_written_start) >> 1);
  65}
  66
  67static ssize_t lifetime_write_kbytes_show(struct ext4_sb_info *sbi, char *buf)
  68{
  69        struct super_block *sb = sbi->s_buddy_cache->i_sb;
  70
  71        if (!sb->s_bdev->bd_part)
  72                return snprintf(buf, PAGE_SIZE, "0\n");
  73        return snprintf(buf, PAGE_SIZE, "%llu\n",
  74                        (unsigned long long)(sbi->s_kbytes_written +
  75                        ((part_stat_read(sb->s_bdev->bd_part,
  76                                         sectors[STAT_WRITE]) -
  77                          EXT4_SB(sb)->s_sectors_written_start) >> 1)));
  78}
  79
  80static ssize_t inode_readahead_blks_store(struct ext4_sb_info *sbi,
  81                                          const char *buf, size_t count)
  82{
  83        unsigned long t;
  84        int ret;
  85
  86        ret = kstrtoul(skip_spaces(buf), 0, &t);
  87        if (ret)
  88                return ret;
  89
  90        if (t && (!is_power_of_2(t) || t > 0x40000000))
  91                return -EINVAL;
  92
  93        sbi->s_inode_readahead_blks = t;
  94        return count;
  95}
  96
  97static ssize_t reserved_clusters_store(struct ext4_sb_info *sbi,
  98                                   const char *buf, size_t count)
  99{
 100        unsigned long long val;
 101        ext4_fsblk_t clusters = (ext4_blocks_count(sbi->s_es) >>
 102                                 sbi->s_cluster_bits);
 103        int ret;
 104
 105        ret = kstrtoull(skip_spaces(buf), 0, &val);
 106        if (ret || val >= clusters)
 107                return -EINVAL;
 108
 109        atomic64_set(&sbi->s_resv_clusters, val);
 110        return count;
 111}
 112
 113static ssize_t trigger_test_error(struct ext4_sb_info *sbi,
 114                                  const char *buf, size_t count)
 115{
 116        int len = count;
 117
 118        if (!capable(CAP_SYS_ADMIN))
 119                return -EPERM;
 120
 121        if (len && buf[len-1] == '\n')
 122                len--;
 123
 124        if (len)
 125                ext4_error(sbi->s_sb, "%.*s", len, buf);
 126        return count;
 127}
 128
 129static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf)
 130{
 131        if (!sbi->s_journal)
 132                return snprintf(buf, PAGE_SIZE, "<none>\n");
 133        return snprintf(buf, PAGE_SIZE, "%d\n",
 134                        task_pid_vnr(sbi->s_journal->j_task));
 135}
 136
 137#define EXT4_ATTR(_name,_mode,_id)                                      \
 138static struct ext4_attr ext4_attr_##_name = {                           \
 139        .attr = {.name = __stringify(_name), .mode = _mode },           \
 140        .attr_id = attr_##_id,                                          \
 141}
 142
 143#define EXT4_ATTR_FUNC(_name,_mode)  EXT4_ATTR(_name,_mode,_name)
 144
 145#define EXT4_ATTR_FEATURE(_name)   EXT4_ATTR(_name, 0444, feature)
 146
 147#define EXT4_ATTR_OFFSET(_name,_mode,_id,_struct,_elname)       \
 148static struct ext4_attr ext4_attr_##_name = {                   \
 149        .attr = {.name = __stringify(_name), .mode = _mode },   \
 150        .attr_id = attr_##_id,                                  \
 151        .attr_ptr = ptr_##_struct##_offset,                     \
 152        .u = {                                                  \
 153                .offset = offsetof(struct _struct, _elname),\
 154        },                                                      \
 155}
 156
 157#define EXT4_RO_ATTR_ES_UI(_name,_elname)                               \
 158        EXT4_ATTR_OFFSET(_name, 0444, pointer_ui, ext4_super_block, _elname)
 159
 160#define EXT4_RW_ATTR_SBI_UI(_name,_elname)      \
 161        EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname)
 162
 163#define EXT4_ATTR_PTR(_name,_mode,_id,_ptr) \
 164static struct ext4_attr ext4_attr_##_name = {                   \
 165        .attr = {.name = __stringify(_name), .mode = _mode },   \
 166        .attr_id = attr_##_id,                                  \
 167        .attr_ptr = ptr_explicit,                               \
 168        .u = {                                                  \
 169                .explicit_ptr = _ptr,                           \
 170        },                                                      \
 171}
 172
 173#define ATTR_LIST(name) &ext4_attr_##name.attr
 174
 175EXT4_ATTR_FUNC(delayed_allocation_blocks, 0444);
 176EXT4_ATTR_FUNC(session_write_kbytes, 0444);
 177EXT4_ATTR_FUNC(lifetime_write_kbytes, 0444);
 178EXT4_ATTR_FUNC(reserved_clusters, 0644);
 179
 180EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, inode_readahead,
 181                 ext4_sb_info, s_inode_readahead_blks);
 182EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
 183EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
 184EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
 185EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
 186EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
 187EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
 188EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
 189EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
 190EXT4_ATTR(trigger_fs_error, 0200, trigger_test_error);
 191EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
 192EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
 193EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
 194EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
 195EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
 196EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
 197EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
 198EXT4_ATTR(first_error_time, 0444, first_error_time);
 199EXT4_ATTR(last_error_time, 0444, last_error_time);
 200EXT4_ATTR(journal_task, 0444, journal_task);
 201
 202static unsigned int old_bump_val = 128;
 203EXT4_ATTR_PTR(max_writeback_mb_bump, 0444, pointer_ui, &old_bump_val);
 204
 205static struct attribute *ext4_attrs[] = {
 206        ATTR_LIST(delayed_allocation_blocks),
 207        ATTR_LIST(session_write_kbytes),
 208        ATTR_LIST(lifetime_write_kbytes),
 209        ATTR_LIST(reserved_clusters),
 210        ATTR_LIST(inode_readahead_blks),
 211        ATTR_LIST(inode_goal),
 212        ATTR_LIST(mb_stats),
 213        ATTR_LIST(mb_max_to_scan),
 214        ATTR_LIST(mb_min_to_scan),
 215        ATTR_LIST(mb_order2_req),
 216        ATTR_LIST(mb_stream_req),
 217        ATTR_LIST(mb_group_prealloc),
 218        ATTR_LIST(max_writeback_mb_bump),
 219        ATTR_LIST(extent_max_zeroout_kb),
 220        ATTR_LIST(trigger_fs_error),
 221        ATTR_LIST(err_ratelimit_interval_ms),
 222        ATTR_LIST(err_ratelimit_burst),
 223        ATTR_LIST(warning_ratelimit_interval_ms),
 224        ATTR_LIST(warning_ratelimit_burst),
 225        ATTR_LIST(msg_ratelimit_interval_ms),
 226        ATTR_LIST(msg_ratelimit_burst),
 227        ATTR_LIST(errors_count),
 228        ATTR_LIST(first_error_time),
 229        ATTR_LIST(last_error_time),
 230        ATTR_LIST(journal_task),
 231        NULL,
 232};
 233
 234/* Features this copy of ext4 supports */
 235EXT4_ATTR_FEATURE(lazy_itable_init);
 236EXT4_ATTR_FEATURE(batched_discard);
 237EXT4_ATTR_FEATURE(meta_bg_resize);
 238#ifdef CONFIG_FS_ENCRYPTION
 239EXT4_ATTR_FEATURE(encryption);
 240#endif
 241#ifdef CONFIG_UNICODE
 242EXT4_ATTR_FEATURE(casefold);
 243#endif
 244EXT4_ATTR_FEATURE(metadata_csum_seed);
 245
 246static struct attribute *ext4_feat_attrs[] = {
 247        ATTR_LIST(lazy_itable_init),
 248        ATTR_LIST(batched_discard),
 249        ATTR_LIST(meta_bg_resize),
 250#ifdef CONFIG_FS_ENCRYPTION
 251        ATTR_LIST(encryption),
 252#endif
 253#ifdef CONFIG_UNICODE
 254        ATTR_LIST(casefold),
 255#endif
 256        ATTR_LIST(metadata_csum_seed),
 257        NULL,
 258};
 259
 260static void *calc_ptr(struct ext4_attr *a, struct ext4_sb_info *sbi)
 261{
 262        switch (a->attr_ptr) {
 263        case ptr_explicit:
 264                return a->u.explicit_ptr;
 265        case ptr_ext4_sb_info_offset:
 266                return (void *) (((char *) sbi) + a->u.offset);
 267        case ptr_ext4_super_block_offset:
 268                return (void *) (((char *) sbi->s_es) + a->u.offset);
 269        }
 270        return NULL;
 271}
 272
 273static ssize_t __print_tstamp(char *buf, __le32 lo, __u8 hi)
 274{
 275        return snprintf(buf, PAGE_SIZE, "%lld",
 276                        ((time64_t)hi << 32) + le32_to_cpu(lo));
 277}
 278
 279#define print_tstamp(buf, es, tstamp) \
 280        __print_tstamp(buf, (es)->tstamp, (es)->tstamp ## _hi)
 281
 282static ssize_t ext4_attr_show(struct kobject *kobj,
 283                              struct attribute *attr, char *buf)
 284{
 285        struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
 286                                                s_kobj);
 287        struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
 288        void *ptr = calc_ptr(a, sbi);
 289
 290        switch (a->attr_id) {
 291        case attr_delayed_allocation_blocks:
 292                return snprintf(buf, PAGE_SIZE, "%llu\n",
 293                                (s64) EXT4_C2B(sbi,
 294                       percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
 295        case attr_session_write_kbytes:
 296                return session_write_kbytes_show(sbi, buf);
 297        case attr_lifetime_write_kbytes:
 298                return lifetime_write_kbytes_show(sbi, buf);
 299        case attr_reserved_clusters:
 300                return snprintf(buf, PAGE_SIZE, "%llu\n",
 301                                (unsigned long long)
 302                                atomic64_read(&sbi->s_resv_clusters));
 303        case attr_inode_readahead:
 304        case attr_pointer_ui:
 305                if (!ptr)
 306                        return 0;
 307                if (a->attr_ptr == ptr_ext4_super_block_offset)
 308                        return snprintf(buf, PAGE_SIZE, "%u\n",
 309                                        le32_to_cpup(ptr));
 310                else
 311                        return snprintf(buf, PAGE_SIZE, "%u\n",
 312                                        *((unsigned int *) ptr));
 313        case attr_pointer_atomic:
 314                if (!ptr)
 315                        return 0;
 316                return snprintf(buf, PAGE_SIZE, "%d\n",
 317                                atomic_read((atomic_t *) ptr));
 318        case attr_feature:
 319                return snprintf(buf, PAGE_SIZE, "supported\n");
 320        case attr_first_error_time:
 321                return print_tstamp(buf, sbi->s_es, s_first_error_time);
 322        case attr_last_error_time:
 323                return print_tstamp(buf, sbi->s_es, s_last_error_time);
 324        case attr_journal_task:
 325                return journal_task_show(sbi, buf);
 326        }
 327
 328        return 0;
 329}
 330
 331static ssize_t ext4_attr_store(struct kobject *kobj,
 332                               struct attribute *attr,
 333                               const char *buf, size_t len)
 334{
 335        struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
 336                                                s_kobj);
 337        struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
 338        void *ptr = calc_ptr(a, sbi);
 339        unsigned long t;
 340        int ret;
 341
 342        switch (a->attr_id) {
 343        case attr_reserved_clusters:
 344                return reserved_clusters_store(sbi, buf, len);
 345        case attr_pointer_ui:
 346                if (!ptr)
 347                        return 0;
 348                ret = kstrtoul(skip_spaces(buf), 0, &t);
 349                if (ret)
 350                        return ret;
 351                if (a->attr_ptr == ptr_ext4_super_block_offset)
 352                        *((__le32 *) ptr) = cpu_to_le32(t);
 353                else
 354                        *((unsigned int *) ptr) = t;
 355                return len;
 356        case attr_inode_readahead:
 357                return inode_readahead_blks_store(sbi, buf, len);
 358        case attr_trigger_test_error:
 359                return trigger_test_error(sbi, buf, len);
 360        }
 361        return 0;
 362}
 363
 364static void ext4_sb_release(struct kobject *kobj)
 365{
 366        struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
 367                                                s_kobj);
 368        complete(&sbi->s_kobj_unregister);
 369}
 370
 371static const struct sysfs_ops ext4_attr_ops = {
 372        .show   = ext4_attr_show,
 373        .store  = ext4_attr_store,
 374};
 375
 376static struct kobj_type ext4_sb_ktype = {
 377        .default_attrs  = ext4_attrs,
 378        .sysfs_ops      = &ext4_attr_ops,
 379        .release        = ext4_sb_release,
 380};
 381
 382static struct kobj_type ext4_feat_ktype = {
 383        .default_attrs  = ext4_feat_attrs,
 384        .sysfs_ops      = &ext4_attr_ops,
 385        .release        = (void (*)(struct kobject *))kfree,
 386};
 387
 388static struct kobject *ext4_root;
 389
 390static struct kobject *ext4_feat;
 391
 392int ext4_register_sysfs(struct super_block *sb)
 393{
 394        struct ext4_sb_info *sbi = EXT4_SB(sb);
 395        int err;
 396
 397        init_completion(&sbi->s_kobj_unregister);
 398        err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, ext4_root,
 399                                   "%s", sb->s_id);
 400        if (err) {
 401                kobject_put(&sbi->s_kobj);
 402                wait_for_completion(&sbi->s_kobj_unregister);
 403                return err;
 404        }
 405
 406        if (ext4_proc_root)
 407                sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
 408        if (sbi->s_proc) {
 409                proc_create_single_data("options", S_IRUGO, sbi->s_proc,
 410                                ext4_seq_options_show, sb);
 411                proc_create_single_data("es_shrinker_info", S_IRUGO,
 412                                sbi->s_proc, ext4_seq_es_shrinker_info_show,
 413                                sb);
 414                proc_create_seq_data("mb_groups", S_IRUGO, sbi->s_proc,
 415                                &ext4_mb_seq_groups_ops, sb);
 416        }
 417        return 0;
 418}
 419
 420void ext4_unregister_sysfs(struct super_block *sb)
 421{
 422        struct ext4_sb_info *sbi = EXT4_SB(sb);
 423
 424        if (sbi->s_proc)
 425                remove_proc_subtree(sb->s_id, ext4_proc_root);
 426        kobject_del(&sbi->s_kobj);
 427}
 428
 429int __init ext4_init_sysfs(void)
 430{
 431        int ret;
 432
 433        ext4_root = kobject_create_and_add("ext4", fs_kobj);
 434        if (!ext4_root)
 435                return -ENOMEM;
 436
 437        ext4_feat = kzalloc(sizeof(*ext4_feat), GFP_KERNEL);
 438        if (!ext4_feat) {
 439                ret = -ENOMEM;
 440                goto root_err;
 441        }
 442
 443        ret = kobject_init_and_add(ext4_feat, &ext4_feat_ktype,
 444                                   ext4_root, "features");
 445        if (ret)
 446                goto feat_err;
 447
 448        ext4_proc_root = proc_mkdir(proc_dirname, NULL);
 449        return ret;
 450
 451feat_err:
 452        kobject_put(ext4_feat);
 453        ext4_feat = NULL;
 454root_err:
 455        kobject_put(ext4_root);
 456        ext4_root = NULL;
 457        return ret;
 458}
 459
 460void ext4_exit_sysfs(void)
 461{
 462        kobject_put(ext4_feat);
 463        ext4_feat = NULL;
 464        kobject_put(ext4_root);
 465        ext4_root = NULL;
 466        remove_proc_entry(proc_dirname, NULL);
 467        ext4_proc_root = NULL;
 468}
 469
 470