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::c_str;
7use kernel::configfs;
8use kernel::configfs::configfs_attrs;
9use kernel::new_mutex;
10use kernel::page::PAGE_SIZE;
11use kernel::prelude::*;
12use kernel::sync::Mutex;
13
14module! {
15 type: RustConfigfs,
16 name: "rust_configfs",
17 authors: ["Rust for Linux Contributors"],
18 description: "Rust configfs sample",
19 license: "GPL",
20}
21
22#[pin_data]
23struct RustConfigfs {
24 #[pin]
25 config: configfs::Subsystem<Configuration>,
26}
27
28#[pin_data]
29struct Configuration {
30 message: &'static CStr,
31 #[pin]
32 bar: Mutex<(KBox<[u8; PAGE_SIZE]>, usize)>,
33}
34
35impl 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
44impl 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]
71impl 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]
92impl 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.to_bytes();
98 page[0..data.len()].copy_from_slice(data);
99 Ok(data.len())
100 }
101}
102
103#[vtable]
104impl 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]
127struct Child {}
128
129impl Child {
130 fn new() -> impl PinInit<Self, Error> {
131 try_pin_init!(Self {})
132 }
133}
134
135#[vtable]
136impl 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]
161impl 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]
174struct GrandChild {}
175
176impl GrandChild {
177 fn new() -> impl PinInit<Self, Error> {
178 try_pin_init!(Self {})
179 }
180}
181
182#[vtable]
183impl 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}