记录一次为 Rock 5B 开发板编译 NTFS3 驱动的过程

0. 前言

最近,感觉到机械硬盘大幅度拖慢了 Windows 10 的 IO,但目前不方便购置 NAS,遂尝试暂时使用 Rock 5B 开发板挂pt下载。
由于硬盘为 NTFS 格式,且存在大量数据,虽然已有一些方案能将 NTFS 文件系统转换为对 linux 友好的文件系统(ext4、btrfs,等),但考虑到该硬盘以后仍然会作为 Windows 系统使用的移动硬盘,于是放弃了转换硬盘文件系统的想法,并尝试为 Rock 5B 开发板引入 NTFS3 驱动。
NTFS3 是 Paragon 公司为 kernel 5.15 引入的内核态 NTFS 驱动,其性能比 kernel 中原有的用户态驱动 ntfs-3g 强许多。
在尝试为 Rock 5B 编译 NTFS3 驱动的过程中遇到了一些问题,并在此记录下来。
编译后的内核模块可以在这里找到:

https://github.com/KatyushaScarlet/ntfs3-dkms/releases

安装说明可参考本文“安装”部分

1. 寻找 NTFS3 5.10 backport

到目前为止,Rock 5B 开发板只有 5.10 版的内核,因此需要一份反向移植到 kernel 5.10 的源码。
经过一番搜寻,首先发现在 Arch AUR 中有一份从 kernel 5.17 的源码中将 NTFS3 反向移植到 5.12 的补丁
其次,在 OpenWrt 论坛中,有一位名为 VA1DER 的开发者制作了从 5.12 到 5.10 的反向移植补丁
然后,还有一位名为 xymopen 的开发者整合了上述的所有源码和补丁,打包成符合 OpenWrt Buildroot 结构的软件包
接下来,就尝试从这里入手。

2. 尝试编译,出现问题

首先,拉取 xymopen 的源码,并安装补丁:

rock@rock5b:~uname -a
Linux rock5b 5.10.110-34-rockchip-gca15bbe36e6c #rockchip SMP Wed Dec 7 06:54:05 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux
rock@rock5b:~ git clone https://github.com/xymopen/openwrt-ntfs3
Cloning into 'openwrt-ntfs3'...
remote: Enumerating objects: 95, done.
remote: Counting objects: 100% (95/95), done.
remote: Compressing objects: 100% (69/69), done.
remote: Total 95 (delta 16), reused 93 (delta 14), pack-reused 0
Unpacking objects: 100% (95/95), 214.88 KiB | 1.20 MiB/s, done.
rock@rock5b:~cd openwrt-ntfs3/kernel/ntfs3/src
rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/src patch -p1 < ../../ntfs3/patches/0001-Revert-iov_iter-Turn-iov_iter_fault_in_readable-into.patch
patching file file.c
rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/srcpatch -p1<../../ntfs3/patches/0002-Revert-vfs-add-rcu-argument-to-get_acl-callback.patch
patching file ntfs_fs.h
patching file xattr.c
rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/src patch -p1 < ../../ntfs3/patches/0003-Revert-iov_iter-replace-iov_iter_copy_from_user_atom.patch
patching file file.c
rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/srcpatch -p1<../../ntfs3/patches/0004-Revert-block-rename-BIO_MAX_PAGES-to-BIO_MAX_VECS.patch
patching file fsntfs.c
rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/src patch -p1 < ../../ntfs3/patches/0005-Revert-mount-attach-mappings-to-mounts.patch
patching file file.c
patching file inode.c
patching file namei.c
patching file ntfs_fs.h
patching file super.c
patching file xattr.c

安装完成后,尝试编译:

rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/srcmake -C \
> /lib/modules/5.10.110-34-rockchip-gca15bbe36e6c/build \
> M=/home/rock/openwrt-ntfs3/kernel/ntfs3/src \
> CONFIG_NTFS3_FS=m \
> CONFIG_NTFS3_LZX_XPRESS=y \
> modules
make: Entering directory '/usr/src/linux-headers-5.10.110-34-rockchip-gca15bbe36e6c'
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/attrib.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/attrlist.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/bitfunc.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/bitmap.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/dir.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/fsntfs.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/frecord.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/file.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/fslog.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/inode.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/index.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lznt.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/namei.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/record.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/run.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/super.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/upcase.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/xattr.o
/home/rock/openwrt-ntfs3/kernel/ntfs3/src/xattr.c:989:9: error: initialization of 'int (*)(const struct xattr_handler *, struct dentry *, struct inode *, const char *, void *, size_t,  int)' {aka 'int (*)(const struct xattr_handler *, struct dentry *, struct inode *, const char *, void *, long unsigned int,  int)'} from incompatible pointer type 'int (*)(const struct xattr_handler *, struct dentry *, struct inode *, const char *, void *, size_t)' {aka 'int (*)(const struct xattr_handler *, struct dentry *, struct inode *, const char *, void *, long unsigned int)'} [-Werror=incompatible-pointer-types]
  989 |  .get = ntfs_getxattr,
      |         ^~~~~~~~~~~~~
/home/rock/openwrt-ntfs3/kernel/ntfs3/src/xattr.c:989:9: note: (near initialization for 'ntfs_other_xattr_handler.get')
cc1: some warnings being treated as errors
make[1]: *** [scripts/Makefile.build:273: /home/rock/openwrt-ntfs3/kernel/ntfs3/src/xattr.o] Error 1
make: *** [Makefile:1920: /home/rock/openwrt-ntfs3/kernel/ntfs3/src] Error 2
make: Leaving directory '/usr/src/linux-headers-5.10.110-34-rockchip-gca15bbe36e6c'
rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/src

发现 ntfs_getxattr 这里有问题,似乎是说这个函数的定义与接口不符。于是检查 .get 的定义:

static const struct xattr_handler ntfs_other_xattr_handler = {
    .prefix = "",
    .get    = ntfs_getxattr,
    .set    = ntfs_setxattr,
    .list   = ntfs_xattr_user_list,
};

发现这个结构体的类型是 xattr_handler。它是内核中表示“属于某一命名空间的扩展属性的处理程序”,其中 set 函数用于根据参数来设置或替换某个扩展属性的值,或者创建一个新的扩展属性;get 函数用于获取指定扩展属性的值。
它的定义在 include/linux/xattr.h 中。
于是检查它在 Rock 5B 的内核中的定义

struct xattr_handler {
    const char *name;
    const char *prefix;
    int flags;      /* fs private flags */
    bool (*list)(struct dentry *dentry);
    int (*get)(const struct xattr_handler *handler, struct dentry *dentry,
           struct inode *inode, const char *name, void *buffer,
           size_t size, int flags);
    int (*set)(const struct xattr_handler *handler, struct dentry *dentry,
           struct inode *inode, const char *name, const void *buffer,
           size_t size, int flags);
};

并将其与 ntfs_getxattr 函数做比对:

static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de,
             struct inode *inode, const char *name, void *buffer,
             size_t size)

可以看出,NTFS3 源码中的 ntfs_getxattr 函数少了一个 int flags 的参数。
那么,这个参数是必要的吗?

3. 定位问题,尝试解决

首先我从 kernel.org 上下载了 kernel 5.15 LTS 的源码,也就是 NTFS3 被引入的内核版本,并检查它的 include/linux/xattr.h 文件中 ntfs_getxattr 的定义。
发现它的定义是这样的:

struct xattr_handler {
    const char *name;
    const char *prefix;
    int flags;      /* fs private flags */
    bool (*list)(struct dentry *dentry);
    int (*get)(const struct xattr_handler *, struct dentry *dentry,
           struct inode *inode, const char *name, void *buffer,
           size_t size);
    int (*set)(const struct xattr_handler *,
           struct user_namespace *mnt_userns, struct dentry *dentry,
           struct inode *inode, const char *name, const void *buffer,
           size_t size, int flags);
};

说明 kernel 的 api 发生了改变。
在 kernel 5.15 及以后的版本中,get 函数取消了int flags 参数,说明这个参数不是必要的。
那么在 kernel 5.10 中其他的文件系统是怎么处理这个参数的呢?
于是,我在 Rock 5B 的内核中搜寻 ext4 文件系统的实现。
/fs/ext4/xattr.h 中找到了几处定义:

extern const struct xattr_handler ext4_xattr_user_handler;
extern const struct xattr_handler ext4_xattr_trusted_handler;
extern const struct xattr_handler ext4_xattr_security_handler;
extern const struct xattr_handler ext4_xattr_hurd_handler;

继续寻找 ext4_xattr_user_handler 的定义:

const struct xattr_handler ext4_xattr_user_handler = {
    .prefix = XATTR_USER_PREFIX,
    .list   = ext4_xattr_user_list,
    .get    = ext4_xattr_user_get,
    .set    = ext4_xattr_user_set,
};

找到相应的 ext4_xattr_user_get 函数:

static int
ext4_xattr_user_get(const struct xattr_handler *handler,
            struct dentry *unused, struct inode *inode,
            const char *name, void *buffer, size_t size, int flags)
{
    if (!test_opt(inode->i_sb, XATTR_USER))
        return -EOPNOTSUPP;
    return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER,
                  name, buffer, size);
}

从这里可以看到,ext4_xattr_user_get 中调用了 ext4_xattr_get 函数,但 flags 参数没有往下传。可能这也是在 kernel 5.15 中取消这个参数的原因。
基本可以确定,在 get 函数中不需要 int flags 参数。
那么,为了使函数签名匹配,往 ntfs_getxattr 函数中添加一个占位参数即可:

static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de,
             struct inode *inode, const char *name, void *buffer,
             size_t size, int flags)

4. 重新编译

rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/src$ make -C \
> /lib/modules/5.10.110-34-rockchip-gca15bbe36e6c/build \
> M=/home/rock/openwrt-ntfs3/kernel/ntfs3/src \
> CONFIG_NTFS3_FS=m \
> CONFIG_NTFS3_LZX_XPRESS=y \
> modules
make: Entering directory '/usr/src/linux-headers-5.10.110-34-rockchip-gca15bbe36e6c'
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/attrib.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/attrlist.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/bitfunc.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/bitmap.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/dir.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/fsntfs.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/frecord.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/file.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/fslog.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/inode.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/index.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lznt.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/namei.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/record.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/run.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/super.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/upcase.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/xattr.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lib/decompress_common.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lib/lzx_decompress.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lib/xpress_decompress.o
  LD [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/ntfs3.o
  MODPOST /home/rock/openwrt-ntfs3/kernel/ntfs3/src/Module.symvers
ERROR: modpost: module ntfs3 uses symbol drop_nlink from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol unload_nls from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol make_bad_inode from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol __mark_inode_dirty from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol clean_bdev_aliases from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol iget5_locked from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol is_bad_inode from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol generic_file_open from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol ll_rw_block from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol mpage_readahead from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol generic_read_dir from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol mpage_readpage from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol __bread_gfp from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol d_obtain_alias from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol write_inode_now from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol file_remove_privs from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol set_nlink from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol sync_dirty_buffer from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol __brelse from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol inode_init_once from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol create_empty_buffers from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol load_nls from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol fiemap_fill_next_extent from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol unlock_new_inode from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol kill_block_super from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol inode_newsize_ok from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol sync_inode_metadata from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol iter_file_splice_write from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol inode_dio_wait from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol ihold from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol fiemap_prep from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol d_splice_alias from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol sync_filesystem from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol __set_page_dirty_buffers from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol sb_set_blocksize from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol __blockdev_direct_IO from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol mark_buffer_dirty from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol init_special_inode from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol generic_file_splice_read from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol clear_inode from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol setattr_prepare from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol generic_fillattr from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
ERROR: modpost: module ntfs3 uses symbol inode_init_owner from namespace VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver, but does not import it.
make[1]: *** [scripts/Makefile.modpost:169: /home/rock/openwrt-ntfs3/kernel/ntfs3/src/Module.symvers] Error 1
make[1]: *** Deleting file '/home/rock/openwrt-ntfs3/kernel/ntfs3/src/Module.symvers'
make: *** [Makefile:1822: modules] Error 2
make: Leaving directory '/usr/src/linux-headers-5.10.110-34-rockchip-gca15bbe36e6c'

再次出现错误,但好在问题不大。
super.c 中添加一行:

MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);

重新编译

rock@rock5b:~/openwrt-ntfs3/kernel/ntfs3/src$ make -C \
> /lib/modules/5.10.110-34-rockchip-gca15bbe36e6c/build \
> M=/home/rock/openwrt-ntfs3/kernel/ntfs3/src \
> CONFIG_NTFS3_FS=m \
> CONFIG_NTFS3_LZX_XPRESS=y \
> modules
make: Entering directory '/usr/src/linux-headers-5.10.110-34-rockchip-gca15bbe36e6c'
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/attrib.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/attrlist.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/bitfunc.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/bitmap.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/dir.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/fsntfs.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/frecord.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/file.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/fslog.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/inode.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/index.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lznt.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/namei.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/record.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/run.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/super.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/upcase.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/xattr.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lib/decompress_common.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lib/lzx_decompress.o
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/lib/xpress_decompress.o
  LD [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/ntfs3.o
  MODPOST /home/rock/openwrt-ntfs3/kernel/ntfs3/src/Module.symvers
  CC [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/ntfs3.mod.o
  LD [M]  /home/rock/openwrt-ntfs3/kernel/ntfs3/src/ntfs3.ko
make: Leaving directory '/usr/src/linux-headers-5.10.110-34-rockchip-gca15bbe36e6c'

编译成功。

5. 安装

为了能使 ntfs3 驱动在开机时自动挂载硬盘,需要将模块添加到 /lib/modules/内核版本/kernel/fs/ntfs3/ 路径中:

$ sudo mkdir /lib/modules/5.10.110-34-rockchip-gca15bbe36e6c/kernel/fs/ntfs3/ -p
$ sudo cp ntfs3.ko /lib/modules/5.10.110-34-rockchip-gca15bbe36e6c/kernel/fs/ntfs3/

并在 /etc/modules 文件中添加 ntfs3 (不含.ko扩展名):

$ sudo vim /etc/modules
# /etc/modules: kernel modules to load at boot time.
# 
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
ntfs3

fstab 中添加挂载选项:
(如果在末尾添加 0 0 ,dmesg中会报错,且无法正常挂载硬盘。暂不了解相关原因)

$ sudo vim /etc/fstab
/dev/sda1   /mnt     ntfs3,iocharset=utf8,defaults,nofail

安装完成。

6. 性能对比

NTFS-3G

rock@rock5b:~$ dd if=/dev/zero of=/mnt/backup/test.bin bs=1G count=1 oflag=dsync
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 23.6311 s, 45.4 MB/s

NTFS3

rock@rock5b:~$ dd if=/dev/zero of=/mnt/backup/test.bin bs=1G count=1 oflag=dsync
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 11.4404 s, 93.9 MB/s

可以看出,NTFS3 的性能几乎是 NTFS-3G 的两倍。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注