Skip to content

Commit f173873

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 49f0b54 commit f173873

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
@@ -106,8 +106,13 @@ pub enum DirEntryType {
106106
impl From<INodeType> for DirEntryType {
107107
fn from(value: INodeType) -> Self {
108108
match value {
109+
INodeType::Fifo => DirEntryType::Fifo,
110+
INodeType::Chr(_, _) => DirEntryType::Chr,
109111
INodeType::Dir => DirEntryType::Dir,
112+
INodeType::Blk(_, _) => DirEntryType::Blk,
110113
INodeType::Reg => DirEntryType::Reg,
114+
INodeType::Lnk => DirEntryType::Lnk,
115+
INodeType::Sock => DirEntryType::Sock,
111116
}
112117
}
113118
}
@@ -269,6 +274,46 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
269274
unsafe { bindings::mapping_set_large_folios(inode.i_mapping) };
270275
bindings::S_IFREG
271276
}
277+
INodeType::Lnk => {
278+
inode.i_op = &Tables::<T>::LNK_INODE_OPERATIONS;
279+
inode.i_data.a_ops = &Tables::<T>::FILE_ADDRESS_SPACE_OPERATIONS;
280+
281+
// SAFETY: `inode` is valid for write as it's a new inode.
282+
unsafe { bindings::inode_nohighmem(inode) };
283+
bindings::S_IFLNK
284+
}
285+
INodeType::Fifo => {
286+
// SAFETY: `inode` is valid for write as it's a new inode.
287+
unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) };
288+
bindings::S_IFIFO
289+
}
290+
INodeType::Sock => {
291+
// SAFETY: `inode` is valid for write as it's a new inode.
292+
unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) };
293+
bindings::S_IFSOCK
294+
}
295+
INodeType::Chr(major, minor) => {
296+
// SAFETY: `inode` is valid for write as it's a new inode.
297+
unsafe {
298+
bindings::init_special_inode(
299+
inode,
300+
bindings::S_IFCHR as _,
301+
bindings::MKDEV(major, minor & bindings::MINORMASK),
302+
)
303+
};
304+
bindings::S_IFCHR
305+
}
306+
INodeType::Blk(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_IFBLK as _,
312+
bindings::MKDEV(major, minor & bindings::MINORMASK),
313+
)
314+
};
315+
bindings::S_IFBLK
316+
}
272317
};
273318

274319
inode.i_mode = (params.mode & 0o777) | u16::try_from(mode)?;
@@ -303,11 +348,26 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
303348
/// The type of the inode.
304349
#[derive(Copy, Clone)]
305350
pub enum INodeType {
351+
/// Named pipe (first-in, first-out) type.
352+
Fifo,
353+
354+
/// Character device type.
355+
Chr(u32, u32),
356+
306357
/// Directory type.
307358
Dir,
308359

360+
/// Block device type.
361+
Blk(u32, u32),
362+
309363
/// Regular file type.
310364
Reg,
365+
366+
/// Symbolic link type.
367+
Lnk,
368+
369+
/// Named unix-domain socket type.
370+
Sock,
311371
}
312372

313373
/// Required inode parameters.
@@ -717,6 +777,34 @@ impl<T: FileSystem + ?Sized> Tables<T> {
717777
}
718778
}
719779

780+
const LNK_INODE_OPERATIONS: bindings::inode_operations = bindings::inode_operations {
781+
lookup: None,
782+
get_link: Some(bindings::page_get_link),
783+
permission: None,
784+
get_inode_acl: None,
785+
readlink: None,
786+
create: None,
787+
link: None,
788+
unlink: None,
789+
symlink: None,
790+
mkdir: None,
791+
rmdir: None,
792+
mknod: None,
793+
rename: None,
794+
setattr: None,
795+
getattr: None,
796+
listxattr: None,
797+
fiemap: None,
798+
update_time: None,
799+
atomic_open: None,
800+
tmpfile: None,
801+
get_acl: None,
802+
set_acl: None,
803+
fileattr_set: None,
804+
fileattr_get: None,
805+
get_offset_ctx: None,
806+
};
807+
720808
const FILE_ADDRESS_SPACE_OPERATIONS: bindings::address_space_operations =
721809
bindings::address_space_operations {
722810
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)