File Index
Files and directories
Sign in
FILE

rust_configfs.rs

File preview with syntax highlighting.

linux-6.19.14/samples/rust/rust_configfs.rs RUST
  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}
~/ Read-only file preview.