@@ -273,6 +273,18 @@ void *rust_helper_alloc_inode_sb(struct super_block *sb,
}
EXPORT_SYMBOL_GPL(rust_helper_alloc_inode_sb);
+unsigned int rust_helper_memalloc_nofs_save(void)
+{
+ return memalloc_nofs_save();
+}
+EXPORT_SYMBOL_GPL(rust_helper_memalloc_nofs_save);
+
+void rust_helper_memalloc_nofs_restore(unsigned int flags)
+{
+ memalloc_nofs_restore(flags);
+}
+EXPORT_SYMBOL_GPL(rust_helper_memalloc_nofs_restore);
+
void rust_helper_i_uid_write(struct inode *inode, uid_t uid)
{
i_uid_write(inode, uid);
@@ -417,6 +417,18 @@ impl<T: FileSystem + ?Sized> Tables<T> {
}
}
+/// Calls `cb` in a nofs allocation context.
+///
+/// That is, if an allocation happens within `cb`, it will have the `__GFP_FS` bit cleared.
+pub fn memalloc_nofs<T>(cb: impl FnOnce() -> T) -> T {
+ // SAFETY: Function is safe to be called from any context.
+ let flags = unsafe { bindings::memalloc_nofs_save() };
+ let ret = cb();
+ // SAFETY: Function is safe to be called from any context.
+ unsafe { bindings::memalloc_nofs_restore(flags) };
+ ret
+}
+
/// Kernel module that exposes a single file system implemented by `T`.
#[pin_data]
pub struct Module<T: FileSystem + ?Sized> {