Skip to content

Commit ad6cae3

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 85179a6 commit ad6cae3

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
@@ -119,8 +119,13 @@ pub mod ro {
119119
impl From<INodeType> for DirEntryType {
120120
fn from(value: INodeType) -> Self {
121121
match value {
122+
INodeType::Fifo => DirEntryType::Fifo,
123+
INodeType::Chr(_, _) => DirEntryType::Chr,
122124
INodeType::Dir => DirEntryType::Dir,
125+
INodeType::Blk(_, _) => DirEntryType::Blk,
123126
INodeType::Reg => DirEntryType::Reg,
127+
INodeType::Lnk => DirEntryType::Lnk,
128+
INodeType::Sock => DirEntryType::Sock,
124129
}
125130
}
126131
}
@@ -280,6 +285,46 @@ pub mod ro {
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)?;
@@ -315,11 +360,26 @@ pub mod ro {
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.
@@ -731,6 +791,34 @@ pub mod ro {
731791
}
732792
}
733793

794+
const LNK_INODE_OPERATIONS: bindings::inode_operations = bindings::inode_operations {
795+
lookup: None,
796+
get_link: Some(bindings::page_get_link),
797+
permission: None,
798+
get_inode_acl: None,
799+
readlink: None,
800+
create: None,
801+
link: None,
802+
unlink: None,
803+
symlink: None,
804+
mkdir: None,
805+
rmdir: None,
806+
mknod: None,
807+
rename: None,
808+
setattr: None,
809+
getattr: None,
810+
listxattr: None,
811+
fiemap: None,
812+
update_time: None,
813+
atomic_open: None,
814+
tmpfile: None,
815+
get_acl: None,
816+
set_acl: None,
817+
fileattr_set: None,
818+
fileattr_get: None,
819+
get_offset_ctx: None,
820+
};
821+
734822
const FILE_ADDRESS_SPACE_OPERATIONS: bindings::address_space_operations =
735823
bindings::address_space_operations {
736824
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::ro::Type 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)