Summary: | При закрытии файлового дескриптора дочерним процессом сбрасываются блокировки | ||
---|---|---|---|
Product: | CIFS@Etersoft | Reporter: | Александр Морозов <amorozov> |
Component: | блокировки файлов и доступ | Assignee: | Pavel Shilovsky <piastry> |
Status: | CLOSED FIXED | QA Contact: | Денис Баранов <baraka> |
Severity: | major | ||
Priority: | P3 | CC: | baraka, lav, sin, sonner |
Version: | не указана | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | Linux | ||
Whiteboard: | |||
Заявки RT: | Связано с: | ||
Дата напоминания: | |||
Bug Depends on: | |||
Bug Blocks: | 3043, 4701, 4987, 5013 | ||
Attachments: | Тест описывающий проблему |
Description
Александр Морозов
2010-02-03 21:49:11 MSK
Просьба потестировать собрать и потестировать. http://git.etersoft.ru/people/piastry/packages/?p=etercifs.git;a=shortlog;h=refs/heads/dev Пока только для 31 ядра. На 30-м ядре проблема осталась, 31-е ещё надо найти. Как оказалось, там разные исходники. Так что на 30-м было бессмысленно проверять. Ну я и написал, что изменил только 31 ядро. Все остальные остались без изменения. Раз нужно 30, то переделал бранч немного http://git.etersoft.ru/people/piastry/packages/?p=etercifs.git;a=shortlog;h=refs/heads/dev . Теперь получается, что блокировка не снимается. Доработал тест. На cifs он выводит такое: F_SETLK F_WRLCK 0: 0 child 1 F_GETLK F_WRLCK 0: 0 locked child 2 F_GETLK F_WRLCK 0: 0 locked F_SETLK F_UNLCK 0: 0 child 3 F_GETLK F_WRLCK 0: 0 locked А надо, чтобы было так: F_SETLK F_WRLCK 0: 0 child 1 F_GETLK F_WRLCK 0: 0 locked child 2 F_GETLK F_WRLCK 0: 0 locked F_SETLK F_UNLCK 0: 0 child 3 F_GETLK F_WRLCK 0: 0 F_UNLCK Created attachment 1495 [details]
Тест описывающий проблему
Написал похожий тест. И на cifs и на локальной фс поведение следующее: [piastry@keepcoding test]$ ../a.out start 2397 ch1: locked ch1: done ch2: locked ch2: done ch3: locked done Не пойму, почему блокировка снятая в дочернем процессе должна как-то повлиять на блокировку, установленную в родительском? разные процессы, разные пиды. Ещё хотел добавить, что поведение одинаковое и с параметром forcemand и без него. В моём тесте блокировка снимается в том процессе, который её поставил. Ставим блокировку в основном процессе: F_SETLK F_WRLCK 0: 0 Запускаем дочерний процесс: child 1 Дочерний процесс проверяет, что блокировка стоит: F_GETLK F_WRLCK 0: 0 locked Дочерний процесс завершается. Запускаем дочерний процесс: child 2 Дочерний процесс проверяет, что блокировка стоит: F_GETLK F_WRLCK 0: 0 locked Дочерний процесс завершается. Снимаем блокировку в основном процессе: F_SETLK F_UNLCK 0: 0 Запускаем дочерний процесс: child 3 Дочерний процесс проверяет, стоит ли блокировка. Её уже сняли, а он её почему-то всё равно видит: F_GETLK F_WRLCK 0: 0 locked Скорее всего проблема будет воспроизводиться и без запуска двух первых процессов. Это просто совмещение с первоначальным тестом. Что касается параметров, с которыми я это всё проверял. Используются те параметры, с которыми должен работать wine. Кстати, поведение при этих параметрах должно отличаться от описанного в POSIX, то есть, соответственно, и от поведения локальной ФС, так что сравнение с ней не всегда будет корректно. Проблема воспроизводится, если запустить хотя бы один дочерний процесс и дать ему завершится: тогда на сервере останется блокировка от родительского, но драйвер о ней знать не будет, и потому снять её не получится. Следовательно, блокировка останется "висеть". Вот решение: http://git.etersoft.ru/people/piastry/packages/?p=etercifs.git;a=shortlog;h=refs/heads/dev Только для 30-ого ядра. Имеется ввиду, что дочернему процессу достаточно не завершиться, а хотя бы закрыть файловый дескриптор (который он унаследовал после fork()). Проверил с помощью lincifs3.c и 1С 7.7. Баг #4987 не воспроизвёлся. Думаю, проблему со сбросом блокировки можно счиать решённой. Вот ещё надо потестировать такой вариант: http://git.etersoft.ru/people/piastry/packages/?p=etercifs.git;a=shortlog;h=refs/heads/dev2 Предыдущий вариант содержал два исправления, первое из которых было бы нежелательным. Этот содержит только второе. С этим вариантом наблюдается вот такая проблема: $ ./lincifs3 333.xls F_SETLK F_WRLCK 0: 0 child 1 F_GETLK F_WRLCK 0: 0 locked child 2 F_GETLK F_WRLCK 0: 0 F_UNLCK F_SETLK F_UNLCK 0: 0 child 3 F_GETLK F_WRLCK 0: 0 F_UNLCK После исследования данного вопроса выяснилось, что при существующей архитектуре wine, нам нужно использовать при операциях чтения/записи и блокировки пид процесса, который открывал файл. Потому при fork() получается, что дочерний процесс при своём завершении снимает блокировки, установленные родительским (блокировки при forcemand привязаны к фиду и полностью наследуются от родительского процесса дочерним). Я думаю так. Если локи делает wine-server, то запросы других процессов на операции с локами можно игнорировать. Этот режим соотвествует логике, в которой Wine сможет передавать файловые дескрипторы другим процессам на чтение-запись и не беспокоится о проблемах их влияния установки/снятия блокировок. Вот только должен ли этот режим быть по умолчанию для mandatory или стоит сделать ещё один флаг открытия файла, явно указывающий на то, что файловый дескриптор будет использоваться в wine? Я думаю, что пробрасывание файлового дескриптора в другой процесс (через fork() или локальный сокет) в любом случае приведёт к неадекватному поведению - без нормальной логики, когда на сервер передаётся PID-процесса, чтобы он мог отличить операции над ним разными процессами. Чтобы определиться с вопросом о необходимости указания дополнительного режима для mandatory блокирования на CIFS, нужно определиться с тем какие режимы работы, при таком монтировании, вообще адекватны. Если forcemand будет рассчитан только для Wine, то это как бы не важно. Но он уже ядре... И хотелось бы сохранить такие сценарии работы CIFS-драйвера, которые доступны в стандартных новых ядрах. А наше пробрасывание ПИДа для Wine эти сценарии ломает. (In reply to comment #16) > один флаг открытия файла, явно указывающий > на то, что файловый дескриптор будет > использоваться в wine? Мне кажется, стоит. ... > Если forcemand будет рассчитан только для Wine, то > это как бы не важно. Но он уже ядре... И На него не надо ориентироваться. Я вообще предлагал флаг wine > хотелось бы сохранить такие сценарии > работы CIFS-драйвера, которые доступны в > стандартных новых ядрах. А наше > пробрасывание ПИДа для Wine эти сценарии > ломает. Нам не уйти от индивидуального поведения для wine, предлагаю его реализовать. (In reply to comment #17) > Нам не уйти от индивидуального поведения > для wine, предлагаю его реализовать. > Ну, как-то так... ничего более разумного с полчетвёртого я тоже не придумал. Вопрос теперь с тем, чтобы определится что включает новый режим. Я вижу две фишки: - пробрасывание в запросах на сервер ПИДа того процесса, который открыл файл, а не того, который выполняет системный вызов. Это бывает при передаче открытых файловых дескрипторов между процессами. - отключение (игнорирование) операций с блокировками для процессов ПИД, которых не совпадает с ПИДом процесса открывшего данных файловый дескриптор. Вроде так... > Вопрос теперь с тем, чтобы определится что
> включает новый режим.
Ещё надо не забыть про сохранение блокировок до закрытия последнего относящегося к файлу дескриптора и, разумеется, share-флаги.
Ситуацию с fork() надо детатьно проработать будет, и изучить вопрос возможных проблем, при отключении блокировок у дочернего процесса при работе с wine. Например, процесс печати в линуксе возможно тоже нуждается в блокировках или другой запускаемый процесс. На данный момент я создал три ветки: 1. dev - решает только проблему залипания блокировки, но не решает проблему её потери после fork(). 2. dev2 - аналог dev, только с пробросанным пидом для операций чтения/записи. 3. dev3 - решает вышеописанную проблему средствами cifs, но при этом wine приложения не смогут прочитать область, которую они сами заблокировали(в плане 1с это видимо не страшно). Собственно ситуация такая. При использовании dev после печати блокировка будет сниматься, потому надо будет закрыть документ и снова открыть(как один из вариантов). dev2 должна вести себя так же на 1С, но это ещё надо проверить тестами. В wine приложениях же, где из заблокированной области захотят читать (или туда писать), должен правильно себя вести dev2. При использовании dev3 мы не прокидываем никакой пид, но возможно на данный момент это самый удачный вариант для 1С (и для других приложений, не читающих из заблокированной области и не пишущих в ней). Нужно протестировать все три варианта при работе с 1С в двух вариантах: 1. forcemand,noperm,direct 2. forcemand,noperm Желательно, проверить все аспекты работы, в том числе и печать. Так же неплохо бы протестировать другие wine приложения, читающие/пишущие в заблокированной областе. Так же в двух варинтах монтирования с direct и без него. (In reply to comment #19) > > Вопрос теперь с тем, чтобы определится что > > включает новый режим. > Ещё надо не забыть про сохранение > блокировок до закрытия последнего > относящегося к файлу дескриптора и, > разумеется, share-флаги. > Сейчас это ("сохранение блокировок"), локально, реализовано средствами wine-сервера, а в сети указанным пробрасыванием ПИДа того процесса, который открыл файл, а не того, который обращается по открытому файловому дескриптору. Последнее как раз и приносит головную боль. Так что, локально, "сохранение блокировок до закрытия последнего относящегося к файлу дескриптора" так и придётся оставить костылями в Wine-сервере - никуда оно не денется, потому что CIFS тут не причём... Ну, а share-флаги отключать этим режимом не обязательно - про них всё равно никто не знает... Но можно и отключить... Только потом, кроме вайна, на этот счёт ещё и тесты править придётся... > Ещё надо не забыть про сохранение > блокировок до закрытия последнего > относящегося к файлу дескриптора и, > разумеется, share-флаги. Я имел в виду, что эти фичи должны работать для wine. > Так что, локально, "сохранение блокировок > до закрытия последнего относящегося к > файлу дескриптора" так и придётся оставить > костылями в Wine-сервере - никуда оно не > денется, потому что CIFS тут не причём... Сейчас etercifs как раз сохраняет блокировки, пока не будет закрыт последний дескриптор. Wine хранит дескрипторы до последнего только на NFS и пр. См. server/fd.c:fd_destroy(): /* special case for file on CIFS - remove in any case */ if (fd->cifs) { if (fd->unix_fd != -1) { close( fd->unix_fd ); fd->unix_fd = -1; } } > Ну, а share-флаги отключать этим режимом не > обязательно - про них всё равно никто не > знает... Но можно и отключить... Только потом, > кроме вайна, на этот счёт ещё и тесты > править придётся... Для wine share-флаги отключать не надо. > На данный момент я создал три ветки:
> ...
На какой из этих веток и при каких параметрах монтирования корректно работает тест wine-etersoft-devel/cifs/lincifs3.c ? Под "корректно" имеется ввиду второй листинг в комментарии #5.
Для dev3. (In reply to comment #22) > > Ещё надо не забыть про сохранение > > блокировок до закрытия последнего > > относящегося к файлу дескриптора и, > > разумеется, share-флаги. > > Я имел в виду, что эти фичи должны работать > для wine. > Если они были, они не должны сломаться. Вопрос ставился так, что нужно было уточнить какие фичи включает новый режим. > > Так что, локально, "сохранение блокировок > > до закрытия последнего относящегося к > > файлу дескриптора" так и придётся оставить > > костылями в Wine-сервере - никуда оно не > > денется, потому что CIFS тут не причём... > > Сейчас etercifs как раз сохраняет блокировки, > пока не будет закрыт последний дескриптор. Это делается за счёт отправки запросов из-под ПИДа того процесса, который открыл файл, причём делает это ("сохраняет блокировки") Samba. И из-за этого, как раз, и сломалась печать, поскольку CUPS, которому передаётся открытый файловый дескриптор: - с одной стороны, должен работать с заблокированным документов - а, с другой, работая из-под того же ПИДа, который открыл это файловый дескриптор (а открывал его ещё wine-server), закрывает файл тем самым сбрасывая все блокировки... Вообще вижу я в этом глубокую архитектурную особенность UNIX, поскольку в mandatory-режиме находятся такие сценарии, при которых приходится, при закрытии файла, сбрасывать блокировки, что мешает работать в mandaory-режиме, как таковом. То есть пробрасывание открытых файловых дескрипторов в Linux, исключает нормальную реализацию mandatory блокировок, без специальных внутренних изменений. Возникает вопрос. А как передаются, и передаются ли вообще, открытые файловые дескрипторы между процессам в Windows? Где бы об этом почитать? Этот вопрос важен для понимания насколько критичен предлагаемый вариант игнорирования установки и снятия блокировок в новом режиме для процессов ПИД, которых не совпадает с ПИДом процесса открывшего соотвествующий файловый дескриптор. Ведь последнее означает, что Wine не сможет передавать открытые им для программ файловые дескрипторы в другие программы так, чтобы блокировки на них работали в других процессах - они ведь игнорироваться будут... > Wine хранит дескрипторы до последнего только > на NFS и пр. См. server/fd.c:fd_destroy(): > Думаю проще... Wine не хранит дескрипторы до последнего только для CIFS. > /* special case for file on CIFS - remove in any case */ > if (fd->cifs) { > if (fd->unix_fd != -1) { > close( fd->unix_fd ); > fd->unix_fd = -1; > } > } > Ну, да... А это для чего так нужно? Чтобы не отслеживать на клиенте то, за чем сервер (то бишь Samba) должен следить. > > Ну, а share-флаги отключать этим режимом не > > обязательно - про них всё равно никто не > > знает... Но можно и отключить... Только потом, > > кроме вайна, на этот счёт ещё и тесты > > править придётся... > > Для wine share-флаги отключать не надо. > Я как раз вёл речь о том, что их вообще можно не трогать... Пусть, как обычно, всегда будут включены, иначе переделывать больше придётся... > Вообще вижу я в этом глубокую > архитектурную особенность UNIX, поскольку в > mandatory-режиме находятся такие сценарии, при > которых приходится, при закрытии файла, > сбрасывать блокировки, что мешает работать > в mandaory-режиме, как таковом. > > То есть пробрасывание открытых файловых > дескрипторов в Linux, исключает нормальную > реализацию mandatory блокировок, без > специальных внутренних изменений. А зачем нам вообще нужны mandatory блокировки? Для взаимодействия wine с Windows-клиентами? > Возникает вопрос. А как передаются, и > передаются ли вообще, открытые файловые > дескрипторы между процессам в Windows? Где бы > об этом почитать? http://msdn.microsoft.com/en-us/library/ms724466(VS.85).aspx (In reply to comment #26) > А зачем нам вообще нужны mandatory блокировки? > Для взаимодействия wine с Windows-клиентами? Да, именно для этого. (In reply to comment #20) > Нужно протестировать все три варианта при > работе с 1С в двух вариантах: > 1. forcemand,noperm,direct > 2. forcemand,noperm > Собрал каждую ветку, начал полное тестирование. Тестирование провожу на клиенты: euclid.office.etersoft.ru 2.6.30-std-def-alt13 , Windows XP сервер: cellar.office.etersoft.ru 2.6.27-ovz-smp-alt9 Дополнил табличку, с результатами тестирования по 1С 7.7: http://wiki.office.etersoft.ru/testing/cifs/testirovanie4.4.2 Сделал новый бранч dev4. Как и dev2, позволяет wine приложениям читать из ими же заблокированных областей, и как dev3 корректно работает с блокировками при fork(). Просьба потестировать с 1С и с wine-etersoft-devel/cifs/lincifs3.c. (In reply to comment #30) > Просьба потестировать с 1С и с Дополнил табличку бранчем 4 . > wine-etersoft-devel/cifs/lincifs3.c. etercifs-4.4.2-alt4.4 MOUNT_OPTIONS=user=guest,pass=,rw,iocharset=utf8,noperm,forcemand ./lincifs3 123.txt F_SETLK F_WRLCK 0: 0 child 1 F_GETLK F_WRLCK 0: 0 locked child 2 F_GETLK F_WRLCK 0: 0 locked F_SETLK F_UNLCK 0: 0 child 3 F_GETLK F_WRLCK 0: 0 F_UNLCK etercifs-4.4.2-alt4.4 MOUNT_OPTIONS=user=guest,pass=,rw,iocharset=utf8,noperm,forcemand,direct ./lincifs3 123.txt F_SETLK F_WRLCK 0: 0 child 1 F_GETLK F_WRLCK 0: 0 locked child 2 F_GETLK F_WRLCK 0: 0 locked F_SETLK F_UNLCK 0: 0 child 3 F_GETLK F_WRLCK 0: 0 F_UNLCK Добавил результаты по тестированию 1С 8.1 Просьба проверить 1С 8.1 с dev4 без direct. По результатам тестирования 1С 7.7 ошибка в "мониторе пользователей" появляется как-то случайно. Надо дополнительно исследовать этот вопрос: протестировать этот параметр несколько раз (например 3) с direct и без него так же на dev4. (In reply to comment #33) > Просьба проверить 1С 8.1 с dev4 без direct. Проверил, сведения в таблице. > По результатам тестирования 1С 7.7 ошибка в > "мониторе пользователей" появляется как-то > ... > так же на dev4. > Проверил еще несколько раз, оказалось что и с direct такая же ситуация как без него (см. таблицу). Самое интересное что 1С показывает что 2 соединения с базой, но пользователя показывает только одного. Способ воспроизведения: Заходим Windows клиентом, затем Linux клиентом. У W - 1 пользователь (он сам), у L-клиента отображаются все пользователи. Так. Тогда надо ещё так же (раза по три) протестировать dev3 с direct и без него. (In reply to comment #35) > Так. Тогда надо ещё так же (раза по три) > протестировать dev3 с direct и без него. > Добавил информацию о тестировании 1С 8.1 с dev3. Я имел ввиду перетестировать 1С 7.7 с dev3 на правильность отображения монитора пользователей ( как и dev4 раза по три с direct и без него ). (In reply to comment #37) > Я имел ввиду перетестировать 1С 7.7 с dev3 на > правильность отображения монитора > пользователей ( как и dev4 раза по три с direct и > без него ). > Проверил еще раз. Оказалось все не так радужно как хотелось бы. Собрал dev4 в 4.4.5-alt1. > Собрал dev4 в 4.4.5-alt1.
А куда положил? В pub/Etersoft/CIFS@Etersoft что-то не видно такого.
Собрал для всех систем на ftp - можно пользоваться. Окей, надо только убрать nounix из дефолтных MOUNT_OPTIONS, а то с ним VVS не работает. И на 4.4.5 тоже не работает c wine,nounix? (In reply to comment #42) > Окей, надо только убрать nounix из дефолтных > MOUNT_OPTIONS, а то с ним VVS не работает. Возможно, я отстал от жизни, но nounix необходим в том случае, если UID на сервере не совпадают с клиентскими. И вообще, в случае виндового сервера, ведь тоже тогда работать не будет (автоматом nounix включится). (In reply to comment #42) > Окей, надо только убрать nounix из дефолтных > MOUNT_OPTIONS, а то с ним VVS не работает. Чего Окей, бага решается в версии 4.4.5 или нет? > И на 4.4.5 тоже не работает c wine,nounix?
VVS на 4.4.5 не работает с forcemand,direct,nounix. C wine,nounix не проверял.
Про несовпадение UID'ов и GID'ов это noperm параметр: http://bugs.etersoft.ru/show_bug.cgi?id=4292#c34 В случае виндового сервера действительно будет nounix, но это не должно повлиять, как похожую функциональность(открытия и установки блокировок) приносит параметр forcemand. Параметр wine влючает необходимую прослойку в CIFS, чтобы он работал с условием особенностей архитектуры wine. В частности он решает проблему, когда процесс выполнять операции чтения и записи на заблокированный им самим же участок (так как блокировку на самом деле ставил wine-server, и при чтении(записи) пиды на блокировке и читающего(пишёщего) процесса не совпадали). Надо тестировать с параметром wine: например - wine или wine,nounix. > И вообще, в случае виндового сервера, ведь > тоже тогда работать не будет (автоматом nounix > включится). Да, оказывается, VVS на виндовой шаре не работает (и с wine, и с wine,nounix). Возможно, стоит создать отдельный баг. > Чего Окей, бага решается в версии 4.4.5 или > нет? Тест wine-etersoft-devel/cifs/lincifs3.c проходит как надо, и соответствующая проблема с печатью в 1С 7.7 также не проявляется. (In reply to comment #46) > Про несовпадение UID'ов и GID'ов это noperm > параметр: > http://bugs.etersoft.ru/show_bug.cgi?id=4292#c34 Нет, это другое. Я про то, что c nounix есть возможность при монтировании задать трансляцию uid/gid. > Параметр wine влючает необходимую прослойку > в CIFS, чтобы он работал с условием > особенностей архитектуры wine. В частности ... Впиши описание про параметр wine в документацию wine-etersoft-doc, пожалуйста. Раз мы вводим новый параметр, его нужно документировать. И есть ли у нас возможность окончательную версию назвать 4.5.0? > Надо тестировать с параметром wine: > например - wine или wine,nounix. Вообще я думал, что имеет смысл ставить nounix при wine? Предлагаю багу текущую багу закрыть и открыть новую для VVS. Можно подробнее, что конкретно не работает на VVS в 4.4.5? на какой операции рушится и т.д.? Работает ли с линукс сервером без параметра nounix? Параметр wine пока включается в себя параметры forcemand и direct, а также включает проброс пида wineserver'а для exe процесса, чтобы чтение/запись работали нормально. (In reply to comment #49) > Предлагаю багу текущую багу закрыть и > открыть новую для VVS. Правильно, ведь VVS не к этой баге. Мы уже проверяли VVS в bug # 4475, предлагаю перейти туда. > Можно подробнее, что > конкретно не работает на VVS в 4.4.5? на какой > операции рушится и т.д.? Работает ли с > линукс сервером без параметра nounix? Без параметра nounix с сервером на Linux работает. По-видимому, в случае с сервером на Windows не работает вот это: > проброс пида wineserver'а для exe процесса, чтобы > чтение/запись работали нормально. Есть тест: wine-etersoft-devel/cifs/lincifs2.c Создал отдельный баг по проблеме с VVS: http://bugs.etersoft.ru/show_bug.cgi?id=5181 Тест проходит успешно. etercifs-4.4.5-alt1 |