Skip to content

Commit 4510d5a

Browse files
authored
Merge pull request #42 from wedsonaf/error_handling
Simplify error handling in file operations.
2 parents 514443c + 410b0f8 commit 4510d5a

File tree

1 file changed

+59
-72
lines changed

1 file changed

+59
-72
lines changed

rust/kernel/src/file_operations.rs

Lines changed: 59 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,34 @@ pub enum SeekFrom {
4141
Current(i64),
4242
}
4343

44+
fn from_kernel_result<T>(r: KernelResult<T>) -> T
45+
where
46+
T: TryFrom<c_types::c_int>,
47+
T::Error: core::fmt::Debug,
48+
{
49+
match r {
50+
Ok(v) => v,
51+
Err(e) => T::try_from(e.to_kernel_errno()).unwrap(),
52+
}
53+
}
54+
55+
macro_rules! from_kernel_result {
56+
($($tt:tt)*) => {{
57+
from_kernel_result((|| {
58+
$($tt)*
59+
})())
60+
}};
61+
}
62+
4463
unsafe extern "C" fn open_callback<T: FileOperations>(
4564
_inode: *mut bindings::inode,
4665
file: *mut bindings::file,
4766
) -> c_types::c_int {
48-
let f = match T::open() {
49-
Ok(f) => Box::new(f),
50-
Err(e) => return e.to_kernel_errno(),
51-
};
52-
(*file).private_data = Box::into_raw(f) as *mut c_types::c_void;
53-
0
67+
from_kernel_result! {
68+
let f = Box::new(T::open()?);
69+
(*file).private_data = Box::into_raw(f) as *mut c_types::c_void;
70+
Ok(0)
71+
}
5472
}
5573

5674
unsafe extern "C" fn read_callback<T: FileOperations>(
@@ -59,25 +77,15 @@ unsafe extern "C" fn read_callback<T: FileOperations>(
5977
len: c_types::c_size_t,
6078
offset: *mut bindings::loff_t,
6179
) -> c_types::c_ssize_t {
62-
let mut data = match UserSlicePtr::new(buf as *mut c_types::c_void, len) {
63-
Ok(ptr) => ptr.writer(),
64-
Err(e) => return e.to_kernel_errno().try_into().unwrap(),
65-
};
66-
let f = &*((*file).private_data as *const T);
67-
// No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
68-
// See discussion in #113
69-
let positive_offset = match (*offset).try_into() {
70-
Ok(v) => v,
71-
Err(_) => return Error::EINVAL.to_kernel_errno().try_into().unwrap(),
72-
};
73-
let read = T::READ.unwrap();
74-
match read(f, &File::from_ptr(file), &mut data, positive_offset) {
75-
Ok(()) => {
76-
let written = len - data.len();
77-
(*offset) += bindings::loff_t::try_from(written).unwrap();
78-
written.try_into().unwrap()
79-
}
80-
Err(e) => e.to_kernel_errno().try_into().unwrap(),
80+
from_kernel_result! {
81+
let mut data = UserSlicePtr::new(buf as *mut c_types::c_void, len)?.writer();
82+
let f = &*((*file).private_data as *const T);
83+
// No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
84+
// See discussion in #113
85+
T::READ.unwrap()(f, &File::from_ptr(file), &mut data, (*offset).try_into()?)?;
86+
let written = len - data.len();
87+
(*offset) += bindings::loff_t::try_from(written).unwrap();
88+
Ok(written.try_into().unwrap())
8189
}
8290
}
8391

@@ -87,25 +95,15 @@ unsafe extern "C" fn write_callback<T: FileOperations>(
8795
len: c_types::c_size_t,
8896
offset: *mut bindings::loff_t,
8997
) -> c_types::c_ssize_t {
90-
let mut data = match UserSlicePtr::new(buf as *mut c_types::c_void, len) {
91-
Ok(ptr) => ptr.reader(),
92-
Err(e) => return e.to_kernel_errno().try_into().unwrap(),
93-
};
94-
let f = &*((*file).private_data as *const T);
95-
// No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
96-
// See discussion in #113
97-
let positive_offset = match (*offset).try_into() {
98-
Ok(v) => v,
99-
Err(_) => return Error::EINVAL.to_kernel_errno().try_into().unwrap(),
100-
};
101-
let write = T::WRITE.unwrap();
102-
match write(f, &mut data, positive_offset) {
103-
Ok(()) => {
104-
let read = len - data.len();
105-
(*offset) += bindings::loff_t::try_from(read).unwrap();
106-
read.try_into().unwrap()
107-
}
108-
Err(e) => e.to_kernel_errno().try_into().unwrap(),
98+
from_kernel_result! {
99+
let mut data = UserSlicePtr::new(buf as *mut c_types::c_void, len)?.reader();
100+
let f = &*((*file).private_data as *const T);
101+
// No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
102+
// See discussion in #113
103+
T::WRITE.unwrap()(f, &mut data, (*offset).try_into()?)?;
104+
let read = len - data.len();
105+
(*offset) += bindings::loff_t::try_from(read).unwrap();
106+
Ok(read.try_into().unwrap())
109107
}
110108
}
111109

@@ -123,20 +121,16 @@ unsafe extern "C" fn llseek_callback<T: FileOperations>(
123121
offset: bindings::loff_t,
124122
whence: c_types::c_int,
125123
) -> bindings::loff_t {
126-
let off = match whence as u32 {
127-
bindings::SEEK_SET => match offset.try_into() {
128-
Ok(v) => SeekFrom::Start(v),
129-
Err(_) => return Error::EINVAL.to_kernel_errno().into(),
130-
},
131-
bindings::SEEK_CUR => SeekFrom::Current(offset),
132-
bindings::SEEK_END => SeekFrom::End(offset),
133-
_ => return Error::EINVAL.to_kernel_errno().into(),
134-
};
135-
let f = &*((*file).private_data as *const T);
136-
let seek = T::SEEK.unwrap();
137-
match seek(f, &File::from_ptr(file), off) {
138-
Ok(off) => off as bindings::loff_t,
139-
Err(e) => e.to_kernel_errno().into(),
124+
from_kernel_result! {
125+
let off = match whence as u32 {
126+
bindings::SEEK_SET => SeekFrom::Start(offset.try_into()?),
127+
bindings::SEEK_CUR => SeekFrom::Current(offset),
128+
bindings::SEEK_END => SeekFrom::End(offset),
129+
_ => return Err(Error::EINVAL),
130+
};
131+
let f = &*((*file).private_data as *const T);
132+
let off = T::SEEK.unwrap()(f, &File::from_ptr(file), off)?;
133+
Ok(off as bindings::loff_t)
140134
}
141135
}
142136

@@ -146,20 +140,13 @@ unsafe extern "C" fn fsync_callback<T: FileOperations>(
146140
end: bindings::loff_t,
147141
datasync: c_types::c_int,
148142
) -> c_types::c_int {
149-
let start = match start.try_into() {
150-
Ok(v) => v,
151-
Err(_) => return Error::EINVAL.to_kernel_errno(),
152-
};
153-
let end = match end.try_into() {
154-
Ok(v) => v,
155-
Err(_) => return Error::EINVAL.to_kernel_errno(),
156-
};
157-
let datasync = datasync != 0;
158-
let fsync = T::FSYNC.unwrap();
159-
let f = &*((*file).private_data as *const T);
160-
match fsync(f, &File::from_ptr(file), start, end, datasync) {
161-
Ok(result) => result.try_into().unwrap(),
162-
Err(e) => e.to_kernel_errno(),
143+
from_kernel_result! {
144+
let start = start.try_into()?;
145+
let end = end.try_into()?;
146+
let datasync = datasync != 0;
147+
let f = &*((*file).private_data as *const T);
148+
let res = T::FSYNC.unwrap()(f, &File::from_ptr(file), start, end, datasync)?;
149+
Ok(res.try_into().unwrap())
163150
}
164151
}
165152

0 commit comments

Comments
 (0)