rust_configfs.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // SPDX-License-Identifier: GPL-2.0
  2. //! Rust configfs sample.
  3. use kernel::alloc::flags;
  4. use kernel::configfs;
  5. use kernel::configfs::configfs_attrs;
  6. use kernel::new_mutex;
  7. use kernel::page::PAGE_SIZE;
  8. use kernel::prelude::*;
  9. use kernel::sync::Mutex;
  10. module! {
  11. type: RustConfigfs,
  12. name: "rust_configfs",
  13. authors: ["Rust for Linux Contributors"],
  14. description: "Rust configfs sample",
  15. license: "GPL",
  16. }
  17. #[pin_data]
  18. struct RustConfigfs {
  19. #[pin]
  20. config: configfs::Subsystem<Configuration>,
  21. }
  22. #[pin_data]
  23. struct Configuration {
  24. message: &'static CStr,
  25. #[pin]
  26. bar: Mutex<(KBox<[u8; PAGE_SIZE]>, usize)>,
  27. }
  28. impl Configuration {
  29. fn new() -> impl PinInit<Self, Error> {
  30. try_pin_init!(Self {
  31. message: c"Hello World\n",
  32. bar <- new_mutex!((KBox::new([0; PAGE_SIZE], flags::GFP_KERNEL)?, 0)),
  33. })
  34. }
  35. }
  36. impl kernel::InPlaceModule for RustConfigfs {
  37. fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
  38. pr_info!("Rust configfs sample (init)\n");
  39. // Define a subsystem with the data type `Configuration`, two
  40. // attributes, `message` and `bar` and child group type `Child`. `mkdir`
  41. // in the directory representing this subsystem will create directories
  42. // backed by the `Child` type.
  43. let item_type = configfs_attrs! {
  44. container: configfs::Subsystem<Configuration>,
  45. data: Configuration,
  46. child: Child,
  47. attributes: [
  48. message: 0,
  49. bar: 1,
  50. ],
  51. };
  52. try_pin_init!(Self {
  53. config <- configfs::Subsystem::new(
  54. c"rust_configfs", item_type, Configuration::new()
  55. ),
  56. })
  57. }
  58. }
  59. #[vtable]
  60. impl configfs::GroupOperations for Configuration {
  61. type Child = Child;
  62. fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<Child>, Error>> {
  63. // Define a group with data type `Child`, one attribute `baz` and child
  64. // group type `GrandChild`. `mkdir` in the directory representing this
  65. // group will create directories backed by the `GrandChild` type.
  66. let tpe = configfs_attrs! {
  67. container: configfs::Group<Child>,
  68. data: Child,
  69. child: GrandChild,
  70. attributes: [
  71. baz: 0,
  72. ],
  73. };
  74. Ok(configfs::Group::new(name.try_into()?, tpe, Child::new()))
  75. }
  76. }
  77. #[vtable]
  78. impl configfs::AttributeOperations<0> for Configuration {
  79. type Data = Configuration;
  80. fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
  81. pr_info!("Show message\n");
  82. let data = container.message.to_bytes();
  83. page[0..data.len()].copy_from_slice(data);
  84. Ok(data.len())
  85. }
  86. }
  87. #[vtable]
  88. impl configfs::AttributeOperations<1> for Configuration {
  89. type Data = Configuration;
  90. fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
  91. pr_info!("Show bar\n");
  92. let guard = container.bar.lock();
  93. let data = guard.0.as_slice();
  94. let len = guard.1;
  95. page[0..len].copy_from_slice(&data[0..len]);
  96. Ok(len)
  97. }
  98. fn store(container: &Configuration, page: &[u8]) -> Result {
  99. pr_info!("Store bar\n");
  100. let mut guard = container.bar.lock();
  101. guard.0[0..page.len()].copy_from_slice(page);
  102. guard.1 = page.len();
  103. Ok(())
  104. }
  105. }
  106. // `pin_data` cannot handle structs without braces.
  107. #[pin_data]
  108. struct Child {}
  109. impl Child {
  110. fn new() -> impl PinInit<Self, Error> {
  111. try_pin_init!(Self {})
  112. }
  113. }
  114. #[vtable]
  115. impl configfs::GroupOperations for Child {
  116. type Child = GrandChild;
  117. fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<GrandChild>, Error>> {
  118. // Define a group with data type `GrandChild`, one attribute `gc`. As no
  119. // child type is specified, it will not be possible to create subgroups
  120. // in this group, and `mkdir`in the directory representing this group
  121. // will return an error.
  122. let tpe = configfs_attrs! {
  123. container: configfs::Group<GrandChild>,
  124. data: GrandChild,
  125. attributes: [
  126. gc: 0,
  127. ],
  128. };
  129. Ok(configfs::Group::new(
  130. name.try_into()?,
  131. tpe,
  132. GrandChild::new(),
  133. ))
  134. }
  135. }
  136. #[vtable]
  137. impl configfs::AttributeOperations<0> for Child {
  138. type Data = Child;
  139. fn show(_container: &Child, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
  140. pr_info!("Show baz\n");
  141. let data = c"Hello Baz\n".to_bytes();
  142. page[0..data.len()].copy_from_slice(data);
  143. Ok(data.len())
  144. }
  145. }
  146. // `pin_data` cannot handle structs without braces.
  147. #[pin_data]
  148. struct GrandChild {}
  149. impl GrandChild {
  150. fn new() -> impl PinInit<Self, Error> {
  151. try_pin_init!(Self {})
  152. }
  153. }
  154. #[vtable]
  155. impl configfs::AttributeOperations<0> for GrandChild {
  156. type Data = GrandChild;
  157. fn show(_container: &GrandChild, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
  158. pr_info!("Show grand child\n");
  159. let data = c"Hello GC\n".to_bytes();
  160. page[0..data.len()].copy_from_slice(data);
  161. Ok(data.len())
  162. }
  163. }