Article 6P2XY kernel_read() returns -EFAULT when passing with the O_DIRECT flag (linux kernel v5.4.0)

kernel_read() returns -EFAULT when passing with the O_DIRECT flag (linux kernel v5.4.0)

by
Chibi Gwen
from LinuxQuestions.org on (#6P2XY)
Hi all,
I'd like to read file contents directly from the disk (bypass kernel's page cache mechanism). In user space, I've achived this by using the O_DIRECT flag with libc's open() function.
To achieve the same goal in kernel space, I've written the following code and compiled it as a kernel module (inspired by this link https://stackoverflow.com/questions/...ry-from-kernel).

Code:#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/err.h>
#include <linux/fcntl.h>
#include <linux/uio.h>

static int __init start(void)
{
printk(KERN_INFO, "module installed\n");

struct file *fp = filp_open("/home/chibigwen/Desktop/ko/nonsense", O_RDONLY | O_DIRECT, 0);
int rv;
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(USER_DS);

if (IS_ERR(fp)) {
printk("filp_open() failed\n");
rv = PTR_ERR(fp);
}
else
{
loff_t pos = 0;

unsigned char *big_buf = kmalloc(0x2000, GFP_KERNEL);

if(big_buf == NULL)
{
printk("bad kmalloc\n");
}

// it seems like we don't need alignment
unsigned char *kread_buf = (unsigned char *)((unsigned long)(big_buf + 0xfff) & ~0xfff);

rv = kernel_read(fp, kread_buf, 0x1000, &pos);

if (rv < 0)
{
printk("bad kernel_read(), rv: %d\n", rv);
}
else
{
printk("kernel_read() reads %d bytes\n", rv);
printk("on disk: %x %x %x\n", kread_buf[0x100], kread_buf[0x101], kread_buf[0x102]);
}

kfree(big_buf);
}
filp_close(fp, NULL);
set_fs(old_fs);

return 0;
}

static void __exit end(void)
{
printk(KERN_INFO, "module uninstalled\n");
}

module_init(start);
module_exit(end);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chibi Gwen");
MODULE_DESCRIPTION("A module to test Direct I/O");
MODULE_VERSION("0.1");However, kernel_read() returns -EFAULT. After some googling, I've found this https://linux-kernel.vger.kernel.nar...-with-o-direct. It seems that my code is obsolete, and kernel_read()/vfs_read() does not work with the O_DIRECT flag. When I remove the O_DIRECT flag, kernel_read() successfully reads data from the file, but it uses the page cache, which is not desired.
I'm wondering if there are alternative methods to perform direct I/O in kernel space. Any suggestions or insights would be greatly appreciated. Thanks in advance!
External Content
Source RSS or Atom Feed
Feed Location https://feeds.feedburner.com/linuxquestions/latest
Feed Title LinuxQuestions.org
Feed Link https://www.linuxquestions.org/questions/
Reply 0 comments