Рейтинг:1

flock не работает с NFSv4

флаг ph

Я не знаю, почему этот код не работает под NFS4, с NFS3 работает отлично. Идея состоит в том, чтобы избежать записи файла, пока процесс все еще читает его.

Хотелось бы отладить, но наш сисадмин не умеет. Что может быть причиной. При нашей установке NFS4 я всегда попадаю в это состояние

  если ( стадо (fp, LOCK_EX) == -1)
    printf("Ошибка: файл %s уже заблокирован\n", fileName);

вся программа такая:

#include <sys/file.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv){

    если (argc<2){
        printf("Использование:\n a.out имя_файла\n");
        вернуть 1;
    }

    символ *имя_файла=argv[1];
    интервал кадров;
     
    /* заблокировать файл, я знаю, что процесс может записать 
    делает мою информацию бесполезной*/
    fp = открыть (имя файла, O_RDONLY);

    если ( стадо (fp, LOCK_EX) == -1) {
        printf("Ошибка: файл %s уже заблокирован\n", fileName);
    }
    еще{
        printf("Хорошо: файл %s заблокирован\n",fileName );
    }

    /* прочитать и проанализировать имя файла 
       другой процесс не должен иметь возможности записи или
       изменить имя файла, пока я его читаю
    */
    вернуть 0;    
}

Редактировать: Я хотел бы уточнить. Это фрагмент кода, который я использую. fileName должен быть действительным существующим файлом

Я читаю имя файла и делаю копию, редактируя несколько частей. Я знаю, пока я это делаю, внешний процесс может обновить имя файла. Я хотел бы использовать семафор, чтобы избежать изменений в этом файле, пока я не закончу с ним. Эта программа работала отлично, пока не перестала это делать. Единственная разница — это файловая система, в которой расположены имена файлов. Он был обновлен с NFS3 до NFS4. Даже ОС (SLE15.2) такая же, как и ядро ​​5.3.18, и использование strerror(errno) приводит к ошибке seg в NFS4. Единственная подсказка, когда я печатаю ("% d", ошибка) - это 9, что должно быть "неправильным дескриптором файла"

Спасибо за вашу помощь

Юлия

Matthew Ife avatar
флаг jo
Строка ```if (flock(fp,LOCK_EX) == -1){``` сообщает только о том, что монопольная блокировка не удалась. Не почему. Измените printf на ```printf("Ошибка: файл %s уже заблокирован: %s\n", fileName, strerror(errno));``` Вы только предполагаете, что это основная проблема с блокировкой но у вас может быть более фундаментальная ошибка (например, попытка заблокировать несуществующий файл).
флаг de
Вы должны напечатать errno (как было предложено другими), чтобы увидеть, почему запрос на блокировку не удался.
djdomi avatar
флаг za
Я считаю, что этот вопрос больше подходит для StackOverflow, а не для этого сайта.
Рейтинг:0
флаг de

NFS v3 не поддерживает блокировку на уровне протокола. Функционал обеспечивается дополнительным (внешним по отношению к протоколу nfs) менеджер замков. С другой стороны, NFS v4 имеет блокировку как часть спецификации. Кроме того, существует два типа замков. Один из них блокировки диапазона байтов, второе это общий доступ. Хотя более поздний вариант — это то, что вам нужно, POSIX API не предоставляет его, поэтому он недоступен для Linux и Unix.

Чтобы заставить блокировку работать с nfs v4 и v3, вам нужно использовать блокировка диапазона байтов который доступен как fcntl или же блокировка функции.

Проверьте код теста блокировки, используемый разработчиками nfs (включая меня) для проверки поведения клиента/сервера независимо от версии протокола.

http://git.linux-nfs.org/?p=steved/cthon04.git;a=blob;f=lock/tlock.c;h=8c837a87976d17c58a25c9bd08d9f935e4521402;hb=HEAD#l835

Рейтинг:0
флаг kz

Я только что проверил справочную страницу flock, в разделе ПРИМЕЧАНИЯ идет важная часть:

Детали NFS
   В ядрах Linux до версии 2.6.11 flock() не блокирует файлы через NFS (т. е. область действия блокировок была ограничена локальной системой). Вместо этого можно использовать блокировку диапазона байтов fcntl(2), которая
   работать по NFS, учитывая достаточно свежую версию Linux и сервер, поддерживающий блокировку.

   Начиная с Linux 2.6.12, клиенты NFS поддерживают блокировки flock(), эмулируя их как блокировки диапазона байтов fcntl(2) для всего файла. Это означает, что блокировки fcntl(2) и flock() взаимодействуют с одним
   другой по NFS. Это также означает, что для установки эксклюзивной блокировки файл должен быть открыт для записи.

   Начиная с Linux 2.6.37, ядро ​​поддерживает режим совместимости, который позволяет рассматривать блокировки flock() (а также блокировки области байтов fcntl(2)) как локальные; см. обсуждение local_lock
   опция в nfs(5).

Вы только открыли файл для чтения, из-за чего вызов стаи не работает.

Julia Fischer avatar
флаг ph
Спасибо. Вы ответили на мой вопрос. Я должен прочитать справочную страницу
Martin avatar
флаг kz
отличный! Если мой ответ решил ваш вопрос, отметьте его как принятый ответ...
Рейтинг:0
флаг jo

Этот раздел кода:

если ( стадо (fp, LOCK_EX) == -1) {
    printf("Ошибка: файл %s уже заблокирован\n", fileName);
}
еще{
    printf("Хорошо: файл %s заблокирован\n",fileName );
}

На самом деле могу только сказать вам, что блокировка не удалась или удалась, но не почему. Вы должны изменить его, чтобы сообщить о ошибаться причину сбоя, так как это может указывать на более фундаментальную проблему с вашей блокировкой, например, на попытку открыть файл, на который у вас нет разрешения или который не существует.

если ( стадо (fp, LOCK_EX) == -1) {
    printf("Ошибка: файл %s уже заблокирован: %s\n", fileName, strerror(errno));
}
еще{
    printf("Хорошо: файл %s заблокирован\n",fileName );
}

Вы также можете включить errno.h в списке включений, чтобы убедиться, что вы выбрали правильную переменную.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.