sysfs.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2021 Google LLC
  4. */
  5. #include <linux/fs.h>
  6. #include <linux/kobject.h>
  7. #include <uapi/linux/incrementalfs.h>
  8. #include "sysfs.h"
  9. #include "data_mgmt.h"
  10. #include "vfs.h"
  11. /******************************************************************************
  12. * Define sys/fs/incrementalfs & sys/fs/incrementalfs/features
  13. *****************************************************************************/
  14. #define INCFS_NODE_FEATURES "features"
  15. #define INCFS_NODE_INSTANCES "instances"
  16. static struct kobject *sysfs_root;
  17. static struct kobject *features_node;
  18. static struct kobject *instances_node;
  19. #define DECLARE_FEATURE_FLAG(name) \
  20. static ssize_t name##_show(struct kobject *kobj, \
  21. struct kobj_attribute *attr, char *buff) \
  22. { \
  23. return sysfs_emit(buff, "supported\n"); \
  24. } \
  25. \
  26. static struct kobj_attribute name##_attr = __ATTR_RO(name)
  27. DECLARE_FEATURE_FLAG(corefs);
  28. DECLARE_FEATURE_FLAG(zstd);
  29. DECLARE_FEATURE_FLAG(v2);
  30. DECLARE_FEATURE_FLAG(bugfix_throttling);
  31. DECLARE_FEATURE_FLAG(bugfix_inode_eviction);
  32. static struct attribute *attributes[] = {
  33. &corefs_attr.attr,
  34. &zstd_attr.attr,
  35. &v2_attr.attr,
  36. &bugfix_throttling_attr.attr,
  37. &bugfix_inode_eviction_attr.attr,
  38. NULL,
  39. };
  40. static const struct attribute_group attr_group = {
  41. .attrs = attributes,
  42. };
  43. int __init incfs_init_sysfs(void)
  44. {
  45. int res = -ENOMEM;
  46. sysfs_root = kobject_create_and_add(INCFS_NAME, fs_kobj);
  47. if (!sysfs_root)
  48. return -ENOMEM;
  49. instances_node = kobject_create_and_add(INCFS_NODE_INSTANCES,
  50. sysfs_root);
  51. if (!instances_node)
  52. goto err_put_root;
  53. features_node = kobject_create_and_add(INCFS_NODE_FEATURES,
  54. sysfs_root);
  55. if (!features_node)
  56. goto err_put_instances;
  57. res = sysfs_create_group(features_node, &attr_group);
  58. if (res)
  59. goto err_put_features;
  60. return 0;
  61. err_put_features:
  62. kobject_put(features_node);
  63. err_put_instances:
  64. kobject_put(instances_node);
  65. err_put_root:
  66. kobject_put(sysfs_root);
  67. return res;
  68. }
  69. void incfs_cleanup_sysfs(void)
  70. {
  71. if (features_node) {
  72. sysfs_remove_group(features_node, &attr_group);
  73. kobject_put(features_node);
  74. }
  75. kobject_put(instances_node);
  76. kobject_put(sysfs_root);
  77. }
  78. /******************************************************************************
  79. * Define sys/fs/incrementalfs/instances/<name>/
  80. *****************************************************************************/
  81. #define __DECLARE_STATUS_FLAG(name) \
  82. static ssize_t name##_show(struct kobject *kobj, \
  83. struct kobj_attribute *attr, char *buff) \
  84. { \
  85. struct incfs_sysfs_node *node = container_of(kobj, \
  86. struct incfs_sysfs_node, isn_sysfs_node); \
  87. \
  88. return sysfs_emit(buff, "%d\n", node->isn_mi->mi_##name); \
  89. } \
  90. \
  91. static struct kobj_attribute name##_attr = __ATTR_RO(name)
  92. #define __DECLARE_STATUS_FLAG64(name) \
  93. static ssize_t name##_show(struct kobject *kobj, \
  94. struct kobj_attribute *attr, char *buff) \
  95. { \
  96. struct incfs_sysfs_node *node = container_of(kobj, \
  97. struct incfs_sysfs_node, isn_sysfs_node); \
  98. \
  99. return sysfs_emit(buff, "%lld\n", node->isn_mi->mi_##name); \
  100. } \
  101. \
  102. static struct kobj_attribute name##_attr = __ATTR_RO(name)
  103. __DECLARE_STATUS_FLAG(reads_failed_timed_out);
  104. __DECLARE_STATUS_FLAG(reads_failed_hash_verification);
  105. __DECLARE_STATUS_FLAG(reads_failed_other);
  106. __DECLARE_STATUS_FLAG(reads_delayed_pending);
  107. __DECLARE_STATUS_FLAG64(reads_delayed_pending_us);
  108. __DECLARE_STATUS_FLAG(reads_delayed_min);
  109. __DECLARE_STATUS_FLAG64(reads_delayed_min_us);
  110. static struct attribute *mount_attributes[] = {
  111. &reads_failed_timed_out_attr.attr,
  112. &reads_failed_hash_verification_attr.attr,
  113. &reads_failed_other_attr.attr,
  114. &reads_delayed_pending_attr.attr,
  115. &reads_delayed_pending_us_attr.attr,
  116. &reads_delayed_min_attr.attr,
  117. &reads_delayed_min_us_attr.attr,
  118. NULL,
  119. };
  120. static void incfs_sysfs_release(struct kobject *kobj)
  121. {
  122. struct incfs_sysfs_node *node = container_of(kobj,
  123. struct incfs_sysfs_node, isn_sysfs_node);
  124. complete(&node->isn_completion);
  125. }
  126. static const struct attribute_group mount_attr_group = {
  127. .attrs = mount_attributes,
  128. };
  129. static struct kobj_type incfs_kobj_node_ktype = {
  130. .sysfs_ops = &kobj_sysfs_ops,
  131. .release = &incfs_sysfs_release,
  132. };
  133. struct incfs_sysfs_node *incfs_add_sysfs_node(const char *name,
  134. struct mount_info *mi)
  135. {
  136. struct incfs_sysfs_node *node = NULL;
  137. int error;
  138. if (!name)
  139. return NULL;
  140. node = kzalloc(sizeof(*node), GFP_NOFS);
  141. if (!node)
  142. return ERR_PTR(-ENOMEM);
  143. node->isn_mi = mi;
  144. init_completion(&node->isn_completion);
  145. kobject_init(&node->isn_sysfs_node, &incfs_kobj_node_ktype);
  146. error = kobject_add(&node->isn_sysfs_node, instances_node, "%s", name);
  147. if (error)
  148. goto err;
  149. error = sysfs_create_group(&node->isn_sysfs_node, &mount_attr_group);
  150. if (error)
  151. goto err;
  152. return node;
  153. err:
  154. /*
  155. * Note kobject_put always calls release, so incfs_sysfs_release will
  156. * free node
  157. */
  158. kobject_put(&node->isn_sysfs_node);
  159. return ERR_PTR(error);
  160. }
  161. void incfs_free_sysfs_node(struct incfs_sysfs_node *node)
  162. {
  163. if (!node)
  164. return;
  165. sysfs_remove_group(&node->isn_sysfs_node, &mount_attr_group);
  166. kobject_put(&node->isn_sysfs_node);
  167. wait_for_completion_interruptible(&node->isn_completion);
  168. kfree(node);
  169. }