由于工作需要,写了一个功能最简单的文件系统,想着再完善一下,当成公开课素材,一来觉得挺好玩,二来觉得可以自己的简历也需要这么一个项目。
这个”我的”(my)文件系统不是为了生产目的,目前只用于学习目的,欢迎更多的朋友来完善,可以参考其他文件系统的代码(当然不能整段copy),但请标明出处。
修改Makefile文件中的KDIR变量对应Linux内核仓库的路径,然后在myfs代码仓库执行以下命令:
make # 生成 myfs.ko
# make clean # 清理编译生成的文件把整个代码仓库目录myfs复制到Linux内核仓库的fs目录下。然后到内核仓库中执行以下命令:
git am fs/myfs/0001-add-support-for-myfs.patch
mv fs/myfs/Makefile.kernel fs/myfs/Makefile
make O=x86_64-build menuconfig
make O=x86_64-build bzImage -j`nproc`
make O=x86_64-build modules -j`nproc`本来想和ksmbd/Makefile中一样用ifneq ($(KERNELRELEASE),)隔离开独立模块和作为内核一部分,但好像没什么卵用,对makefile熟悉的朋友可以告诉我要怎么写。
参考fs/smb/server/server.c写了一个日志开关功能,使用请参考《smb调试方法》。
控制命令如下:
cat /sys/class/myfs-ctrl/debug # 查看日志开关,打开的日志类型有中括号
echo all > /sys/class/myfs-ctrl/debug # 全部切换
echo main > /sys/class/myfs-ctrl/debug # 只切换main用以下命令挂载:
mount -t myfs /dev/sda /mnt
mount
lsblk
df
umount /mnt如果编译内核打开了CONFIG_BLK_DEV_LOOP配置,可以挂载文件:
mount -t myfs -o loop /dev/sda /mnt#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/limits.h>
int main()
{
int res = syscall(__NR_openat, AT_FDCWD, "/mnt", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY);
printf("result: %d\n", res);
return 0;
}文件系统的模块加载函数是init_myfs(),模块卸载函数是exit_myfs()。可作为独立模块编译,也可作为内核一部分编译,内核配置选项是CONFIG_MYFS。
引入struct file_system_type myfs_fs_type,实现.mount和.kill_sb方法,但测试发现mount时会panic,用scripts/faddr2line脚本解析栈信息,发现在legacy_get_tree()中得到的struct dentry *root为空,所以是还没能得到root的dentry和inode。
为了方便调试,引入调试日志函数接口myfs_debug()。接着在myfs_fill_super()函数中获取root inode,但mount时却报错:
mount: /mnt: mount(2) system call failed: Not a directory.。查看代码发现是root inode不是目录类型,所以将root inode的i_mode设置成目录类型,这时就能挂载成功。
但这时df -Th命令还不能输出myfs相关的信息,引入struct super_operations myfs_sops且实现.statfs方法,df -Th命令就可输出相关信息。
引入myfs_dir_operations和myfs_file_operations,但是ls /mnt还是报错ls: cannot open directory '/mnt': Not a directory,具体原因待定位。