Etercifs/history
История вопроса с CIFS
Модуль ядра Linux под названием cifs был разработан при активном участии компании IBM в рамках проекта под названием linux-cifs. На основе исходных текстов проекта Etersoft собирала пакет linux-cifs, последней стабильной версией которого является linux-cifs-1.50c-alt4 (вернее, это последний релиз, выпущенный Виталием перед экспериментальными изменениями, которые начал производить Евгений).
Но на новых ядрах этот пакет не собирался, поэтому Евгений взял исходники из новой версии cifs и применил наши патчи. В результате пакет (последний релиз - linux-cifs-1.54-alt2) на новых ядрах работает, но нестабильно.
В результате обдумывания этого вопроса возникло предложение следать для каждого ядра свою версию. То есть, я брал исходную версию cifs из каждого конкретного ядра (из git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git ), патчил её, и собирал. Результатом стали пакеты linux-cifs-2.6.23, linux-cifs-2.6.24, linux-cifs-2.6.25. Версию для ядра 2.6.25-std-def-alt7 - из пакета linux-cifs-2.6.25 я тестировал и проблем с падением не заметил (см. http://bugs.etersoft.ru/show_bug.cgi?id=2220#c9 )
В дальнейшем было решено отказаться от нескольких независимых пакетов и выделить отдельно скрипты установки (пакет linux-cifs) и запуска и отдельно - исходники для разных ядер (пакеты kernel-source-etercifs* ) и при сборке автоматически выбирать нужные исходники, если для данного ядра они установлены.
А совсем в дальнейшем, в конце сентября 2008 года было решено вести две версии пакета: старую и новую. В старой версии для Этерсофтовских флагов используются биты 29-31, а в новой - 21-23. Вот одинаковая для всех исходников разница:
diff --git a/cifs/file.c b/cifs/file.c index b1506ab..7e03334 100644 --- a/cifs/file.c +++ b/cifs/file.c @@ -113,7 +113,7 @@ static inline int cifs_get_share_flags(unsigned int flags) { if (!etersoft_flag) return FILE_SHARE_ALL; - return ((~(flags>>29))&7); + return ((~(flags>>21))&7); } /* all arguments to this function must be checked for validity in caller */
То, что было ранее - это старая версия. Название linux-cifs для пакета оставлено.
Новый пакет называется соответственно etercifs. Служба тоже называется etercifs.
Пакеты конфликтуют друг с другом, то есть не могут одновременно стоять в системе.
Далее во всех примерах будет фигурировать etercifs.
Исходники, начиная с версий 3.3 для etercifs и 3.2 для linux-cifs, пакуются в сам пакет, а не отдельно.
Зачем нужен драйвер
В стандарте CIFS есть режим разделения файла, то есть можно блокировать только некоторые действия: чтение, запись, чтение и запись, удаление . Драйвер cifs.ko из ядра Linux не поддерживают эту часть протокола. Патчи Etersofs созданы для решения этой проблемы. В частности, добавляется новые параметр (const int share_flags) в функцию открытия файла CIFSSMBOpen.
Проблемы с блокировками следующие:
- режим открытия файла (решается расширением параметра функции open)
- установка блокировок через fcntl (может некорректно транслироваться в CIFS)
- oplocks (то есть правильное управление кэшированием). Тут самое сложное, потому что должно работать W заблокировал, записал, разблокировал. G заблокировал, прочитал, разблокировал. Важно гарантировать, что G получит новые данные, а не из кэша.
Замечания и пояснения к изменениям
1. Произошло "раздвоение" пакета на linux-cifs и etercifs в связи с изменением флагов в etercifs.
2. Поскольку для каждого ядра - свои исходники, то мы больше не предоставляем в собранном виде драйвер etercifs.ko
3. Удален build.sh и некоторая часть из него перекочевала прямо в спек
4. Удалено ещё много чего ненужного и нужного, чтобы не путаться. Впоследствии, когда понадобится - добавим. Например, для gentoo. Не претендую на то, что это сделано правильно.
5. Теперь архиректура - noarch
6. Сильно поменялся buildmodule.sh. Он теперь лежит отдельно и алгоритм его работы описан далее.
Устаревшее: постановка задачи
Основная задача: сообщить samba-серверу о режиме разрешения другим доступа к файлу, и получить ответ, разрешён ли доступ нам. Из этого следует, что файл должен быть открыт с соответствующими правами.
Из-за реализации открытия файлов в Linux через модуль ядра можно это это сообщить только дополнительным вызовом (при этом придётся повторно открывать файл).
Особая сложность при сообщении о доступе из wineserver - поскольку потребуется открывать файл параллельно с открытием через системный вызов.
Возможно единственный вариант передачи нужной нам информации - через блокировки.
Вариант реализации |
Плюсы |
Минусы |
SAMBA-сервер |
Будет работать с любой ОС Проще всего в реализации - добавить обращение к libwine-etersoft и всё (нельзя из-за GPL) |
Требуется сборка сервера под каждую платформу Неправильное (временное) решение |
CIFS-модуль ядра |
Может работать с любым CIFS-сервером (и Windows в том числе) Изменения в CIFS-модуле не страшно отдать под GPL |
Будет работать только в Linux Проблемы со сборкой модулей под все ядра Всё равно менять wineserver для обращения к модулю |
wineserver - реализовать в нём обращение по CIFS |
Самый правильный и независимый способ, позволит в дальнейшем всю функциональность реализовать. |
Самый сложный вариант, много работы Нет проверенной клиентской библиотеки (libcli_smb) для SAMBA4 (но есть libsmbclient из SAMBA3 с необходимой функциональностью Проблема с несовместимостью лицензий (LGPL для wineserver и GPL для libcli_smb)
|
SAMBA4: обработка открытия файла осуществляется в odb_tdb_open_file, откуда вызывается share_conflict для сверки shared и access.
модуль ядра cifs: CIFSSMBOpen, там заполняются ShareAccess и DesiredAccess
wineserver: файл fd.c, функция check_sharing