Сбой прямого ввода-вывода в пространстве ядраLinux

Ответить Пред. темаСлед. тема
Anonymous
 Сбой прямого ввода-вывода в пространстве ядра

Сообщение Anonymous »

По некоторым причинам мне удается читать файл непосредственно с диска (т. е. в обход страничного кэша) в ядре Linux x64 (v5.4.0).
У пользователя пространство, это можно сделать, передав флаг O_DIRECT в open(). Вот мой код пользовательского пространства (и он отлично работает):

Код: Выделить всё

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
int fd = open(filepath, O_RDONLY | O_DIRECT);
if (fd == -1) {
perror("open");
return 1;
}

struct stat fstat;
stat("musl-hello", &fstat);
int blksize = (int)fstat.st_blksize;
int align = blksize-1;

const char *big_buf = (char *) malloc(blksize + align);

unsigned char *buff = (char *)( (unsigned long)(big_buf+align) & ~align );

if(read(fd, buff, (size_t)blksize) < 1)
{
//Error handling
free(big_buf);
return -1;
}

return 0;
}

Чтобы достичь той же цели в пространстве ядра, я прочитал этот вопрос. Насколько я понимаю, для правильной работы vfs_read() есть два ограничения:
  • буфер должен поступать из пользовательского пространства
  • буфер должен быть выровнен по размеру блока
Я попробовал следующий код (при условии, что размер блока равен 0x1000 в моем коде пользовательского пространства 0x1000 работает нормально):

Код: Выделить всё

mm_segment_t old_fs;
struct file *fp;
int rv = 0;
old_fs = get_fs();
set_fs(KERNEL_DS);
fp = filp_open(fpath, O_RDONLY | O_DIRECT, 0); // fpath is the path to the file to be read

if (IS_ERR(fp))
{
printk("filp_open failed\n");
}
else
{
loff_t pos = 0;
unsigned char *big_buf = kmalloc(0x2000, GFP_KERNEL);

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

// it seems kmalloc already aligned big_buf
unsigned char *aligned_buf = (unsigned char *)((unsigned long)(big_buf + 0xfff) & ~0xfff);

rv = vfs_read(fp, (void __user *)aligned_buf, 0x1000, &pos);
if (rv < 0)
{
printk("vfs_read() err, rv: %d\n", rv);
}

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

set_fs(old_fs);
Я думаю, что в моем коде два вышеупомянутых ограничения уже удовлетворены. Однако vfs_read() по-прежнему возвращает -EFAULT.
Любая помощь или предложения приветствуются и очень ценятся!

Подробнее здесь: https://stackoverflow.com/questions/787 ... pace-fails
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Linux»