sysfs.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. #include <linux/time.h>
  10. #include <linux/fs.h>
  11. #include <linux/seq_file.h>
  12. #include <linux/proc_fs.h>
  13. #include "ext4.h"
  14. #include "ext4_jbd2.h"
  15. typedef enum {
  16. attr_noop,
  17. attr_delayed_allocation_blocks,
  18. attr_session_write_kbytes,
  19. attr_lifetime_write_kbytes,
  20. attr_reserved_clusters,
  21. attr_inode_readahead,
  22. attr_trigger_test_error,
  23. attr_feature,
  24. attr_pointer_ui,
  25. attr_pointer_atomic,
  26. } attr_id_t;
  27. typedef enum {
  28. ptr_explicit,
  29. ptr_ext4_sb_info_offset,
  30. ptr_ext4_super_block_offset,
  31. } attr_ptr_t;
  32. static const char *proc_dirname = "fs/ext4";
  33. static struct proc_dir_entry *ext4_proc_root;
  34. struct ext4_attr {
  35. struct attribute attr;
  36. short attr_id;
  37. short attr_ptr;
  38. union {
  39. int offset;
  40. void *explicit_ptr;
  41. } u;
  42. };
  43. static ssize_t session_write_kbytes_show(struct ext4_attr *a,
  44. struct ext4_sb_info *sbi, char *buf)
  45. {
  46. struct super_block *sb = sbi->s_buddy_cache->i_sb;
  47. if (!sb->s_bdev->bd_part)
  48. return snprintf(buf, PAGE_SIZE, "0\n");
  49. return snprintf(buf, PAGE_SIZE, "%lu\n",
  50. (part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
  51. sbi->s_sectors_written_start) >> 1);
  52. }
  53. static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
  54. struct ext4_sb_info *sbi, char *buf)
  55. {
  56. struct super_block *sb = sbi->s_buddy_cache->i_sb;
  57. if (!sb->s_bdev->bd_part)
  58. return snprintf(buf, PAGE_SIZE, "0\n");
  59. return snprintf(buf, PAGE_SIZE, "%llu\n",
  60. (unsigned long long)(sbi->s_kbytes_written +
  61. ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
  62. EXT4_SB(sb)->s_sectors_written_start) >> 1)));
  63. }
  64. static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
  65. struct ext4_sb_info *sbi,
  66. const char *buf, size_t count)
  67. {
  68. unsigned long t;
  69. int ret;
  70. ret = kstrtoul(skip_spaces(buf), 0, &t);
  71. if (ret)
  72. return ret;
  73. if (t && (!is_power_of_2(t) || t > 0x40000000))
  74. return -EINVAL;
  75. sbi->s_inode_readahead_blks = t;
  76. return count;
  77. }
  78. static ssize_t reserved_clusters_store(struct ext4_attr *a,
  79. struct ext4_sb_info *sbi,
  80. const char *buf, size_t count)
  81. {
  82. unsigned long long val;
  83. ext4_fsblk_t clusters = (ext4_blocks_count(sbi->s_es) >>
  84. sbi->s_cluster_bits);
  85. int ret;
  86. ret = kstrtoull(skip_spaces(buf), 0, &val);
  87. if (ret || val >= clusters)
  88. return -EINVAL;
  89. atomic64_set(&sbi->s_resv_clusters, val);
  90. return count;
  91. }
  92. static ssize_t trigger_test_error(struct ext4_attr *a,
  93. struct ext4_sb_info *sbi,
  94. const char *buf, size_t count)
  95. {
  96. int len = count;
  97. if (!capable(CAP_SYS_ADMIN))
  98. return -EPERM;
  99. if (len && buf[len-1] == '\n')
  100. len--;
  101. if (len)
  102. ext4_error(sbi->s_sb, "%.*s", len, buf);
  103. return count;
  104. }
  105. #define EXT4_ATTR(_name,_mode,_id) \
  106. static struct ext4_attr ext4_attr_##_name = { \
  107. .attr = {.name = __stringify(_name), .mode = _mode }, \
  108. .attr_id = attr_##_id, \
  109. }
  110. #define EXT4_ATTR_FUNC(_name,_mode) EXT4_ATTR(_name,_mode,_name)
  111. #define EXT4_ATTR_FEATURE(_name) EXT4_ATTR(_name, 0444, feature)
  112. #define EXT4_ATTR_OFFSET(_name,_mode,_id,_struct,_elname) \
  113. static struct ext4_attr ext4_attr_##_name = { \
  114. .attr = {.name = __stringify(_name), .mode = _mode }, \
  115. .attr_id = attr_##_id, \
  116. .attr_ptr = ptr_##_struct##_offset, \
  117. .u = { \
  118. .offset = offsetof(struct _struct, _elname),\
  119. }, \
  120. }
  121. #define EXT4_RO_ATTR_ES_UI(_name,_elname) \
  122. EXT4_ATTR_OFFSET(_name, 0444, pointer_ui, ext4_super_block, _elname)
  123. #define EXT4_RW_ATTR_SBI_UI(_name,_elname) \
  124. EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname)
  125. #define EXT4_ATTR_PTR(_name,_mode,_id,_ptr) \
  126. static struct ext4_attr ext4_attr_##_name = { \
  127. .attr = {.name = __stringify(_name), .mode = _mode }, \
  128. .attr_id = attr_##_id, \
  129. .attr_ptr = ptr_explicit, \
  130. .u = { \
  131. .explicit_ptr = _ptr, \
  132. }, \
  133. }
  134. #define ATTR_LIST(name) &ext4_attr_##name.attr
  135. EXT4_ATTR_FUNC(delayed_allocation_blocks, 0444);
  136. EXT4_ATTR_FUNC(session_write_kbytes, 0444);
  137. EXT4_ATTR_FUNC(lifetime_write_kbytes, 0444);
  138. EXT4_ATTR_FUNC(reserved_clusters, 0644);
  139. EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, inode_readahead,
  140. ext4_sb_info, s_inode_readahead_blks);
  141. EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
  142. EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
  143. EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
  144. EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
  145. EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
  146. EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
  147. EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
  148. EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
  149. EXT4_ATTR(trigger_fs_error, 0200, trigger_test_error);
  150. EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
  151. EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
  152. EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
  153. EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
  154. EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
  155. EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
  156. EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
  157. EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time);
  158. EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time);
  159. static unsigned int old_bump_val = 128;
  160. EXT4_ATTR_PTR(max_writeback_mb_bump, 0444, pointer_ui, &old_bump_val);
  161. static struct attribute *ext4_attrs[] = {
  162. ATTR_LIST(delayed_allocation_blocks),
  163. ATTR_LIST(session_write_kbytes),
  164. ATTR_LIST(lifetime_write_kbytes),
  165. ATTR_LIST(reserved_clusters),
  166. ATTR_LIST(inode_readahead_blks),
  167. ATTR_LIST(inode_goal),
  168. ATTR_LIST(mb_stats),
  169. ATTR_LIST(mb_max_to_scan),
  170. ATTR_LIST(mb_min_to_scan),
  171. ATTR_LIST(mb_order2_req),
  172. ATTR_LIST(mb_stream_req),
  173. ATTR_LIST(mb_group_prealloc),
  174. ATTR_LIST(max_writeback_mb_bump),
  175. ATTR_LIST(extent_max_zeroout_kb),
  176. ATTR_LIST(trigger_fs_error),
  177. ATTR_LIST(err_ratelimit_interval_ms),
  178. ATTR_LIST(err_ratelimit_burst),
  179. ATTR_LIST(warning_ratelimit_interval_ms),
  180. ATTR_LIST(warning_ratelimit_burst),
  181. ATTR_LIST(msg_ratelimit_interval_ms),
  182. ATTR_LIST(msg_ratelimit_burst),
  183. ATTR_LIST(errors_count),
  184. ATTR_LIST(first_error_time),
  185. ATTR_LIST(last_error_time),
  186. NULL,
  187. };
  188. /* Features this copy of ext4 supports */
  189. EXT4_ATTR_FEATURE(lazy_itable_init);
  190. EXT4_ATTR_FEATURE(batched_discard);
  191. EXT4_ATTR_FEATURE(meta_bg_resize);
  192. #ifdef CONFIG_EXT4_FS_ENCRYPTION
  193. EXT4_ATTR_FEATURE(encryption);
  194. #endif
  195. EXT4_ATTR_FEATURE(metadata_csum_seed);
  196. static struct attribute *ext4_feat_attrs[] = {
  197. ATTR_LIST(lazy_itable_init),
  198. ATTR_LIST(batched_discard),
  199. ATTR_LIST(meta_bg_resize),
  200. #ifdef CONFIG_EXT4_FS_ENCRYPTION
  201. ATTR_LIST(encryption),
  202. #endif
  203. ATTR_LIST(metadata_csum_seed),
  204. NULL,
  205. };
  206. static void *calc_ptr(struct ext4_attr *a, struct ext4_sb_info *sbi)
  207. {
  208. switch (a->attr_ptr) {
  209. case ptr_explicit:
  210. return a->u.explicit_ptr;
  211. case ptr_ext4_sb_info_offset:
  212. return (void *) (((char *) sbi) + a->u.offset);
  213. case ptr_ext4_super_block_offset:
  214. return (void *) (((char *) sbi->s_es) + a->u.offset);
  215. }
  216. return NULL;
  217. }
  218. static ssize_t ext4_attr_show(struct kobject *kobj,
  219. struct attribute *attr, char *buf)
  220. {
  221. struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
  222. s_kobj);
  223. struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
  224. void *ptr = calc_ptr(a, sbi);
  225. switch (a->attr_id) {
  226. case attr_delayed_allocation_blocks:
  227. return snprintf(buf, PAGE_SIZE, "%llu\n",
  228. (s64) EXT4_C2B(sbi,
  229. percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
  230. case attr_session_write_kbytes:
  231. return session_write_kbytes_show(a, sbi, buf);
  232. case attr_lifetime_write_kbytes:
  233. return lifetime_write_kbytes_show(a, sbi, buf);
  234. case attr_reserved_clusters:
  235. return snprintf(buf, PAGE_SIZE, "%llu\n",
  236. (unsigned long long)
  237. atomic64_read(&sbi->s_resv_clusters));
  238. case attr_inode_readahead:
  239. case attr_pointer_ui:
  240. if (!ptr)
  241. return 0;
  242. if (a->attr_ptr == ptr_ext4_super_block_offset)
  243. return snprintf(buf, PAGE_SIZE, "%u\n",
  244. le32_to_cpup(ptr));
  245. else
  246. return snprintf(buf, PAGE_SIZE, "%u\n",
  247. *((unsigned int *) ptr));
  248. case attr_pointer_atomic:
  249. if (!ptr)
  250. return 0;
  251. return snprintf(buf, PAGE_SIZE, "%d\n",
  252. atomic_read((atomic_t *) ptr));
  253. case attr_feature:
  254. return snprintf(buf, PAGE_SIZE, "supported\n");
  255. }
  256. return 0;
  257. }
  258. static ssize_t ext4_attr_store(struct kobject *kobj,
  259. struct attribute *attr,
  260. const char *buf, size_t len)
  261. {
  262. struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
  263. s_kobj);
  264. struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
  265. void *ptr = calc_ptr(a, sbi);
  266. unsigned long t;
  267. int ret;
  268. switch (a->attr_id) {
  269. case attr_reserved_clusters:
  270. return reserved_clusters_store(a, sbi, buf, len);
  271. case attr_pointer_ui:
  272. if (!ptr)
  273. return 0;
  274. ret = kstrtoul(skip_spaces(buf), 0, &t);
  275. if (ret)
  276. return ret;
  277. if (a->attr_ptr == ptr_ext4_super_block_offset)
  278. *((__le32 *) ptr) = cpu_to_le32(t);
  279. else
  280. *((unsigned int *) ptr) = t;
  281. return len;
  282. case attr_inode_readahead:
  283. return inode_readahead_blks_store(a, sbi, buf, len);
  284. case attr_trigger_test_error:
  285. return trigger_test_error(a, sbi, buf, len);
  286. }
  287. return 0;
  288. }
  289. static void ext4_sb_release(struct kobject *kobj)
  290. {
  291. struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
  292. s_kobj);
  293. complete(&sbi->s_kobj_unregister);
  294. }
  295. static const struct sysfs_ops ext4_attr_ops = {
  296. .show = ext4_attr_show,
  297. .store = ext4_attr_store,
  298. };
  299. static struct kobj_type ext4_sb_ktype = {
  300. .default_attrs = ext4_attrs,
  301. .sysfs_ops = &ext4_attr_ops,
  302. .release = ext4_sb_release,
  303. };
  304. static struct kobj_type ext4_ktype = {
  305. .sysfs_ops = &ext4_attr_ops,
  306. };
  307. static struct kset ext4_kset = {
  308. .kobj = {.ktype = &ext4_ktype},
  309. };
  310. static struct kobj_type ext4_feat_ktype = {
  311. .default_attrs = ext4_feat_attrs,
  312. .sysfs_ops = &ext4_attr_ops,
  313. };
  314. static struct kobject ext4_feat = {
  315. .kset = &ext4_kset,
  316. };
  317. #define PROC_FILE_SHOW_DEFN(name) \
  318. static int name##_open(struct inode *inode, struct file *file) \
  319. { \
  320. return single_open(file, ext4_seq_##name##_show, PDE_DATA(inode)); \
  321. } \
  322. \
  323. static const struct file_operations ext4_seq_##name##_fops = { \
  324. .owner = THIS_MODULE, \
  325. .open = name##_open, \
  326. .read = seq_read, \
  327. .llseek = seq_lseek, \
  328. .release = single_release, \
  329. }
  330. #define PROC_FILE_LIST(name) \
  331. { __stringify(name), &ext4_seq_##name##_fops }
  332. PROC_FILE_SHOW_DEFN(es_shrinker_info);
  333. PROC_FILE_SHOW_DEFN(options);
  334. static struct ext4_proc_files {
  335. const char *name;
  336. const struct file_operations *fops;
  337. } proc_files[] = {
  338. PROC_FILE_LIST(options),
  339. PROC_FILE_LIST(es_shrinker_info),
  340. PROC_FILE_LIST(mb_groups),
  341. { NULL, NULL },
  342. };
  343. int ext4_register_sysfs(struct super_block *sb)
  344. {
  345. struct ext4_sb_info *sbi = EXT4_SB(sb);
  346. struct ext4_proc_files *p;
  347. int err;
  348. sbi->s_kobj.kset = &ext4_kset;
  349. init_completion(&sbi->s_kobj_unregister);
  350. err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL,
  351. "%s", sb->s_id);
  352. if (err)
  353. return err;
  354. if (ext4_proc_root)
  355. sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
  356. if (sbi->s_proc) {
  357. for (p = proc_files; p->name; p++)
  358. proc_create_data(p->name, S_IRUGO, sbi->s_proc,
  359. p->fops, sb);
  360. }
  361. return 0;
  362. }
  363. void ext4_unregister_sysfs(struct super_block *sb)
  364. {
  365. struct ext4_sb_info *sbi = EXT4_SB(sb);
  366. struct ext4_proc_files *p;
  367. if (sbi->s_proc) {
  368. for (p = proc_files; p->name; p++)
  369. remove_proc_entry(p->name, sbi->s_proc);
  370. remove_proc_entry(sb->s_id, ext4_proc_root);
  371. }
  372. kobject_del(&sbi->s_kobj);
  373. }
  374. int __init ext4_init_sysfs(void)
  375. {
  376. int ret;
  377. kobject_set_name(&ext4_kset.kobj, "ext4");
  378. ext4_kset.kobj.parent = fs_kobj;
  379. ret = kset_register(&ext4_kset);
  380. if (ret)
  381. return ret;
  382. ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype,
  383. NULL, "features");
  384. if (ret)
  385. kset_unregister(&ext4_kset);
  386. else
  387. ext4_proc_root = proc_mkdir(proc_dirname, NULL);
  388. return ret;
  389. }
  390. void ext4_exit_sysfs(void)
  391. {
  392. kobject_put(&ext4_feat);
  393. kset_unregister(&ext4_kset);
  394. remove_proc_entry(proc_dirname, NULL);
  395. ext4_proc_root = NULL;
  396. }