sys/vfs/hammer2: Add initial multi-volumes support for HAMMER2
commit0b7381572b131c74051832dc251604e7f77b5a54
authorTomohiro Kusumi <tkusumi@netbsd.org>
Fri, 25 Dec 2020 16:36:00 +0000 (26 01:36 +0900)
committerTomohiro Kusumi <tkusumi@netbsd.org>
Sat, 26 Dec 2020 09:04:02 +0000 (26 18:04 +0900)
tree4d51061fc2ca8ac1bd0c68f810b34e2c64e07a1c
parentbfb67b1bd1a4401995b5b7b592ef8628019b9113
sys/vfs/hammer2: Add initial multi-volumes support for HAMMER2

This commit adds initial multi-volumes support for HAMMER2. Maximum
supported volumes is 64. The feature and implementation is similar to
multi-volumes support in HAMMER1.

1. ondisk changes
=================
This commit bumps volume header version from 1 to 2, and adds four new
volume header fields using reserved fields in version 1. Other ondisk
structures are unchanged.
* "volu_id" - volume id from 0 to 63, where 0 represents root volume.
* "nvolumes" - number of volumes. All volumes have same the same value.
* "total_size" - sum of "volu_size" in volumes. All volumes have the
  same value.
* "volu_loff[HAMMER2_MAX_VOLUMES]" - A 512 bytes table which contains
  start offset of max 64 volumes within "total_size". All volumes have
  the same value.

Version 1 volume header has 0 for above fields, so HAMMER2 internally
treats "nvolumes" as 1, and "total_size" as "volu_size" to be able to
handle version 1 and 2 transparently.

All volumes have 4 headers, but only root volume ones are relevant.
Non-root volume headers have their own unique "volu_id" and "volu_size",
but other fields are unimportant and never used. Non-root volume headers
have sroot blockset[i] whose type is HAMMER2_BREF_TYPE_INVALID. Non-root
volume headers don't have boot/aux area, so freemap area start from
offset 0. Non-root volume headers are readonly and never updated after
creation. This means non-root volumes are just extra storage to extend
fs size and internally make up a single virtual volume whose size is
"total_size".

It currently doesn't automatically upgrade an existing version 1 fs to
version 2. Only newly created fs becomes version 2 for now.

2. volumes layout
=================
Basically similar to HAMMER1. A first block device argument provided for
newfs_hammer2(8) becomes the root volume, and if specified remaining
devices extend "total_size" as non-root volumes. All volumes except for
the last one have 1GiB (freemap level1) aligned "volu_size".

This means each volume's start offset within "total_size" is also 1GiB
(freemap level1) aligned. The start offsets of volumes are stored in
volu_loff[HAMMER2_MAX_VOLUMES]. Each volu_loff[n] (0 <= n < nvolumes)
represents start offset of volume n within "total_size". Unused volumes
have -1 for volu_loff[n].
e.g. If a fs consists of 1 volume, volu_loff[0] has 0 and rests have -1.
e.g. If a fs consists of 3 volumes, x GiB root volume, y GiB volume,
  and z GiB volume, volu_loff[0] has 0, volu_loff[1] has x, volu_loff[2]
  has x+y, and rests have -1.

Low level I/O function in HAMMER2 uses this linear offsets table to
determine a device vnode to use and relative offset within the device
vnode, for a given blockref's "data_off". This is different from HAMMER1
where logical offset had embedded volume id bits (i.e. there were holes
in logical address space). HAMMER2 needs this table to support multi-
volumes without changing current logical offset mechanism.

Unless all volumes are specified and mountable, mount_hammer2(8) fails
like it failed in HAMMER1. This also applies to other userspace commands
which require volumes specification, except for fstyp(8).

3. userspace commands
=====================
Basically same as or similar to HAMMER1.
* newfs_hammer2(8) takes a list of block device paths as argv[].
* mount_hammer2(8) takes block device paths or names in "a:b:c:..."
  format.
* hammer2(8) takes block device paths or names in "a:b:c:..." format for
  directives which require volumes specification. This commit also adds
  "volume-list" directive and an ioctl command HAMMER2IOC_VOLUME_LIST,
  which are similar to the one in HAMMER1.
* fsck_hammer2(8) takes device paths or names in "a:b:c:..." format.
* fstyp(8) takes device paths in "path1:path2:path3:..." format.

4. limitations
==============
* hammer2(8) "info" directive ignores multi-volumes block devices.
* hammer2(8) "growfs" directive doesn't support multi-volumes fs.
* fstyp(8) is unable to find PFS label via -l option if the PFS inode or
  its parent indirect blocks are located beyond root volume.
* hammer2(8) doesn't support "volume-add" and "volume-del" directives
  which existed in HAMMER1, and there is currently no plan to support.
34 files changed:
sbin/fsck_hammer2/Makefile
sbin/fsck_hammer2/destroy.c
sbin/fsck_hammer2/reconstruct.c
sbin/fsck_hammer2/test.c
sbin/hammer2/Makefile
sbin/hammer2/cmd_debug.c
sbin/hammer2/cmd_info.c
sbin/hammer2/cmd_volume.c [copied from sbin/hammer2/hammer2_subs.h with 50% similarity]
sbin/hammer2/hammer2.8
sbin/hammer2/hammer2.h
sbin/hammer2/hammer2_subs.h
sbin/hammer2/main.c
sbin/hammer2/ondisk.c [new file with mode: 0644]
sbin/hammer2/subs.c
sbin/mount_hammer2/mount_hammer2.c
sbin/newfs_hammer2/Makefile
sbin/newfs_hammer2/newfs_hammer2.8
sbin/newfs_hammer2/newfs_hammer2.c
sys/conf/files
sys/vfs/hammer2/Makefile
sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_bulkfree.c
sys/vfs/hammer2/hammer2_disk.h
sys/vfs/hammer2/hammer2_flush.c
sys/vfs/hammer2/hammer2_freemap.c
sys/vfs/hammer2/hammer2_io.c
sys/vfs/hammer2/hammer2_ioctl.c
sys/vfs/hammer2/hammer2_ioctl.h
sys/vfs/hammer2/hammer2_ondisk.c [new file with mode: 0644]
sys/vfs/hammer2/hammer2_subr.c
sys/vfs/hammer2/hammer2_vfsops.c
usr.sbin/fstyp/fstyp.c
usr.sbin/fstyp/fstyp.h
usr.sbin/fstyp/hammer2.c