191 lines · 5.2 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 //! Rust configfs sample. use kernel::alloc::flags;use kernel::configfs;use kernel::configfs::configfs_attrs;use kernel::new_mutex;use kernel::page::PAGE_SIZE;use kernel::prelude::*;use kernel::sync::Mutex; module! {    type: RustConfigfs,    name: "rust_configfs",    authors: ["Rust for Linux Contributors"],    description: "Rust configfs sample",    license: "GPL",} #[pin_data]struct RustConfigfs {    #[pin]    config: configfs::Subsystem<Configuration>,} #[pin_data]struct Configuration {    message: &'static CStr,    #[pin]    bar: Mutex<(KBox<[u8; PAGE_SIZE]>, usize)>,} impl Configuration {    fn new() -> impl PinInit<Self, Error> {        try_pin_init!(Self {            message: c"Hello World\n",            bar <- new_mutex!((KBox::new([0; PAGE_SIZE], flags::GFP_KERNEL)?, 0)),        })    }} impl kernel::InPlaceModule for RustConfigfs {    fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {        pr_info!("Rust configfs sample (init)\n");         // Define a subsystem with the data type `Configuration`, two        // attributes, `message` and `bar` and child group type `Child`. `mkdir`        // in the directory representing this subsystem will create directories        // backed by the `Child` type.        let item_type = configfs_attrs! {            container: configfs::Subsystem<Configuration>,            data: Configuration,            child: Child,            attributes: [                message: 0,                bar: 1,            ],        };         try_pin_init!(Self {            config <- configfs::Subsystem::new(                c"rust_configfs", item_type, Configuration::new()            ),        })    }} #[vtable]impl configfs::GroupOperations for Configuration {    type Child = Child;     fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<Child>, Error>> {        // Define a group with data type `Child`, one attribute `baz` and child        // group type `GrandChild`. `mkdir` in the directory representing this        // group will create directories backed by the `GrandChild` type.        let tpe = configfs_attrs! {            container: configfs::Group<Child>,            data: Child,            child: GrandChild,            attributes: [                baz: 0,            ],        };         Ok(configfs::Group::new(name.try_into()?, tpe, Child::new()))    }} #[vtable]impl configfs::AttributeOperations<0> for Configuration {    type Data = Configuration;     fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {        pr_info!("Show message\n");        let data = container.message.to_bytes();        page[0..data.len()].copy_from_slice(data);        Ok(data.len())    }} #[vtable]impl configfs::AttributeOperations<1> for Configuration {    type Data = Configuration;     fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {        pr_info!("Show bar\n");        let guard = container.bar.lock();        let data = guard.0.as_slice();        let len = guard.1;        page[0..len].copy_from_slice(&data[0..len]);        Ok(len)    }     fn store(container: &Configuration, page: &[u8]) -> Result {        pr_info!("Store bar\n");        let mut guard = container.bar.lock();        guard.0[0..page.len()].copy_from_slice(page);        guard.1 = page.len();        Ok(())    }} // `pin_data` cannot handle structs without braces.#[pin_data]struct Child {} impl Child {    fn new() -> impl PinInit<Self, Error> {        try_pin_init!(Self {})    }} #[vtable]impl configfs::GroupOperations for Child {    type Child = GrandChild;     fn make_group(&self, name: &CStr) -> Result<impl PinInit<configfs::Group<GrandChild>, Error>> {        // Define a group with data type `GrandChild`, one attribute `gc`. As no        // child type is specified, it will not be possible to create subgroups        // in this group, and `mkdir`in the directory representing this group        // will return an error.        let tpe = configfs_attrs! {            container: configfs::Group<GrandChild>,            data: GrandChild,            attributes: [                gc: 0,            ],        };         Ok(configfs::Group::new(            name.try_into()?,            tpe,            GrandChild::new(),        ))    }} #[vtable]impl configfs::AttributeOperations<0> for Child {    type Data = Child;     fn show(_container: &Child, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {        pr_info!("Show baz\n");        let data = c"Hello Baz\n".to_bytes();        page[0..data.len()].copy_from_slice(data);        Ok(data.len())    }} // `pin_data` cannot handle structs without braces.#[pin_data]struct GrandChild {} impl GrandChild {    fn new() -> impl PinInit<Self, Error> {        try_pin_init!(Self {})    }} #[vtable]impl configfs::AttributeOperations<0> for GrandChild {    type Data = GrandChild;     fn show(_container: &GrandChild, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {        pr_info!("Show grand child\n");        let data = c"Hello GC\n".to_bytes();        page[0..data.len()].copy_from_slice(data);        Ok(data.len())    }}