btrfs: stripe_alloc: control the policy with a filesystem property
A mount option is an awkward fit for write-hole protection: it occupies
a mount-option bit, and protection silently lapses whenever the option
is forgotten -- an fstab edit, a rescue mount, a recovery boot -- which
is exactly when a degraded raid56 is most likely to be written.
Control the policy with a "stripe_alloc" filesystem property instead,
following the property system's compression precedent: a btrfs.
namespace xattr, user-visible and admin-controlled, on the top-level
subvolume's root directory. Set it once (setfattr -n btrfs.stripe_alloc
-v 1, or btrfs property once btrfs-progs learns the name) and it is
persistent: the kernel applies it when the root directory inode loads
its properties during mount, before any user IO. Deleting the xattr
disables the policy; open runs drain at the next commit's retirement,
which runs unconditionally. Stray copies of the xattr -- a received or
cloned subvolume -- are ignored: only the top-level root carries the
policy, so receiving a stream from a stripe_alloc filesystem cannot
flip the policy on the destination.
The support checks (free space tree, not zoned, no remap-tree, not
mixed block groups) are enforced both when the property is set and when
it is applied at mount. The mixed block group test matters most here.
btrfs_check_mountopts() refuses mixed for the mount option, and without
the same test this would be a second way in that skips it -- enabling a
policy the series does not support there, after the block group read
that would have warned about uncovered metadata has already run, so the
user is told the filesystem is protected and it is not.
This stays within the series' no-on-disk-format-change constraint, and
that is the compatibility story: an older kernel mounts the filesystem
read-write and simply uses the legacy allocator, which is fully
compatible because the on-disk layout is unchanged. New kernels honor
the property during the feature's long-tail testing period; if no use
case surfaces where stripe-exclusive allocation is worse than the write
hole it protects against, it can eventually become the only allocation
mode and the property a no-op.
Known old-kernel interactions with the btrfs. namespace: existing
kernels list and read the xattr (the btrfs. get path is a plain xattr
read) but refuse to set or remove unknown property names, so the flag
can only be managed from a kernel that knows it. btrfs-progs
interaction (check, property list) with an unrecognized property is a
userspace compatibility item to verify and, if needed, patch.
The mount option is kept for now as a non-persistent override. Later
protection stages with different risk profiles (the log-tree
full-stripe relocation) should be gated by their own property rather
than widening this one, so their testing exposure can be controlled
independently.
Assisted-by: Claude:claude-fable-5
(cherry picked from commit
ecd4d3de8a0493f7c406d919d533f88e8b45390c)