sysfs.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * This file is part of UBIFS.
  4. *
  5. * Copyright (C) 2021 Cisco Systems
  6. *
  7. * Author: Stefan Schaeckeler
  8. */
  9. #include <linux/fs.h>
  10. #include "ubifs.h"
  11. enum attr_id_t {
  12. attr_errors_magic,
  13. attr_errors_node,
  14. attr_errors_crc,
  15. };
  16. struct ubifs_attr {
  17. struct attribute attr;
  18. enum attr_id_t attr_id;
  19. };
  20. #define UBIFS_ATTR(_name, _mode, _id) \
  21. static struct ubifs_attr ubifs_attr_##_name = { \
  22. .attr = {.name = __stringify(_name), .mode = _mode }, \
  23. .attr_id = attr_##_id, \
  24. }
  25. #define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
  26. UBIFS_ATTR_FUNC(errors_magic, 0444);
  27. UBIFS_ATTR_FUNC(errors_crc, 0444);
  28. UBIFS_ATTR_FUNC(errors_node, 0444);
  29. #define ATTR_LIST(name) (&ubifs_attr_##name.attr)
  30. static struct attribute *ubifs_attrs[] = {
  31. ATTR_LIST(errors_magic),
  32. ATTR_LIST(errors_node),
  33. ATTR_LIST(errors_crc),
  34. NULL,
  35. };
  36. ATTRIBUTE_GROUPS(ubifs);
  37. static ssize_t ubifs_attr_show(struct kobject *kobj,
  38. struct attribute *attr, char *buf)
  39. {
  40. struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
  41. kobj);
  42. struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);
  43. switch (a->attr_id) {
  44. case attr_errors_magic:
  45. return sysfs_emit(buf, "%u\n", sbi->stats->magic_errors);
  46. case attr_errors_node:
  47. return sysfs_emit(buf, "%u\n", sbi->stats->node_errors);
  48. case attr_errors_crc:
  49. return sysfs_emit(buf, "%u\n", sbi->stats->crc_errors);
  50. }
  51. return 0;
  52. };
  53. static void ubifs_sb_release(struct kobject *kobj)
  54. {
  55. struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj);
  56. complete(&c->kobj_unregister);
  57. }
  58. static const struct sysfs_ops ubifs_attr_ops = {
  59. .show = ubifs_attr_show,
  60. };
  61. static const struct kobj_type ubifs_sb_ktype = {
  62. .default_groups = ubifs_groups,
  63. .sysfs_ops = &ubifs_attr_ops,
  64. .release = ubifs_sb_release,
  65. };
  66. static const struct kobj_type ubifs_ktype = {
  67. .sysfs_ops = &ubifs_attr_ops,
  68. };
  69. static struct kset ubifs_kset = {
  70. .kobj = {.ktype = &ubifs_ktype},
  71. };
  72. int ubifs_sysfs_register(struct ubifs_info *c)
  73. {
  74. int ret, n;
  75. char dfs_dir_name[UBIFS_DFS_DIR_LEN];
  76. c->stats = kzalloc_obj(struct ubifs_stats_info);
  77. if (!c->stats) {
  78. ret = -ENOMEM;
  79. goto out_last;
  80. }
  81. n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN, UBIFS_DFS_DIR_NAME,
  82. c->vi.ubi_num, c->vi.vol_id);
  83. if (n >= UBIFS_DFS_DIR_LEN) {
  84. /* The array size is too small */
  85. ret = -EINVAL;
  86. goto out_free;
  87. }
  88. c->kobj.kset = &ubifs_kset;
  89. init_completion(&c->kobj_unregister);
  90. ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
  91. "%s", dfs_dir_name);
  92. if (ret)
  93. goto out_put;
  94. return 0;
  95. out_put:
  96. kobject_put(&c->kobj);
  97. wait_for_completion(&c->kobj_unregister);
  98. out_free:
  99. kfree(c->stats);
  100. out_last:
  101. ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n",
  102. c->vi.ubi_num, c->vi.vol_id, ret);
  103. return ret;
  104. }
  105. void ubifs_sysfs_unregister(struct ubifs_info *c)
  106. {
  107. kobject_del(&c->kobj);
  108. kobject_put(&c->kobj);
  109. wait_for_completion(&c->kobj_unregister);
  110. kfree(c->stats);
  111. }
  112. int __init ubifs_sysfs_init(void)
  113. {
  114. int ret;
  115. kobject_set_name(&ubifs_kset.kobj, "ubifs");
  116. ubifs_kset.kobj.parent = fs_kobj;
  117. ret = kset_register(&ubifs_kset);
  118. if (ret)
  119. kset_put(&ubifs_kset);
  120. return ret;
  121. }
  122. void ubifs_sysfs_exit(void)
  123. {
  124. kset_unregister(&ubifs_kset);
  125. }