Учебный проект по курсу ОС университета ИТМО магистратуры JetBrains.
Автор работы: Крыштапович Виктор.
FUSE является библиотекой Linux для реализации файловых систем в пространстве имён пользователя (user namespace). Проект предназначен для ОС Linux, в частности, для Ubuntu 18.04, но может быть запущен и на других дистрибутивах Linux с большой вероятностью.
Для сборки и тестирования файловой системы необходимо поставить зависимость:
sudo apt-get install libfuse-dev
По крайней мере именно такая зависимость позволила скомпилировать проект с FUSE на ОС Ubuntu 18.04.
Помимо этого, необходимо скачать исходники lz4 (см. ссылку 3) и использовать их при компиляции проекта.
Для сборки проекта предусмотрен простенький makefile
, который позволяет собрать файловую систему с помощью команды make
. В этом случае появится исполняемый файл fuse-lz4.fs
, который и представляет из себя пользовательскую файловую систему, которую можно смонтировать в желаемое место. Для очистки сборки используйте make clean
. Для сборки потребуется компилятор gcc
.
За основу взята файловая система из примеров passthough_ll.c, которая дублирует работу файловой системы. Для сборки необходимо наличие файла config.h
, в котором перечислена конфигурация операционной системы, т.е. что она умеет.
В makefile
можно собрать много чего интересного:
make ssfs
-- собирает тупую файловую систему на минималках. Код там несложныйmake passthrough
-- более продвинутый пример, который собирает приемлимый по производительности вариант файловой системы, зеркалирующий корень файловой системы. Однако это не самый быстрый вариант (есть вариант низкоуровневой реализации на FUSE, либо можно вообще писать на уровне ядра и забыть о FUSE)make framecompress
-- собирает исполняемый файлframeCompress.o
, который сжимает файлы с помощью алгоритмаlz4
в блочном режиме, также разжимает их и проверяет соответствие сжатого файла оригинальному. Один из кандидатов на встраивание в нашу целевую файловую системуmake fuse_write_substituter
-- собирает файловую систему на базеpassthough_ll.c
, которая уже менее бесполезна, но всё ещё очень бесполезна -- заменяет все записываемые блоки на диск на фамилию и имя автора данного проекта.- Сборка основного проекта
fuse-lz4
осуществляется просто командойmake
, илиmake build
Таким образом, нетрудно догадаться, что успешное решение задачи заключается в том, чтобы интегрировать реализацию блочного сжатия файлов в п.3 в делегирующую реализацию файловой системы passthrough
. Скопируем этот файл в fuse_lz4.c
и будем добавлять в него соответствующую реализацию алгоритма сжатия данных.
После сборки с помощью make
файловая система запускается так:
./fuse-lz4.fs -f mountpoint
где mountpoint
-- это пустая целевая папка, в которую монтируется наша файловая система. В папку mount
зеркалируется корень системы, однако все операции перехвачены тем или иным способом. В частности, в данный момент перехвачены операции чтения и записи файлов, в которых производится, соответственно, расжатие и сжатие в соответствии с алгоритмом LZ4.
Таким образом, Запись в файлов в папке mountpoint, к которой примонтирована файловая система, ведёт к их сжатию с помощью LZ4!
Для удобства можно добавить символическую ссылку вглубь mountpoint
, которая будет становиться валидной при монтировании файловой системы (жёсткую делать не рекомендуется).
Для размонтирования можно применять следующие команды:
fusermount [OPTIONS] mountpoint
В особо плохих случаях (как в моём, для которого старая схема монтирования не поддерживается):
sudo umount [-f] [-l] mountpoint
- Избавиться от реальных и потенциальных багов при компрессии в файловой системе.
На данный момент файловая система хорошо справляется с последовательным чтением и записью файлов на диск. Однако, при редактировании большого файла таким образом, что данные конечного блока начинают смещаться, может произойти потеря данных, т.к. перезаписывается файловая структура. Поэтому не рекомендуется пользоваться текстовыми редакторами внутри файловой системы, однако пользоваться только операциями на уровне файлов, такие как копирование, перемещение, удаление файлов, и т.д.
Несмотря на то, что внутри файловой системы не рекомендуется редактировать текстовые файлы, это безопасно делать в двух случаях: если файл помещается в размер записываемого блока, который ОС использует по умолчанию, либо при записи в конец файла.
Файл до компрессии (тот, что виден пользователю):
Файл после компрессии (тот, что на самом деле хранится на диске):
Таким образом, на диске хранится не сам файл в чистом виде, а его сжатая версия с помощью алгоритма LZ4.
- https://github.com/libfuse/libfuse
- https://github.com/thyu/lz4xx/blob/master/include/lz4.h
- https://github.com/lz4/lz4/
- https://github.com/gordan-bobic/zfs-fuse
- https://www.howtoinstall.co/en/ubuntu/trusty/libfuse-dev
- Хороший туториал по написанию простейшей ФС: https://www.maastaar.net/fuse/linux/filesystem/c/2016/05/21/writing-a-simple-filesystem-using-fuse/
- Часть два туториала про Simple Stupid File System: https://www.maastaar.net/fuse/linux/filesystem/c/2016/05/21/writing-a-simple-filesystem-using-fuse/
- Хороший старт для разрабатываемого кейса находится тут. Это пример файловой системы, которая делегирует все операции стандартной библиотеке libc: https://libfuse.github.io/doxygen/example_2passthrough_8c.html
- Отличная статья о LZ4: https://habr.com/en/company/yandex/blog/452778/, но свой LZ4 не будем реализовывать, воспользуемся популярным, упоминаемым в статье (см. п. 3)
- https://github.com/acozzette/BUSE -- Это как FUSE, только BUSE. Возможно, с помощью него задача решается легче