mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-01-13 16:52:05 +03:00
Linux 6.17 compat: Fix broken projectquota on 6.17
We need to specifically use the FX_XFLAG_* macros in zpl_ioctl_*attr() codepaths, and the FS_*_FL macros in the zpl_ioctl_*flags() codepaths. The earlier code just assumes the FS_*_FL macros for both codepaths. The 6.17 kernel add a bitmask check in copy_fsxattr_from_user() that exposed this error via failing 'projectquota' ZTS tests. Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Tony Hutter <hutter2@llnl.gov> Closes #17884 Closes #17869
This commit is contained in:
parent
8e7a310860
commit
b8ee796945
@ -145,11 +145,11 @@ zfs_project_handle_one(const char *name, zfs_project_control_t *zpc)
|
||||
switch (zpc->zpc_op) {
|
||||
case ZFS_PROJECT_OP_LIST:
|
||||
(void) printf("%5u %c %s\n", fsx.fsx_projid,
|
||||
(fsx.fsx_xflags & ZFS_PROJINHERIT_FL) ? 'P' : '-', name);
|
||||
(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT) ? 'P' : '-', name);
|
||||
goto out;
|
||||
case ZFS_PROJECT_OP_CHECK:
|
||||
if (fsx.fsx_projid == zpc->zpc_expected_projid &&
|
||||
fsx.fsx_xflags & ZFS_PROJINHERIT_FL)
|
||||
fsx.fsx_xflags & FS_XFLAG_PROJINHERIT)
|
||||
goto out;
|
||||
|
||||
if (!zpc->zpc_newline) {
|
||||
@ -164,29 +164,30 @@ zfs_project_handle_one(const char *name, zfs_project_control_t *zpc)
|
||||
"(%u/%u)\n", name, fsx.fsx_projid,
|
||||
(uint32_t)zpc->zpc_expected_projid);
|
||||
|
||||
if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
|
||||
if (!(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT))
|
||||
(void) printf("%s - project inherit flag is not set\n",
|
||||
name);
|
||||
|
||||
goto out;
|
||||
case ZFS_PROJECT_OP_CLEAR:
|
||||
if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL) &&
|
||||
if (!(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT) &&
|
||||
(zpc->zpc_keep_projid ||
|
||||
fsx.fsx_projid == ZFS_DEFAULT_PROJID))
|
||||
goto out;
|
||||
|
||||
fsx.fsx_xflags &= ~ZFS_PROJINHERIT_FL;
|
||||
fsx.fsx_xflags &= ~FS_XFLAG_PROJINHERIT;
|
||||
if (!zpc->zpc_keep_projid)
|
||||
fsx.fsx_projid = ZFS_DEFAULT_PROJID;
|
||||
break;
|
||||
case ZFS_PROJECT_OP_SET:
|
||||
if (fsx.fsx_projid == zpc->zpc_expected_projid &&
|
||||
(!zpc->zpc_set_flag || fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
|
||||
(!zpc->zpc_set_flag ||
|
||||
fsx.fsx_xflags & FS_XFLAG_PROJINHERIT))
|
||||
goto out;
|
||||
|
||||
fsx.fsx_projid = zpc->zpc_expected_projid;
|
||||
if (zpc->zpc_set_flag)
|
||||
fsx.fsx_xflags |= ZFS_PROJINHERIT_FL;
|
||||
fsx.fsx_xflags |= FS_XFLAG_PROJINHERIT;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
@ -194,11 +195,30 @@ zfs_project_handle_one(const char *name, zfs_project_control_t *zpc)
|
||||
}
|
||||
|
||||
ret = ioctl(fd, ZFS_IOC_FSSETXATTR, &fsx);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("failed to set xattr for %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
|
||||
if (errno == ENOTSUP) {
|
||||
char *kver = zfs_version_kernel();
|
||||
/*
|
||||
* Special case: a module/userspace version mismatch can
|
||||
* return ENOTSUP due to us fixing the XFLAGs bits in
|
||||
* #17884. In that case give a hint to the user that
|
||||
* they should take action to make the versions match.
|
||||
*/
|
||||
if (strcmp(kver, ZFS_META_ALIAS) != 0) {
|
||||
fprintf(stderr,
|
||||
gettext("Warning: The zfs module version "
|
||||
"(%s) and userspace\nversion (%s) do not "
|
||||
"match up. This may be the\ncause of the "
|
||||
"\"Operation not supported\" error.\n"),
|
||||
kver, ZFS_META_ALIAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
return (ret);
|
||||
|
||||
@ -35,18 +35,16 @@
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
#ifdef FS_PROJINHERIT_FL
|
||||
#define ZFS_PROJINHERIT_FL FS_PROJINHERIT_FL
|
||||
#else
|
||||
#define ZFS_PROJINHERIT_FL 0x20000000
|
||||
#endif
|
||||
|
||||
#ifdef FS_IOC_FSGETXATTR
|
||||
typedef struct fsxattr zfsxattr_t;
|
||||
|
||||
#define ZFS_IOC_FSGETXATTR FS_IOC_FSGETXATTR
|
||||
#define ZFS_IOC_FSSETXATTR FS_IOC_FSSETXATTR
|
||||
#else
|
||||
/* Non-Linux OS */
|
||||
#define FS_PROJINHERIT_FL 0x20000000
|
||||
#define FS_XFLAG_PROJINHERIT FS_PROJINHERIT_FL
|
||||
|
||||
struct zfsxattr {
|
||||
uint32_t fsx_xflags; /* xflags field value (get/set) */
|
||||
uint32_t fsx_extsize; /* extsize field value (get/set) */
|
||||
|
||||
@ -76,6 +76,7 @@ libspl_sys_HEADERS += \
|
||||
%D%/os/linux/sys/param.h \
|
||||
%D%/os/linux/sys/stat.h \
|
||||
%D%/os/linux/sys/sysmacros.h \
|
||||
%D%/os/linux/sys/vfs.h \
|
||||
%D%/os/linux/sys/zfs_context_os.h
|
||||
|
||||
libspl_ia32_HEADERS = \
|
||||
|
||||
33
lib/libspl/include/os/linux/sys/vfs.h
Normal file
33
lib/libspl/include/os/linux/sys/vfs.h
Normal file
@ -0,0 +1,33 @@
|
||||
// SPDX-License-Identifier: CDDL-1.0
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or https://opensource.org/licenses/CDDL-1.0.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/* Copyright 2025 by Lawrence Livermore National Security, LLC. */
|
||||
|
||||
/* This is the Linux userspace version of include/os/linux/spl/sys/vfs.h */
|
||||
|
||||
#ifndef _LIBSPL_SYS_VFS_H
|
||||
#define _LIBSPL_SYS_VFS_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#endif
|
||||
@ -684,28 +684,44 @@ zpl_fadvise(struct file *filp, loff_t offset, loff_t len, int advice)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#define ZFS_FL_USER_VISIBLE (FS_FL_USER_VISIBLE | ZFS_PROJINHERIT_FL)
|
||||
#define ZFS_FL_USER_MODIFIABLE (FS_FL_USER_MODIFIABLE | ZFS_PROJINHERIT_FL)
|
||||
#define ZFS_FL_USER_VISIBLE (FS_FL_USER_VISIBLE | FS_PROJINHERIT_FL)
|
||||
#define ZFS_FL_USER_MODIFIABLE (FS_FL_USER_MODIFIABLE | FS_PROJINHERIT_FL)
|
||||
|
||||
|
||||
static struct {
|
||||
uint64_t zfs_flag;
|
||||
uint32_t fs_flag;
|
||||
uint32_t xflag;
|
||||
} flags_lookup[] = {
|
||||
{ZFS_IMMUTABLE, FS_IMMUTABLE_FL, FS_XFLAG_IMMUTABLE},
|
||||
{ZFS_APPENDONLY, FS_APPEND_FL, FS_XFLAG_APPEND},
|
||||
{ZFS_NODUMP, FS_NODUMP_FL, FS_XFLAG_NODUMP},
|
||||
{ZFS_PROJINHERIT, FS_PROJINHERIT_FL, FS_XFLAG_PROJINHERIT}
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
__zpl_ioctl_getflags(struct inode *ip)
|
||||
{
|
||||
uint64_t zfs_flags = ITOZ(ip)->z_pflags;
|
||||
uint32_t ioctl_flags = 0;
|
||||
for (int i = 0; i < ARRAY_SIZE(flags_lookup); i++)
|
||||
if (zfs_flags & flags_lookup[i].zfs_flag)
|
||||
ioctl_flags |= flags_lookup[i].fs_flag;
|
||||
|
||||
if (zfs_flags & ZFS_IMMUTABLE)
|
||||
ioctl_flags |= FS_IMMUTABLE_FL;
|
||||
return (ioctl_flags);
|
||||
}
|
||||
|
||||
if (zfs_flags & ZFS_APPENDONLY)
|
||||
ioctl_flags |= FS_APPEND_FL;
|
||||
static uint32_t
|
||||
__zpl_ioctl_getxflags(struct inode *ip)
|
||||
{
|
||||
uint64_t zfs_flags = ITOZ(ip)->z_pflags;
|
||||
uint32_t ioctl_flags = 0;
|
||||
|
||||
if (zfs_flags & ZFS_NODUMP)
|
||||
ioctl_flags |= FS_NODUMP_FL;
|
||||
for (int i = 0; i < ARRAY_SIZE(flags_lookup); i++)
|
||||
if (zfs_flags & flags_lookup[i].zfs_flag)
|
||||
ioctl_flags |= flags_lookup[i].xflag;
|
||||
|
||||
if (zfs_flags & ZFS_PROJINHERIT)
|
||||
ioctl_flags |= ZFS_PROJINHERIT_FL;
|
||||
|
||||
return (ioctl_flags & ZFS_FL_USER_VISIBLE);
|
||||
return (ioctl_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -719,6 +735,7 @@ zpl_ioctl_getflags(struct file *filp, void __user *arg)
|
||||
int err;
|
||||
|
||||
flags = __zpl_ioctl_getflags(file_inode(filp));
|
||||
flags = flags & ZFS_FL_USER_VISIBLE;
|
||||
err = copy_to_user(arg, &flags, sizeof (flags));
|
||||
|
||||
return (err);
|
||||
@ -742,7 +759,7 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva)
|
||||
xoptattr_t *xoap;
|
||||
|
||||
if (ioctl_flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL |
|
||||
ZFS_PROJINHERIT_FL))
|
||||
FS_PROJINHERIT_FL))
|
||||
return (-EOPNOTSUPP);
|
||||
|
||||
if (ioctl_flags & ~ZFS_FL_USER_MODIFIABLE)
|
||||
@ -773,7 +790,51 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva)
|
||||
xoap->xoa_appendonly);
|
||||
FLAG_CHANGE(FS_NODUMP_FL, ZFS_NODUMP, XAT_NODUMP,
|
||||
xoap->xoa_nodump);
|
||||
FLAG_CHANGE(ZFS_PROJINHERIT_FL, ZFS_PROJINHERIT, XAT_PROJINHERIT,
|
||||
FLAG_CHANGE(FS_PROJINHERIT_FL, ZFS_PROJINHERIT, XAT_PROJINHERIT,
|
||||
xoap->xoa_projinherit);
|
||||
|
||||
#undef FLAG_CHANGE
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
__zpl_ioctl_setxflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva)
|
||||
{
|
||||
uint64_t zfs_flags = ITOZ(ip)->z_pflags;
|
||||
xoptattr_t *xoap;
|
||||
|
||||
if (ioctl_flags & ~(FS_XFLAG_IMMUTABLE | FS_XFLAG_APPEND |
|
||||
FS_XFLAG_NODUMP | FS_XFLAG_PROJINHERIT))
|
||||
return (-EOPNOTSUPP);
|
||||
|
||||
if ((fchange(ioctl_flags, zfs_flags, FS_XFLAG_IMMUTABLE,
|
||||
ZFS_IMMUTABLE) ||
|
||||
fchange(ioctl_flags, zfs_flags, FS_XFLAG_APPEND, ZFS_APPENDONLY)) &&
|
||||
!capable(CAP_LINUX_IMMUTABLE))
|
||||
return (-EPERM);
|
||||
|
||||
if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
|
||||
return (-EACCES);
|
||||
|
||||
xva_init(xva);
|
||||
xoap = xva_getxoptattr(xva);
|
||||
|
||||
#define FLAG_CHANGE(iflag, zflag, xflag, xfield) do { \
|
||||
if (((ioctl_flags & (iflag)) && !(zfs_flags & (zflag))) || \
|
||||
((zfs_flags & (zflag)) && !(ioctl_flags & (iflag)))) { \
|
||||
XVA_SET_REQ(xva, (xflag)); \
|
||||
(xfield) = ((ioctl_flags & (iflag)) != 0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
FLAG_CHANGE(FS_XFLAG_IMMUTABLE, ZFS_IMMUTABLE, XAT_IMMUTABLE,
|
||||
xoap->xoa_immutable);
|
||||
FLAG_CHANGE(FS_XFLAG_APPEND, ZFS_APPENDONLY, XAT_APPENDONLY,
|
||||
xoap->xoa_appendonly);
|
||||
FLAG_CHANGE(FS_XFLAG_NODUMP, ZFS_NODUMP, XAT_NODUMP,
|
||||
xoap->xoa_nodump);
|
||||
FLAG_CHANGE(FS_XFLAG_PROJINHERIT, ZFS_PROJINHERIT, XAT_PROJINHERIT,
|
||||
xoap->xoa_projinherit);
|
||||
|
||||
#undef FLAG_CHANGE
|
||||
@ -814,7 +875,7 @@ zpl_ioctl_getxattr(struct file *filp, void __user *arg)
|
||||
struct inode *ip = file_inode(filp);
|
||||
int err;
|
||||
|
||||
fsx.fsx_xflags = __zpl_ioctl_getflags(ip);
|
||||
fsx.fsx_xflags = __zpl_ioctl_getxflags(ip);
|
||||
fsx.fsx_projid = ITOZ(ip)->z_projid;
|
||||
err = copy_to_user(arg, &fsx, sizeof (fsx));
|
||||
|
||||
@ -838,7 +899,7 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg)
|
||||
if (!zpl_is_valid_projid(fsx.fsx_projid))
|
||||
return (-EINVAL);
|
||||
|
||||
err = __zpl_ioctl_setflags(ip, fsx.fsx_xflags, &xva);
|
||||
err = __zpl_ioctl_setxflags(ip, fsx.fsx_xflags, &xva);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user