⇐ index
CHANGE FUNCTION from_raw() in device.rs
Why the problem was should be resolved?
In this discussion, is suggest by Boqun Feng that the function from_raw() in rust/kernel/device.rs can make confusions because, the from_raw() function is the name of function in ARef kernel library and in Arc rust standard library.
The ARef::from_raw() and Arch::from_raw() functions don't increments the refcount, and our function in rust/kernel/device.rs increments the refcount.
So, if any developer see this function with this semantics can get confusing, because the your first think usually can be that the Device::from_raw() don't increments the refcount.
But, in the zulipchat, the maintaners were in doubt about two questions:
1) Should we change the Device::from_raw() function for don't increment the refcount, or.
2) Should we change the name of Device::from_raw() function for avoid confusions.
My proposed solution
The function Device::from_raw(), was have the follow structure:
pub unsafe fn from_raw(ptr: *mut bindings::device) -> ARef {
// SAFETY: By the safety requirements, ptr is valid.
// Initially increase the reference count by one to compensate for the final decrement once
// this newly created `ARef` instance is dropped.
unsafe { bindings::get_device(ptr) };
// CAST: `Self` is a `repr(transparent)` wrapper around `bindings::device`.
let ptr = ptr.cast::();
// SAFETY: `ptr` is valid by the safety requirements of this function. By the above call to
// `bindings::get_device` we also own a reference to the underlying `struct device`.
unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(ptr)) }
}
The function call the "bindings::get_device(prt)". This functions is a function in a .c file. This get_device() in .c file increments the refcount of ptr.
After, the Device::from_raw() return the ARef::from_raw(), that return a raw pointer to ptr.
But, in the device.rs have a function called as_ref() that return a point with a cast to Device trait. Is this exactly what we need. But the as_ref don't increment a refcount. For increments a refcount, we need call .into() function, like follow:
let dev = unsafe { Device::as_ref() }.into();
So, maybe we don't need create another function for get a raw pointer for device, because is a simple comando to have in your driver... only "let dev = unsafe { Device::as_ref() }.into();"
We are fine in removing of from_raw() function, and if the drivers developers need a reference with refcount to Device only do { Device::as_ref() }.into().
But this generate a problem: When the developers need write this again, again and again, somebody will create a function for this in some time.
So, I suggest rename the from_raw() function to get_device() for consistence with the get_device() in .c file, and only return { Device::as_ref() }.into(). And this is like follow:
pub unsafe fn get_device(ptr: *mut bindings::device) -> ARef {
// SAFETY: By the safety requirements ptr is valid
unsafe { Self::as_ref(ptr) }.into()
}
And this change is accepted for Greg Kroah-Hartman, and is release together of 6.12 version
How test this
of course, you need have the rust instalation in your computer, as a as bindings, and anothers tools for compile the rust code on the linux kernel.
The documentation for able your rust code in your linux repositorie is here
You can create this file in sample/rust/device.rs
use kernel::device::Device;
use kernel::prelude::*;
use kernel::types::ARef;
module! {
type: DeviceTest,
name: "device_test",
author: "Test device",
description: "A simple module for test device",
license: "GPL",
}
struct DeviceTest;
impl kernel::Module for DeviceTest {
fn init(_module: &'static ThisModule) -> Result {
pr_info!("initial device test");
let device = create_and_get_device();
pr_info!("device created");
Ok(DeviceTest)
}
}
impl Drop for DeviceTest {
fn drop(&mut self) {
pr_info!("bye bye driver test");
}
}
fn create_and_get_device() -> ARef {
let device = unsafe { Device::get_device(core::ptr::null_mut()) };
device
}
And, I will to make available a diff for will be apply in your linux repositorie for enable this sample code in cofigurations:
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index b0f74a81c8f9..c27a150b520f 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -37,4 +37,9 @@ config SAMPLE_RUST_HOSTPROGS
If unsure, say N.
+config SAMPLE_RUST_DEVICE_TEST
+ bool "Sample rust device test"
+ help
+ this is a module for test device
+
endif # SAMPLES_RUST
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index 03086dabbea4..f1ef941d92ad 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -2,5 +2,6 @@
obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o
obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o
+obj-$(CONFIG_SAMPLE_RUST_DEVICE_TEST) += device.o
subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs
For apply this you can save this diff in any file and run this command:
git apply path/to/file.diff
Now, you need able this in menu config.
make LLVM=1 menuconfig
You need browse until "Kernel hacking -> Sample kernel code -> Rust samples -> Sample rust device test".
and enable all configurations that you need.
compile the kernel:
make LLVM=1
And you can install this kernel on your Pc moving the bzImage to you /boot path and creating the initramfs and updating the grub (and this can be differente for differentes linux distributions). Or you can run this in a qemu if you already have the image for initialize, like this:
qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0 earlyprintk=serial" -drive file=ubuntu.qcow2,format=qcow2 -m 1024 -enable-kvm -net nic -net user,hostfwd=tcp::2222-:22 -nographic -d int,cpu_reset
The ubuntu.qcow2 is a image which I create for test my changes in kernel linux.
If you don't know how you can create this image, I suggest for you for search about this in anything like google, or ask about this for any IA like chatGPT. One of this options can be help you.
When you is runing this in your machine or in qemu, you can run the
dmesg
in terminal, and you can see the prints "initial device test" and the "device created".
Links
* Mailing list
* Discussion on zulipchat
* Issue on github