LCOV - code coverage report
Current view: top level - fs/ext4 - sysfs.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 24 182 13.2 %
Date: 2021-04-22 12:43:58 Functions: 2 14 14.3 %

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

Generated by: LCOV version 1.14