华为作为中国代表性的技术型企业,一直在不断推出自己的技术实现,并努力推广到世界,这一点是非常值得称赞的。从大概上游Linux 4.19左右,邮件列表开始出现一个EROFS的东西,不断有邮件的往来。因为太小众,所以当时没有太留意,只是因为EROFS这个名字和写只读文件系统时返回的错误名字一样,所以就留下了印象,其实都没注意到是华为的人做的。最近华为推出新手机,并宣扬自己为手机系统新写的文件系统的新闻不断发酵。我才开始注意到EROFS原来是华为的人写的,并且已经被merge到了Linux内核主线。
作为一个从事操作系统行业,文件系统方向的人,面对这样一个由国人推出的已经进了Linux项目主线的新文件系统,我觉得我有必要稍微关注一下。于是在晚上刚开完会后,现在是2019-03-27晚上21:18分,我开始了第一次对EROFS的初探。为什么要写上时间?因为我下面的一些操作可能会在项目日趋完善后出现变化,所以时间点变相代表我操作的“版本号”。
这是一个全新的项目,所以怎么使用我也毫无头绪,网上文档及其少,用Google搜索Linux EROFS得到的大部分是Linux怎么处理EROFS错误,或者华为发布EROFS的新闻。新闻内容没什么参考价值,所以erofs在邮件列表的邮件成了重要的信息来源:
https://marc.info/?l=linux-fsdevel&m=152776480425624
还有一个LWN上关于EROFS的介绍:
https://lwn.net/Articles/760964/
但是因为我是付费的用户,所以能打开这个文章,不知道一般用户是不是能打开。如果打不开也没关系,内容并不多,还不如看上面的邮件列表的邮件。
从一些内容上我们知道了EROFS还有一个用户态工具,我找了一下,项目地址在:
https://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git
有用的信息我暂时就找到这三个,这已经够我看一阵子了,今晚是肯定看不完。我们下面还是先完成初探的内容,将这个新的文件系统用起来。
因为EROFS已经进的Linux的主线,所以找到并编译安装它是使用它第一件要做的事情
# git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
# make menuconfig
在进入config界面后,我并不知道EROFS的编译选项在哪,所以先搜索EROFS,看到如下图所示:
从描述可以看出那个EROFSFS基本就是我们要找的,它没有在filesystem目录下,而是在Device Drivers下面,而且目前还作为Staging drivers存在。嗯……看来我要冒着很大的Crash的风险来试试它了。按照上面所示我们找到EROFS_FS的编译选项的位置:
我们选择将其编译为模块
# make -j32 && make -j16 modules_install && make install
(此处省略一个小时,/me 先小睡一会。。。)
。。。。
。。。。
好了,编译好了,没有出现编译错误。由于当前正是Linux的5.1.0-rc2阶段,所以装的kernel默认是/boot/vmlinuz-5.1.0-rc2+,我们选择将其默认启动后重启系统:
# grubby --set-default=/boot/vmlinuz-5.1.0-rc2+
# shutdown -r now
系统boot起新的kernel后erofs不是被自动加载的(毕竟它还是个staging阶段的driver),我们把它加载上来:
# find /lib/modules/`uname -r` -name erofs*
/lib/modules/5.1.0-rc2+/kernel/drivers/staging/erofs
/lib/modules/5.1.0-rc2+/kernel/drivers/staging/erofs/erofs.ko
# lsmod|grep erofs
# modprobe erofs
# dmesg|tail
...
[19474.968155] erofs: module is from the staging directory, the quality is unknown, you have been warned.
[19474.987076] erofs: initializing erofs 1.0pre1
[19474.992463] erofs: successfully to initialize erofs
# lsmod|grep erofs
erofs 147456 0
嗯....加载上了,它“贴心”的还提示我"the quality is unknown, you have been warned"。下面该做什么呢?有了这样一个module,我们要想办法用起来。正好作者还提供了一个用户层工具erofs-utils,我们把那个项目也clone下来:
# git clone git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git
Cloning into 'erofs-utils'...
remote: Counting objects: 147, done.
remote: Compressing objects: 100% (143/143), done.
remote: Total 147 (delta 83), reused 2 (delta 0)
Receiving objects: 100% (147/147), 55.02 KiB | 678.00 KiB/s, done.
Resolving deltas: 100% (83/83), done.
warning: remote HEAD refers to nonexistent ref, unable to checkout.
# ls
# git branch
# git branch -a
remotes/origin/mkfs-dev
空的?作者也真是心大,看来这确实是一个初级阶段的项目,连HEAD refer都没弄好。好在作者没有忘记push mkfs-dev分支,我们切到这个分支上看看。
# git checkout -b mkfs-dev remotes/origin/mkfs-dev
Branch 'mkfs-dev' set up to track remote branch 'mkfs-dev' from 'origin'.
Switched to a new branch 'mkfs-dev'
# ls
AUTHORS autogen.sh ChangeLog configure.ac COPYING include Makefile.am mkfs NEWS README
嗯,这回有东西了。老规矩,未知的东西先看文档。也没有什么特别的manual文档,那就看README吧:
下面引用的文档内容版权归文档作者所有:
mkfs.erofs
mkfs.erofs is a user-space tool to create erofs filesystem images.
It can create 2 main types of erofs images, compressed and uncompressed:
- For compressed images, it is able to integrate several compression
algorithms, lz4 is supported according to the current erofs kernel
implementation.
- For uncompressed images, it can decide whether the last page of
a file should be inlined or not properly [1].Note that mkfs.erofs can only be linked statically with lz4 library
due to the dependency of experimental lz4hc apis which were added in
lz4 1.8.0. Anyway, it's a good start to begin with building the latest
lz4 library statically first. :)Dependencies
lz4-1.8.0 or aboveHow to build with lz4 static library
./configure --with-lz4=
eg. if lz4 lib has been installed into fold of /usr/local/lib
./configure --with-lz4=/usr/local/lib && make
On Fedora, static lz4 can be installed using:
yum install lz4-static.x86_64
To build you should run this first:
$ ./autogen.sh
$ ./configure
$ make
先看介绍和编译部分,需要lz4的库,版本要求lz4-1.8.0以上。我先看看我的repo里有没有:
# yum info lz4
....
Available Packages
Name : lz4
Version : 1.8.1.2
Release : 4.el8
Arch : x86_64
Size : 92 k
Source : lz4-1.8.1.2-4.el8.src.rpm
Repo : beaker-BaseOS
Summary : Extremely fast compression algorithm
URL : https://lz4.github.io/lz4/
License : GPLv2+ and BSD
Description : LZ4 is an extremely fast loss-less compression algorithm, providing compression
: speed at 400 MB/s per core, scalable with multi-core CPU. It also features
: an extremely fast decoder, with speed in multiple GB/s per core, typically
: reaching RAM speed limits on multi-core systems.
嗯,很不错,我大Red Hat (已经被IBM买走了 T_T )的最新系统支持这个库,版本正好在1.8以上。省去我自己下载编译的功夫了,我们将lz4及其库文件都装上:
# yum install lz4 lz4-libs lz4-devel lz4-static
然后尝试编译erofs-utils,文档上写的很清楚,我们照着执行一下试试看有没有问题:
# cd erofs-utils
# ./autogen.sh
# ./configure
# make -j4
Lucky! 没有问题!我们得到了重要的mkfs文件:
# ls mkfs/mkfs.erofs -l
-rwxr-xr-x. 1 root root 239480 Mar 27 11:36 mkfs/mkfs.erofs
# ./mkfs/mkfs.erofs
mkfs.erofs 0.1 Mar 27 2019 11:36:50
Usage:
[-z ] [-d ]
[target path] [source directory]
好吧,虽然它没有--help/-h这个选项,但是它还是大方的告诉了我自己的版本号和usage。再来看文档:
Usage:
$ ./mkfs.erofs
mkfs.erofs v1.0 Nov 17 2018 19:47:21Usage:
[-z] [-d ]
[target path] [source directory]-d -- set debugging level
-z -- enablecompression (only lz4hc is supported) Target path, source directory are both needed.
Usage:
$ ./mkfs.erofs
mkfs.erofs v1.0 Nov 17 2018 19:47:21Usage:
[-z] [-d ]
[target path] [source directory]-d -- set debugging level
-z -- enablecompression (only lz4hc is supported) Target path, source directory are both needed.
文档解释了-d和-z两个选项的意思,一个是设置debug的级别,一个是选择压缩算法,但是好像目前就只有lz4hc一个被支持,所以这两个选项我们先都不尝试了。然后target path和source directory是都需要的。那我们就试一下好了:
# dd if=/dev/zero of=/home/erofs_disk bs=512 count=23000
23000+0 records in
23000+0 records out
11776000 bytes (12 MB, 11 MiB) copied, 0.306837 s, 38.4 MB/s
# mkdir /home/srcd
# cp README /home/srcd
# cp COPYING /home/srcd
# cp ChangeLog /home/srcd
# cp Makefile /home/srcd
# ./mkfs/mkfs.erofs /home/erofs_disk /home/srcd/
c_version: [0.1 Mar 27 2019 11:36:50]
c_img_path: [/home/erofs_disk]
c_src_path: [/home/srcd]
c_dbg_lvl: [ 0]
c_dry_run: [ 0]
c_alg_name: [ none]
c_compr_maxsz: [ 921600]
c_compr_lvl: [ 0]
c_compr_boundary: [ 128]
c_compr_ratio_limit: [ 100]
# mount -t erofs /home/erofs_disk /mnt/scratch -oloop
# dmesg|tail
[21656.252653] loop: module loaded
[21656.288268] erofs: read_super, device -> /dev/loop0
[21656.293824] erofs: options -> (null)
[21656.298229] erofs: root inode @ nid 0
[21656.302805] erofs: mounted on /dev/loop0 with opts: (null).
# mount|grep erofs
/home/erofs_disk on /mnt/scratch type erofs (ro,relatime,user_xattr,acl)
# ls -li /mnt/scratch
total 48
79 -rw-r--r--. 1 root root 0 Mar 27 11:51 ChangeLog
4 -rw-r--r--. 1 root root 18729 Mar 27 11:51 COPYING
80 -rw-r--r--. 1 root root 25649 Mar 27 11:51 Makefile
1408 -rw-r--r--. 1 root root 3744 Mar 27 11:51 README
# echo > /mnt/scratch/file
bash: /mnt/scratch/file: Read-only file system
# mount -t erofs /home/erofs_disk /mnt/scratch -oremount,rw
# cat /proc/mounts |grep erofs
/dev/loop0 /mnt/scratch erofs ro,relatime,user_xattr,acl 0 0
# dmesg|tail
# echo > /mnt/scratch/file
bash: /mnt/scratch/file: Read-only file system
没报什么错,但是也没有被改成rw。
不死心,卸载文件系统重新尝试以指定rw的方式直接挂载试试:
# umount /mnt/scratch
# dmesg|tail
[22737.057138] erofs: unmounted for /dev/loop0
# mount -t erofs /home/erofs_disk /mnt/scratch -oloop,rw
# echo $?
0
# dmesg
[22818.902072] erofs: read_super, device -> /dev/loop0
[22818.907548] erofs: options -> (null)
[22818.911625] erofs: root inode @ nid 0
[22818.915838] erofs: mounted on /dev/loop0 with opts: (null).
# cat /proc/mounts |grep erofs
/dev/loop0 /mnt/scratch erofs ro,relatime,user_xattr,acl 0 0
# echo > /mnt/scratch/file
bash: /mnt/scratch/file: Read-only file system
嗯,很坚挺,打死不动^_^
作为初探,今天就先放过它吧,改天再想办法让他panic(如果我有时间的话)。原理性的东西其实也并不是多新的技术,应该也不会跳出一直以来compression filesystem的圈。实现细节也还没怎么看,好像和ext4对metadata的组织有点类似,但是因为是只读的,所以可以省去很多东西,但是因为压缩功能,要新增一些东西。总之今天就先到这吧,熄灯,睡觉。