存储配额
JuiceFS 同时支持文件系统总配额和子目录配额,均可用于限制可用容量和可用 inode 数量。文件系统配额和目录配额均是硬限制,当文件系统总配额用尽时,后续写入会返回 ENOSPC(No space left)错误;而当目录配额用尽时,后续写入会返回 EDQUOT(Disk quota exceeded)错误。
存储限额设置会保存在元数据引擎中以供所有挂载点读取,每个挂载点的客户端也会缓存自己的已用容量和 inodes 数,周期性地向元数据引擎同步。与此同时,客户端也会周期性地从元数据引擎读取最新的用量值,从而实现用量信息在每个挂载点之间 同步,但这种信息同步机制并不能保证用量数据被精确统计,可能会存在十秒级延迟。
文件系统配额
JuiceFS v1.0 支持文件系统级别的存储配额。以 Linux 环境为例,使用系统自带的 df 命令可以看到,一个 JuiceFS 类型的文件系统默认的容量标识为 1.0P :
$ df -Th | grep juicefs
JuiceFS:ujfs fuse.juicefs 1.0P 682M 1.0P 1% /mnt
JuiceFS 通过 FUSE 实现对 POSIX 接口的支持,因为底层通常是容量能够无限扩展的对象存储,所以标识容量只是一个估值(也代表无限制)并非实际容量,它会随着实际用量动态变化。
通过客户端自带的 config 命令可以查看一个文件系统的详细信息:
$ juicefs config $METAURL
{
"Name": "ujfs",
"UUID": "1aa6d290-279b-432f-b9b5-9d7fd597dec2",
"Storage": "minio",
"Bucket": "127.0.0.1:9000/jfs1",
"AccessKey": "herald",
"SecretKey": "removed",
"BlockSize": 4096,
"Compression": "none",
"Shards": 0,
"Partitions": 0,
"Capacity": 0,
"Inodes": 0,
"TrashDays": 0
}
限制总容量
可以在创建文件系统时通过 --capacity 设置容量限额,单位 GiB,例如创建一个可用容量为 100 GiB 文件系统的:
juicefs format --storage minio \
--bucket 127.0.0.1:9000/jfs1 \
... \
--capacity 100 \
$METAURL myjfs
也可以通过 config 命令,为一个已创建的文件系统设置容量限额:
$ juicefs config $METAURL --capacity 100
2022/01/27 12:31:39.506322 juicefs[16259] <INFO>: Meta address: postgres://herald@127.0.0.1:5432/jfs1
2022/01/27 12:31:39.521232 juicefs[16259] <WARNING>: The latency to database is too high: 14.771783ms
capacity: 0 GiB -> 100 GiB
设置了存储限额的文件系统,标识容量会变成限制容量:
$ df -Th | grep juicefs
JuiceFS:ujfs fuse.juicefs 100G 682M 100G 1% /mnt
限制 inode 总量
在 Linux 系统中,每个文件(文件夹也是文件的一种)不论大小都有一个 inode,因此限制 inode 数量等同于限制文件数量。
可以在创建文件系统时通过 --inodes 设置限额,例如:
juicefs format --storage minio \
--bucket 127.0.0.1:9000/jfs1 \
... \
--inodes 100 \
$METAURL myjfs
以上命令创建的文件系统仅允许存储 100 个文件,但不限制单个文件的大小,比如单个文件 1TB 甚至更大也没有问题,只要文件总数不超过 100 个即可。
也可以通过 config 命令,为一个已创建的文件系统设置容量限额:
$ juicefs config $METAURL --inodes 100
2022/01/27 12:35:37.311465 juicefs[16407] <INFO>: Meta address: postgres://herald@127.0.0.1:5432/jfs1
2022/01/27 12:35:37.322991 juicefs[16407] <WARNING>: The latency to database is too high: 11.413961ms
inodes: 0 -> 100
组合使用
你可以结合 --capacity 和 --inodes 更灵活的设置文件系统的容量限额,比如,创建一个文件系统,限制总容量为 100TiB 且仅允许存储 100000 文件:
juicefs format --storage minio \
--bucket 127.0.0.1:9000/jfs1 \
... \
--capacity 102400 \
--inodes 100000 \
$METAURL myjfs
同样地,对于已创建的文件系统,可分别进行设置:
juicefs config $METAURL --capacity 102400
juicefs config $METAURL --inodes 100000
客户端会定期从元数据引擎读取最新的文件系统存储限额设置来更新本地的设置。刷新间隔由 --heartbeat 参数控制(默认值:12 秒)。其他挂载点可能需要等待最多一个 heartbeat 间隔时间才能完成限额设置的更新。
目录配额
JuiceFS v1.1 开始支持目录级别的存储配额,可以使用 juicefs quota 子命令进行目录配额管理和查询。
由于用量统计需要挂载客户端支持,请确保除所有可写入客户端已升级到 v1.1.0 以上版本再使用此特性。
限制目录容量
可以使用 juicefs quota set $METAURL --path $DIR --capacity $N 设置目录容量限额,单位 GiB。例如给目录/test设置 1GiB 的容量配额:
$ juicefs quota set $METAURL --path /test --capacity 1
+-------+---------+---------+------+-----------+-------+-------+
| Path | Size | Used | Use% | Inodes | IUsed | IUse% |
+-------+---------+---------+------+-----------+-------+-------+
| /test | 1.0 GiB | 1.6 MiB | 0% | unlimited | 314 | |
+-------+---------+---------+------+-----------+-------+-------+
设置成功后你可以看到有一个表格描述当前设置配额的目录、配额大小、当前用量等信息。
quota 子命令的使用无需本地挂载点,期望输入的目录路径为相对 JuiceFS 根目录的路径而非本地挂载路径。给大目录设置配额可能需要等待较长时间,因为需要计算目录当前用量。
如果需要查询某个目录的配额和当前用量,可以使用 juicefs quota get $METAURL --path $DIR 命令:
$ juicefs quota get $METAURL --path /test
+-------+---------+---------+------+-----------+-------+-------+
| Path | Size | Used | Use% | Inodes | IUsed | IUse% |
+-------+---------+---------+------+-----------+-------+-------+
| /test | 1.0 GiB | 1.6 MiB | 0% | unlimited | 314 | |
+-------+---------+---------+------+-----------+-------+-------+
也可以使用 juicefs quota ls $METAURL 命令列出所有的目录配额。
限制目录的 inode 总量
可以使用 juicefs quota set $METAURL --path $DIR --inodes $N 设置目录 inode 限额,单位为个。例如给目录/test设置 400 个 inode 的配额:
$ juicefs quota set $METAURL --path /test --inodes 400
+-------+---------+---------+------+--------+-------+-------+
| Path | Size | Used | Use% | Inodes | IUsed | IUse% |
+-------+---------+---------+------+--------+-------+-------+
| /test | 1.0 GiB | 1.6 MiB | 0% | 400 | 314 | 78% |
+-------+---------+---------+------+--------+-------+-------+
组合使用
可以结合 --capacity 和 --inodes 更灵活地设置目录的容量限额。比如,给/test目录设置 10GiB 和 1000 个 inode 的配额:
$ juicefs quota set $METAURL --path /test --capacity 10 --inodes 1000
+-------+--------+---------+------+--------+-------+-------+
| Path | Size | Used | Use% | Inodes | IUsed | IUse% |
+-------+--------+---------+------+--------+-------+-------+
| /test | 10 GiB | 1.6 MiB | 0% | 1,000 | 314 | 31% |
+-------+--------+---------+------+--------+-------+-------+
另外,你也可以不限制目录的容量和 inode 数(设为 0 表示不限制),只通过 quota 命令统计目录的当前用量:
$ juicefs quota set $METAURL --path /test --capacity 0 --inodes 0
+-------+-----------+---------+------+-----------+-------+-------+
| Path | Size | Used | Use% | Inodes | IUsed | IUse% |
+-------+-----------+---------+------+-----------+-------+-------+
| /test | unlimited | 1.6 MiB | | unlimited | 314 | |
+-------+-----------+---------+------+-----------+-------+-------+
配额嵌套
JuiceFS 允许自由地设置各级目录配额,实际使用的时候会递归地向上查询,确保当前目录用量满足每一级目录的配额设置。也就是说,就算父目录设置了一个较小的配额,也不影响子目录可以设置更大配额。
子目录挂载
JuiceFS 支持使用 --subdir 挂载任意子目录。如果挂载的子目录设置了目录配额,则可以使用系统自带的 df 命令查看目录配额和当前使用量。比如文件系统配额为 1PiB 和 10M 个 inode,而 /test 目录的配额为 1GiB 和 400 个 inode。使用根目录挂载时 df 命令的输出为:
$ df -h
Filesystem Size Used Avail Use% Mounted on
...
JuiceFS:myjfs 1.0P 1.6M 1.0P 1% /mnt/jfs
$ df -i -h
Filesystem Inodes IUsed IFree IUse% Mounted on
...
JuiceFS:myjfs 11M 315 10M 1% /mnt/jfs
而使用 /test 子目录挂载时,df 命令的输出为:
$ df -h
Filesystem Size Used Avail Use% Mounted on
...
JuiceFS:myjfs 1.0G 1.6M 1023M 1% /mnt/jfs
$ df -i -h
Filesystem Inodes IUsed IFree IUse% Mounted on
...
JuiceFS:myjfs 400 314 86 79% /mnt/jfs
当挂载的子目录没有设置配额,JuiceFS 会逐级往上查询直到找到最近的目录配额再返回给 df。如果有多级父目录均设置目录配额,JuiceFS 会在计算后返回最小的可用容量和 inode 数量。
用户与组配额
除了目录配额,JuiceFS 还支持按 UID(用户)和 GID(组)设置存储配额。用户配额和组配额同样是硬限制,超限写入会返回 EDQUOT(Disk quota exceeded)错误。
与目录配额不同,用户/组配额不依赖目录层级,而是按文件和目录的属主信息(UID/GID)统计和限制。
用户/组配额是基于 UID/GID 的数字 ID 进行统计,不依赖用户名和组名。你可以使用 id 命令查看具体 UID/GID。
设置用户配额
可以通过 --uid 指定用户,为其设置容量和 inode 配额。例如将 UID 为 1000 的用户限制为 2 GiB 和 200 个 inode:
$ juicefs quota set $METAURL --uid 1000 --capacity 2 --inodes 200
+---------+---------+---------+------+--------+-------+-------+
| User ID | Size | Used | Use% | Inodes | IUsed | IUse% |
+---------+---------+---------+------+--------+-------+-------+
| 1000| 2.0 GiB | 1.6 MiB | 0% | 200 | 12 | 6% |
+---------+---------+---------+------+--------+-------+-------+
查询和删除用户配额:
juicefs quota get $METAURL --uid 1000
juicefs quota delete $METAURL --uid 1000
设置组配额
可以通过 --gid 指定组,为其设置容量和 inode 配额。例如将 GID 为 100 的组限制为 5 GiB 和 500 个 inode:
$ juicefs quota set $METAURL --gid 100 --capacity 5 --inodes 500
+----------+---------+---------+------+--------+-------+-------+
| Group ID | Size | Used | Use% | Inodes | IUsed | IUse% |
+----------+---------+---------+------+--------+-------+-------+
| 100 | 5.0 GiB | 3.2 MiB | 0% | 500 | 21 | 4% |
+----------+---------+---------+------+--------+-------+-------+
查询和删除组配额:
juicefs quota get $METAURL --gid 100
juicefs quota delete $METAURL --gid 100
列出所有配额
使用 juicefs quota list $METAURL 可以同时列出目录、用户和组的配额。输出中会通过 uid:<id> / gid:<id> 标识用户和组配额。
一致性检查与修复
和目录配额一样,用户/组配额也可能因为异常退出等原因出现用量偏差。可用 check 子命令检查并修复。
检查所有用户和组配额:
juicefs quota check $METAURL
仅检查某个用户或组:
juicefs quota check $METAURL --uid 1000
juicefs quota check $METAURL --gid 100
发现不一致后,使用 --repair 执行修复:
juicefs quota check $METAURL --repair
统计口径说明
用户/组配额统计以写入后对象的属主 UID/GID 为准,而不是以“发起操作的客户端账号”直接计费。
例如,在启用了 setgid 的目录下创建文件时,文件 GID 可能会继承父目录组,此时会消耗继承后的组配额。
用量检查与修复
由于目录用量的更新是滞后且异步的,在异常情况下可能会发生丢失(比如 客户端意外退出)。我们可以使用 juicefs quota check $METAURL --path $DIR 命令进行检查或修复:
$ juicefs quota check $METAURL --path /test
2023/05/23 15:40:12.704576 juicefs[1638846] <INFO>: quota of /test is consistent [base.go:839]
+-------+--------+---------+------+--------+-------+-------+
| Path | Size | Used | Use% | Inodes | IUsed | IUse% |
+-------+--------+---------+------+--------+-------+-------+
| /test | 10 GiB | 1.6 MiB | 0% | 1,000 | 314 | 31% |
+-------+--------+---------+------+--------+-------+-------+
目录用量正确时会输出当前的目录配额用量;失败时候则会输出错误日志:
$ juicefs quota check $METAURL --path /test
2023/05/23 15:48:17.494604 juicefs[1639997] <WARNING>: /test: quota(314, 4.0 KiB) != summary(314, 1.6 MiB) [base.go:843]
2023/05/23 15:48:17.494644 juicefs[1639997] <FATAL>: quota of /test is inconsistent, please repair it with --repair flag [main.go:31]
这时你可以使用 --repair 选项来修复目录用量:
$ juicefs quota check $METAURL --path /test --repair
2023/05/23 15:50:08.737086 juicefs[1640281] <WARNING>: /test: quota(314, 4.0 KiB) != summary(314, 1.6 MiB) [base.go:843]
2023/05/23 15:50:08.737123 juicefs[1640281] <INFO>: repairing... [base.go:852]
+-------+--------+---------+------+--------+-------+-------+
| Path | Size | Used | Use% | Inodes | IUsed | IUse% |
+-------+--------+---------+------+--------+-------+-------+
| /test | 10 GiB | 1.6 MiB | 0% | 1,000 | 314 | 31% |
+-------+--------+---------+------+--------+-------+-------+
用量统计口径梳理
下文统一梳理 JuiceFS 在三种用量统计维度下的计量口径:
- 全局用量:文件系统级总用量(文件系统配额使用量)。
- 目录用量:目录配额使用量(
juicefs quota --path ...、summary/info相关目录统计)。 - 用户/组用量:用户配额与组配额使用量(
--uid/--gid)。
核心差异
| 对象类型 | 全局用量 | 目录用量 | 用户/组用量 |
|---|---|---|---|
| 普通文件 | 按文件数据大小计入(按 4KiB 对齐) | 按目录树中的文件计入(按 4KiB 对齐) | 按文件属主 UID/GID 计入(按 4KiB 对齐) |
| 硬链接文件 | 同一 inode 只计一次,不因新增链接重复计费 | 每个目录项都会计入对应目录(同一 inode 在不同目录/同目录多链接可重复体现在目录用量) | 同一 inode 只计一次,不因新增链接重复计费 |
| 目录及其他文件 | 计入 inode;空间按元数据最小粒度(等效 4KiB) | 计入 inode;空间按元数据最小粒度(等效 4KiB) | 计入 inode;空间按元数据最小粒度(等效 4KiB) |
| 回收 站文件 | 移入回收站后仍计入;仅在回收站真正清理后释放 | 从原目录树移出后,不再计入原目录/祖先目录;回收站目录支持实时统计,暂不支持设置配额 | 移入回收站后仍计入原属主 UID/GID;仅在回收站真正清理后释放 |
详细说明
- 普通文件
普通文件在三类统计中都以文件长度为基础,按 4KiB 对齐计入空间,并计入 1 个 inode。
- 硬链接文件
硬链接的关键在于「是否按 inode 去重」:
- 全局用量与用户/组用量按 inode 去重:新建硬链接只增加目录项,不增加新的文件实体,因此不会重复增加这两类用量。
- 目录用量按目录树中的目录项累计:硬链接创建在某个目录下,会增加该目录(及其祖先目录)的目录用量。
- 目录及其他非普通文件
目录、符号链接及其他非普通文件主要消耗 inode,空间占用量默认为 4KiB。
- 回收站文件
开启回收站后,删除操作通常是“移动到回收站”而非立即物理删除:
- 对全局用量与用户/组用量:移动到回收站时不会立刻释放;只有回收站清理后才会下降。
- 对目录用量:对象从原目录树移出后,原目录配额用量会下降;回收站目录支持实时统计,暂不支持设置配额。


