FUSE协议解析

由于以前有项目是用到FUSE,将S3等对象存储映射为文件存储的,但我不是负责那一块,所以一直只是知道FUSE是个什么东西,而没有用过。刚好趁着没工作的这段时间,学习Golang,顺便把FUSE也了解下,实现了一个简易版的libfuse: https://github.com/mingforpc/fuse-go和一个可以将HDFS Mount到本地文件夹的程序: https://github.com/mingforpc/hadoop-fs

由于刚学并整理,如有遗漏或者错误!请拼命指出,谢谢!

什么是FUSE

FUSE的全称是Filesystem in Userspace,即用户空间文件系统,是系统内核提供的一个功能,使得可以在用户态下实现一个自定义的文件系统。比如CEPH和GlusterFS等都有使用到FUSE。

libfuse则是提供给用户态下的开发包。

FUSE是怎么交互的

FUSE是通过读写/dev/fuse让用户态的文件系统进程和内核通信的。

大概流程

程序需要先打开/dev/fuse,然后通过mount()/dev/fuse的fd,进程的用户id和组id传入,进行文件系统的挂载。

PS: libfuse通过自己写的fusermount程序(编译安装libfuse后会在/bin/下),可以让我们实现的文件系统程序在非root权限下挂载,这部分我还不是很了解,我自己实现的go版libfuse也只是依赖于这个fusermount。

FUSE的指令号、对应的函数、请求格式与响应

程序从/dev/fuse中读取请求,不需要担心像TCP有半包粘包等问题,一次读取一条请求。buffer不够大,会报异常。

请求和响应,都是以二进制字节表示的,下文中的结构体只是为了方便看。

请求头

每个命令的前 40 bytes为请求头,转为Golang的结构体如下:

1
2
3
4
5
6
7
8
9
10
11
// Each query starts with a FuseInHeader
type FuseInHeader struct {
Len uint32
Opcode uint32
Unique uint64
Nodeid uint64
Uid uint32
Gid uint32
Pid uint32
Padding uint32
}
  • Len: 是整个请求的字节数长度,包括请求头后的具体内容
  • Opcode: 请求的类型
  • Unique: 该请求唯一标识,响应中要对应着该Unique
  • Nodeid: 该请求针对的文件nodeid,目标文件或者文件夹的nodeid
  • Uid: 对该文件/文件夹操作的进程的用户ID
  • Gid: 对该文件/文件夹操作的进程的用户组ID
  • Pid: 对该文件/文件夹操作的进程的进程ID

响应头

程序写入/dev/fuse的每个响应的前 16 bytes为响应头,转为Golang的结构体如下:

1
2
3
4
5
type FuseOutHeader struct {
Len uint32
Error int32
Unique uint64
}
  • Len: 是整个响应的字节数长度,包括响应头后的具体内容
  • Error: 一个负数的错误码,成功返回0,其他对应着系统(error.h)的错误代码,但是为负数,每个操作的错误返回可以查看linux man中相应的函数
  • Unique: 对应者请求的唯一标识

请求类型和具体结构

数字对应着请求中的Opcode

FUSE_LOOKUP = 1

lookup()函数,Look up a directory entry by name and get its attributes.

如解析所说,获取代请求头Nodeid文件夹下该名字的文件的属性,包含着 inode id等。

请求头后的实体
1
2
3
type FuseLookupIn struct {
Name string // 字符串结尾的`\0`会计算到长度中,解析时需注意
}
  • Name: 文件名
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
type FuseEntryOut struct {
NodeId uint64 /* Inode ID */
Generation uint64 /* Inode generation: nodeid:gen must be unique for the fs's lifetime */
EntryValid uint64 /* Cache timeout for the name */
AttrValid uint64 /* Cache timeout for the attributes */
EntryValidNsec uint32
AttrValidNsec uint32

Attr FuseAttr
}

type FuseAttr struct {
Ino uint64
Size uint64
Blocks uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Blksize uint32
Padding uint32
}
  • NodeId: 文件的Inode ID
  • Generation: 同一个文件, nodeid和gen的组合,必须在整个文件系统的生命周期中唯一
  • EntryValid: 对于文件的Name的缓存时间,单位是秒
  • EntryValidNsec: 同上,但是该属性表示毫秒部分
  • AttrValid: 对于文件的属性的缓存时间,单位是秒
  • AttrValidNsec: 同上,但是该属性表示毫秒部分
  • Attr: 该文件的属性,可以对应属性的意义可以参考文件属性stat
FUSE_FORGET = 2

forget()函数,Forget about an inode

不需要返回任何响应的操作。

请求头后的实体
1
2
3
4
// forget (should not send any reply)
type FuseForgetIn struct {
Nlookup uint64
}
FUSE_GETATTR = 3

getattr()函数,Get file attributes.

请求头后的实体
1
2
3
4
5
type FuseGetattrIn struct {
GetattrFlags uint32
Dummy uint32
Fh uint64
}
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type FuseAttrOut struct {
AttrValid uint64 /* Cache timeout for the attributes */
AttrValidNsec uint32
Dummp uint32

Attr FuseAttr
}

type FuseAttr struct {
Ino uint64
Size uint64
Blocks uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Blksize uint32
Padding uint32
}
  • AttrValid: 属性的有效时间,单位秒
  • AttrValidNsec: 同上,但是该属性表示毫秒部分
  • Attr: 该文件的属性,可以对应属性的意义可以参考文件属性stat
FUSE_SETATTR = 4

setattr()函数,Set file attributes

请求头后的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type FuseSetattrIn struct {
Valid uint32
Padding uint32
Fh uint64
Size uint64
LockOwner uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Unused4 uint32
Uid uint32
Gid uint32
Unused5 uint32
}
  • Valid: 用来标识需要给文件设置哪些属性的:
    • FUSE_SET_ATTR_MODE = (1 << 0)
    • FUSE_SET_ATTR_UID = (1 << 1)
    • FUSE_SET_ATTR_GID = (1 << 2)
    • FUSE_SET_ATTR_SIZE = (1 << 3)
    • FUSE_SET_ATTR_ATIME = (1 << 4)
    • FUSE_SET_ATTR_MTIME = (1 << 5)
    • FUSE_SET_ATTR_ATIME_NOW = (1 << 7)
    • FUSE_SET_ATTR_MTIME_NOW = (1 << 8)
    • FUSE_SET_ATTR_CTIME = (1 << 10)
  • Size: 文件的大小
  • Atime 和 AtimeNsec: 文件的 access time
  • Mtime 和 MtimeNsec: 文件的 modification time
  • Ctime 和 CtimeNsec: 文件的 status time
  • Mode: 文件的模式(文件类型和权限)
  • Uid: 文件所属的用户
  • Gid: 文件所属的用户组
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type FuseAttrOut struct {
AttrValid uint64 /* Cache timeout for the attributes */
AttrValidNsec uint32
Dummp uint32

Attr FuseAttr
}

type FuseAttr struct {
Ino uint64
Size uint64
Blocks uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Blksize uint32
Padding uint32
}

readlink()函数,Read symbolic link

请求头后的实体

FUSE_READLINK 请求头后没有实体。

响应头的实体
1
2
3
type FuseReadlinkOut struct {
Path string
}

symlink()函数,Create a symbolic link

请求头后的实体
1
2
3
4
5
type FuseSymlinkIn struct {
Name string

LinkName string
}

Name 和 LinkName 之间会以 ‘\0’分隔。

  • Name: 软连接文件的文件名
  • LinkName: 软连接所连接的文件名
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
type FuseEntryOut struct {
NodeId uint64 /* Inode ID */
Generation uint64 /* Inode generation: nodeid:gen must be unique for the fs's lifetime */
EntryValid uint64 /* Cache timeout for the name */
AttrValid uint64 /* Cache timeout for the attributes */
EntryValidNsec uint32
AttrValidNsec uint32

Attr FuseAttr
}

type FuseAttr struct {
Ino uint64
Size uint64
Blocks uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Blksize uint32
Padding uint32
}

属性见lookup中的。

FUSE_MKNOD = 8

mknod()函数,Create file node

请求头后的实体
1
2
3
4
5
6
7
8
type FuseMknodIn struct {
Mode uint32
Rdev uint32
Umask uint32
Padding uint32

Name string
}
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
type FuseEntryOut struct {
NodeId uint64 /* Inode ID */
Generation uint64 /* Inode generation: nodeid:gen must be unique for the fs's lifetime */
EntryValid uint64 /* Cache timeout for the name */
AttrValid uint64 /* Cache timeout for the attributes */
EntryValidNsec uint32
AttrValidNsec uint32

Attr FuseAttr
}

type FuseAttr struct {
Ino uint64
Size uint64
Blocks uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Blksize uint32
Padding uint32
}

属性见lookup中的。

FUSE_MKDIR = 9

mkdir()函数,Create a directory

请求头后的实体
1
2
3
4
5
6
type FuseMkdirIn struct {
Mode uint32
Umask uint32

Name string
}
  • Mode: 目录的模式(包含文件类型和权限)
  • Name: 要创建的目录的名称
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
type FuseEntryOut struct {
NodeId uint64 /* Inode ID */
Generation uint64 /* Inode generation: nodeid:gen must be unique for the fs's lifetime */
EntryValid uint64 /* Cache timeout for the name */
AttrValid uint64 /* Cache timeout for the attributes */
EntryValidNsec uint32
AttrValidNsec uint32

Attr FuseAttr
}

type FuseAttr struct {
Ino uint64
Size uint64
Blocks uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Blksize uint32
Padding uint32
}

属性见lookup中的。

unlink()函数, Remove a directory

请求头后的实体
1
2
3
type FuseUnlinkIn struct {
Name string
}
  • Name: 要删除的目录名字
响应头的实体

无需响应实体,只需返回响应头

FUSE_RMDIR = 11

rmdir()函数,Remove a directory

请求头后的实体

参考unlink()

响应头的实体

参考unlink()

FUSE_RENAME = 12

rename()函数,Rename a file

请求头后的实体
1
2
3
4
5
6
7
type FuseRenameIn struct {
NewDir uint64

OldName string

NewName string
}
  • NewDir: 新目录的 inode id(旧目录的inode id在请求头中)
  • OldName: 旧文件名
  • NewName: 新文件名
响应头的实体

无需响应实体,只需返回响应头

link()函数, Create a hard link

请求头后的实体
1
2
3
4
type FuseLinkIn struct {
OldNodeid uint64
NewName string
}
响应头的实体
1
2
3
type FuseReadlinkOut struct {
Path string
}
FUSE_OPEN = 14

open()函数,Open a file

请求头后的实体
1
2
3
4
type FuseOpenIn struct {
Flags uint32
Unused uint32
}
响应头的实体
1
2
3
4
5
type FuseOpenOut struct {
Fh uint64
OpenFlags uint32
Padding uint32
}
FUSE_READ = 15

read()函数,Read data

请求头后的实体
1
2
3
4
5
6
7
8
9
type FuseReadIn struct {
Fh uint64
Offset uint64
Size uint32
ReadFlags uint32
LockOwner uint64
Flags uint32
Padding uint32
}
  • Offset: 读取开始位置,相对于文件开头的偏移量
  • Size: 内核缓存区的大小(读取的数据大小不能超过这个限制)
响应头的实体
1
2
3
type FuseReadOut struct {
Content []byte
}

在响应头后紧跟着读取的二进制数据

FUSE_WRITE = 16

write()函数,Write data

请求头后的实体
1
2
3
4
5
6
7
8
9
10
11
type FuseWriteIn struct {
Fh uint64
Offset uint64
Size uint32
WriteFlags uint32
LockOwner uint64
Flags uint32
Padding uint32

Buf []byte
}
  • Offset: 开始写入数据位置的偏移量
  • Size: 写入数据的字节数
  • Buf: 写入的数据
响应头的实体
1
2
3
4
type FuseWriteOut struct {
Size uint32
Padding uint32
}
  • Size: 成功写入数据的字节数
FUSE_STATFS = 17

statfs()函数,Get file system statistics

请求头后的实体

statfs只有请求头

响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
type FuseStatfs struct {
Blocks uint64
Bfree uint64
Bavail uint64
Files uint64
Ffree uint64
Bsize uint32
NameLen uint32
Frsize uint32
Padding uint32
Spare [6]uint32
}
FUSE_RELEASE = 18

release()函数,Release an open file

请求头后的实体
1
2
3
4
5
6
type FuseReleaseIn struct {
Fh uint64
Flags uint32
ReleaseFlags uint32
LockOwner uint64
}
响应头的实体

release只需响应头返回成功与否

FUSE_FSYNC = 20

fsync()函数,Synchronize file contents

请求头后的实体
1
2
3
4
5
type FuseFsyncIn struct {
Fh uint64
FsyncFlags uint32
Padding uint32
}
响应头的实体

fsync只需响应头返回成功与否

FUSE_SETXATTR = 21

setxattr()函数,Set an extended attribute

请求头后的实体
1
2
3
4
5
6
7
type FuseSetxattrIn struct {
Size uint32
Flags uint32

Name string
Value string
}
  • Size: 是Value的字节数
  • Name: 文件扩展属性的属性名
  • Value: 文件扩展属性的值
响应头的实体

setxattr只需响应头返回成功与否

FUSE_GETXATTR = 22

getxattr()函数,Get an extended attribute

请求头后的实体
1
2
3
4
5
6
type FuseGetxattrIn struct {
Size uint32
Padding uint32

Name string
}
  • Size: Name的长度
  • Name: 要获取的文件扩展属性的名字
响应头的实体
1
2
3
4
5
6
type FuseGetxattrOut struct {
Size uint32
Padding uint32

Value string
}
  • Size: 表示返回的Value大小
  • Value: 文件扩展属性Name对应的值
FUSE_LISTXATTR = 23

listxattr()函数, List extended attribute names

请求头后的实体
1
2
3
4
type FuseListxattrIn struct {
Size uint32
Padding uint32
}
  • Size: 表示内核接收的缓存大小
响应头的实体
1
2
3
4
5
6
type FuseListxattrOut struct {
Size uint32
Padding uint32

Value string
}
  • Size: 表示返回的Value大小
  • Value: 包含文件额外属性名的字符串,格式类似"user.name\0system.name"

FuseListxattrIn中的Size为0, 不需要往FuseListxattrOut写入Value。

特殊

  • 当Value为空时,响应实体为FuseListxattrOut
  • 当Value有值时,响应实体不需要FuseListxattrOut,而是在响应头FuseOutHeader后紧跟着Value的值
FUSE_REMOVEXATTR = 24

removexattr()函数,Remove an extended attribute

请求头后的实体
1
2
3
type FuseRemovexattrIn struct {
Name string
}
  • Name: 要删除的文件额外属性名
响应头的实体

removexattr只需响应头返回成功与否

FUSE_FLUSH = 25

flush()函数,Flush method

请求头后的实体
1
2
3
4
5
6
type FuseFlushIn struct {
Fh uint64
Unused uint32
Padding uint32
LockOwner uint64
}
响应头的实体

flush只需响应头返回成功与否

FUSE_INIT = 26

init()函数, Initialize filesystem

Fuse文件系统的初始化函数,当Mount以后,从/dev/fuse读到的第一个请求就是init,只有初始化后,才会接收到其他请求。

请求头后的实体
1
2
3
4
5
6
type FuseInitIn struct {
Major uint32
Minor uint32
MaxReadahead uint32
Flags uint32
}
  • Major: Fuse的主版本号
  • Minor: Fuse的副版本号
  • Flags: 内核Fuse能提供的功能
    • FUSE_ASYNC_READ = (1 << 0)
    • FUSE_POSIX_LOCKS = (1 << 1)
    • FUSE_FILE_OPS = (1 << 2)
    • FUSE_ATOMIC_O_TRUNC = (1 << 3)
    • FUSE_EXPORT_SUPPORT = (1 << 4)
    • FUSE_BIG_WRITES = (1 << 5)
    • FUSE_DONT_MASK = (1 << 6)
    • FUSE_SPLICE_WRITE = (1 << 7)
    • FUSE_SPLICE_MOVE = (1 << 8)
    • FUSE_SPLICE_READ = (1 << 9)
    • FUSE_FLOCK_LOCKS = (1 << 10)
    • FUSE_HAS_IOCTL_DIR = (1 << 11)
    • FUSE_AUTO_INVAL_DATA = (1 << 12)
    • FUSE_DO_READDIRPLUS = (1 << 13)
    • FUSE_READDIRPLUS_AUTO = (1 << 14)
    • FUSE_ASYNC_DIO = (1 << 15)
    • FUSE_WRITEBACK_CACHE = (1 << 16)
    • FUSE_NO_OPEN_SUPPORT = (1 << 17)
    • FUSE_PARALLEL_DIROPS = (1 << 18)
    • FUSE_HANDLE_KILLPRIV = (1 << 19)
    • FUSE_POSIX_ACL = (1 << 20)
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
type FuseInitOut struct {
Major uint32
Minor uint32
MaxReadahead uint32
Flags uint32
MaxBackground uint16
CongestionThreshold uint16
MaxWrite uint32
TimeGran uint32
Unused [9]uint32
}
  • Major: 主版本号
  • Minor: 副版本号
  • Flags: 程序希望Fuse提供的功能
FUSE_OPENDIR = 27

opendir()函数,Open a directory

请求头后的实体
1
2
3
4
type FuseOpenIn struct {
Flags uint32
Unused uint32
}
响应头的实体
1
2
3
4
5
type FuseOpenOut struct {
Fh uint64
OpenFlags uint32
Padding uint32
}
FUSE_READDIR = 28

readdir()函数,Read directory

请求头后的实体
1
2
3
4
5
6
7
8
9
type FuseReadIn struct {
Fh uint64
Offset uint64
Size uint32
ReadFlags uint32
LockOwner uint64
Flags uint32
Padding uint32
}
  • Offset: 开始的偏移量
  • Size: 内核所能接收的字节数大小
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
type FuseReadOut struct {
Content []byte
}

type FuseDirent struct {
Ino uint64
Off uint64
NameLen uint32
DirType uint32
Name string
}

读取目录比较特殊,读取目录是返回有目录中哪些文件的,FuseReadOut中是多个FuseDirent的二进制格式。

并且FuseReadOut的大小不能超过,FuseReadIn中Size的大小。

同时,每个FuseDirent的二进制字节数,必须要凑齐为8的倍数,比如某个FuseDirent的字节数是30,必须在其后加上"\0\0"以凑齐32。

FUSE_RELEASEDIR = 29

releasedir()函数,Release an open directory

请求头后的实体
1
2
3
4
5
6
type FuseReleaseIn struct {
Fh uint64
Flags uint32
ReleaseFlags uint32
LockOwner uint64
}
响应头的实体

releasedir只需响应头返回成功与否

FUSE_FSYNCDIR = 30

fsyncdir()函数,Synchronize directory contents

请求头后的实体
1
2
3
4
5
type FuseFsyncIn struct {
Fh uint64
FsyncFlags uint32
Padding uint32
}
响应头的实体

fsyncdir只需响应头返回成功与否

FUSE_GETLK = 31

getlk()函数,Test for a POSIX file lock

请求头后的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type FuseLkIn struct {
Fh uint64
Owner uint64
Lk FuseFileLock
LkFlags uint32
Padding uint32
}

type FuseFileLock struct {
Start uint64
End uint64
Type uint32
Pid uint32 /* tgid */
}
响应头的实体
1
2
3
4
5
6
type FuseFileLock struct {
Start uint64
End uint64
Type uint32
Pid uint32 /* tgid */
}
FUSE_SETLK = 32

setlk()函数,Acquire, modify or release a POSIX file lock

请求头后的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type FuseLkIn struct {
Fh uint64
Owner uint64
Lk FuseFileLock
LkFlags uint32
Padding uint32
}

type FuseFileLock struct {
Start uint64
End uint64
Type uint32
Pid uint32 /* tgid */
}
响应头的实体
1
2
3
4
5
6
type FuseFileLock struct {
Start uint64
End uint64
Type uint32
Pid uint32 /* tgid */
}
FUSE_SETLKW = 33

setlk()相同

FUSE_ACCESS = 34

access()函数,Check file access permissions

请求头后的实体
1
2
3
4
type FuseAccessIn struct {
Mask uint32
Padding uint32
}
响应头的实体

access只需响应头返回成功与否

FUSE_CREATE = 35

create()函数,Create and open a file

请求头后的实体
1
2
3
4
5
6
7
8
type FuseCreateIn struct {
Flags uint32
Mode uint32
Umask uint32
Padding uint32

Name string
}
  • Mode: 文件类型以及权限模式
  • Name: 文件名
响应头的实体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
type FuseCreateOut struct {
Entry FuseEntryOut
Open FuseOpenOut
}

type FuseEntryOut struct {
NodeId uint64 /* Inode ID */
Generation uint64 /* Inode generation: nodeid:gen must be unique for the fs's lifetime */
EntryValid uint64 /* Cache timeout for the name */
AttrValid uint64 /* Cache timeout for the attributes */
EntryValidNsec uint32
AttrValidNsec uint32

Attr FuseAttr
}

type FuseAttr struct {
Ino uint64
Size uint64
Blocks uint64
Atime uint64
Mtime uint64
Ctime uint64
AtimeNsec uint32
MtimeNsec uint32
CtimeNsec uint32
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Blksize uint32
Padding uint32
}

type FuseOpenOut struct {
Fh uint64
OpenFlags uint32
Padding uint32
}

create的响应实体FuseCreateOut需要有FuseEntryOutFuseOpenOut的结构

FUSE_INTERRUPT = 36

程序中断接收到的请求

请求头后的实体
1
2
3
struct FuseInterruptIn {
uint64_t unique;
};
FUSE_BMAP = 37

bmap()函数,Map block index within file to block index within device

请求头后的实体
1
2
3
4
5
type FuseBmapIn struct {
Block uint64
BlockSize uint32
Padding uint32
}
响应头的实体
1
2
3
type FuseBmapOut struct {
Block uint64
}
FUSE_DESTROY = 38

destory()函数,Clean up filesystem.

没有请求实体,不需要返回响应。

FUSE_IOCTL = 39

ioctl()函数

请求头后的实体
1
2
3
4
5
6
7
8
9
10
type FuseIoctlIn struct {
Fh uint64
Flags uint32
Cmd uint32
Arg uint64
InSize uint32
OutSize uint32

InBuf []byte
}
响应头的实体
1
2
3
4
5
6
type FuseIoctlOut struct {
Result int32
Flags uint32
InIovs uint32
OutIovs uint32
}
FUSE_POLL = 40

poll()函数,Poll for IO readiness

请求头后的实体
1
2
3
4
5
6
type FusePollIn struct {
Fh uint64
Kh uint64
Flags uint32
Events uint32
}
响应头的实体
1
2
3
4
type FusePollOut struct {
Revents uint32
Padding uint32
}
FUSE_BATCH_FORGET = 42

forget_multi()函数,Forget about multiple inodes

不需要响应

请求头后的实体
1
2
3
4
5
6
7
8
9
10
11
type FuseBatchForgetIn struct {
Count uint32
Dummy uint32

NodeList []FuseForgetOne
}

type FuseForgetOne struct {
Nodeid uint64
Nlookup uint64
}
FUSE_FALLOCATE = 43

fallocate()函数,Allocate requested space.

请求头后的实体
1
2
3
4
5
6
7
type FuseFallocateIn struct {
Fh uint64
Offset uint64
Length uint64
Mode uint32
Padding uint32
}
响应头的实体

fallocate只需响应头返回成功与否

FUSE_READDIRPLUS = 44

readdirplus()函数,Read directory with attributes

请求头后的实体
1
2
3
4
5
6
7
8
9
type FuseReadIn struct {
Fh uint64
Offset uint64
Size uint32
ReadFlags uint32
LockOwner uint64
Flags uint32
Padding uint32
}
响应头的实体
1
2
3
type FuseReadOut struct {
Content []byte
}
FUSE_RENAME2 = 45

参考rename但请求略有不同

请求头后的实体
1
2
3
4
5
6
7
8
type FuseRename2In struct {
NewDir uint64
Flags uint32
Padding uint32

OldName string
NewName string
}
响应头的实体

rename只需响应头返回成功与否