mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-27 04:32:16 +03:00
libzfs: use mount_setattr for selective remount including legacy mounts
When a namespace property is changed via zfs set, libzfs remounts the filesystem to propagate the new VFS mount flags. The current approach uses mount(2) with MS_REMOUNT, which reads all namespace properties from ZFS and applies them together. This has two problems: 1. Linux VFS resets unspecified per-mount flags on remount. If an administrator sets a temporary flag (e.g. mount -o remount,noatime), a subsequent zfs set on any namespace property clobbers it. 2. Two concurrent zfs set operations on different namespace properties can overwrite each other's mount flags. Additionally, legacy datasets (mountpoint=legacy) were never remounted on namespace property changes since zfs_is_mountable() returns false for them. Add zfs_mount_setattr() which uses mount_setattr(2) to selectively update only the mount flags that correspond to the changed property. For legacy datasets, /proc/mounts is iterated to update all mountpoints. On kernels without mount_setattr (ENOSYS), non-legacy datasets fall back to a full remount; legacy mounts are skipped to avoid clobbering temporary flags. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Signed-off-by: Ameer Hamza <ahamza@ixsystems.com> Closes #18257
This commit is contained in:
@@ -103,6 +103,47 @@ zfs_share_protocol_name(enum sa_protocol protocol)
|
||||
return (sa_protocol_names[protocol]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns B_TRUE if the property is a namespace property that requires
|
||||
* a remount to take effect.
|
||||
*/
|
||||
boolean_t
|
||||
zfs_is_namespace_prop(zfs_prop_t prop)
|
||||
{
|
||||
switch (prop) {
|
||||
case ZFS_PROP_ATIME:
|
||||
case ZFS_PROP_RELATIME:
|
||||
case ZFS_PROP_DEVICES:
|
||||
case ZFS_PROP_EXEC:
|
||||
case ZFS_PROP_SETUID:
|
||||
case ZFS_PROP_READONLY:
|
||||
case ZFS_PROP_XATTR:
|
||||
case ZFS_PROP_NBMAND:
|
||||
return (B_TRUE);
|
||||
default:
|
||||
return (B_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the ZFS_MNT_PROP_* flag for a namespace property.
|
||||
*/
|
||||
uint32_t
|
||||
zfs_namespace_prop_flag(zfs_prop_t prop)
|
||||
{
|
||||
switch (prop) {
|
||||
case ZFS_PROP_ATIME: return (ZFS_MNT_PROP_ATIME);
|
||||
case ZFS_PROP_RELATIME: return (ZFS_MNT_PROP_RELATIME);
|
||||
case ZFS_PROP_DEVICES: return (ZFS_MNT_PROP_DEVICES);
|
||||
case ZFS_PROP_EXEC: return (ZFS_MNT_PROP_EXEC);
|
||||
case ZFS_PROP_SETUID: return (ZFS_MNT_PROP_SETUID);
|
||||
case ZFS_PROP_READONLY: return (ZFS_MNT_PROP_READONLY);
|
||||
case ZFS_PROP_XATTR: return (ZFS_MNT_PROP_XATTR);
|
||||
case ZFS_PROP_NBMAND: return (ZFS_MNT_PROP_NBMAND);
|
||||
default: return (0);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
dir_is_empty_stat(const char *dirname)
|
||||
{
|
||||
@@ -225,7 +266,7 @@ zfs_is_mounted(zfs_handle_t *zhp, char **where)
|
||||
* that the caller has verified the sanity of mounting the dataset at
|
||||
* its mountpoint to the extent the caller wants.
|
||||
*/
|
||||
static boolean_t
|
||||
boolean_t
|
||||
zfs_is_mountable_internal(zfs_handle_t *zhp)
|
||||
{
|
||||
if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
|
||||
|
||||
Reference in New Issue
Block a user