LINUX.ORG.RU

fuse, поведение ФС


0

1

Добрый вечер. Продолжая тему "FusePy и смежные вопросы".

Я хочу сделать write buffer, но возникает вопрос: нужно, стоит ли из него читать? Предположим такую ситуацию:

Процесс А открывает файл в режиме rw. Процесс Б открывает тот же файл в этом же режиме. Процесс А пишет в файл 4к данных по смещению 4к.

Теперь мы читаем тот же сегмент по смещению 4к. Если flush НЕ вызван, то что должен прочитать процесс А и процесс Б?

Проблема чтения из write-buffer'а осложнена тем, что мы не можем выделить непрерывный сегмент под запись: клац

Другими словами, нет гарантии, что запись будет последовательна. А значит для чтения из writebuffer'a придется читать всю очередь записи для текущего хендла.

man 2 write

POSIX requires that a read(2) which can be proved to occur after a
write() has returned returns the new data. Note that not all file sys-
tems are POSIX conforming.

Manhunt ★★★★★
()

Бекенд-то под твоей ФС какой? А то может, буфер вообще будет лишним.
Для самого общего случая можно сделать буфер в виде разреженного массива, в который ты будешь делать все write. А отдельный «поток» будет следить за массивом и если он оказался непустым, флашить всё подряд. Соответственно, не будет непонятных размеров очереди, из которой надо наковыривать нужные данные.
Попутно избавишься от двойного флаша по одному и тому же смещению, если вдруг случится два write в одно место.
Можно это всё реализовать как модуль fuse, который можно втыкать перед любым драйвером, а не вшивать намертво в твой один. Возможно, такой уже есть.

const86 ★★★★★
()
Ответ на: комментарий от const86

Сейчас в качестве бекенда используется redis, обернутый в класс, реализующий read, write, truncate. Т.е. потом я хочу попробовать поюзать в качестве бекенда хранения MongoDB и т.д.

На тему необходимости использовать wb. Неизвестно реализованы ли в ядре какие-нибудь кэши. К примеру, если я буду читать/писать файл по одному символу, ядро будет запрашивать блок, или втупую транслировать запрос низкоуровневому api fs? Если втупую, то кэш должен делать я.

Пока бекенд хранит чанки размером в 4096 байт. Значит, чтобы переписать 2 байта в блоке мне нужно считать этот блок, изменить и только потом записать. И самый плохой случай: записываемый фрагмент пересекает границу chunk_size, тогда придется читать сразу 2 блока. Чтобы как-то минимизировать лишние потери при чтении wb вроде как нужен.

В принципе пока можно сделать это и неоптимизированно. Просто в таком случае запись еще и должна быть однопоточной: переписывая фрагменты, пересекающие chunk_size нам надо будет их сначала читать, а следовательно, будет возможность попортить данные с этим stale write, если мы прочитали старые данные.

Тут нужно тестировать многие вещи, а времени уже практически нет на это все. Поэтому я пошел играть в скайрим)

division_hell
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.