Bug 4341

Summary: Проблема сбрасывания блокировки при закрытии файлового дескриптора
Product: WINE@Etersoft Reporter: Евгений Синельников <sin>
Component: Сетевые файловые системыAssignee: Александр Морозов <amorozov>
Status: CLOSED FIXED QA Contact: Евгений Савин <horch>
Severity: normal    
Priority: P3 CC: alter, lav, lbeasty, piastry, sin
Version: 1.0.11   
Target Milestone: ---   
Hardware: PC   
OS: All   
URL: http://bugs.etersoft.ru/show_bug.cgi?id=4132
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on:    
Bug Blocks: 4316    
Attachments: Пример теста на снятие блокировок после закрытия файла

Description Евгений Синельников 2009-10-05 23:20:16 MSD
Этот вопрос ранее обсуждался в контексте вставки костылей в CIFS.

Проблема возникает из-за того, что сетевая ФС удалённо снимает при закрытии файлов блокировки согласно POSIX.

В связи с этим WINE по-разному себя ведёт на разных ФС:

"""
Локально и на NFS.
1. Win-программа открывает файл xxx -> wineserver открывает файл xxx и получает дескриптор 1, устанавливает специальные блокировки, обозначающие SHARE-флаги 
2. Win-программа открывает файл xxx второй раз -> wineserver открывает файл xxx и получает дескриптор 2. Проверяется, что мы не нарушим sharing, если откроем файл, устанавливаются блокировки, обозначающие SHARE-флаги
3. Win-программа закрывает файл xxx -> wineserver помечает соответствующий дескриптор как закрытый. Если мы закроем дескриптор тут, то мы сбросим блокировки и потеряем информацию о SHARE-флагах
4. Win-программа закрывает файл xxx -> wineserver закрывает дескрипторы 1 и 2

CIFS
1. Win-программа открывает файл xxx -> wineserver открывает файл xxx с параметрами, описывающими SHARE-флаги, и получает дескриптор 1
2. Win-программа открывает файл xxx второй раз -> wineserver открывает файл xxx с параметрами, описывающими SHARE-флаги, и получает дескриптор 2. Если SHARE-флаги не совместимы с предыдущими, то файл открыть не удастся.
3. Win-программа закрывает файл xxx -> wineserver закрывает дескриптор 2
4. Win-программа закрывает файл xxx -> wineserver закрывает дескриптор 1

Почему мы не можем действовать в случае CIFS так же, как в локальном случае.
Допустим, мы открываем файл с GENERIC_WRITE и FILE_SHARE_READ|FILE_SHARE_WRITE, получаем дескриптор 1. Затем открываем его с GENERIC_READ и FILE_SHARE_WRITE, получаем дескриптро 2, закрываем дескриптор 2. Теперь мы не сможем открыть его с GENERIC_READ ещё раз.
"""

Хотелось бы уточнить проводил ли кто-нибудь тесты на поведение CIFS в описанном случае повторного открытия файла?

Далее я приведу свои...
Comment 1 Евгений Синельников 2009-10-05 23:45:28 MSD
Created attachment 1332 [details]
Пример теста на снятие блокировок после закрытия файла

Прилагаю простой тест на повторное открытие, соответствующее снятие блокировок и последующее чтение из первого ФС.

Вот как это работает эталонно на локальной ФС:
$ ./raw6
start 32166
server start 32167
server open for 5
server second open for 6
server close 6
server send 5
server file not locked
fd received=5 (len=1)
file 5 not locked
done

Аналогично всё ведёт себя и при обычном монтировании в CIFS (-oguest,noperm)
$ ./raw6
start 32451
server start 32452
server open for 5
server second open for 6
server close 6
server send 5
server file not locked
fd received=5 (len=1)
file 5 not locked
done

А вот при использовании forcemand и nounix начинаются чудеса:
$ ./raw6
start 32601
server start 32602
server open for 5
server second open for 6
server close 6
server send 5
server file not locked
fd received=5 (len=1)
file 5 not locked
read failed on 5 (Permission denied)
done

Причём на это влияет установка блокировки в первом файле и последующее открытие второго...
Comment 2 Евгений Синельников 2009-10-05 23:53:37 MSD
Очевидно, что проблема в связке Samba->CIFS->(Использование)

Вопрос в том, как должен работать  WINE... Мы его подстраиваем под особенности Samba+CIFS или нет?

Вообще проблема есть в самой Samba, которая довольно странно отрабатывает на разных запросах.

Можно пытаться перебрать все варианты... Но мне бы хотелось уточнить сценарии использования Samba+CIFS в WINE, иначе сложно добиться его нормальной работы...

На примере теста на снятие блокировок после закрытия файла показано, что в Samba+CIFS есть странности. Эти странности входят в набор сценариев работы для WINE?
Comment 3 Евгений Синельников 2009-10-06 00:03:11 MSD
Ещё более интересный эффект наблюдается, если фиксировать не вторую блокировку, а первую:
$ diff -u raw6.old raw6.c
--- raw6.old    2009-10-05 23:58:22 +0400
+++ raw6.c      2009-10-05 23:56:25 +0400
@@ -165,8 +165,8 @@

     flk.l_type = F_WRLCK;
     flk.l_whence = SEEK_SET;
-    flk.l_start = 1;
-    flk.l_len = 2;
+    flk.l_start = 0;
+    flk.l_len = 1;

     if (fcntl(fd, F_GETLK, &flk) < 0)
         fprintf(stderr, "fcntl get lock on %d failed (%s)\n", fd, strerror(errno));


Для обычного монтирования всё нормально:
$ ./raw6
start 374
server start 375
server open for 5
server second open for 6
server close 6
fd received=5 (len=1)
file 5 not locked
done
server send 5
server file not locked

А для forcemand наблюдаем отсутствие снятия блокировок после закрытия файлов -  в общем то, что и хотелось бы вроде как:
$ ./raw6
start 382
server start 383
server open for 5
server second open for 6
server close 6
server send 5
server file not locked
fd received=5 (len=1)
file 5 locked by 382
read failed on 5 (Permission denied)
done

Сие гадание и перебор параметров печальны... Слишком много исходов...
Comment 4 Евгений Синельников 2009-10-06 00:06:06 MSD
Резюмирую,

forcemand (и mandatory нормально срабатывает и блокировки не снимаются) нас как бы всем устраивает, но непонятно почему Permission Denied на чтении - вероятно здесь придётся лезть в самбу....
Comment 5 Евгений Синельников 2009-10-06 00:16:48 MSD
О! Ну, надо же... Добавил свои костыли для пробрасывания Pid'а

Проблема Permission Denied пропала... Но пропало снятие блокировок...

Далее добавил два накопанных в исходниках самбы параметра (должно быть достаточно одного):
   posix locking = false
   blocking locks = false

Всё получилось!!!
Тесты прошли!!!

Нужно проверить VVS...

Сделаю новую сборку etercifs - расскажу как оно должно настраиваться... Но это уже завтра...