Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2
3//! Rust configfs sample.
4
5use kernel::alloc::flags;
6use kernel::configfs;
7use kernel::configfs::configfs_attrs;
8use kernel::new_mutex;
9use kernel::page::PAGE_SIZE;
10use kernel::prelude::*;
11use kernel::sync::Mutex;
12
13module! {
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]
22struct RustConfigfs {
23 #[pin]
24 config: configfs::Subsystem<Configuration>,
25}
26
27#[pin_data]
28struct Configuration {
29 message: &'static CStr,
30 #[pin]
31 bar: Mutex<(KBox<[u8; PAGE_SIZE]>, usize)>,
32}
33
34impl 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
43impl 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]
70impl 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]
91impl 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]
103impl 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]
126struct Child {}
127
128impl Child {
129 fn new() -> impl PinInit<Self, Error> {
130 try_pin_init!(Self {})
131 }
132}
133
134#[vtable]
135impl 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]
160impl 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]
173struct GrandChild {}
174
175impl GrandChild {
176 fn new() -> impl PinInit<Self, Error> {
177 try_pin_init!(Self {})
178 }
179}
180
181#[vtable]
182impl 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}