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