Skip to content

Commit ecc6d49

Browse files
committed
rust: fs: introduce more inode types
This patch introduces symlinks, pipes, sockets, char devices and block devices as types of inodes that can be created by Rust file systems. Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com>
1 parent 0d231e7 commit ecc6d49

3 files changed

Lines changed: 102 additions & 1 deletion

File tree

rust/helpers.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,12 @@ void rust_helper_mapping_set_large_folios(struct address_space *mapping)
227227
}
228228
EXPORT_SYMBOL_GPL(rust_helper_mapping_set_large_folios);
229229

230+
unsigned int rust_helper_MKDEV(unsigned int major, unsigned int minor)
231+
{
232+
return MKDEV(major, minor);
233+
}
234+
EXPORT_SYMBOL_GPL(rust_helper_MKDEV);
235+
230236
/*
231237
* `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
232238
* 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
@@ -117,8 +117,13 @@ pub enum DirEntryType {
117117
impl From<INodeType> for DirEntryType {
118118
fn from(value: INodeType) -> Self {
119119
match value {
120+
INodeType::Fifo => DirEntryType::Fifo,
121+
INodeType::Chr(_, _) => DirEntryType::Chr,
120122
INodeType::Dir => DirEntryType::Dir,
123+
INodeType::Blk(_, _) => DirEntryType::Blk,
121124
INodeType::Reg => DirEntryType::Reg,
125+
INodeType::Lnk => DirEntryType::Lnk,
126+
INodeType::Sock => DirEntryType::Sock,
122127
}
123128
}
124129
}
@@ -280,6 +285,46 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
280285
unsafe { bindings::mapping_set_large_folios(inode.i_mapping) };
281286
bindings::S_IFREG
282287
}
288+
INodeType::Lnk => {
289+
inode.i_op = &Tables::<T>::LNK_INODE_OPERATIONS;
290+
inode.i_data.a_ops = &Tables::<T>::FILE_ADDRESS_SPACE_OPERATIONS;
291+
292+
// SAFETY: `inode` is valid for write as it's a new inode.
293+
unsafe { bindings::inode_nohighmem(inode) };
294+
bindings::S_IFLNK
295+
}
296+
INodeType::Fifo => {
297+
// SAFETY: `inode` is valid for write as it's a new inode.
298+
unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) };
299+
bindings::S_IFIFO
300+
}
301+
INodeType::Sock => {
302+
// SAFETY: `inode` is valid for write as it's a new inode.
303+
unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) };
304+
bindings::S_IFSOCK
305+
}
306+
INodeType::Chr(major, minor) => {
307+
// SAFETY: `inode` is valid for write as it's a new inode.
308+
unsafe {
309+
bindings::init_special_inode(
310+
inode,
311+
bindings::S_IFCHR as _,
312+
bindings::MKDEV(major, minor & bindings::MINORMASK),
313+
)
314+
};
315+
bindings::S_IFCHR
316+
}
317+
INodeType::Blk(major, minor) => {
318+
// SAFETY: `inode` is valid for write as it's a new inode.
319+
unsafe {
320+
bindings::init_special_inode(
321+
inode,
322+
bindings::S_IFBLK as _,
323+
bindings::MKDEV(major, minor & bindings::MINORMASK),
324+
)
325+
};
326+
bindings::S_IFBLK
327+
}
283328
};
284329

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

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

324384
/// Required inode parameters.
@@ -725,6 +785,34 @@ impl<T: FileSystem + ?Sized> Tables<T> {
725785
}
726786
}
727787

788+
const LNK_INODE_OPERATIONS: bindings::inode_operations = bindings::inode_operations {
789+
lookup: None,
790+
get_link: Some(bindings::page_get_link),
791+
permission: None,
792+
get_inode_acl: None,
793+
readlink: None,
794+
create: None,
795+
link: None,
796+
unlink: None,
797+
symlink: None,
798+
mkdir: None,
799+
rmdir: None,
800+
mknod: None,
801+
rename: None,
802+
setattr: None,
803+
getattr: None,
804+
listxattr: None,
805+
fiemap: None,
806+
update_time: None,
807+
atomic_open: None,
808+
tmpfile: None,
809+
get_acl: None,
810+
set_acl: None,
811+
fileattr_set: None,
812+
fileattr_get: None,
813+
get_offset_ctx: None,
814+
};
815+
728816
const FILE_ADDRESS_SPACE_OPERATIONS: bindings::address_space_operations =
729817
bindings::address_space_operations {
730818
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;
@@ -129,6 +135,7 @@ impl fs::FileSystem for RoFs {
129135
fn read_folio(inode: &INode<Self>, mut folio: LockedFolio<'_>) -> Result {
130136
let data = match inode.ino() {
131137
2 => ENTRIES[2].contents,
138+
3 => ENTRIES[3].contents,
132139
_ => return Err(EINVAL),
133140
};
134141

0 commit comments

Comments
 (0)