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