LCOV - code coverage report
Current view: top level - fs/ext4 - sysfs.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 57 190 30.0 %
Date: 2023-07-31 20:08:22 Functions: 7 16 43.8 %

          Line data    Source code
       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             : #include <linux/part_stat.h>
      17             : 
      18             : #include "ext4.h"
      19             : #include "ext4_jbd2.h"
      20             : 
      21             : typedef enum {
      22             :         attr_noop,
      23             :         attr_delayed_allocation_blocks,
      24             :         attr_session_write_kbytes,
      25             :         attr_lifetime_write_kbytes,
      26             :         attr_reserved_clusters,
      27             :         attr_sra_exceeded_retry_limit,
      28             :         attr_inode_readahead,
      29             :         attr_trigger_test_error,
      30             :         attr_first_error_time,
      31             :         attr_last_error_time,
      32             :         attr_feature,
      33             :         attr_pointer_ui,
      34             :         attr_pointer_ul,
      35             :         attr_pointer_u64,
      36             :         attr_pointer_u8,
      37             :         attr_pointer_string,
      38             :         attr_pointer_atomic,
      39             :         attr_journal_task,
      40             : } attr_id_t;
      41             : 
      42             : typedef enum {
      43             :         ptr_explicit,
      44             :         ptr_ext4_sb_info_offset,
      45             :         ptr_ext4_super_block_offset,
      46             : } attr_ptr_t;
      47             : 
      48             : static const char proc_dirname[] = "fs/ext4";
      49             : static struct proc_dir_entry *ext4_proc_root;
      50             : 
      51             : struct ext4_attr {
      52             :         struct attribute attr;
      53             :         short attr_id;
      54             :         short attr_ptr;
      55             :         unsigned short attr_size;
      56             :         union {
      57             :                 int offset;
      58             :                 void *explicit_ptr;
      59             :         } u;
      60             : };
      61             : 
      62           0 : static ssize_t session_write_kbytes_show(struct ext4_sb_info *sbi, char *buf)
      63             : {
      64           0 :         struct super_block *sb = sbi->s_buddy_cache->i_sb;
      65             : 
      66           0 :         return sysfs_emit(buf, "%lu\n",
      67           0 :                         (part_stat_read(sb->s_bdev, sectors[STAT_WRITE]) -
      68           0 :                          sbi->s_sectors_written_start) >> 1);
      69             : }
      70             : 
      71           0 : static ssize_t lifetime_write_kbytes_show(struct ext4_sb_info *sbi, char *buf)
      72             : {
      73           0 :         struct super_block *sb = sbi->s_buddy_cache->i_sb;
      74             : 
      75           0 :         return sysfs_emit(buf, "%llu\n",
      76           0 :                         (unsigned long long)(sbi->s_kbytes_written +
      77           0 :                         ((part_stat_read(sb->s_bdev, sectors[STAT_WRITE]) -
      78           0 :                           EXT4_SB(sb)->s_sectors_written_start) >> 1)));
      79             : }
      80             : 
      81           0 : static ssize_t inode_readahead_blks_store(struct ext4_sb_info *sbi,
      82             :                                           const char *buf, size_t count)
      83             : {
      84           0 :         unsigned long t;
      85           0 :         int ret;
      86             : 
      87           0 :         ret = kstrtoul(skip_spaces(buf), 0, &t);
      88           0 :         if (ret)
      89           0 :                 return ret;
      90             : 
      91           0 :         if (t && (!is_power_of_2(t) || t > 0x40000000))
      92             :                 return -EINVAL;
      93             : 
      94           0 :         sbi->s_inode_readahead_blks = t;
      95           0 :         return count;
      96             : }
      97             : 
      98           0 : static ssize_t reserved_clusters_store(struct ext4_sb_info *sbi,
      99             :                                    const char *buf, size_t count)
     100             : {
     101           0 :         unsigned long long val;
     102           0 :         ext4_fsblk_t clusters = (ext4_blocks_count(sbi->s_es) >>
     103           0 :                                  sbi->s_cluster_bits);
     104           0 :         int ret;
     105             : 
     106           0 :         ret = kstrtoull(skip_spaces(buf), 0, &val);
     107           0 :         if (ret || val >= clusters)
     108             :                 return -EINVAL;
     109             : 
     110           0 :         atomic64_set(&sbi->s_resv_clusters, val);
     111           0 :         return count;
     112             : }
     113             : 
     114           0 : static ssize_t trigger_test_error(struct ext4_sb_info *sbi,
     115             :                                   const char *buf, size_t count)
     116             : {
     117           0 :         int len = count;
     118             : 
     119           0 :         if (!capable(CAP_SYS_ADMIN))
     120             :                 return -EPERM;
     121             : 
     122           0 :         if (len && buf[len-1] == '\n')
     123           0 :                 len--;
     124             : 
     125           0 :         if (len)
     126           0 :                 ext4_error(sbi->s_sb, "%.*s", len, buf);
     127           0 :         return count;
     128             : }
     129             : 
     130           0 : static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf)
     131             : {
     132           0 :         if (!sbi->s_journal)
     133           0 :                 return sysfs_emit(buf, "<none>\n");
     134           0 :         return sysfs_emit(buf, "%d\n",
     135             :                         task_pid_vnr(sbi->s_journal->j_task));
     136             : }
     137             : 
     138             : #define EXT4_ATTR(_name,_mode,_id)                                      \
     139             : static struct ext4_attr ext4_attr_##_name = {                           \
     140             :         .attr = {.name = __stringify(_name), .mode = _mode },           \
     141             :         .attr_id = attr_##_id,                                          \
     142             : }
     143             : 
     144             : #define EXT4_ATTR_FUNC(_name,_mode)  EXT4_ATTR(_name,_mode,_name)
     145             : 
     146             : #define EXT4_ATTR_FEATURE(_name)   EXT4_ATTR(_name, 0444, feature)
     147             : 
     148             : #define EXT4_ATTR_OFFSET(_name,_mode,_id,_struct,_elname)       \
     149             : static struct ext4_attr ext4_attr_##_name = {                   \
     150             :         .attr = {.name = __stringify(_name), .mode = _mode },   \
     151             :         .attr_id = attr_##_id,                                  \
     152             :         .attr_ptr = ptr_##_struct##_offset,                     \
     153             :         .u = {                                                  \
     154             :                 .offset = offsetof(struct _struct, _elname),\
     155             :         },                                                      \
     156             : }
     157             : 
     158             : #define EXT4_ATTR_STRING(_name,_mode,_size,_struct,_elname)     \
     159             : static struct ext4_attr ext4_attr_##_name = {                   \
     160             :         .attr = {.name = __stringify(_name), .mode = _mode },   \
     161             :         .attr_id = attr_pointer_string,                         \
     162             :         .attr_size = _size,                                     \
     163             :         .attr_ptr = ptr_##_struct##_offset,                     \
     164             :         .u = {                                                  \
     165             :                 .offset = offsetof(struct _struct, _elname),\
     166             :         },                                                      \
     167             : }
     168             : 
     169             : #define EXT4_RO_ATTR_ES_UI(_name,_elname)                               \
     170             :         EXT4_ATTR_OFFSET(_name, 0444, pointer_ui, ext4_super_block, _elname)
     171             : 
     172             : #define EXT4_RO_ATTR_ES_U8(_name,_elname)                               \
     173             :         EXT4_ATTR_OFFSET(_name, 0444, pointer_u8, ext4_super_block, _elname)
     174             : 
     175             : #define EXT4_RO_ATTR_ES_U64(_name,_elname)                              \
     176             :         EXT4_ATTR_OFFSET(_name, 0444, pointer_u64, ext4_super_block, _elname)
     177             : 
     178             : #define EXT4_RO_ATTR_ES_STRING(_name,_elname,_size)                     \
     179             :         EXT4_ATTR_STRING(_name, 0444, _size, ext4_super_block, _elname)
     180             : 
     181             : #define EXT4_RW_ATTR_SBI_UI(_name,_elname)      \
     182             :         EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname)
     183             : 
     184             : #define EXT4_RW_ATTR_SBI_UL(_name,_elname)      \
     185             :         EXT4_ATTR_OFFSET(_name, 0644, pointer_ul, ext4_sb_info, _elname)
     186             : 
     187             : #define EXT4_RO_ATTR_SBI_ATOMIC(_name,_elname)  \
     188             :         EXT4_ATTR_OFFSET(_name, 0444, pointer_atomic, ext4_sb_info, _elname)
     189             : 
     190             : #define EXT4_ATTR_PTR(_name,_mode,_id,_ptr) \
     191             : static struct ext4_attr ext4_attr_##_name = {                   \
     192             :         .attr = {.name = __stringify(_name), .mode = _mode },   \
     193             :         .attr_id = attr_##_id,                                  \
     194             :         .attr_ptr = ptr_explicit,                               \
     195             :         .u = {                                                  \
     196             :                 .explicit_ptr = _ptr,                           \
     197             :         },                                                      \
     198             : }
     199             : 
     200             : #define ATTR_LIST(name) &ext4_attr_##name.attr
     201             : 
     202             : EXT4_ATTR_FUNC(delayed_allocation_blocks, 0444);
     203             : EXT4_ATTR_FUNC(session_write_kbytes, 0444);
     204             : EXT4_ATTR_FUNC(lifetime_write_kbytes, 0444);
     205             : EXT4_ATTR_FUNC(reserved_clusters, 0644);
     206             : EXT4_ATTR_FUNC(sra_exceeded_retry_limit, 0444);
     207             : 
     208             : EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, inode_readahead,
     209             :                  ext4_sb_info, s_inode_readahead_blks);
     210             : EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
     211             : EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
     212             : EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
     213             : EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
     214             : EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
     215             : EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
     216             : EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
     217             : EXT4_RW_ATTR_SBI_UI(mb_max_linear_groups, s_mb_max_linear_groups);
     218             : EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
     219             : EXT4_ATTR(trigger_fs_error, 0200, trigger_test_error);
     220             : EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
     221             : EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
     222             : EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
     223             : EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
     224             : EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
     225             : EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
     226             : EXT4_RW_ATTR_SBI_UI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order);
     227             : #ifdef CONFIG_EXT4_DEBUG
     228             : EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail);
     229             : #endif
     230             : EXT4_RO_ATTR_SBI_ATOMIC(warning_count, s_warning_count);
     231             : EXT4_RO_ATTR_SBI_ATOMIC(msg_count, s_msg_count);
     232             : EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
     233             : EXT4_RO_ATTR_ES_U8(first_error_errcode, s_first_error_errcode);
     234             : EXT4_RO_ATTR_ES_U8(last_error_errcode, s_last_error_errcode);
     235             : EXT4_RO_ATTR_ES_UI(first_error_ino, s_first_error_ino);
     236             : EXT4_RO_ATTR_ES_UI(last_error_ino, s_last_error_ino);
     237             : EXT4_RO_ATTR_ES_U64(first_error_block, s_first_error_block);
     238             : EXT4_RO_ATTR_ES_U64(last_error_block, s_last_error_block);
     239             : EXT4_RO_ATTR_ES_UI(first_error_line, s_first_error_line);
     240             : EXT4_RO_ATTR_ES_UI(last_error_line, s_last_error_line);
     241             : EXT4_RO_ATTR_ES_STRING(first_error_func, s_first_error_func, 32);
     242             : EXT4_RO_ATTR_ES_STRING(last_error_func, s_last_error_func, 32);
     243             : EXT4_ATTR(first_error_time, 0444, first_error_time);
     244             : EXT4_ATTR(last_error_time, 0444, last_error_time);
     245             : EXT4_ATTR(journal_task, 0444, journal_task);
     246             : EXT4_RW_ATTR_SBI_UI(mb_prefetch, s_mb_prefetch);
     247             : EXT4_RW_ATTR_SBI_UI(mb_prefetch_limit, s_mb_prefetch_limit);
     248             : EXT4_RW_ATTR_SBI_UL(last_trim_minblks, s_last_trim_minblks);
     249             : 
     250             : static unsigned int old_bump_val = 128;
     251             : EXT4_ATTR_PTR(max_writeback_mb_bump, 0444, pointer_ui, &old_bump_val);
     252             : 
     253             : static struct attribute *ext4_attrs[] = {
     254             :         ATTR_LIST(delayed_allocation_blocks),
     255             :         ATTR_LIST(session_write_kbytes),
     256             :         ATTR_LIST(lifetime_write_kbytes),
     257             :         ATTR_LIST(reserved_clusters),
     258             :         ATTR_LIST(sra_exceeded_retry_limit),
     259             :         ATTR_LIST(inode_readahead_blks),
     260             :         ATTR_LIST(inode_goal),
     261             :         ATTR_LIST(mb_stats),
     262             :         ATTR_LIST(mb_max_to_scan),
     263             :         ATTR_LIST(mb_min_to_scan),
     264             :         ATTR_LIST(mb_order2_req),
     265             :         ATTR_LIST(mb_stream_req),
     266             :         ATTR_LIST(mb_group_prealloc),
     267             :         ATTR_LIST(mb_max_linear_groups),
     268             :         ATTR_LIST(max_writeback_mb_bump),
     269             :         ATTR_LIST(extent_max_zeroout_kb),
     270             :         ATTR_LIST(trigger_fs_error),
     271             :         ATTR_LIST(err_ratelimit_interval_ms),
     272             :         ATTR_LIST(err_ratelimit_burst),
     273             :         ATTR_LIST(warning_ratelimit_interval_ms),
     274             :         ATTR_LIST(warning_ratelimit_burst),
     275             :         ATTR_LIST(msg_ratelimit_interval_ms),
     276             :         ATTR_LIST(msg_ratelimit_burst),
     277             :         ATTR_LIST(mb_best_avail_max_trim_order),
     278             :         ATTR_LIST(errors_count),
     279             :         ATTR_LIST(warning_count),
     280             :         ATTR_LIST(msg_count),
     281             :         ATTR_LIST(first_error_ino),
     282             :         ATTR_LIST(last_error_ino),
     283             :         ATTR_LIST(first_error_block),
     284             :         ATTR_LIST(last_error_block),
     285             :         ATTR_LIST(first_error_line),
     286             :         ATTR_LIST(last_error_line),
     287             :         ATTR_LIST(first_error_func),
     288             :         ATTR_LIST(last_error_func),
     289             :         ATTR_LIST(first_error_errcode),
     290             :         ATTR_LIST(last_error_errcode),
     291             :         ATTR_LIST(first_error_time),
     292             :         ATTR_LIST(last_error_time),
     293             :         ATTR_LIST(journal_task),
     294             : #ifdef CONFIG_EXT4_DEBUG
     295             :         ATTR_LIST(simulate_fail),
     296             : #endif
     297             :         ATTR_LIST(mb_prefetch),
     298             :         ATTR_LIST(mb_prefetch_limit),
     299             :         ATTR_LIST(last_trim_minblks),
     300             :         NULL,
     301             : };
     302             : ATTRIBUTE_GROUPS(ext4);
     303             : 
     304             : /* Features this copy of ext4 supports */
     305             : EXT4_ATTR_FEATURE(lazy_itable_init);
     306             : EXT4_ATTR_FEATURE(batched_discard);
     307             : EXT4_ATTR_FEATURE(meta_bg_resize);
     308             : #ifdef CONFIG_FS_ENCRYPTION
     309             : EXT4_ATTR_FEATURE(encryption);
     310             : EXT4_ATTR_FEATURE(test_dummy_encryption_v2);
     311             : #endif
     312             : #if IS_ENABLED(CONFIG_UNICODE)
     313             : EXT4_ATTR_FEATURE(casefold);
     314             : #endif
     315             : #ifdef CONFIG_FS_VERITY
     316             : EXT4_ATTR_FEATURE(verity);
     317             : #endif
     318             : EXT4_ATTR_FEATURE(metadata_csum_seed);
     319             : EXT4_ATTR_FEATURE(fast_commit);
     320             : #if IS_ENABLED(CONFIG_UNICODE) && defined(CONFIG_FS_ENCRYPTION)
     321             : EXT4_ATTR_FEATURE(encrypted_casefold);
     322             : #endif
     323             : 
     324             : static struct attribute *ext4_feat_attrs[] = {
     325             :         ATTR_LIST(lazy_itable_init),
     326             :         ATTR_LIST(batched_discard),
     327             :         ATTR_LIST(meta_bg_resize),
     328             : #ifdef CONFIG_FS_ENCRYPTION
     329             :         ATTR_LIST(encryption),
     330             :         ATTR_LIST(test_dummy_encryption_v2),
     331             : #endif
     332             : #if IS_ENABLED(CONFIG_UNICODE)
     333             :         ATTR_LIST(casefold),
     334             : #endif
     335             : #ifdef CONFIG_FS_VERITY
     336             :         ATTR_LIST(verity),
     337             : #endif
     338             :         ATTR_LIST(metadata_csum_seed),
     339             :         ATTR_LIST(fast_commit),
     340             : #if IS_ENABLED(CONFIG_UNICODE) && defined(CONFIG_FS_ENCRYPTION)
     341             :         ATTR_LIST(encrypted_casefold),
     342             : #endif
     343             :         NULL,
     344             : };
     345             : ATTRIBUTE_GROUPS(ext4_feat);
     346             : 
     347           9 : static void *calc_ptr(struct ext4_attr *a, struct ext4_sb_info *sbi)
     348             : {
     349           9 :         switch (a->attr_ptr) {
     350           0 :         case ptr_explicit:
     351           0 :                 return a->u.explicit_ptr;
     352           9 :         case ptr_ext4_sb_info_offset:
     353           9 :                 return (void *) (((char *) sbi) + a->u.offset);
     354           0 :         case ptr_ext4_super_block_offset:
     355           0 :                 return (void *) (((char *) sbi->s_es) + a->u.offset);
     356             :         }
     357             :         return NULL;
     358             : }
     359             : 
     360             : static ssize_t __print_tstamp(char *buf, __le32 lo, __u8 hi)
     361             : {
     362           0 :         return sysfs_emit(buf, "%lld\n",
     363           0 :                         ((time64_t)hi << 32) + le32_to_cpu(lo));
     364             : }
     365             : 
     366             : #define print_tstamp(buf, es, tstamp) \
     367             :         __print_tstamp(buf, (es)->tstamp, (es)->tstamp ## _hi)
     368             : 
     369           0 : static ssize_t ext4_attr_show(struct kobject *kobj,
     370             :                               struct attribute *attr, char *buf)
     371             : {
     372           0 :         struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
     373             :                                                 s_kobj);
     374           0 :         struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
     375           0 :         void *ptr = calc_ptr(a, sbi);
     376             : 
     377           0 :         switch (a->attr_id) {
     378           0 :         case attr_delayed_allocation_blocks:
     379           0 :                 return sysfs_emit(buf, "%llu\n",
     380           0 :                                 (s64) EXT4_C2B(sbi,
     381             :                        percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
     382           0 :         case attr_session_write_kbytes:
     383           0 :                 return session_write_kbytes_show(sbi, buf);
     384           0 :         case attr_lifetime_write_kbytes:
     385           0 :                 return lifetime_write_kbytes_show(sbi, buf);
     386           0 :         case attr_reserved_clusters:
     387           0 :                 return sysfs_emit(buf, "%llu\n",
     388             :                                 (unsigned long long)
     389             :                                 atomic64_read(&sbi->s_resv_clusters));
     390           0 :         case attr_sra_exceeded_retry_limit:
     391           0 :                 return sysfs_emit(buf, "%llu\n",
     392             :                                 (unsigned long long)
     393           0 :                         percpu_counter_sum(&sbi->s_sra_exceeded_retry_limit));
     394           0 :         case attr_inode_readahead:
     395             :         case attr_pointer_ui:
     396           0 :                 if (!ptr)
     397             :                         return 0;
     398           0 :                 if (a->attr_ptr == ptr_ext4_super_block_offset)
     399           0 :                         return sysfs_emit(buf, "%u\n",
     400             :                                         le32_to_cpup(ptr));
     401             :                 else
     402           0 :                         return sysfs_emit(buf, "%u\n",
     403             :                                         *((unsigned int *) ptr));
     404           0 :         case attr_pointer_ul:
     405           0 :                 if (!ptr)
     406             :                         return 0;
     407           0 :                 return sysfs_emit(buf, "%lu\n",
     408             :                                 *((unsigned long *) ptr));
     409           0 :         case attr_pointer_u8:
     410           0 :                 if (!ptr)
     411             :                         return 0;
     412           0 :                 return sysfs_emit(buf, "%u\n",
     413           0 :                                 *((unsigned char *) ptr));
     414           0 :         case attr_pointer_u64:
     415           0 :                 if (!ptr)
     416             :                         return 0;
     417           0 :                 if (a->attr_ptr == ptr_ext4_super_block_offset)
     418           0 :                         return sysfs_emit(buf, "%llu\n",
     419             :                                         le64_to_cpup(ptr));
     420             :                 else
     421           0 :                         return sysfs_emit(buf, "%llu\n",
     422             :                                         *((unsigned long long *) ptr));
     423           0 :         case attr_pointer_string:
     424           0 :                 if (!ptr)
     425             :                         return 0;
     426           0 :                 return sysfs_emit(buf, "%.*s\n", a->attr_size,
     427             :                                 (char *) ptr);
     428           0 :         case attr_pointer_atomic:
     429           0 :                 if (!ptr)
     430             :                         return 0;
     431           0 :                 return sysfs_emit(buf, "%d\n",
     432             :                                 atomic_read((atomic_t *) ptr));
     433           0 :         case attr_feature:
     434           0 :                 return sysfs_emit(buf, "supported\n");
     435           0 :         case attr_first_error_time:
     436           0 :                 return print_tstamp(buf, sbi->s_es, s_first_error_time);
     437           0 :         case attr_last_error_time:
     438           0 :                 return print_tstamp(buf, sbi->s_es, s_last_error_time);
     439           0 :         case attr_journal_task:
     440           0 :                 return journal_task_show(sbi, buf);
     441             :         }
     442             : 
     443             :         return 0;
     444             : }
     445             : 
     446           9 : static ssize_t ext4_attr_store(struct kobject *kobj,
     447             :                                struct attribute *attr,
     448             :                                const char *buf, size_t len)
     449             : {
     450           9 :         struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
     451             :                                                 s_kobj);
     452           9 :         struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
     453           9 :         void *ptr = calc_ptr(a, sbi);
     454           9 :         unsigned long t;
     455           9 :         int ret;
     456             : 
     457           9 :         switch (a->attr_id) {
     458           0 :         case attr_reserved_clusters:
     459           0 :                 return reserved_clusters_store(sbi, buf, len);
     460           9 :         case attr_pointer_ui:
     461           9 :                 if (!ptr)
     462             :                         return 0;
     463           9 :                 ret = kstrtoul(skip_spaces(buf), 0, &t);
     464           9 :                 if (ret)
     465           0 :                         return ret;
     466           9 :                 if (a->attr_ptr == ptr_ext4_super_block_offset)
     467           0 :                         *((__le32 *) ptr) = cpu_to_le32(t);
     468             :                 else
     469           9 :                         *((unsigned int *) ptr) = t;
     470           9 :                 return len;
     471           0 :         case attr_pointer_ul:
     472           0 :                 if (!ptr)
     473             :                         return 0;
     474           0 :                 ret = kstrtoul(skip_spaces(buf), 0, &t);
     475           0 :                 if (ret)
     476           0 :                         return ret;
     477           0 :                 *((unsigned long *) ptr) = t;
     478           0 :                 return len;
     479           0 :         case attr_inode_readahead:
     480           0 :                 return inode_readahead_blks_store(sbi, buf, len);
     481           0 :         case attr_trigger_test_error:
     482           0 :                 return trigger_test_error(sbi, buf, len);
     483             :         }
     484             :         return 0;
     485             : }
     486             : 
     487        2518 : static void ext4_sb_release(struct kobject *kobj)
     488             : {
     489        2518 :         struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
     490             :                                                 s_kobj);
     491        2518 :         complete(&sbi->s_kobj_unregister);
     492        2518 : }
     493             : 
     494           0 : static void ext4_feat_release(struct kobject *kobj)
     495             : {
     496           0 :         kfree(kobj);
     497           0 : }
     498             : 
     499             : static const struct sysfs_ops ext4_attr_ops = {
     500             :         .show   = ext4_attr_show,
     501             :         .store  = ext4_attr_store,
     502             : };
     503             : 
     504             : static const struct kobj_type ext4_sb_ktype = {
     505             :         .default_groups = ext4_groups,
     506             :         .sysfs_ops      = &ext4_attr_ops,
     507             :         .release        = ext4_sb_release,
     508             : };
     509             : 
     510             : static const struct kobj_type ext4_feat_ktype = {
     511             :         .default_groups = ext4_feat_groups,
     512             :         .sysfs_ops      = &ext4_attr_ops,
     513             :         .release        = ext4_feat_release,
     514             : };
     515             : 
     516         417 : void ext4_notify_error_sysfs(struct ext4_sb_info *sbi)
     517             : {
     518         417 :         sysfs_notify(&sbi->s_kobj, NULL, "errors_count");
     519         417 : }
     520             : 
     521             : static struct kobject *ext4_root;
     522             : 
     523             : static struct kobject *ext4_feat;
     524             : 
     525        2517 : int ext4_register_sysfs(struct super_block *sb)
     526             : {
     527        2517 :         struct ext4_sb_info *sbi = EXT4_SB(sb);
     528        2517 :         int err;
     529             : 
     530        2517 :         init_completion(&sbi->s_kobj_unregister);
     531        2517 :         err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, ext4_root,
     532        2517 :                                    "%s", sb->s_id);
     533        2517 :         if (err) {
     534           0 :                 kobject_put(&sbi->s_kobj);
     535           0 :                 wait_for_completion(&sbi->s_kobj_unregister);
     536           0 :                 return err;
     537             :         }
     538             : 
     539        2517 :         if (ext4_proc_root)
     540        2517 :                 sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
     541        2517 :         if (sbi->s_proc) {
     542        2517 :                 proc_create_single_data("options", S_IRUGO, sbi->s_proc,
     543             :                                 ext4_seq_options_show, sb);
     544        2517 :                 proc_create_single_data("es_shrinker_info", S_IRUGO,
     545             :                                 sbi->s_proc, ext4_seq_es_shrinker_info_show,
     546             :                                 sb);
     547        2517 :                 proc_create_single_data("fc_info", 0444, sbi->s_proc,
     548             :                                         ext4_fc_info_show, sb);
     549        2517 :                 proc_create_seq_data("mb_groups", S_IRUGO, sbi->s_proc,
     550             :                                 &ext4_mb_seq_groups_ops, sb);
     551        2517 :                 proc_create_single_data("mb_stats", 0444, sbi->s_proc,
     552             :                                 ext4_seq_mb_stats_show, sb);
     553        2517 :                 proc_create_seq_data("mb_structs_summary", 0444, sbi->s_proc,
     554             :                                 &ext4_mb_seq_structs_summary_ops, sb);
     555             :         }
     556             :         return 0;
     557             : }
     558             : 
     559        2518 : void ext4_unregister_sysfs(struct super_block *sb)
     560             : {
     561        2518 :         struct ext4_sb_info *sbi = EXT4_SB(sb);
     562             : 
     563        2518 :         if (sbi->s_proc)
     564        2518 :                 remove_proc_subtree(sb->s_id, ext4_proc_root);
     565        2518 :         kobject_del(&sbi->s_kobj);
     566        2518 : }
     567             : 
     568          12 : int __init ext4_init_sysfs(void)
     569             : {
     570          12 :         int ret;
     571             : 
     572          12 :         ext4_root = kobject_create_and_add("ext4", fs_kobj);
     573          12 :         if (!ext4_root)
     574             :                 return -ENOMEM;
     575             : 
     576          12 :         ext4_feat = kzalloc(sizeof(*ext4_feat), GFP_KERNEL);
     577          12 :         if (!ext4_feat) {
     578           0 :                 ret = -ENOMEM;
     579           0 :                 goto root_err;
     580             :         }
     581             : 
     582          12 :         ret = kobject_init_and_add(ext4_feat, &ext4_feat_ktype,
     583             :                                    ext4_root, "features");
     584          12 :         if (ret)
     585           0 :                 goto feat_err;
     586             : 
     587          12 :         ext4_proc_root = proc_mkdir(proc_dirname, NULL);
     588          12 :         return ret;
     589             : 
     590             : feat_err:
     591           0 :         kobject_put(ext4_feat);
     592           0 :         ext4_feat = NULL;
     593           0 : root_err:
     594           0 :         kobject_put(ext4_root);
     595           0 :         ext4_root = NULL;
     596           0 :         return ret;
     597             : }
     598             : 
     599           0 : void ext4_exit_sysfs(void)
     600             : {
     601           0 :         kobject_put(ext4_feat);
     602           0 :         ext4_feat = NULL;
     603           0 :         kobject_put(ext4_root);
     604           0 :         ext4_root = NULL;
     605           0 :         remove_proc_entry(proc_dirname, NULL);
     606           0 :         ext4_proc_root = NULL;
     607           0 : }
     608             : 

Generated by: LCOV version 1.14