Skip to content

Commit 6032d93

Browse files
committed
rust: fs: introduce more inode types
Allow Rust file system modules to create inodes that are symlinks, pipes, sockets, char devices and block devices (in addition to the already-supported directories and regular files). Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent 3f94966 commit 6032d93

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed

rust/helpers.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ void rust_helper_mapping_set_large_folios(struct address_space *mapping)
244244
}
245245
EXPORT_SYMBOL_GPL(rust_helper_mapping_set_large_folios);
246246

247+
unsigned int rust_helper_MKDEV(unsigned int major, unsigned int minor)
248+
{
249+
return MKDEV(major, minor);
250+
}
251+
EXPORT_SYMBOL_GPL(rust_helper_MKDEV);
252+
247253
/*
248254
* `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
249255
* use it in contexts where Rust expects a `usize` like slice (array) indices.

rust/kernel/fs.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,13 @@ pub enum DirEntryType {
112112
impl From<INodeType> for DirEntryType {
113113
fn from(value: INodeType) -> Self {
114114
match value {
115+
INodeType::Fifo => DirEntryType::Fifo,
116+
INodeType::Chr(_, _) => DirEntryType::Chr,
115117
INodeType::Dir => DirEntryType::Dir,
118+
INodeType::Blk(_, _) => DirEntryType::Blk,
116119
INodeType::Reg => DirEntryType::Reg,
120+
INodeType::Lnk => DirEntryType::Lnk,
121+
INodeType::Sock => DirEntryType::Sock,
117122
}
118123
}
119124
}
@@ -281,6 +286,46 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
281286
unsafe { bindings::mapping_set_large_folios(inode.i_mapping) };
282287
bindings::S_IFREG
283288
}
289+
INodeType::Lnk => {
290+
inode.i_op = &Tables::<T>::LNK_INODE_OPERATIONS;
291+
inode.i_data.a_ops = &Tables::<T>::FILE_ADDRESS_SPACE_OPERATIONS;
292+
293+
// SAFETY: `inode` is valid for write as it's a new inode.
294+
unsafe { bindings::inode_nohighmem(inode) };
295+
bindings::S_IFLNK
296+
}
297+
INodeType::Fifo => {
298+
// SAFETY: `inode` is valid for write as it's a new inode.
299+
unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) };
300+
bindings::S_IFIFO
301+
}
302+
INodeType::Sock => {
303+
// SAFETY: `inode` is valid for write as it's a new inode.
304+
unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) };
305+
bindings::S_IFSOCK
306+
}
307+
INodeType::Chr(major, minor) => {
308+
// SAFETY: `inode` is valid for write as it's a new inode.
309+
unsafe {
310+
bindings::init_special_inode(
311+
inode,
312+
bindings::S_IFCHR as _,
313+
bindings::MKDEV(major, minor & bindings::MINORMASK),
314+
)
315+
};
316+
bindings::S_IFCHR
317+
}
318+
INodeType::Blk(major, minor) => {
319+
// SAFETY: `inode` is valid for write as it's a new inode.
320+
unsafe {
321+
bindings::init_special_inode(
322+
inode,
323+
bindings::S_IFBLK as _,
324+
bindings::MKDEV(major, minor & bindings::MINORMASK),
325+
)
326+
};
327+
bindings::S_IFBLK
328+
}
284329
};
285330

286331
inode.i_mode = (params.mode & 0o777) | u16::try_from(mode)?;
@@ -315,11 +360,26 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
315360
/// The type of the inode.
316361
#[derive(Copy, Clone)]
317362
pub enum INodeType {
363+
/// Named pipe (first-in, first-out) type.
364+
Fifo,
365+
366+
/// Character device type.
367+
Chr(u32, u32),
368+
318369
/// Directory type.
319370
Dir,
320371

372+
/// Block device type.
373+
Blk(u32, u32),
374+
321375
/// Regular file type.
322376
Reg,
377+
378+
/// Symbolic link type.
379+
Lnk,
380+
381+
/// Named unix-domain socket type.
382+
Sock,
323383
}
324384

325385
/// Required inode parameters.
@@ -701,6 +761,34 @@ impl<T: FileSystem + ?Sized> Tables<T> {
701761
}
702762
}
703763

764+
const LNK_INODE_OPERATIONS: bindings::inode_operations = bindings::inode_operations {
765+
lookup: None,
766+
get_link: Some(bindings::page_get_link),
767+
permission: None,
768+
get_inode_acl: None,
769+
readlink: None,
770+
create: None,
771+
link: None,
772+
unlink: None,
773+
symlink: None,
774+
mkdir: None,
775+
rmdir: None,
776+
mknod: None,
777+
rename: None,
778+
setattr: None,
779+
getattr: None,
780+
listxattr: None,
781+
fiemap: None,
782+
update_time: None,
783+
atomic_open: None,
784+
tmpfile: None,
785+
get_acl: None,
786+
set_acl: None,
787+
fileattr_set: None,
788+
fileattr_get: None,
789+
get_offset_ctx: None,
790+
};
791+
704792
const FILE_ADDRESS_SPACE_OPERATIONS: bindings::address_space_operations =
705793
bindings::address_space_operations {
706794
writepage: None,

samples/rust/rust_rofs.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct Entry {
2323
contents: &'static [u8],
2424
}
2525

26-
const ENTRIES: [Entry; 3] = [
26+
const ENTRIES: [Entry; 4] = [
2727
Entry {
2828
name: b".",
2929
ino: 1,
@@ -42,6 +42,12 @@ const ENTRIES: [Entry; 3] = [
4242
etype: INodeType::Reg,
4343
contents: b"hello\n",
4444
},
45+
Entry {
46+
name: b"link.txt",
47+
ino: 3,
48+
etype: INodeType::Lnk,
49+
contents: b"./test.txt",
50+
},
4551
];
4652

4753
struct RoFs;
@@ -125,6 +131,7 @@ impl fs::FileSystem for RoFs {
125131
fn read_folio(inode: &INode<Self>, mut folio: LockedFolio<'_>) -> Result {
126132
let data = match inode.ino() {
127133
2 => ENTRIES[2].contents,
134+
3 => ENTRIES[3].contents,
128135
_ => return Err(EINVAL),
129136
};
130137

0 commit comments

Comments
 (0)