rnbd-srv-sysfs.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * RDMA Network Block Driver
  4. *
  5. * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved.
  6. * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved.
  7. * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved.
  8. */
  9. #undef pr_fmt
  10. #define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt
  11. #include <uapi/linux/limits.h>
  12. #include <linux/kobject.h>
  13. #include <linux/sysfs.h>
  14. #include <linux/stat.h>
  15. #include <linux/list.h>
  16. #include <linux/moduleparam.h>
  17. #include <linux/device.h>
  18. #include "rnbd-srv.h"
  19. static struct device *rnbd_dev;
  20. static struct class *rnbd_dev_class;
  21. static struct kobject *rnbd_devs_kobj;
  22. static void rnbd_srv_dev_release(struct kobject *kobj)
  23. {
  24. struct rnbd_srv_dev *dev;
  25. dev = container_of(kobj, struct rnbd_srv_dev, dev_kobj);
  26. kfree(dev);
  27. }
  28. static struct kobj_type dev_ktype = {
  29. .sysfs_ops = &kobj_sysfs_ops,
  30. .release = rnbd_srv_dev_release
  31. };
  32. int rnbd_srv_create_dev_sysfs(struct rnbd_srv_dev *dev,
  33. struct block_device *bdev)
  34. {
  35. struct kobject *bdev_kobj;
  36. int ret;
  37. ret = kobject_init_and_add(&dev->dev_kobj, &dev_ktype,
  38. rnbd_devs_kobj, "%pg", bdev);
  39. if (ret) {
  40. kobject_put(&dev->dev_kobj);
  41. return ret;
  42. }
  43. dev->dev_sessions_kobj = kobject_create_and_add("sessions",
  44. &dev->dev_kobj);
  45. if (!dev->dev_sessions_kobj) {
  46. ret = -ENOMEM;
  47. goto free_dev_kobj;
  48. }
  49. bdev_kobj = &disk_to_dev(bdev->bd_disk)->kobj;
  50. ret = sysfs_create_link(&dev->dev_kobj, bdev_kobj, "block_dev");
  51. if (ret)
  52. goto put_sess_kobj;
  53. return 0;
  54. put_sess_kobj:
  55. kobject_put(dev->dev_sessions_kobj);
  56. free_dev_kobj:
  57. kobject_del(&dev->dev_kobj);
  58. kobject_put(&dev->dev_kobj);
  59. return ret;
  60. }
  61. void rnbd_srv_destroy_dev_sysfs(struct rnbd_srv_dev *dev)
  62. {
  63. sysfs_remove_link(&dev->dev_kobj, "block_dev");
  64. kobject_del(dev->dev_sessions_kobj);
  65. kobject_put(dev->dev_sessions_kobj);
  66. kobject_del(&dev->dev_kobj);
  67. kobject_put(&dev->dev_kobj);
  68. }
  69. static ssize_t read_only_show(struct kobject *kobj, struct kobj_attribute *attr,
  70. char *page)
  71. {
  72. struct rnbd_srv_sess_dev *sess_dev;
  73. sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
  74. return sysfs_emit(page, "%d\n",
  75. !(sess_dev->open_flags & FMODE_WRITE));
  76. }
  77. static struct kobj_attribute rnbd_srv_dev_session_ro_attr =
  78. __ATTR_RO(read_only);
  79. static ssize_t access_mode_show(struct kobject *kobj,
  80. struct kobj_attribute *attr,
  81. char *page)
  82. {
  83. struct rnbd_srv_sess_dev *sess_dev;
  84. sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
  85. return sysfs_emit(page, "%s\n",
  86. rnbd_access_mode_str(sess_dev->access_mode));
  87. }
  88. static struct kobj_attribute rnbd_srv_dev_session_access_mode_attr =
  89. __ATTR_RO(access_mode);
  90. static ssize_t mapping_path_show(struct kobject *kobj,
  91. struct kobj_attribute *attr, char *page)
  92. {
  93. struct rnbd_srv_sess_dev *sess_dev;
  94. sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
  95. return sysfs_emit(page, "%s\n", sess_dev->pathname);
  96. }
  97. static struct kobj_attribute rnbd_srv_dev_session_mapping_path_attr =
  98. __ATTR_RO(mapping_path);
  99. static ssize_t rnbd_srv_dev_session_force_close_show(struct kobject *kobj,
  100. struct kobj_attribute *attr, char *page)
  101. {
  102. return sysfs_emit(page, "Usage: echo 1 > %s\n",
  103. attr->attr.name);
  104. }
  105. static ssize_t rnbd_srv_dev_session_force_close_store(struct kobject *kobj,
  106. struct kobj_attribute *attr,
  107. const char *buf, size_t count)
  108. {
  109. struct rnbd_srv_sess_dev *sess_dev;
  110. sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
  111. if (!sysfs_streq(buf, "1")) {
  112. rnbd_srv_err(sess_dev, "%s: invalid value: '%s'\n",
  113. attr->attr.name, buf);
  114. return -EINVAL;
  115. }
  116. rnbd_srv_info(sess_dev, "force close requested\n");
  117. rnbd_srv_sess_dev_force_close(sess_dev, attr);
  118. return count;
  119. }
  120. static struct kobj_attribute rnbd_srv_dev_session_force_close_attr =
  121. __ATTR(force_close, 0644,
  122. rnbd_srv_dev_session_force_close_show,
  123. rnbd_srv_dev_session_force_close_store);
  124. static struct attribute *rnbd_srv_default_dev_sessions_attrs[] = {
  125. &rnbd_srv_dev_session_access_mode_attr.attr,
  126. &rnbd_srv_dev_session_ro_attr.attr,
  127. &rnbd_srv_dev_session_mapping_path_attr.attr,
  128. &rnbd_srv_dev_session_force_close_attr.attr,
  129. NULL,
  130. };
  131. static struct attribute_group rnbd_srv_default_dev_session_attr_group = {
  132. .attrs = rnbd_srv_default_dev_sessions_attrs,
  133. };
  134. void rnbd_srv_destroy_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev)
  135. {
  136. sysfs_remove_group(&sess_dev->kobj,
  137. &rnbd_srv_default_dev_session_attr_group);
  138. kobject_del(&sess_dev->kobj);
  139. kobject_put(&sess_dev->kobj);
  140. }
  141. static void rnbd_srv_sess_dev_release(struct kobject *kobj)
  142. {
  143. struct rnbd_srv_sess_dev *sess_dev;
  144. sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
  145. rnbd_destroy_sess_dev(sess_dev, sess_dev->keep_id);
  146. }
  147. static struct kobj_type rnbd_srv_sess_dev_ktype = {
  148. .sysfs_ops = &kobj_sysfs_ops,
  149. .release = rnbd_srv_sess_dev_release,
  150. };
  151. int rnbd_srv_create_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev)
  152. {
  153. int ret;
  154. ret = kobject_init_and_add(&sess_dev->kobj, &rnbd_srv_sess_dev_ktype,
  155. sess_dev->dev->dev_sessions_kobj, "%s",
  156. sess_dev->sess->sessname);
  157. if (ret) {
  158. kobject_put(&sess_dev->kobj);
  159. return ret;
  160. }
  161. ret = sysfs_create_group(&sess_dev->kobj,
  162. &rnbd_srv_default_dev_session_attr_group);
  163. if (ret) {
  164. kobject_del(&sess_dev->kobj);
  165. kobject_put(&sess_dev->kobj);
  166. }
  167. return ret;
  168. }
  169. int rnbd_srv_create_sysfs_files(void)
  170. {
  171. int err;
  172. rnbd_dev_class = class_create(THIS_MODULE, "rnbd-server");
  173. if (IS_ERR(rnbd_dev_class))
  174. return PTR_ERR(rnbd_dev_class);
  175. rnbd_dev = device_create(rnbd_dev_class, NULL,
  176. MKDEV(0, 0), NULL, "ctl");
  177. if (IS_ERR(rnbd_dev)) {
  178. err = PTR_ERR(rnbd_dev);
  179. goto cls_destroy;
  180. }
  181. rnbd_devs_kobj = kobject_create_and_add("devices", &rnbd_dev->kobj);
  182. if (!rnbd_devs_kobj) {
  183. err = -ENOMEM;
  184. goto dev_destroy;
  185. }
  186. return 0;
  187. dev_destroy:
  188. device_destroy(rnbd_dev_class, MKDEV(0, 0));
  189. cls_destroy:
  190. class_destroy(rnbd_dev_class);
  191. return err;
  192. }
  193. void rnbd_srv_destroy_sysfs_files(void)
  194. {
  195. kobject_del(rnbd_devs_kobj);
  196. kobject_put(rnbd_devs_kobj);
  197. device_destroy(rnbd_dev_class, MKDEV(0, 0));
  198. class_destroy(rnbd_dev_class);
  199. }