Укажите отработанное время

Отработанное время:
Продуктивное время:
Bug 4077 - VVS: совместная работа по CIFS   Make a simular bug
Summary: VVS: совместная работа по CIFS
Status: CLOSED FIXED
Alias: None
Product: WINE@Etersoft
Classification: Продукты (Products)
Component: Файловые операции (show other bugs)
Version: 1.0.10
Hardware: PC All
: P4 minor
Target Milestone: ---
Assignee: Александр Морозов
QA Contact: Денис Баранов
URL:
Whiteboard:
Keywords:
Depends on: 4316
Blocks: 3043 4284 4448 4475
  Show dependency treegraph
 
In work:
Reported: 2009-07-01 08:19 MSD by Константин Кондратюк
Modified: 2009-12-14 11:52 MSK (History)
3 users (show)

See Also:
Заявки RT:
Связано с:
Дата напоминания:


Attachments
простой тест на чтение после блокировки (893 bytes, text/plain)
2010-11-18 03:58 MSK, Евгений Синельников
Details
запись strace для простого теста (767.85 KB, application/x-bzip2)
2010-11-18 03:58 MSK, Евгений Синельников
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Константин Кондратюк 2009-07-01 08:19:37 MSD
При попытке работать с базой одного пользователя намертво блокируется вся база для другого. Если один пользователь запускает две копии программы, вроде блокировки срабатывают корректно.

В Windows, конечно же, работает и для разных пользователей...
Comment 1 Vitaly Lipatov 2009-07-26 19:47:39 MSD
Нужно проверить на 1.0.11.
Comment 2 Денис Баранов 2009-07-27 19:26:03 MSD
Проверено на WINE@Etersoft 1.0.11 eter2.2/eter1, etercifs 4.3.8  ошибка повторяется - совместный режим не работает.
Comment 3 Vitaly Lipatov 2009-07-27 20:03:56 MSD
Поспешил, надо проверять на новой сборке 1.0.11-eter3, где не будет вопросов по winelocktest.
Comment 4 Денис Баранов 2009-07-30 16:45:40 MSD
Проверил на WINE@Etersoft 1.0.11 eter4.1/eter2, совместный режим не работает (проверил на nfs и etercifs).
Comment 5 Александр Морозов 2009-07-30 17:38:52 MSD
VVS - это что? Где лежит дистрибутив?
Comment 6 Константин Кондратюк 2009-07-30 18:30:20 MSD
http://vvs.ru/

Дистрибутив:
"/var/ftp/pvt/Windows/Buh - Учётные/vvs_demo.exe"
Comment 7 Александр Морозов 2009-09-15 16:25:14 MSD
По NFS совместно работает. На NFS должны лежать не только файлы базы данных, но и сетевые файлы Paradox (де-факто это один файл PDOXUSRS.NET). Это настраивается в "Подключение к базе данных".
Comment 8 Александр Морозов 2009-09-15 18:49:56 MSD
При работе с базой на CIFS VVS зависает. Лог по +file:

trace:file:CreateFileW L"E:\\VVS_4077_NET\\PDOXUSRS.NET" GENERIC_READ GENERIC_WRITE FILE_SHARE_READ FILE_SHARE_WRITE  creation 3 attributes 0x10000080
................
trace:file:CreateFileW returning 0x114
................
trace:file:LockFile 0x114 000000000 000000001
trace:file:ReadFile 0x114 0x6bde4dbc 13030 0x32eee8 (nil)

В логах strace при этом:

poll([{fd=14, events=POLLIN}], 1, -1)   = 1 ([{fd=14, revents=POLLIN}])
read(14, 0x66cbb0, 13030)               = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=14, events=POLLIN}], 1, -1)   = 1 ([{fd=14, revents=POLLIN}])
read(14, 0x66cbb0, 13030)               = -1 EAGAIN (Resource temporarily unavailable)

В NtReadFile вызывается read, он возвращает -1 и ошибку EAGAIN. Если возвращается EAGAIN, то read вызывается снова, и это происходит бесконечное число раз. Процесс, который вызывает read, получает дескриптор от wineserver`а через сокет.

EAGAIN возвращается также при чтении файла на CIFS из созданного с помощью fork потомка, если до этого родитель установил блокировку (см. wine-etersoft-devel/cifs/lincifs2).
Comment 9 Александр Морозов 2009-09-15 19:23:58 MSD
Судя по тому, что сказано, в разделе "Mandatory locking" в man fcntl, EAGAIN должен возвращаться в случае, если неблокирующий read не может завершиться из-за mandatory блокировки. При выполнении fork блокировки теряются. Так что поведение wine-etersoft-devel/cifs/lincifs2 вроде как не является багом.
Comment 10 Александр Морозов 2009-09-15 21:10:10 MSD
POSIX-блокировки не передаются при передаче дескрипторов файлов через UNIX-сокеты. Проверил на локальной ФС. Так что поведение CIFS в данном случае вполне корректно.
Comment 11 Александр Морозов 2009-09-16 13:03:17 MSD
2 sin: Можно ли сделать, чтобы блокировки на CIFS были не mandatory, а advisory?
Comment 12 Евгений Синельников 2009-09-16 16:06:26 MSD
(In reply to comment #11)
> 2 sin: Можно ли сделать, чтобы блокировки на
> CIFS были не mandatory, а advisory?
> 

Давайте уточним, при каких условиях, мы что хотим видеть.
Ты предлагаешь advisory блокировки при отключённых unix extensions получить?

Там ведь API исходное и расширенное... Судя по коду, за эту логику отвечает Samba. Драйвер только вызовы, в основном, пробрасывает. Нужно смотреть...
Comment 13 Александр Морозов 2009-09-16 16:38:39 MSD
> Давайте уточним, при каких условиях, мы что
> хотим видеть.
> Ты предлагаешь advisory блокировки при
> отключённых unix extensions получить?

Да, можно и так. Хочется, чтобы на Linux-машине можно было читать (писать в) файл, даже если он заблокирован другим процессом.

В man smb.conf упоминается параметр strict locking. Это не включение/выключение mandatory locking?
Comment 14 Евгений Синельников 2009-09-22 22:48:20 MSD
Created attachment 1320 [details]
простой тест на чтение после блокировки

Прикладываю тест, который мне дал Саша. Тест действительно выявляет проблему.
Comment 15 Евгений Синельников 2009-09-22 23:06:55 MSD
Created attachment 1321 [details]
запись strace для простого теста

Прикладываю запись strace для простого теста.

Из этой записи видно, что open(), для файла PDOXUSRS.NET, выполняется только один раз. Потом процесс залипает... Видно, что операции на файлом, действительно производятся в отдельном процессе, я так понимаю, что это и есть wineserver.

Примечательно, что залипание происходит в недрах wine без обращения к открытому файлу... Такое ощущение, что wineserver слетает и перестаёт откликаться...

На Windows этот тест проходит. Стоит отметить, что этот тест повторяется как на etercifs+wine-etersoft, так и на обычных cifs+wine...

В общем, проблема общая... видимо, архитектурная...

Стоит обратить внимание на вызов LockFile из теста:
LockFile(hFile, 0, 0, 1, 0);
Может быть дело в параметрах?
http://msdn.microsoft.com/en-us/library/aa365202%28VS.85%29.aspx
Comment 16 Евгений Синельников 2009-09-23 13:03:56 MSD
(In reply to comment #15)
> Стоит обратить внимание на вызов LockFile из
> теста:
> LockFile(hFile, 0, 0, 1, 0);
> Может быть дело в параметрах?
> http://msdn.microsoft.com/en-us/library/aa365202%28VS.85%29.aspx
> 

Я проверил этот момент. Действительно, вот такое изменение:
$ diff -u test1.c test2.c
--- test1.c     2009-09-22 20:44:56 +0400
+++ test2.c     2009-09-23 12:57:51 +0400
@@ -20,7 +20,7 @@
     if (hFile == INVALID_HANDLE_VALUE)
         return 1;

-    if (!LockFile(hFile, 0, 0, 1, 0))
+    if (!LockFile(hFile, 0, 1, 1, 0))
         fprintf(stderr, "LockFile failed\n");

     if (!ReadFile(hFile, buf, sizeof(buf), &bytes, NULL))

исправляет ситуацию... То есть проблема в проверке границ... Причём, где-то в недрах wineserver.
Comment 17 Александр Морозов 2009-09-23 13:31:05 MSD
> Примечательно, что залипание происходит в
> недрах wine без обращения к открытому файлу...
> Такое ощущение, что wineserver слетает и
> перестаёт откликаться...

Происходит зацикливание в ntdll:NtReadFile, внутри for (;;). wineserver не зависает. В то время, как тест зациклился, другие wine-программы прекрасно работают. К wineserver можно подключиться с помощью strace -p<pid> и посмотреть, что он делает.

> В общем, проблема общая... видимо,
> архитектурная...

Да, проблема архитектурная. Вызовы open(...) и fcntl(fd, F_SETLK, ...) выполняет процесс wineserver. Вызов read(fd, ...) выполняет процесс, соответствующий exe-файлу, получая fd от wineserver. В случае, если блокировки advisory, как это обычно и есть на локальных ФС в Linux, read(fd, ...) без проблем читает файл. В случае CIFS блокировка mandatory, поэтому read не читает заблокированный участок, а возвращает EAGAIN.

Что касается LockFile...

BOOL WINAPI LockFile(
  __in  HANDLE hFile, /* Хэндл файла */
  __in  DWORD dwFileOffsetLow, /* Младшие 32 бита смещения, по которому устанавливается блокировка */
  __in  DWORD dwFileOffsetHigh, /* Старшие 32 бита смещения, по которому устанавливается блокировка */
  __in  DWORD nNumberOfBytesToLockLow, /* Младшие 32 бита длины участка, который блокируется */
  __in  DWORD nNumberOfBytesToLockHigh  /* Старшие 32 бита длины участка, который блокируется */
);

В тесте ставилась блокировка на один первый байт файла и затем запрашивалось чтение с начала файла. Ты изменил смешение с 0, на 4 гигабайта. Поэтому чтение стало происходить с незаблокированного участка. С чтением с незаблокированного участка никаких проблем нет.
Comment 18 Евгений Синельников 2009-09-23 14:35:52 MSD
(In reply to comment #17)
> > Примечательно, что залипание происходит в
> > недрах wine без обращения к открытому файлу...
> > Такое ощущение, что wineserver слетает и
> > перестаёт откликаться...
> 
> Происходит зацикливание в ntdll:NtReadFile, внутри
> for (;;). wineserver не зависает. В то время, как тест
> зациклился, другие wine-программы прекрасно
> работают. К wineserver можно подключиться с
> помощью strace -p<pid> и посмотреть, что он
> делает.
> 
> > В общем, проблема общая... видимо,
> > архитектурная...
> 
> Да, проблема архитектурная. Вызовы open(...) и
> fcntl(fd, F_SETLK, ...) выполняет процесс wineserver.
> Вызов read(fd, ...) выполняет процесс,
> соответствующий exe-файлу, получая fd от

Это невозможно... Во-первых, нельзя просто так передать номер открытого файлового дескриптора от процесса к процессу, что бы они нормально работали. Это должны быть уже не процессы в обычном смысле, а потоки, или контексты исполнения с общими файловыми дескрипторами, что достигается специальными параметрами к вызову clone(). Не думаю, что wine использует последнее, поскольку это Linux-специфично. Хотя проверить это стоит...

Во-вторых, strace чётко показывает, что на открытом файловом дескрипторе после установки блокировки, никаких операций не происходит... Читать никто не пытается... А EAGAIN возникает, как я понимаю, на чтении их сокета (или другого механизма IPC), через который основной процесс общается с wineserver'ом.

При этом winserver залипает, периодически просыпаясь в надежде чего-то дождаться:
...
10323 read(15, 0x60cb96, 13030)         = -1 EAGAIN (Resource temporarily unavailable)
10323 poll([{fd=15, events=POLLIN}], 1, -1) = 1 ([{fd=15, revents=POLLIN}])
10336 <... epoll_wait resumed> {}, 128, 10) = 0
10323 read(15,  <unfinished ...>
10336 gettimeofday( <unfinished ...>
10323 <... read resumed> 0x60cb96, 13030) = -1 EAGAIN (Resource temporarily unavailable)
10336 <... gettimeofday resumed> {1253642890, 28698}, NULL) = 0
10323 poll([{fd=15, events=POLLIN}], 1, -1 <unfinished ...>
10336 epoll_wait(10,  <unfinished ...>
10323 <... poll resumed> )              = 1 ([{fd=15, revents=POLLIN}])
10323 read(15, 0x60cb96, 13030)         = -1 EAGAIN (Resource temporarily unavailable)
10323 poll([{fd=15, events=POLLIN}], 1, -1) = 1 ([{fd=15, revents=POLLIN}])
...

> wineserver. В случае, если блокировки advisory, как
> это обычно и есть на локальных ФС в Linux, read(fd,
> ...) без проблем читает файл. В случае CIFS
> блокировка mandatory, поэтому read не читает
> заблокированный участок, а возвращает EAGAIN.
> 

Дело именно в CIFS или Wine... Чего ждёт winserver? Где-нибудь описана его архитектура? В какой части кода wine искать обработку запросов на файловые операции winserver'а?

> Что касается LockFile...

Да, я понял, где ошибся...
Что же... это упрощает тесты...
Comment 19 Евгений Синельников 2009-09-23 15:15:23 MSD
Обнаружил, что следующее изменение в тесте позволяет избежать залипания:
$ diff -u test1.c test3.c
--- test1.c     2009-09-22 20:44:56 +0400
+++ test3.c     2009-09-23 14:53:35 +0400
@@ -15,7 +15,7 @@
             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
 #endif
     hFile = CreateFileA("PDOXUSRS.NET",
-            GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+            GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
     if (hFile == INVALID_HANDLE_VALUE)
         return 1;

При этом блокировка ставится на запись и не проходит:
fcntl64(30, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1}, 0xbf942608) = -1 EBADF (Bad file descriptor)

Сама по себе блокировка не проходит (файл-то открыт только на чтение), а самому wine-приложению, при этом, ошибка после вызова LockFile() не возвращается.

То есть тест получается проходит из-за того, что блокировка реально не срабатывает, хотя вызов ошибки не возвращает...


Пробую другой вариант - на запись:
$ diff -u test1.c test4.c
--- test1.c     2009-09-22 20:44:56 +0400
+++ test4.c     2009-09-23 14:55:50 +0400
@@ -15,7 +15,7 @@
             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
 #endif
     hFile = CreateFileA("PDOXUSRS.NET",
-            GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+            GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
     if (hFile == INVALID_HANDLE_VALUE)
         return 1;
@@ -23,7 +23,7 @@
     if (!LockFile(hFile, 0, 0, 1, 0))
         fprintf(stderr, "LockFile failed\n");

-    if (!ReadFile(hFile, buf, sizeof(buf), &bytes, NULL))
+    if (!WriteFile(hFile, buf, sizeof(buf), &bytes, NULL))
         fprintf(stderr, "ReadFile failed\n");

     CloseHandle(hFile);

Получаю тот же эффект - залипания, но теперь уже на запись...
Comment 20 Александр Морозов 2009-09-23 15:20:19 MSD
> Это невозможно... Во-первых, нельзя просто
> так передать номер открытого файлового
> дескриптора от процесса к процессу, что бы
> они нормально работали.

Есть механизм передачи файового дескриптора через UNIX-сокет в составе ancillary data (см. man 2 recvmsg, man 3 cmsg, man 4 unix).

> Во-вторых, strace чётко показывает, что на
> открытом файловом дескрипторе после
> установки блокировки, никаких операций не
> происходит... Читать никто не пытается... А
> EAGAIN возникает, как я понимаю, на чтении их
> сокета (или другого механизма IPC), через
> который основной процесс общается с
> wineserver'ом.

В приаттаченном выше логе 10336 - это wineserver, 10323 - это программа, соответствующая exe-файлу.

wineserver открывает файл:
10336 open("/home/sin/.wine/dosdevices/d:/upload/wine/PDOXUSRS.NET", O_RDWR|O_NOCTTY|O_NONBLOCK|O_LARGEFILE|0x800000) = 32
...............
wineserver посылает открытый дескриптор exe-процессу:
10336 sendmsg(21, {msg_name(0)=NULL, msg_iov(1)=[{"0\0\0\0", 4}], msg_controllen=16, {cmsg_len=16, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {32}}, msg_flags=0}, 0) = 4
...............
exe-процесс получает дескриптор:
10323 recvmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"0\0\0\0", 4}], msg_controllen=16, {cmsg_len=16, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {15}}, msg_flags=0}, 0) = 4
...............
exe-процесс пытается читать:
10323 read(15, 0x60cb96, 13030)         = -1 EAGAIN (Resource temporarily unavailable)
10323 poll([{fd=15, events=POLLIN}], 1, -1) = 1 ([{fd=15, revents=POLLIN}])
10323 read(15, 0x60cb96, 13030)         = -1 EAGAIN (Resource temporarily unavailable)
10323 poll([{fd=15, events=POLLIN}], 1, -1) = 1 ([{fd=15, revents=POLLIN}])

Как видно, EAGAIN возникает при чтении файла exe-процессом.

> При этом winserver залипает, периодически
> просыпаясь в надежде чего-то дождаться:

Он как-то так и работает.

> Дело именно в CIFS или Wine... Чего ждёт winserver?
> Где-нибудь описана его архитектура? В какой
> части кода wine искать обработку запросов на
> файловые операции winserver'а?

wineserver крутится в main_loop или main_loop_epoll, зависит от системы. См. server/fd.c
Comment 21 Александр Морозов 2009-09-23 15:24:19 MSD
(In reply to comment #19)
> Обнаружил, что следующее изменение в тесте
> позволяет избежать залипания:
> $ diff -u test1.c test3.c
> --- test1.c     2009-09-22 20:44:56 +0400
> +++ test3.c     2009-09-23 14:53:35 +0400
> @@ -15,7 +15,7 @@
>              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
> NULL);
>  #endif
>      hFile = CreateFileA("PDOXUSRS.NET",
> -            GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
> NULL,
> +            GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
>              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
> NULL);
>      if (hFile == INVALID_HANDLE_VALUE)
>          return 1;
> 
> При этом блокировка ставится на запись и не
> проходит:
> fcntl64(30, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1},
> 0xbf942608) = -1 EBADF (Bad file descriptor)
> 
> Сама по себе блокировка не проходит
> (файл-то открыт только на чтение), а самому
> wine-приложению, при этом, ошибка после
> вызова LockFile() не возвращается.
> 
> То есть тест получается проходит из-за
> того, что блокировка реально не
> срабатывает, хотя вызов ошибки не
> возвращает...

Думаю, это не сложно исправить.
Comment 22 Александр Морозов 2009-09-23 15:56:31 MSD
> > При этом блокировка ставится на запись и не
> > проходит:
> > fcntl64(30, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1},
> > 0xbf942608) = -1 EBADF (Bad file descriptor)

Это на какой версии WINE и на какой ФС?
Comment 23 Евгений Синельников 2009-09-23 16:41:32 MSD
(In reply to comment #22)
> > > При этом блокировка ставится на запись и не
> > > проходит:
> > > fcntl64(30, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=0, len=1},
> > > 0xbf942608) = -1 EBADF (Bad file descriptor)
> 
> Это на какой версии WINE и на какой ФС?
> 

Действительно...

обычный cifs от ядра:
2.6.30-std-def-alt10
Наш wine из Сизифа:
Wine from Etersoft 1.1.22-eter1

На cifs-4.3.8-alt5 + wine из Сизифа ошибка повторяется...

На cifs-4.3.8-alt5 + wine-1.0.11 (eter8/eter3) Network fcntl64() завершается без ошибки...

То есть наши хаки, уже исправляют эту проблему... Интересно...

При этом на запись всё то же залипание...
Comment 24 Евгений Синельников 2009-10-05 16:06:18 MSD
Вопрос, а кто-нибудь пробовал запускать VVS с параметрами noperm,forcemand ?
Comment 25 Александр Морозов 2009-10-05 16:48:41 MSD
> Вопрос, а кто-нибудь пробовал запускать VVS с
> параметрами noperm,forcemand ?

Смонтировал на atlant (2.6.30-std-def-alt10) такой командой:
mount -o uid=1660,gid=100,noperm,forcemand //cellar/sharewine /mnt/cifs
В результате в выводе mount появилась строка:
//cellar/sharewine on /mnt/cifs type cifs (rw,mand)
Тестовая программа из комментария #14 на CIFS зависает.
Comment 26 Евгений Синельников 2009-10-05 18:20:46 MSD
(In reply to comment #25)
> > Вопрос, а кто-нибудь пробовал запускать VVS с
> > параметрами noperm,forcemand ?
> 
> Смонтировал на atlant (2.6.30-std-def-alt10) такой
> командой:
> mount -o uid=1660,gid=100,noperm,forcemand //cellar/sharewine /mnt/cifs
> В результате в выводе mount появилась строка:
> //cellar/sharewine on /mnt/cifs type cifs (rw,mand)
> Тестовая программа из комментария #14 на CIFS
> зависает.
> 

Интересно как... А вот у меня тесты не зависают... А можно туда ssh?
Comment 27 Александр Морозов 2009-10-05 18:48:16 MSD
> Интересно как... А вот у меня тесты не
> зависают... А можно туда ssh?

На atlant можно зайти с builder`а или с server`а.
Comment 28 Александр Морозов 2009-10-08 16:16:46 MSD
VVS на CIFS работает с настройками, приведёнными в комментарии #32 к ошибке 4316.
Comment 29 Vitaly Lipatov 2009-10-08 19:49:17 MSD
Лучше писать в следующем стиле, а то получается закрытие информации: какие-то конфиги, приложенные к какой-то баге с комментарием, что ничего не работает.

Эти параметры: 
В smb.conf
strict locking = no
posix locking = false

Отличается от обычных добавлением posix locking.

При монтировании использовались
noperm,forcemand
(и только они).
Обычно мы ещё применяли direct.
Comment 30 Александр Морозов 2009-10-08 20:02:34 MSD
> Отличается от обычных добавлением posix locking.

А где можно увидеть то, что считается _обычными_ параметрами?
Comment 31 Vitaly Lipatov 2009-10-09 11:37:29 MSD
(In reply to comment #30)
> > Отличается от обычных добавлением posix locking.
> 
> А где можно увидеть то, что считается
> _обычными_ параметрами?
Обычные - это настройки по умолчанию.
Увидеть их описание можно в документации по WINE@Etersoft. 
http://etersoft.ru/wine/manual