Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Falloc error checks and collapse #18

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion SQUIRRELFS_CONFIG
Original file line number Diff line number Diff line change
Expand Up @@ -5197,4 +5197,4 @@ CONFIG_ARCH_USE_MEMTEST=y
CONFIG_RUST_OVERFLOW_CHECKS=y
# CONFIG_RUST_BUILD_ASSERT_ALLOW is not set
# end of Rust hacking
# end of Kernel hacking
# end of Kernel hacking
1 change: 1 addition & 0 deletions fs/hayleyfs/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub(crate) const MAX_FILENAME_LEN: usize = 110;
pub(crate) const MAX_PAGES: u64 = u64::MAX;
pub(crate) const MAX_LINKS: u16 = u16::MAX;
pub(crate) const DENTRIES_PER_PAGE: usize = 32;
pub(crate) const MAX_FILE_SIZE: u64 = 1000000; // TODO: get a correct number for this.
hayley-leblanc marked this conversation as resolved.
Show resolved Hide resolved

/// Reserved pages
#[allow(dead_code)]
Expand Down
146 changes: 139 additions & 7 deletions fs/hayleyfs/h_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::defs::*;
use crate::h_inode::*;
use crate::typestate::*;
use crate::volatile::*;
use crate::namei::*;
use crate::{end_timing, fence_vec, init_timing, start_timing};
use core::{ffi, marker::Sync, ptr, sync::atomic::Ordering};
use kernel::prelude::*;
Expand All @@ -12,6 +13,7 @@ use kernel::{
iomap, mm,
};


pub(crate) struct Adapter {}

impl<T: Sync> file::OpenAdapter<T> for Adapter {
Expand All @@ -20,6 +22,21 @@ impl<T: Sync> file::OpenAdapter<T> for Adapter {
}
}

// FLags for fallocate modes

#[repr(i32)]
#[allow(non_camel_case_types)]
enum FALLOC_FLAG {
FALLOC_FL_KEEP_SIZE = 0x01,
FALLOC_FL_PUNCH_HOLE = 0x02,
// FALLOC_FL_NO_HIDE_STALE = 0x04,
FALLOC_FL_COLLAPSE_RANGE = 0x08,
FALLOC_FL_ZERO_RANGE = 0x10,
FALLOC_FL_INSERT_RANGE = 0x20,
// FALLOC_FL_UNSHARE_RANGE = 0x40,
}
Comment on lines +27 to +37
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to import these flags from rust/bindings/bindings_generated.rs. If they aren't there, we probably have to add the file in which they are defined by the kernel to rust/bindings/bindings_helper.h. The Rust build system incorporated with the kernel uses this .h file to set up Rust-friendly definitions of everything defined by files it includes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, looks like they are defined as C macros for some reason, which makes our lives a little more difficult. The automatic binding generation doesn't work on C macros, sohe cleanest way to handle this at the moment would be to manually add a wrapper for each macro in rust/helpers.c, following the same style as the existing functions in that file.



pub(crate) struct FileOps;
#[vtable]
impl file::Operations for FileOps {
Expand Down Expand Up @@ -85,7 +102,7 @@ impl file::Operations for FileOps {
Ok((bytes_written, _)) => Ok(bytes_written.try_into()?),
Err(e) => Err(e),
}
}
}

fn read(
_data: (),
Expand Down Expand Up @@ -128,13 +145,19 @@ impl file::Operations for FileOps {
}

fn fallocate(
_data: (),
_file: &file::File,
_mode: i32,
_offset: i64,
_len: i64,
data: (),
file: &file::File,
mode: i32,
offset: i64,
len: i64,
) -> Result<u64> {
Err(EINVAL)
let inode: &mut fs::INode = unsafe { &mut *file.inode().cast() };

let sb = inode.i_sb();
let fs_info_raw = unsafe { (*sb).s_fs_info };
let sbi = unsafe { &mut *(fs_info_raw as *mut SbInfo) };
hayley-leblanc marked this conversation as resolved.
Show resolved Hide resolved

return hayleyfs_fallocate(inode, sbi, data, file, mode, offset, len);
}

fn ioctl(data: (), file: &file::File, cmd: &mut file::IoctlCommand) -> Result<i32> {
Expand All @@ -151,6 +174,115 @@ impl file::Operations for FileOps {
}
}


fn hayleyfs_fallocate(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Looks like the default mode for fallocate got lost when moving the code over to the new function though (or is it going to be replaced with something else?)

inode: &mut fs::INode,
sbi: &mut SbInfo,
data: (),
file: &file::File,
mode: i32,
offset: i64,
len: i64,
) -> Result<u64> {
let pi = sbi.get_init_reg_inode_by_vfs_inode(inode.get_inner())?;

// let pi_info = pi.get_inode_info()?;
let initial_size: u64 = pi.get_size() as u64;

/*
* Error checks beforehand, sourced from below:
* https://man7.org/linux/man-pages/man2/fallocate.2.html#ERRORS
*/
let falloc_fl_insert_range = mode & FALLOC_FLAG::FALLOC_FL_INSERT_RANGE as i32 == 1;
let falloc_fl_collapse_range = mode & FALLOC_FLAG::FALLOC_FL_COLLAPSE_RANGE as i32 == 1;
let falloc_fl_keep_size = mode & FALLOC_FLAG::FALLOC_FL_KEEP_SIZE as i32 == 1;
let falloc_fl_zero_range = mode & FALLOC_FLAG::FALLOC_FL_ZERO_RANGE as i32 == 1;
let falloc_fl_punch_hole = mode & FALLOC_FLAG::FALLOC_FL_PUNCH_HOLE as i32 == 1;

/*
* EINVAL: offset was less than 0, or len was less than or equal to 0.
*/
if offset < 0 || len <= 0 {
return Err(EINVAL);
}

pr_info!("Gets past offset and length check");

let len_u64: u64 = len.try_into().unwrap();
let offset_u64: u64 = offset.try_into().unwrap();
let final_file_size : u64 = len_u64 + offset_u64;

/*
* EFBIG: offset+len exceeds the maximum file size.
*/
if final_file_size > MAX_FILE_SIZE {
return Err(EFBIG);
}

pr_info!("Gets past file size check");

/*
* EFBIG: mode is FALLOC_FL_INSERT_RANGE, and the current file
* size+len exceeds the maximum file size.
*/
if falloc_fl_insert_range && (initial_size + len_u64 > MAX_FILE_SIZE) {
pr_info!("Fails the insert_range check.");
return Err(EFBIG);
}

/*
* EINTR: A signal was caught during execution; see signal(7).
*/
// TODO: implement me!

/*
* EINVAL: mode is FALLOC_FL_COLLAPSE_RANGE and the range specified
* by offset plus len reaches or passes the end of the file.
*
* EINVAL: mode is FALLOC_FL_COLLAPSE_RANGE or
* FALLOC_FL_INSERT_RANGE, but either offset or len is not a
* multiple of the filesystem block size.
*/
if falloc_fl_collapse_range &&
offset_u64 + len_u64 >= initial_size ||
(offset_u64 % HAYLEYFS_PAGESIZE != 0 || len_u64 % HAYLEYFS_PAGESIZE != 0) // Treat pages as blocks?
{
return Err(EINVAL);
}

/*
* EINVAL: mode is FALLOC_FL_INSERT_RANGE and the range specified by
* offset reaches or passes the end of the file.
*
* EINVAL: mode is FALLOC_FL_COLLAPSE_RANGE or
* FALLOC_FL_INSERT_RANGE, but either offset or len is not a
* multiple of the filesystem block size.
*/
if falloc_fl_insert_range &&
(offset_u64 >= initial_size) ||
(offset_u64 % HAYLEYFS_PAGESIZE != 0 || len_u64 % HAYLEYFS_PAGESIZE != 0)
{
return Err(EINVAL);
}

/*
* EINVAL: mode contains one of FALLOC_FL_COLLAPSE_RANGE or
* FALLOC_FL_INSERT_RANGE and also other flags; no other
* flags are permitted with FALLOC_FL_COLLAPSE_RANGE or
* FALLOC_FL_INSERT_RANGE.
*/
if (falloc_fl_insert_range && falloc_fl_collapse_range) ||
(
(falloc_fl_insert_range ^ falloc_fl_collapse_range) &&
falloc_fl_keep_size || falloc_fl_zero_range || falloc_fl_punch_hole
)
{
return Err(EINVAL);
}

Ok(0)
}

#[allow(dead_code)]
fn hayleyfs_write<'a>(
sbi: &'a SbInfo,
Expand Down
2 changes: 1 addition & 1 deletion fs/hayleyfs/namei.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,7 @@ fn hayleyfs_symlink<'a>(
}

// TODO: return a type indicating that the truncate has completed
fn hayleyfs_truncate<'a>(
pub(crate) fn hayleyfs_truncate<'a>(
sbi: &SbInfo,
pi: InodeWrapper<'a, Clean, Start, RegInode>,
size: i64,
Expand Down
58 changes: 58 additions & 0 deletions fs/hayleyfs/update_fs.sh
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this file do anything anymore? If not, let's remove it (or move it to the tests/ directory if it does help with something that I didn't see on a quick scan).

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash
source /home/rustfs/.bashrc
source /home/rustfs/.profile
Comment on lines +2 to +3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this references some files that are not part of the repo; if there is something defined in these files that is required for this script, you should copy it into the script or include it in a file that is part of the repo.


t_flag=0

# Use getopts to process the flags
while getopts "t" opt; do
case $opt in
t)
t_flag=1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
;;
esac
done

cd ../../
pwd

# Makes sure the step runs.
step() {
echo -n "Executing: $@ "
"$@"

result=$?
if [ $result -ne 0 ]; then
echo "Command failed"
exit 0
else
echo "✅"
fi
}


sudo umount /dev/pmem0
sudo rmmod hayleyfs

echo
echo "Removed old file system. Now starting mount of new one."
echo

# step make LLVM=-14 fs/hayleyfs/hayleyfs.ko
# step sudo insmod fs/hayleyfs/hayleyfs.ko
# step sudo mount -o init -t hayleyfs /dev/pmem0 /mnt/pmem
echo

echo "File system module rebuilt, loaded, and mounted successfully."

if [ $t_flag -eq 1 ]; then
echo "-t was set; Running tests."

cd tests/

pwd
./test_fs.sh
fi
Loading