Skip to content

Commit 26093bb

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 0cfce9e commit 26093bb

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
}
@@ -272,6 +277,46 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
272277
unsafe { bindings::mapping_set_large_folios(inode.i_mapping) };
273278
bindings::S_IFREG
274279
}
280+
INodeType::Lnk => {
281+
inode.i_op = &Tables::<T>::LNK_INODE_OPERATIONS;
282+
inode.i_data.a_ops = &Tables::<T>::FILE_ADDRESS_SPACE_OPERATIONS;
283+
284+
// SAFETY: `inode` is valid for write as it's a new inode.
285+
unsafe { bindings::inode_nohighmem(inode) };
286+
bindings::S_IFLNK
287+
}
288+
INodeType::Fifo => {
289+
// SAFETY: `inode` is valid for write as it's a new inode.
290+
unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) };
291+
bindings::S_IFIFO
292+
}
293+
INodeType::Sock => {
294+
// SAFETY: `inode` is valid for write as it's a new inode.
295+
unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) };
296+
bindings::S_IFSOCK
297+
}
298+
INodeType::Chr(major, minor) => {
299+
// SAFETY: `inode` is valid for write as it's a new inode.
300+
unsafe {
301+
bindings::init_special_inode(
302+
inode,
303+
bindings::S_IFCHR as _,
304+
bindings::MKDEV(major, minor & bindings::MINORMASK),
305+
)
306+
};
307+
bindings::S_IFCHR
308+
}
309+
INodeType::Blk(major, minor) => {
310+
// SAFETY: `inode` is valid for write as it's a new inode.
311+
unsafe {
312+
bindings::init_special_inode(
313+
inode,
314+
bindings::S_IFBLK as _,
315+
bindings::MKDEV(major, minor & bindings::MINORMASK),
316+
)
317+
};
318+
bindings::S_IFBLK
319+
}
275320
};
276321

277322
inode.i_mode = (params.mode & 0o777) | u16::try_from(mode)?;
@@ -306,11 +351,26 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
306351
/// The type of the inode.
307352
#[derive(Copy, Clone)]
308353
pub enum INodeType {
354+
/// Named pipe (first-in, first-out) type.
355+
Fifo,
356+
357+
/// Character device type.
358+
Chr(u32, u32),
359+
309360
/// Directory type.
310361
Dir,
311362

363+
/// Block device type.
364+
Blk(u32, u32),
365+
312366
/// Regular file type.
313367
Reg,
368+
369+
/// Symbolic link type.
370+
Lnk,
371+
372+
/// Named unix-domain socket type.
373+
Sock,
314374
}
315375

316376
/// Required inode parameters.
@@ -720,6 +780,34 @@ impl<T: FileSystem + ?Sized> Tables<T> {
720780
}
721781
}
722782

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