Модуль ядра проверяет, существует ли файл - PullRequest
1 голос
/ 30 апреля 2020

Я делаю некоторые расширения для модуля ядра nandsim , и у меня возникают проблемы с поиском правильного способа проверить, существует ли файл перед его открытием. Я прочитал этот вопрос , который описывает, как основные операции c открытия / чтения / записи go, но у меня возникают проблемы с выяснением того, применяются ли обычные флаги open (2) и как здесь.

Я хорошо знаю, что чтение и запись файлов в модулях ядра - плохая практика; этот код уже существует в ядре и уже читает и записывает файлы. Я просто пытаюсь внести некоторые коррективы в то, что уже на месте. В настоящее время, когда модуль загружается и получает указание использовать файл кэша (указанный как строковый путь при вызове modprobe), он использует filp_open (), чтобы открыть файл или создать его, если он не существует:

/* in nandsim.c */
...
module_param(cache_file,   charp, 0400);
...
MODULE_PARM_DESC(cache_file,    "File to use to cache nand pages instead of memory");
...
struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);

Вы можете спросить: "Что вы на самом деле хотите здесь сделать?" Я хочу включить заголовок для файла кэша, чтобы его можно было использовать повторно, если необходимо перезагрузить систему. Включая информацию о геометрии nand-страницы и количестве страниц в начале этого файла, я могу с большей легкостью смоделировать ряд состояний ошибки, которые в противном случае были бы невозможны в среде nandsim. Если я смогу отключить модуль nandsim во время файловых операций или изменить файл поддержки для моделирования реального режима отказа, я смогу воссоздать эффект net этих условий ошибки. Это позволило бы мне вернуть имитированное устройство в оперативный режим с помощью nandsim и оценить, насколько хорошо отказоустойчивая файловая система выполняет свою работу.

Мой мыслительный процесс заключался в том, чтобы изменить его следующим образом, чтобы оно не сработало пытаюсь принудительно создать файл, который уже существует:

struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
if(IS_ERR(cfile)){
    printk(KERN_INFO "File didn't exist: %ld", PTR_ERR(cfile));
    /* Do header setup for first-time run of NAND simulation */
}
else{
    /* Read header and validate against system parameters.  Recover operations */
}

Я вижу ошибку, но это не та ошибка, которую я ожидал. Он сообщает errno 14, EFAULT (неверный адрес) вместо errno 17 EEXIST (файл существует). Я не хочу работать с этим, потому что я хотел бы, чтобы это было как идиоматизм c и как можно более правильным.

Есть ли какой-то другой способ, которым я должен делать это?

Мне нужно как-то указать, что путь к файлу находится в адресном пространстве пользователя? Если так, то почему это не так в коде, как это было?

РЕДАКТИРОВАТЬ: я смог получить надежную ошибку, пытаясь открыть только с O_RDWR и O_LARGEFILE, что привело к ENOENT. До сих пор не ясно, почему мой первоначальный подход был неверным, и каков наилучший способ достижения sh моей цели. Тем не менее, если кто-то более опытный может прокомментировать это, я могу добавить это в качестве решения.

1 Ответ

0 голосов
/ 01 мая 2020

Действительно, filp_open ожидает путь к файлу, который находится в адресном пространстве ядра. Доказательством является использование getname_kernel. Вы можете имитировать c это для вашего случая использования с чем-то вроде этого:

struct filename *name = getname(cache_file);
struct file *cfile = ERR_CAST(name);

if (!IS_ERR(name)) {
        cfile = file_open_name(name, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
        if (IS_ERR(cfile))
                return PTR_ERR(cfile);

        putname(name);
}

Обратите внимание, что getname ожидает адрес пространства пользователя и является эквивалентом getname_kernel.

...