mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 02:48:59 -04:00
237 lines
8.3 KiB
Markdown
237 lines
8.3 KiB
Markdown
# branches
|
|
|
|
The `branches` argument is a colon (':') delimited list of paths to be
|
|
pooled together. It does not matter if the paths are on the same or
|
|
different filesystems nor does it matter [the filesystem
|
|
type](../faq/compatibility_and_integration.md/#what-filesystems-can-be-used-as-branches)
|
|
(within reason). Used and available space metrics will not be
|
|
duplicated for paths on the same filesystem and any features which
|
|
aren't supported by the underlying filesystem (such as file attributes
|
|
or extended attributes) will return the appropriate errors.
|
|
|
|
Branches currently have two options which can be set. A
|
|
[mode](#branch-mode) which impacts whether or not the branch is
|
|
included in a policy calculation and a individual
|
|
[minfreespace](#minfreespace) value. The values are set by
|
|
prepending an `=` at the end of a branch designation and using commas
|
|
as delimiters. Example: `/mnt/hdd/disk0=RW,1234`
|
|
|
|
|
|
### branch mode
|
|
|
|
- RW: (read/write) - Default behavior. Will be eligible in all policy
|
|
categories.
|
|
- RO: (read-only) - Will be excluded from `create` and `action`
|
|
policies. Same as a read-only mounted filesystem would be (though
|
|
faster to process).
|
|
- NC: (no-create) - Will be excluded from `create` policies. You can't
|
|
create on that branch but you can change or delete.
|
|
|
|
|
|
### minfreespace
|
|
|
|
Same purpose and syntax as the [global option](minfreespace.md) but
|
|
specific to the branch. Defaults to the global value.
|
|
|
|
|
|
### resolution
|
|
|
|
Each colon-delimited branch designation is resolved independently when
|
|
the `branches` option is parsed, both at startup and when it is updated
|
|
through the runtime API:
|
|
|
|
1. The path portion is expanded as a glob.
|
|
2. If the glob matches one or more directories, each match becomes a
|
|
branch.
|
|
3. If the glob has no matches, mergerfs logs a notice and keeps the
|
|
configured path unchanged as a single, literal branch.
|
|
4. mergerfs resolves each resulting path with `realpath`. If that
|
|
succeeds, the canonical path is stored. If it fails, typically
|
|
because the path does not exist yet, the unchanged path is stored.
|
|
5. A path which exists but is not a directory is logged and skipped. A
|
|
path which does not exist is logged but retained.
|
|
|
|
Consequently, a literal branch such as `/mnt/hdd/disk0/foobar` may be
|
|
configured before it exists and can become usable after
|
|
`/mnt/hdd/disk0` is mounted. Branch resolution is not repeated in the
|
|
background, however. If `/mnt/hdd/disk0/*` has no matches when it is
|
|
resolved, mergerfs stores the literal path `/mnt/hdd/disk0/*`;
|
|
directories which match it later are not discovered automatically.
|
|
Update `branches` through the runtime API or restart mergerfs to
|
|
resolve the glob again.
|
|
|
|
|
|
### globbing
|
|
|
|
To make it easier to include multiple branches mergerfs supports
|
|
[globbing](http://linux.die.net/man/7/glob). **The globbing tokens
|
|
MUST be escaped when using via the shell else the shell itself will
|
|
apply the glob itself.**
|
|
|
|
```
|
|
# mergerfs /mnt/hdd/\*:/mnt/ssd/\* /media
|
|
```
|
|
|
|
The above line will use all directories within `/mnt/hdd` and
|
|
`/mnt/ssd`.
|
|
|
|
To have the pool mounted at boot or otherwise accessible from related
|
|
tools use `/etc/fstab`.
|
|
|
|
```
|
|
# <file system> <mount point> <type> <options> <dump> <pass>
|
|
/mnt/hdd/*:/mnt/ssd/* /media mergerfs minfreespace=16G 0 0
|
|
```
|
|
|
|
**NOTE:** The globbing is done at mount or when updated using the
|
|
runtime API. If a new directory is added matching the glob after the
|
|
fact it will not be automatically included.
|
|
|
|
A convenient way to configure branches is to use
|
|
[symlinks](../quickstart.md/#etcfstab-w-config-file).
|
|
|
|
|
|
## branch setup
|
|
|
|
`mergerfs` does **not** require any special setup of branch paths in
|
|
order to be used however here are some suggestions.
|
|
|
|
|
|
### layout
|
|
|
|
When you have a large collection of storage devices, types of storage,
|
|
and types of interconnects it can be useful to have a verbose naming
|
|
convention. My preference is to create a directory within `/mnt/` for
|
|
each major type of storage device and/or interconnect. `hdd` for
|
|
traditional hard drives; `ssd` for slower SATA based SSDs; `nvme` for
|
|
M.2 or U.2 NVME SSDs; `remote` for NFS, SMB, sshfs, etc.
|
|
|
|
The mount points within those directories are named after the size of
|
|
the storage and its serial number in the case of physical storage and
|
|
the hostname and remote filesystem for remote.
|
|
|
|
```
|
|
$ ls -lh /mnt/
|
|
total 16K
|
|
drwxr-xr-x 8 root root 4.0K Aug 18 2024 hdd
|
|
drwxr-xr-x 6 root root 4.0K Oct 8 2024 nvme
|
|
drwxr-xr-x 3 root root 4.0K Aug 24 2024 remote
|
|
drwxr-xr-x 3 root root 4.0K Jul 14 2024 ssd
|
|
|
|
$ ls -lh /mnt/hdd/
|
|
total 8K
|
|
d--------- 2 root root 4.0K Apr 14 15:58 10T-01234567
|
|
d--------- 2 root root 4.0K Apr 12 20:51 20T-12345678
|
|
|
|
$ ls -lh /mnt/nvme/
|
|
total 8K
|
|
d--------- 2 root root 4.0K Apr 14 16:00 1T-ABCDEFGH
|
|
d--------- 2 root root 4.0K Apr 14 23:24 1T-BCDEFGHI
|
|
|
|
$ ls -lh /mnt/remote/
|
|
total 8K
|
|
d--------- 2 root root 4.0K Apr 12 20:23 foo-sshfs
|
|
d--------- 2 root root 4.0K Apr 12 20:24 bar-nfs
|
|
|
|
# You can find the serial number of a drive using lsblk
|
|
$ lsblk -d -o NAME,PATH,SIZE,SERIAL
|
|
NAME PATH SIZE SERIAL
|
|
sda /dev/sda 9.1T 01234567
|
|
sdb /dev/sdb 18.2T 12345678
|
|
nvme0n1 /dev/nvme0n1 953.9G ABCDEFGH
|
|
nvme1n1 /dev/nvme1n1 953.9G BCDEFGHI
|
|
```
|
|
|
|
|
|
### permissions and mode
|
|
|
|
#### mount points
|
|
|
|
To ensure the directory is **only** used as a point to mount another
|
|
filesystem it is good to lock it down as much as possible. Be sure to
|
|
do this **before** mounting a filesystem to it.
|
|
|
|
```
|
|
$ sudo chown root:root /mnt/hdd/10T-XYZ
|
|
$ sudo chmod 0000 /mnt/hdd/10T-XYZ
|
|
$ sudo setfattr -n user.mergerfs.branch_mounts_here
|
|
$ sudo chattr +i /mnt/hdd/10T-XYZ
|
|
```
|
|
|
|
The extended attribute `user.mergerfs.branch_mounts_here` is used by
|
|
the [branches-mount-timeout](branches-mount-timeout.md) option to
|
|
recognize whether or not a mergerfs branch path points to the intended
|
|
filesystem.
|
|
|
|
The `chattr` is likely to only work on EXT{2,3,4} filesystems but will
|
|
restrict even `root` from modifying the directory or its content but
|
|
is still able to be a mount point.
|
|
|
|
|
|
#### mounted filesystems
|
|
|
|
For those new to Linux, intending to be the primary individual logged
|
|
into the system, or simply want to simplify permissions it is
|
|
recommended to set the root of mounted filesystems like `/tmp/` is set
|
|
to. Owned by `root`, `ugo+rwx` and [sticky
|
|
bit](https://en.wikipedia.org/wiki/Sticky_bit) set.
|
|
|
|
This must be done **after** mounting the filesystem to the target
|
|
mount point.
|
|
|
|
```
|
|
$ sudo chown root:root /mnt/hdd/10T-SERIALNUM
|
|
$ sudo chmod 1777 /mnt/hdd/10T-SERIALNUM
|
|
$ sudo setfattr -n user.mergerfs.branch /mnt/hdd/10T-SERIALNUM
|
|
```
|
|
|
|
|
|
### formatting
|
|
|
|
While even less relevant to mergerfs than the details above the topic
|
|
does com up regularly with mergerfs users. When it comes to
|
|
partitioning and formatting it is suggested to keep things
|
|
simple. Most users of mergerfs will be using the whole drive capacity
|
|
and as such have a singular partition and filesystem on that
|
|
partition. Something many people don't realize is that the partition
|
|
is not necessary and actually can become problematic.
|
|
|
|
Rather than creating paritions just format the block device. Let's use
|
|
`/dev/sda` as an example.
|
|
|
|
```
|
|
$ lsblk -d -o NAME,PATH,SERIAL /dev/sda
|
|
NAME PATH SERIAL
|
|
sda /dev/sda 01234567
|
|
|
|
$ sudo mkfs.ext4 -m0 -L 01234567 /dev/sda
|
|
mke2fs 1.47.0 (5-Feb-2023)
|
|
Discarding device blocks: done
|
|
Creating filesystem with 262144 4k blocks and 65536 inodes
|
|
Filesystem UUID: ede8bf96-9aff-464e-a4fb-a4ab8a197cd7
|
|
Superblock backups stored on blocks:
|
|
32768, 98304, 163840, 229376
|
|
|
|
Allocating group tables: done
|
|
Writing inode tables: done
|
|
Creating journal (8192 blocks): done
|
|
Writing superblocks and filesystem accounting information: done
|
|
```
|
|
|
|
You can then use the serial number as the identifier in `fstab`.
|
|
|
|
```
|
|
# <file system> <mount point> <type> <options> <dump> <pass>
|
|
LABEL=01234567 /mnt/hdd/10TB-01234567 auto nofail 0 2
|
|
```
|
|
|
|
Benefits of doing it this way?
|
|
|
|
* One less thing (partitions) to configure and worry about.
|
|
* Guarantees alignment of blocks
|
|
* Makes it easier to use the drive with different enclosures. Some
|
|
SATA to USB adapters use 4K blocks while the drive itself is using
|
|
512b. If you create partitions with one block size and move the
|
|
drive to a controller that uses the other the offset on the device
|
|
where the filesystem starts will be misinterpreted. It is possible
|
|
to manually fix this but it isn't well documented and avoidable.
|