sysfs.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Simple file system for zoned block devices exposing zones as files.
  4. *
  5. * Copyright (C) 2022 Western Digital Corporation or its affiliates.
  6. */
  7. #include <linux/fs.h>
  8. #include <linux/seq_file.h>
  9. #include <linux/blkdev.h>
  10. #include "zonefs.h"
  11. struct zonefs_sysfs_attr {
  12. struct attribute attr;
  13. ssize_t (*show)(struct zonefs_sb_info *sbi, char *buf);
  14. };
  15. #define ZONEFS_SYSFS_ATTR_RO(name) \
  16. static struct zonefs_sysfs_attr zonefs_sysfs_attr_##name = __ATTR_RO(name)
  17. #define ATTR_LIST(name) &zonefs_sysfs_attr_##name.attr
  18. static ssize_t zonefs_sysfs_attr_show(struct kobject *kobj,
  19. struct attribute *attr, char *buf)
  20. {
  21. struct zonefs_sb_info *sbi =
  22. container_of(kobj, struct zonefs_sb_info, s_kobj);
  23. struct zonefs_sysfs_attr *zonefs_attr =
  24. container_of(attr, struct zonefs_sysfs_attr, attr);
  25. if (!zonefs_attr->show)
  26. return 0;
  27. return zonefs_attr->show(sbi, buf);
  28. }
  29. static ssize_t max_wro_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
  30. {
  31. return sysfs_emit(buf, "%u\n", sbi->s_max_wro_seq_files);
  32. }
  33. ZONEFS_SYSFS_ATTR_RO(max_wro_seq_files);
  34. static ssize_t nr_wro_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
  35. {
  36. return sysfs_emit(buf, "%d\n", atomic_read(&sbi->s_wro_seq_files));
  37. }
  38. ZONEFS_SYSFS_ATTR_RO(nr_wro_seq_files);
  39. static ssize_t max_active_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
  40. {
  41. return sysfs_emit(buf, "%u\n", sbi->s_max_active_seq_files);
  42. }
  43. ZONEFS_SYSFS_ATTR_RO(max_active_seq_files);
  44. static ssize_t nr_active_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
  45. {
  46. return sysfs_emit(buf, "%d\n", atomic_read(&sbi->s_active_seq_files));
  47. }
  48. ZONEFS_SYSFS_ATTR_RO(nr_active_seq_files);
  49. static struct attribute *zonefs_sysfs_attrs[] = {
  50. ATTR_LIST(max_wro_seq_files),
  51. ATTR_LIST(nr_wro_seq_files),
  52. ATTR_LIST(max_active_seq_files),
  53. ATTR_LIST(nr_active_seq_files),
  54. NULL,
  55. };
  56. ATTRIBUTE_GROUPS(zonefs_sysfs);
  57. static void zonefs_sysfs_sb_release(struct kobject *kobj)
  58. {
  59. struct zonefs_sb_info *sbi =
  60. container_of(kobj, struct zonefs_sb_info, s_kobj);
  61. complete(&sbi->s_kobj_unregister);
  62. }
  63. static const struct sysfs_ops zonefs_sysfs_attr_ops = {
  64. .show = zonefs_sysfs_attr_show,
  65. };
  66. static const struct kobj_type zonefs_sb_ktype = {
  67. .default_groups = zonefs_sysfs_groups,
  68. .sysfs_ops = &zonefs_sysfs_attr_ops,
  69. .release = zonefs_sysfs_sb_release,
  70. };
  71. static struct kobject *zonefs_sysfs_root;
  72. int zonefs_sysfs_register(struct super_block *sb)
  73. {
  74. struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
  75. int ret;
  76. super_set_sysfs_name_id(sb);
  77. init_completion(&sbi->s_kobj_unregister);
  78. ret = kobject_init_and_add(&sbi->s_kobj, &zonefs_sb_ktype,
  79. zonefs_sysfs_root, "%s", sb->s_id);
  80. if (ret) {
  81. kobject_put(&sbi->s_kobj);
  82. wait_for_completion(&sbi->s_kobj_unregister);
  83. return ret;
  84. }
  85. sbi->s_sysfs_registered = true;
  86. return 0;
  87. }
  88. void zonefs_sysfs_unregister(struct super_block *sb)
  89. {
  90. struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
  91. if (!sbi || !sbi->s_sysfs_registered)
  92. return;
  93. kobject_del(&sbi->s_kobj);
  94. kobject_put(&sbi->s_kobj);
  95. wait_for_completion(&sbi->s_kobj_unregister);
  96. }
  97. int __init zonefs_sysfs_init(void)
  98. {
  99. zonefs_sysfs_root = kobject_create_and_add("zonefs", fs_kobj);
  100. if (!zonefs_sysfs_root)
  101. return -ENOMEM;
  102. return 0;
  103. }
  104. void zonefs_sysfs_exit(void)
  105. {
  106. kobject_put(zonefs_sysfs_root);
  107. zonefs_sysfs_root = NULL;
  108. }