* [PATCH v2 1/4] libfrog: add wrappers for file_getattr/file_setattr syscalls
2025-08-27 15:15 ` [PATCH v2 0/4] xfsprogs: utilize file_getattr() and file_setattr() Andrey Albershteyn
@ 2025-08-27 15:15 ` Andrey Albershteyn
2025-08-28 14:34 ` Darrick J. Wong
2025-08-27 15:15 ` [PATCH v2 2/4] xfs_quota: utilize file_setattr to set prjid on special files Andrey Albershteyn
` (2 subsequent siblings)
3 siblings, 1 reply; 18+ messages in thread
From: Andrey Albershteyn @ 2025-08-27 15:15 UTC (permalink / raw)
To: aalbersh, linux-fsdevel, linux-xfs
Add wrappers for new file_getattr/file_setattr inode syscalls which will
be used by xfs_quota and xfs_io.
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
---
configure.ac | 1 +
include/builddefs.in | 5 +++
include/linux.h | 20 +++++++++
libfrog/Makefile | 2 +
libfrog/file_attr.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++
libfrog/file_attr.h | 35 +++++++++++++++
m4/package_libcdev.m4 | 19 ++++++++
7 files changed, 204 insertions(+)
diff --git a/configure.ac b/configure.ac
index 195ee6dddf61..a3206d53e7e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -156,6 +156,7 @@ AC_PACKAGE_NEED_RCU_INIT
AC_HAVE_PWRITEV2
AC_HAVE_COPY_FILE_RANGE
AC_HAVE_CACHESTAT
+AC_HAVE_FILE_ATTR
AC_NEED_INTERNAL_FSXATTR
AC_NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG
AC_NEED_INTERNAL_FSCRYPT_POLICY_V2
diff --git a/include/builddefs.in b/include/builddefs.in
index 04b4e0880a84..d727b55b854f 100644
--- a/include/builddefs.in
+++ b/include/builddefs.in
@@ -97,6 +97,7 @@ HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@
HAVE_PWRITEV2 = @have_pwritev2@
HAVE_COPY_FILE_RANGE = @have_copy_file_range@
HAVE_CACHESTAT = @have_cachestat@
+HAVE_FILE_ATTR = @have_file_attr@
NEED_INTERNAL_FSXATTR = @need_internal_fsxattr@
NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG = @need_internal_fscrypt_add_key_arg@
NEED_INTERNAL_FSCRYPT_POLICY_V2 = @need_internal_fscrypt_policy_v2@
@@ -169,6 +170,10 @@ ifeq ($(ENABLE_GETTEXT),yes)
GCFLAGS += -DENABLE_GETTEXT
endif
+ifeq ($(HAVE_FILE_ATTR),yes)
+LCFLAGS += -DHAVE_FILE_ATTR
+endif
+
# Override these if C++ needs other options
SANITIZER_CXXFLAGS = $(SANITIZER_CFLAGS)
GCXXFLAGS = $(GCFLAGS)
diff --git a/include/linux.h b/include/linux.h
index 6e83e073aa2e..993789f01b3a 100644
--- a/include/linux.h
+++ b/include/linux.h
@@ -16,6 +16,7 @@
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
#include <inttypes.h>
#include <malloc.h>
#include <getopt.h>
@@ -202,6 +203,25 @@ struct fsxattr {
};
#endif
+/*
+ * Use FILE_ATTR_SIZE_VER0 (linux/fs.h) instead of build system HAVE_FILE_ATTR
+ * as this header could be included in other places where HAVE_FILE_ATTR is not
+ * defined (e.g. xfstests's conftest.c in ./configure)
+ */
+#ifndef FILE_ATTR_SIZE_VER0
+/*
+ * We need to define file_attr if it's missing to know how to convert it to
+ * fsxattr
+ */
+struct file_attr {
+ __u32 fa_xflags;
+ __u32 fa_extsize;
+ __u32 fa_nextents;
+ __u32 fa_projid;
+ __u32 fa_cowextsize;
+};
+#endif
+
#ifndef FS_IOC_FSGETXATTR
/*
* Flags for the fsx_xflags field
diff --git a/libfrog/Makefile b/libfrog/Makefile
index 560bad417ee4..268fa26638d7 100644
--- a/libfrog/Makefile
+++ b/libfrog/Makefile
@@ -24,6 +24,7 @@ fsproperties.c \
fsprops.c \
getparents.c \
histogram.c \
+file_attr.c \
list_sort.c \
linux.c \
logging.c \
@@ -55,6 +56,7 @@ fsprops.h \
getparents.h \
handle_priv.h \
histogram.h \
+file_attr.h \
logging.h \
paths.h \
projects.h \
diff --git a/libfrog/file_attr.c b/libfrog/file_attr.c
new file mode 100644
index 000000000000..1d42895477ae
--- /dev/null
+++ b/libfrog/file_attr.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Red Hat, Inc.
+ * All Rights Reserved.
+ */
+
+#include "file_attr.h"
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <asm/types.h>
+#include <fcntl.h>
+
+static void
+file_attr_to_fsxattr(
+ const struct file_attr *fa,
+ struct fsxattr *fsxa)
+{
+ memset(fsxa, 0, sizeof(struct fsxattr));
+
+ fsxa->fsx_xflags = fa->fa_xflags;
+ fsxa->fsx_extsize = fa->fa_extsize;
+ fsxa->fsx_nextents = fa->fa_nextents;
+ fsxa->fsx_projid = fa->fa_projid;
+ fsxa->fsx_cowextsize = fa->fa_cowextsize;
+
+}
+
+static void
+fsxattr_to_file_attr(
+ const struct fsxattr *fsxa,
+ struct file_attr *fa)
+{
+ memset(fa, 0, sizeof(struct file_attr));
+
+ fa->fa_xflags = fsxa->fsx_xflags;
+ fa->fa_extsize = fsxa->fsx_extsize;
+ fa->fa_nextents = fsxa->fsx_nextents;
+ fa->fa_projid = fsxa->fsx_projid;
+ fa->fa_cowextsize = fsxa->fsx_cowextsize;
+}
+
+int
+xfrog_file_getattr(
+ const int dfd,
+ const char *path,
+ const struct stat *stat,
+ struct file_attr *fa,
+ const unsigned int at_flags)
+{
+ int error;
+ int fd;
+ struct fsxattr fsxa;
+
+#ifdef HAVE_FILE_ATTR
+ error = syscall(__NR_file_getattr, dfd, path, fa,
+ sizeof(struct file_attr), at_flags);
+ if (error && errno != ENOSYS)
+ return error;
+
+ if (!error)
+ return error;
+#endif
+
+ if (SPECIAL_FILE(stat->st_mode)) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ fd = open(path, O_RDONLY|O_NOCTTY);
+ if (fd == -1)
+ return fd;
+
+ error = ioctl(fd, FS_IOC_FSGETXATTR, &fsxa);
+ close(fd);
+ if (error)
+ return error;
+
+ fsxattr_to_file_attr(&fsxa, fa);
+
+ return error;
+}
+
+int
+xfrog_file_setattr(
+ const int dfd,
+ const char *path,
+ const struct stat *stat,
+ struct file_attr *fa,
+ const unsigned int at_flags)
+{
+ int error;
+ int fd;
+ struct fsxattr fsxa;
+
+#ifdef HAVE_FILE_ATTR
+ error = syscall(__NR_file_setattr, dfd, path, fa,
+ sizeof(struct file_attr), at_flags);
+ if (error && errno != ENOSYS)
+ return error;
+
+ if (!error)
+ return error;
+#endif
+
+ if (SPECIAL_FILE(stat->st_mode)) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ fd = open(path, O_RDONLY|O_NOCTTY);
+ if (fd == -1)
+ return fd;
+
+ file_attr_to_fsxattr(fa, &fsxa);
+
+ error = ioctl(fd, FS_IOC_FSSETXATTR, fa);
+ close(fd);
+
+ return error;
+}
diff --git a/libfrog/file_attr.h b/libfrog/file_attr.h
new file mode 100644
index 000000000000..ad33241bbffa
--- /dev/null
+++ b/libfrog/file_attr.h
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Red Hat, Inc.
+ * All Rights Reserved.
+ */
+#ifndef __LIBFROG_FILE_ATTR_H__
+#define __LIBFROG_FILE_ATTR_H__
+
+#include "linux.h"
+#include <sys/stat.h>
+
+#define SPECIAL_FILE(x) \
+ (S_ISCHR((x)) \
+ || S_ISBLK((x)) \
+ || S_ISFIFO((x)) \
+ || S_ISLNK((x)) \
+ || S_ISSOCK((x)))
+
+int
+xfrog_file_getattr(
+ const int dfd,
+ const char *path,
+ const struct stat *stat,
+ struct file_attr *fa,
+ const unsigned int at_flags);
+
+int
+xfrog_file_setattr(
+ const int dfd,
+ const char *path,
+ const struct stat *stat,
+ struct file_attr *fa,
+ const unsigned int at_flags);
+
+#endif /* __LIBFROG_FILE_ATTR_H__ */
diff --git a/m4/package_libcdev.m4 b/m4/package_libcdev.m4
index b77ac1a7580a..6a267dab7ab7 100644
--- a/m4/package_libcdev.m4
+++ b/m4/package_libcdev.m4
@@ -274,3 +274,22 @@ AC_DEFUN([AC_PACKAGE_CHECK_LTO],
AC_SUBST(lto_cflags)
AC_SUBST(lto_ldflags)
])
+
+#
+# Check if we have a file_getattr/file_setattr system call (Linux)
+#
+AC_DEFUN([AC_HAVE_FILE_ATTR],
+ [ AC_MSG_CHECKING([for file_getattr/file_setattr syscalls])
+ AC_LINK_IFELSE(
+ [ AC_LANG_PROGRAM([[
+#define _GNU_SOURCE
+#include <sys/syscall.h>
+#include <unistd.h>
+ ]], [[
+syscall(__NR_file_getattr, 0, 0, 0, 0, 0);
+ ]])
+ ], have_file_attr=yes
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no))
+ AC_SUBST(have_file_attr)
+ ])
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/4] libfrog: add wrappers for file_getattr/file_setattr syscalls
2025-08-27 15:15 ` [PATCH v2 1/4] libfrog: add wrappers for file_getattr/file_setattr syscalls Andrey Albershteyn
@ 2025-08-28 14:34 ` Darrick J. Wong
0 siblings, 0 replies; 18+ messages in thread
From: Darrick J. Wong @ 2025-08-28 14:34 UTC (permalink / raw)
To: Andrey Albershteyn; +Cc: aalbersh, linux-fsdevel, linux-xfs
On Wed, Aug 27, 2025 at 05:15:53PM +0200, Andrey Albershteyn wrote:
> Add wrappers for new file_getattr/file_setattr inode syscalls which will
> be used by xfs_quota and xfs_io.
>
> Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
> ---
> configure.ac | 1 +
> include/builddefs.in | 5 +++
> include/linux.h | 20 +++++++++
> libfrog/Makefile | 2 +
> libfrog/file_attr.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++
> libfrog/file_attr.h | 35 +++++++++++++++
> m4/package_libcdev.m4 | 19 ++++++++
> 7 files changed, 204 insertions(+)
>
> diff --git a/configure.ac b/configure.ac
> index 195ee6dddf61..a3206d53e7e0 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -156,6 +156,7 @@ AC_PACKAGE_NEED_RCU_INIT
> AC_HAVE_PWRITEV2
> AC_HAVE_COPY_FILE_RANGE
> AC_HAVE_CACHESTAT
> +AC_HAVE_FILE_ATTR
> AC_NEED_INTERNAL_FSXATTR
> AC_NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG
> AC_NEED_INTERNAL_FSCRYPT_POLICY_V2
> diff --git a/include/builddefs.in b/include/builddefs.in
> index 04b4e0880a84..d727b55b854f 100644
> --- a/include/builddefs.in
> +++ b/include/builddefs.in
> @@ -97,6 +97,7 @@ HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@
> HAVE_PWRITEV2 = @have_pwritev2@
> HAVE_COPY_FILE_RANGE = @have_copy_file_range@
> HAVE_CACHESTAT = @have_cachestat@
> +HAVE_FILE_ATTR = @have_file_attr@
> NEED_INTERNAL_FSXATTR = @need_internal_fsxattr@
> NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG = @need_internal_fscrypt_add_key_arg@
> NEED_INTERNAL_FSCRYPT_POLICY_V2 = @need_internal_fscrypt_policy_v2@
> @@ -169,6 +170,10 @@ ifeq ($(ENABLE_GETTEXT),yes)
> GCFLAGS += -DENABLE_GETTEXT
> endif
>
> +ifeq ($(HAVE_FILE_ATTR),yes)
> +LCFLAGS += -DHAVE_FILE_ATTR
> +endif
> +
> # Override these if C++ needs other options
> SANITIZER_CXXFLAGS = $(SANITIZER_CFLAGS)
> GCXXFLAGS = $(GCFLAGS)
> diff --git a/include/linux.h b/include/linux.h
> index 6e83e073aa2e..993789f01b3a 100644
> --- a/include/linux.h
> +++ b/include/linux.h
> @@ -16,6 +16,7 @@
> #include <sys/param.h>
> #include <sys/sysmacros.h>
> #include <sys/stat.h>
> +#include <sys/syscall.h>
> #include <inttypes.h>
> #include <malloc.h>
> #include <getopt.h>
> @@ -202,6 +203,25 @@ struct fsxattr {
> };
> #endif
>
> +/*
> + * Use FILE_ATTR_SIZE_VER0 (linux/fs.h) instead of build system HAVE_FILE_ATTR
> + * as this header could be included in other places where HAVE_FILE_ATTR is not
> + * defined (e.g. xfstests's conftest.c in ./configure)
> + */
> +#ifndef FILE_ATTR_SIZE_VER0
> +/*
> + * We need to define file_attr if it's missing to know how to convert it to
> + * fsxattr
> + */
> +struct file_attr {
> + __u32 fa_xflags;
> + __u32 fa_extsize;
> + __u32 fa_nextents;
> + __u32 fa_projid;
> + __u32 fa_cowextsize;
> +};
> +#endif
> +
> #ifndef FS_IOC_FSGETXATTR
> /*
> * Flags for the fsx_xflags field
> diff --git a/libfrog/Makefile b/libfrog/Makefile
> index 560bad417ee4..268fa26638d7 100644
> --- a/libfrog/Makefile
> +++ b/libfrog/Makefile
> @@ -24,6 +24,7 @@ fsproperties.c \
> fsprops.c \
> getparents.c \
> histogram.c \
> +file_attr.c \
> list_sort.c \
> linux.c \
> logging.c \
> @@ -55,6 +56,7 @@ fsprops.h \
> getparents.h \
> handle_priv.h \
> histogram.h \
> +file_attr.h \
> logging.h \
> paths.h \
> projects.h \
> diff --git a/libfrog/file_attr.c b/libfrog/file_attr.c
> new file mode 100644
> index 000000000000..1d42895477ae
> --- /dev/null
> +++ b/libfrog/file_attr.c
> @@ -0,0 +1,122 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2024 Red Hat, Inc.
Nit: You might as well make that 2025
> + * All Rights Reserved.
> + */
> +
> +#include "file_attr.h"
> +#include <stdio.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <sys/syscall.h>
> +#include <asm/types.h>
> +#include <fcntl.h>
> +
> +static void
> +file_attr_to_fsxattr(
> + const struct file_attr *fa,
> + struct fsxattr *fsxa)
> +{
> + memset(fsxa, 0, sizeof(struct fsxattr));
> +
> + fsxa->fsx_xflags = fa->fa_xflags;
> + fsxa->fsx_extsize = fa->fa_extsize;
> + fsxa->fsx_nextents = fa->fa_nextents;
> + fsxa->fsx_projid = fa->fa_projid;
> + fsxa->fsx_cowextsize = fa->fa_cowextsize;
> +
> +}
> +
> +static void
> +fsxattr_to_file_attr(
> + const struct fsxattr *fsxa,
> + struct file_attr *fa)
> +{
> + memset(fa, 0, sizeof(struct file_attr));
> +
> + fa->fa_xflags = fsxa->fsx_xflags;
> + fa->fa_extsize = fsxa->fsx_extsize;
> + fa->fa_nextents = fsxa->fsx_nextents;
> + fa->fa_projid = fsxa->fsx_projid;
> + fa->fa_cowextsize = fsxa->fsx_cowextsize;
> +}
> +
> +int
> +xfrog_file_getattr(
> + const int dfd,
> + const char *path,
> + const struct stat *stat,
> + struct file_attr *fa,
> + const unsigned int at_flags)
> +{
> + int error;
> + int fd;
> + struct fsxattr fsxa;
> +
> +#ifdef HAVE_FILE_ATTR
> + error = syscall(__NR_file_getattr, dfd, path, fa,
> + sizeof(struct file_attr), at_flags);
Nit: ^^^^^^^^^^ tabs, not spaces, for indenting please.
> + if (error && errno != ENOSYS)
> + return error;
> +
> + if (!error)
> + return error;
> +#endif
> +
> + if (SPECIAL_FILE(stat->st_mode)) {
> + errno = EOPNOTSUPP;
> + return -1;
> + }
> +
> + fd = open(path, O_RDONLY|O_NOCTTY);
> + if (fd == -1)
> + return fd;
> +
> + error = ioctl(fd, FS_IOC_FSGETXATTR, &fsxa);
> + close(fd);
> + if (error)
> + return error;
> +
> + fsxattr_to_file_attr(&fsxa, fa);
> +
> + return error;
> +}
> +
> +int
> +xfrog_file_setattr(
> + const int dfd,
> + const char *path,
> + const struct stat *stat,
> + struct file_attr *fa,
> + const unsigned int at_flags)
> +{
> + int error;
> + int fd;
> + struct fsxattr fsxa;
> +
> +#ifdef HAVE_FILE_ATTR
> + error = syscall(__NR_file_setattr, dfd, path, fa,
> + sizeof(struct file_attr), at_flags);
> + if (error && errno != ENOSYS)
> + return error;
> +
> + if (!error)
> + return error;
> +#endif
> +
> + if (SPECIAL_FILE(stat->st_mode)) {
> + errno = EOPNOTSUPP;
> + return -1;
> + }
> +
> + fd = open(path, O_RDONLY|O_NOCTTY);
> + if (fd == -1)
> + return fd;
> +
> + file_attr_to_fsxattr(fa, &fsxa);
> +
> + error = ioctl(fd, FS_IOC_FSSETXATTR, fa);
> + close(fd);
> +
> + return error;
> +}
> diff --git a/libfrog/file_attr.h b/libfrog/file_attr.h
> new file mode 100644
> index 000000000000..ad33241bbffa
> --- /dev/null
> +++ b/libfrog/file_attr.h
> @@ -0,0 +1,35 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2024 Red Hat, Inc.
> + * All Rights Reserved.
> + */
> +#ifndef __LIBFROG_FILE_ATTR_H__
> +#define __LIBFROG_FILE_ATTR_H__
> +
> +#include "linux.h"
> +#include <sys/stat.h>
> +
> +#define SPECIAL_FILE(x) \
> + (S_ISCHR((x)) \
> + || S_ISBLK((x)) \
> + || S_ISFIFO((x)) \
> + || S_ISLNK((x)) \
> + || S_ISSOCK((x)))
> +
> +int
> +xfrog_file_getattr(
> + const int dfd,
> + const char *path,
> + const struct stat *stat,
> + struct file_attr *fa,
> + const unsigned int at_flags);
> +
> +int
> +xfrog_file_setattr(
> + const int dfd,
> + const char *path,
> + const struct stat *stat,
> + struct file_attr *fa,
> + const unsigned int at_flags);
> +
> +#endif /* __LIBFROG_FILE_ATTR_H__ */
> diff --git a/m4/package_libcdev.m4 b/m4/package_libcdev.m4
> index b77ac1a7580a..6a267dab7ab7 100644
> --- a/m4/package_libcdev.m4
> +++ b/m4/package_libcdev.m4
> @@ -274,3 +274,22 @@ AC_DEFUN([AC_PACKAGE_CHECK_LTO],
> AC_SUBST(lto_cflags)
> AC_SUBST(lto_ldflags)
> ])
> +
> +#
> +# Check if we have a file_getattr/file_setattr system call (Linux)
> +#
> +AC_DEFUN([AC_HAVE_FILE_ATTR],
I would call the symbol AC_HAVE_FILE_GETATTR because you're not checking
the struct file_attr itself, just the syscall number.
Other than those nits, everything looks good here.
--D
> + [ AC_MSG_CHECKING([for file_getattr/file_setattr syscalls])
> + AC_LINK_IFELSE(
> + [ AC_LANG_PROGRAM([[
> +#define _GNU_SOURCE
> +#include <sys/syscall.h>
> +#include <unistd.h>
> + ]], [[
> +syscall(__NR_file_getattr, 0, 0, 0, 0, 0);
> + ]])
> + ], have_file_attr=yes
> + AC_MSG_RESULT(yes),
> + AC_MSG_RESULT(no))
> + AC_SUBST(have_file_attr)
> + ])
>
> --
> 2.49.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 2/4] xfs_quota: utilize file_setattr to set prjid on special files
2025-08-27 15:15 ` [PATCH v2 0/4] xfsprogs: utilize file_getattr() and file_setattr() Andrey Albershteyn
2025-08-27 15:15 ` [PATCH v2 1/4] libfrog: add wrappers for file_getattr/file_setattr syscalls Andrey Albershteyn
@ 2025-08-27 15:15 ` Andrey Albershteyn
2025-08-28 14:39 ` Darrick J. Wong
2025-08-27 15:15 ` [PATCH v2 3/4] xfs_io: make ls/chattr work with " Andrey Albershteyn
2025-08-27 15:15 ` [PATCH v2 4/4] xfs_db: use file_setattr to copy attributes on special files with rdump Andrey Albershteyn
3 siblings, 1 reply; 18+ messages in thread
From: Andrey Albershteyn @ 2025-08-27 15:15 UTC (permalink / raw)
To: aalbersh, linux-fsdevel, linux-xfs; +Cc: Andrey Albershteyn
From: Andrey Albershteyn <aalbersh@redhat.com>
Utilize new file_getattr/file_setattr syscalls to set project ID on
special files. Previously, special files were skipped due to lack of the
way to call FS_IOC_SETFSXATTR ioctl on them. The quota accounting was
therefore missing these inodes (special files created before project
setup). The ones created after project initialization did inherit the
projid flag from the parent.
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
quota/project.c | 142 +++++++++++++++++++++++++++++---------------------------
1 file changed, 74 insertions(+), 68 deletions(-)
diff --git a/quota/project.c b/quota/project.c
index adb26945fa57..857b1abe71c7 100644
--- a/quota/project.c
+++ b/quota/project.c
@@ -4,14 +4,17 @@
* All Rights Reserved.
*/
+#include <unistd.h>
#include "command.h"
#include "input.h"
#include "init.h"
+#include "libfrog/file_attr.h"
#include "quota.h"
static cmdinfo_t project_cmd;
static prid_t prid;
static int recurse_depth = -1;
+static int dfd;
enum {
CHECK_PROJECT = 0x1,
@@ -19,13 +22,6 @@ enum {
CLEAR_PROJECT = 0x4,
};
-#define EXCLUDED_FILE_TYPES(x) \
- (S_ISCHR((x)) \
- || S_ISBLK((x)) \
- || S_ISFIFO((x)) \
- || S_ISLNK((x)) \
- || S_ISSOCK((x)))
-
static void
project_help(void)
{
@@ -85,8 +81,8 @@ check_project(
int flag,
struct FTW *data)
{
- struct fsxattr fsx;
- int fd;
+ int error;
+ struct file_attr fa;
if (recurse_depth >= 0 && data->level > recurse_depth)
return 0;
@@ -96,30 +92,30 @@ check_project(
fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
return 0;
}
- if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
- fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
- return 0;
- }
- if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
- exitcode = 1;
- fprintf(stderr, _("%s: cannot open %s: %s\n"),
- progname, path, strerror(errno));
- } else if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
- exitcode = 1;
+ error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
+ if (error && errno == EOPNOTSUPP) {
+ if (SPECIAL_FILE(stat->st_mode)) {
+ fprintf(stderr, _("%s: skipping special file %s: %s\n"),
+ progname, path, strerror(errno));
+ return 0;
+ }
+ }
+ if (error) {
fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
- progname, path, strerror(errno));
- } else {
- if (fsx.fsx_projid != prid)
- printf(_("%s - project identifier is not set"
- " (inode=%u, tree=%u)\n"),
- path, fsx.fsx_projid, (unsigned int)prid);
- if (!(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT) && S_ISDIR(stat->st_mode))
- printf(_("%s - project inheritance flag is not set\n"),
- path);
+ progname, path, strerror(errno));
+ exitcode = 1;
+ return 0;
}
- if (fd != -1)
- close(fd);
+
+ if (fa.fa_projid != prid)
+ printf(_("%s - project identifier is not set"
+ " (inode=%u, tree=%u)\n"),
+ path, fa.fa_projid, (unsigned int)prid);
+ if (!(fa.fa_xflags & FS_XFLAG_PROJINHERIT) && S_ISDIR(stat->st_mode))
+ printf(_("%s - project inheritance flag is not set\n"),
+ path);
+
return 0;
}
@@ -130,8 +126,8 @@ clear_project(
int flag,
struct FTW *data)
{
- struct fsxattr fsx;
- int fd;
+ int error;
+ struct file_attr fa;
if (recurse_depth >= 0 && data->level > recurse_depth)
return 0;
@@ -141,32 +137,32 @@ clear_project(
fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
return 0;
}
- if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
- fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
- return 0;
+
+ error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
+ if (error && errno == EOPNOTSUPP) {
+ if (SPECIAL_FILE(stat->st_mode)) {
+ fprintf(stderr, _("%s: skipping special file %s: %s\n"),
+ progname, path, strerror(errno));
+ return 0;
+ }
}
- if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
- exitcode = 1;
- fprintf(stderr, _("%s: cannot open %s: %s\n"),
- progname, path, strerror(errno));
- return 0;
- } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) {
- exitcode = 1;
+ if (error) {
fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
- progname, path, strerror(errno));
- close(fd);
+ progname, path, strerror(errno));
+ exitcode = 1;
return 0;
}
- fsx.fsx_projid = 0;
- fsx.fsx_xflags &= ~FS_XFLAG_PROJINHERIT;
- if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) {
- exitcode = 1;
+ fa.fa_projid = 0;
+ fa.fa_xflags &= ~FS_XFLAG_PROJINHERIT;
+
+ error = xfrog_file_setattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
+ if (error) {
fprintf(stderr, _("%s: cannot clear project on %s: %s\n"),
progname, path, strerror(errno));
+ exitcode = 1;
}
- close(fd);
return 0;
}
@@ -177,8 +173,8 @@ setup_project(
int flag,
struct FTW *data)
{
- struct fsxattr fsx;
- int fd;
+ struct file_attr fa;
+ int error;
if (recurse_depth >= 0 && data->level > recurse_depth)
return 0;
@@ -188,32 +184,33 @@ setup_project(
fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
return 0;
}
- if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
- fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
- return 0;
+
+ error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
+ if (error && errno == EOPNOTSUPP) {
+ if (SPECIAL_FILE(stat->st_mode)) {
+ fprintf(stderr, _("%s: skipping special file %s\n"),
+ progname, path);
+ return 0;
+ }
}
- if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
- exitcode = 1;
- fprintf(stderr, _("%s: cannot open %s: %s\n"),
- progname, path, strerror(errno));
- return 0;
- } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) {
- exitcode = 1;
+ if (error) {
fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
- progname, path, strerror(errno));
- close(fd);
+ progname, path, strerror(errno));
+ exitcode = 1;
return 0;
}
- fsx.fsx_projid = prid;
- fsx.fsx_xflags |= FS_XFLAG_PROJINHERIT;
- if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) {
- exitcode = 1;
+ fa.fa_projid = prid;
+ if (S_ISDIR(stat->st_mode))
+ fa.fa_xflags |= FS_XFLAG_PROJINHERIT;
+
+ error = xfrog_file_setattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
+ if (error) {
fprintf(stderr, _("%s: cannot set project on %s: %s\n"),
progname, path, strerror(errno));
+ exitcode = 1;
}
- close(fd);
return 0;
}
@@ -223,6 +220,13 @@ project_operations(
char *dir,
int type)
{
+ dfd = open(dir, O_RDONLY|O_NOCTTY);
+ if (dfd < -1) {
+ printf(_("Error opening dir %s for project %s...\n"), dir,
+ project);
+ return;
+ }
+
switch (type) {
case CHECK_PROJECT:
printf(_("Checking project %s (path %s)...\n"), project, dir);
@@ -237,6 +241,8 @@ project_operations(
nftw(dir, clear_project, 100, FTW_PHYS|FTW_MOUNT);
break;
}
+
+ close(dfd);
}
static void
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/4] xfs_quota: utilize file_setattr to set prjid on special files
2025-08-27 15:15 ` [PATCH v2 2/4] xfs_quota: utilize file_setattr to set prjid on special files Andrey Albershteyn
@ 2025-08-28 14:39 ` Darrick J. Wong
2025-08-29 15:42 ` Andrey Albershteyn
0 siblings, 1 reply; 18+ messages in thread
From: Darrick J. Wong @ 2025-08-28 14:39 UTC (permalink / raw)
To: Andrey Albershteyn; +Cc: aalbersh, linux-fsdevel, linux-xfs
On Wed, Aug 27, 2025 at 05:15:54PM +0200, Andrey Albershteyn wrote:
> From: Andrey Albershteyn <aalbersh@redhat.com>
>
> Utilize new file_getattr/file_setattr syscalls to set project ID on
> special files. Previously, special files were skipped due to lack of the
> way to call FS_IOC_SETFSXATTR ioctl on them. The quota accounting was
> therefore missing these inodes (special files created before project
> setup). The ones created after project initialization did inherit the
> projid flag from the parent.
>
> Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
> ---
> quota/project.c | 142 +++++++++++++++++++++++++++++---------------------------
> 1 file changed, 74 insertions(+), 68 deletions(-)
>
> diff --git a/quota/project.c b/quota/project.c
> index adb26945fa57..857b1abe71c7 100644
> --- a/quota/project.c
> +++ b/quota/project.c
> @@ -4,14 +4,17 @@
> * All Rights Reserved.
> */
>
> +#include <unistd.h>
> #include "command.h"
> #include "input.h"
> #include "init.h"
> +#include "libfrog/file_attr.h"
> #include "quota.h"
>
> static cmdinfo_t project_cmd;
> static prid_t prid;
> static int recurse_depth = -1;
> +static int dfd;
>
> enum {
> CHECK_PROJECT = 0x1,
> @@ -19,13 +22,6 @@ enum {
> CLEAR_PROJECT = 0x4,
> };
>
> -#define EXCLUDED_FILE_TYPES(x) \
> - (S_ISCHR((x)) \
> - || S_ISBLK((x)) \
> - || S_ISFIFO((x)) \
> - || S_ISLNK((x)) \
> - || S_ISSOCK((x)))
> -
> static void
> project_help(void)
> {
> @@ -85,8 +81,8 @@ check_project(
> int flag,
> struct FTW *data)
> {
> - struct fsxattr fsx;
> - int fd;
> + int error;
> + struct file_attr fa;
>
> if (recurse_depth >= 0 && data->level > recurse_depth)
> return 0;
> @@ -96,30 +92,30 @@ check_project(
> fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
> return 0;
> }
> - if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
> - fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
> - return 0;
> - }
>
> - if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
> - exitcode = 1;
> - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> - progname, path, strerror(errno));
> - } else if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
> - exitcode = 1;
> + error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> + if (error && errno == EOPNOTSUPP) {
> + if (SPECIAL_FILE(stat->st_mode)) {
> + fprintf(stderr, _("%s: skipping special file %s: %s\n"),
> + progname, path, strerror(errno));
> + return 0;
> + }
> + }
> + if (error) {
> fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> - progname, path, strerror(errno));
> - } else {
> - if (fsx.fsx_projid != prid)
> - printf(_("%s - project identifier is not set"
> - " (inode=%u, tree=%u)\n"),
> - path, fsx.fsx_projid, (unsigned int)prid);
> - if (!(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT) && S_ISDIR(stat->st_mode))
> - printf(_("%s - project inheritance flag is not set\n"),
> - path);
> + progname, path, strerror(errno));
> + exitcode = 1;
> + return 0;
> }
> - if (fd != -1)
> - close(fd);
> +
> + if (fa.fa_projid != prid)
> + printf(_("%s - project identifier is not set"
> + " (inode=%u, tree=%u)\n"),
> + path, fa.fa_projid, (unsigned int)prid);
> + if (!(fa.fa_xflags & FS_XFLAG_PROJINHERIT) && S_ISDIR(stat->st_mode))
> + printf(_("%s - project inheritance flag is not set\n"),
> + path);
> +
> return 0;
> }
>
> @@ -130,8 +126,8 @@ clear_project(
> int flag,
> struct FTW *data)
> {
> - struct fsxattr fsx;
> - int fd;
> + int error;
> + struct file_attr fa;
>
> if (recurse_depth >= 0 && data->level > recurse_depth)
> return 0;
> @@ -141,32 +137,32 @@ clear_project(
> fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
> return 0;
> }
> - if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
> - fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
> - return 0;
> +
> + error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> + if (error && errno == EOPNOTSUPP) {
> + if (SPECIAL_FILE(stat->st_mode)) {
> + fprintf(stderr, _("%s: skipping special file %s: %s\n"),
> + progname, path, strerror(errno));
> + return 0;
> + }
> }
>
> - if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
> - exitcode = 1;
> - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> - progname, path, strerror(errno));
> - return 0;
> - } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) {
> - exitcode = 1;
> + if (error) {
> fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> - progname, path, strerror(errno));
> - close(fd);
> + progname, path, strerror(errno));
> + exitcode = 1;
> return 0;
> }
>
> - fsx.fsx_projid = 0;
> - fsx.fsx_xflags &= ~FS_XFLAG_PROJINHERIT;
> - if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) {
> - exitcode = 1;
> + fa.fa_projid = 0;
> + fa.fa_xflags &= ~FS_XFLAG_PROJINHERIT;
> +
> + error = xfrog_file_setattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> + if (error) {
> fprintf(stderr, _("%s: cannot clear project on %s: %s\n"),
> progname, path, strerror(errno));
> + exitcode = 1;
> }
> - close(fd);
> return 0;
> }
>
> @@ -177,8 +173,8 @@ setup_project(
> int flag,
> struct FTW *data)
> {
> - struct fsxattr fsx;
> - int fd;
> + struct file_attr fa;
> + int error;
>
> if (recurse_depth >= 0 && data->level > recurse_depth)
> return 0;
> @@ -188,32 +184,33 @@ setup_project(
> fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
> return 0;
> }
> - if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
> - fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
> - return 0;
> +
> + error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> + if (error && errno == EOPNOTSUPP) {
> + if (SPECIAL_FILE(stat->st_mode)) {
> + fprintf(stderr, _("%s: skipping special file %s\n"),
> + progname, path);
> + return 0;
> + }
> }
>
> - if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
> - exitcode = 1;
> - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> - progname, path, strerror(errno));
> - return 0;
> - } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) {
> - exitcode = 1;
> + if (error) {
> fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> - progname, path, strerror(errno));
> - close(fd);
> + progname, path, strerror(errno));
> + exitcode = 1;
> return 0;
> }
>
> - fsx.fsx_projid = prid;
> - fsx.fsx_xflags |= FS_XFLAG_PROJINHERIT;
> - if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) {
> - exitcode = 1;
> + fa.fa_projid = prid;
> + if (S_ISDIR(stat->st_mode))
> + fa.fa_xflags |= FS_XFLAG_PROJINHERIT;
Hrm, interesting change in projinherit logic -- is this because the new
setattr code rejects projinherit on non-directories?
> +
> + error = xfrog_file_setattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> + if (error) {
> fprintf(stderr, _("%s: cannot set project on %s: %s\n"),
> progname, path, strerror(errno));
> + exitcode = 1;
> }
> - close(fd);
> return 0;
> }
>
> @@ -223,6 +220,13 @@ project_operations(
> char *dir,
> int type)
> {
> + dfd = open(dir, O_RDONLY|O_NOCTTY);
Nit: spaces around the pipe char^acter, please.
--D
> + if (dfd < -1) {
> + printf(_("Error opening dir %s for project %s...\n"), dir,
> + project);
> + return;
> + }
> +
> switch (type) {
> case CHECK_PROJECT:
> printf(_("Checking project %s (path %s)...\n"), project, dir);
> @@ -237,6 +241,8 @@ project_operations(
> nftw(dir, clear_project, 100, FTW_PHYS|FTW_MOUNT);
> break;
> }
> +
> + close(dfd);
> }
>
> static void
>
> --
> 2.49.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/4] xfs_quota: utilize file_setattr to set prjid on special files
2025-08-28 14:39 ` Darrick J. Wong
@ 2025-08-29 15:42 ` Andrey Albershteyn
0 siblings, 0 replies; 18+ messages in thread
From: Andrey Albershteyn @ 2025-08-29 15:42 UTC (permalink / raw)
To: Darrick J. Wong; +Cc: aalbersh, linux-fsdevel, linux-xfs
On 2025-08-28 07:39:16, Darrick J. Wong wrote:
> On Wed, Aug 27, 2025 at 05:15:54PM +0200, Andrey Albershteyn wrote:
> > From: Andrey Albershteyn <aalbersh@redhat.com>
> >
> > Utilize new file_getattr/file_setattr syscalls to set project ID on
> > special files. Previously, special files were skipped due to lack of the
> > way to call FS_IOC_SETFSXATTR ioctl on them. The quota accounting was
> > therefore missing these inodes (special files created before project
> > setup). The ones created after project initialization did inherit the
> > projid flag from the parent.
> >
> > Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
> > ---
> > quota/project.c | 142 +++++++++++++++++++++++++++++---------------------------
> > 1 file changed, 74 insertions(+), 68 deletions(-)
> >
> > diff --git a/quota/project.c b/quota/project.c
> > index adb26945fa57..857b1abe71c7 100644
> > --- a/quota/project.c
> > +++ b/quota/project.c
> > @@ -4,14 +4,17 @@
> > * All Rights Reserved.
> > */
> >
> > +#include <unistd.h>
> > #include "command.h"
> > #include "input.h"
> > #include "init.h"
> > +#include "libfrog/file_attr.h"
> > #include "quota.h"
> >
> > static cmdinfo_t project_cmd;
> > static prid_t prid;
> > static int recurse_depth = -1;
> > +static int dfd;
> >
> > enum {
> > CHECK_PROJECT = 0x1,
> > @@ -19,13 +22,6 @@ enum {
> > CLEAR_PROJECT = 0x4,
> > };
> >
> > -#define EXCLUDED_FILE_TYPES(x) \
> > - (S_ISCHR((x)) \
> > - || S_ISBLK((x)) \
> > - || S_ISFIFO((x)) \
> > - || S_ISLNK((x)) \
> > - || S_ISSOCK((x)))
> > -
> > static void
> > project_help(void)
> > {
> > @@ -85,8 +81,8 @@ check_project(
> > int flag,
> > struct FTW *data)
> > {
> > - struct fsxattr fsx;
> > - int fd;
> > + int error;
> > + struct file_attr fa;
> >
> > if (recurse_depth >= 0 && data->level > recurse_depth)
> > return 0;
> > @@ -96,30 +92,30 @@ check_project(
> > fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
> > return 0;
> > }
> > - if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
> > - fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
> > - return 0;
> > - }
> >
> > - if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
> > - exitcode = 1;
> > - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> > - progname, path, strerror(errno));
> > - } else if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
> > - exitcode = 1;
> > + error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> > + if (error && errno == EOPNOTSUPP) {
> > + if (SPECIAL_FILE(stat->st_mode)) {
> > + fprintf(stderr, _("%s: skipping special file %s: %s\n"),
> > + progname, path, strerror(errno));
> > + return 0;
> > + }
> > + }
> > + if (error) {
> > fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> > - progname, path, strerror(errno));
> > - } else {
> > - if (fsx.fsx_projid != prid)
> > - printf(_("%s - project identifier is not set"
> > - " (inode=%u, tree=%u)\n"),
> > - path, fsx.fsx_projid, (unsigned int)prid);
> > - if (!(fsx.fsx_xflags & FS_XFLAG_PROJINHERIT) && S_ISDIR(stat->st_mode))
> > - printf(_("%s - project inheritance flag is not set\n"),
> > - path);
> > + progname, path, strerror(errno));
> > + exitcode = 1;
> > + return 0;
> > }
> > - if (fd != -1)
> > - close(fd);
> > +
> > + if (fa.fa_projid != prid)
> > + printf(_("%s - project identifier is not set"
> > + " (inode=%u, tree=%u)\n"),
> > + path, fa.fa_projid, (unsigned int)prid);
> > + if (!(fa.fa_xflags & FS_XFLAG_PROJINHERIT) && S_ISDIR(stat->st_mode))
> > + printf(_("%s - project inheritance flag is not set\n"),
> > + path);
> > +
> > return 0;
> > }
> >
> > @@ -130,8 +126,8 @@ clear_project(
> > int flag,
> > struct FTW *data)
> > {
> > - struct fsxattr fsx;
> > - int fd;
> > + int error;
> > + struct file_attr fa;
> >
> > if (recurse_depth >= 0 && data->level > recurse_depth)
> > return 0;
> > @@ -141,32 +137,32 @@ clear_project(
> > fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
> > return 0;
> > }
> > - if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
> > - fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
> > - return 0;
> > +
> > + error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> > + if (error && errno == EOPNOTSUPP) {
> > + if (SPECIAL_FILE(stat->st_mode)) {
> > + fprintf(stderr, _("%s: skipping special file %s: %s\n"),
> > + progname, path, strerror(errno));
> > + return 0;
> > + }
> > }
> >
> > - if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
> > - exitcode = 1;
> > - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> > - progname, path, strerror(errno));
> > - return 0;
> > - } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) {
> > - exitcode = 1;
> > + if (error) {
> > fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> > - progname, path, strerror(errno));
> > - close(fd);
> > + progname, path, strerror(errno));
> > + exitcode = 1;
> > return 0;
> > }
> >
> > - fsx.fsx_projid = 0;
> > - fsx.fsx_xflags &= ~FS_XFLAG_PROJINHERIT;
> > - if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) {
> > - exitcode = 1;
> > + fa.fa_projid = 0;
> > + fa.fa_xflags &= ~FS_XFLAG_PROJINHERIT;
> > +
> > + error = xfrog_file_setattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> > + if (error) {
> > fprintf(stderr, _("%s: cannot clear project on %s: %s\n"),
> > progname, path, strerror(errno));
> > + exitcode = 1;
> > }
> > - close(fd);
> > return 0;
> > }
> >
> > @@ -177,8 +173,8 @@ setup_project(
> > int flag,
> > struct FTW *data)
> > {
> > - struct fsxattr fsx;
> > - int fd;
> > + struct file_attr fa;
> > + int error;
> >
> > if (recurse_depth >= 0 && data->level > recurse_depth)
> > return 0;
> > @@ -188,32 +184,33 @@ setup_project(
> > fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
> > return 0;
> > }
> > - if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
> > - fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
> > - return 0;
> > +
> > + error = xfrog_file_getattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> > + if (error && errno == EOPNOTSUPP) {
> > + if (SPECIAL_FILE(stat->st_mode)) {
> > + fprintf(stderr, _("%s: skipping special file %s\n"),
> > + progname, path);
> > + return 0;
> > + }
> > }
> >
> > - if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
> > - exitcode = 1;
> > - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> > - progname, path, strerror(errno));
> > - return 0;
> > - } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx) < 0) {
> > - exitcode = 1;
> > + if (error) {
> > fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> > - progname, path, strerror(errno));
> > - close(fd);
> > + progname, path, strerror(errno));
> > + exitcode = 1;
> > return 0;
> > }
> >
> > - fsx.fsx_projid = prid;
> > - fsx.fsx_xflags |= FS_XFLAG_PROJINHERIT;
> > - if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx) < 0) {
> > - exitcode = 1;
> > + fa.fa_projid = prid;
> > + if (S_ISDIR(stat->st_mode))
> > + fa.fa_xflags |= FS_XFLAG_PROJINHERIT;
>
> Hrm, interesting change in projinherit logic -- is this because the new
> setattr code rejects projinherit on non-directories?
They don't reject it so far, but I think PROJINHERIT was never set
on files (according to xfs_flags2diflags()).
>
> > +
> > + error = xfrog_file_setattr(dfd, path, stat, &fa, AT_SYMLINK_NOFOLLOW);
> > + if (error) {
> > fprintf(stderr, _("%s: cannot set project on %s: %s\n"),
> > progname, path, strerror(errno));
> > + exitcode = 1;
> > }
> > - close(fd);
> > return 0;
> > }
> >
> > @@ -223,6 +220,13 @@ project_operations(
> > char *dir,
> > int type)
> > {
> > + dfd = open(dir, O_RDONLY|O_NOCTTY);
>
> Nit: spaces around the pipe char^acter, please.
>
> --D
>
> > + if (dfd < -1) {
> > + printf(_("Error opening dir %s for project %s...\n"), dir,
> > + project);
> > + return;
> > + }
> > +
> > switch (type) {
> > case CHECK_PROJECT:
> > printf(_("Checking project %s (path %s)...\n"), project, dir);
> > @@ -237,6 +241,8 @@ project_operations(
> > nftw(dir, clear_project, 100, FTW_PHYS|FTW_MOUNT);
> > break;
> > }
> > +
> > + close(dfd);
> > }
> >
> > static void
> >
> > --
> > 2.49.0
> >
> >
>
--
- Andrey
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 3/4] xfs_io: make ls/chattr work with special files
2025-08-27 15:15 ` [PATCH v2 0/4] xfsprogs: utilize file_getattr() and file_setattr() Andrey Albershteyn
2025-08-27 15:15 ` [PATCH v2 1/4] libfrog: add wrappers for file_getattr/file_setattr syscalls Andrey Albershteyn
2025-08-27 15:15 ` [PATCH v2 2/4] xfs_quota: utilize file_setattr to set prjid on special files Andrey Albershteyn
@ 2025-08-27 15:15 ` Andrey Albershteyn
2025-08-28 14:40 ` Darrick J. Wong
2025-08-27 15:15 ` [PATCH v2 4/4] xfs_db: use file_setattr to copy attributes on special files with rdump Andrey Albershteyn
3 siblings, 1 reply; 18+ messages in thread
From: Andrey Albershteyn @ 2025-08-27 15:15 UTC (permalink / raw)
To: aalbersh, linux-fsdevel, linux-xfs; +Cc: Andrey Albershteyn
From: Andrey Albershteyn <aalbersh@redhat.com>
With new file_getattr/file_setattr syscalls we can now list/change file
attributes on special files instead for ignoring them.
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
---
io/attr.c | 138 +++++++++++++++++++++++++++++++++++++-------------------------
io/io.h | 2 +-
io/stat.c | 2 +-
3 files changed, 84 insertions(+), 58 deletions(-)
diff --git a/io/attr.c b/io/attr.c
index fd82a2e73801..1005450ac9f9 100644
--- a/io/attr.c
+++ b/io/attr.c
@@ -8,6 +8,7 @@
#include "input.h"
#include "init.h"
#include "io.h"
+#include "libfrog/file_attr.h"
static cmdinfo_t chattr_cmd;
static cmdinfo_t lsattr_cmd;
@@ -113,7 +114,7 @@ chattr_help(void)
}
void
-printxattr(
+print_xflags(
uint flags,
int verbose,
int dofname,
@@ -156,36 +157,36 @@ lsattr_callback(
int status,
struct FTW *data)
{
- struct fsxattr fsx;
- int fd;
+ struct file_attr fa;
+ int error;
if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
- if ((fd = open(path, O_RDONLY)) == -1) {
- fprintf(stderr, _("%s: cannot open %s: %s\n"),
- progname, path, strerror(errno));
- exitcode = 1;
- } else if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
+ error = xfrog_file_getattr(AT_FDCWD, path, stat, &fa,
+ AT_SYMLINK_NOFOLLOW);
+ if (error) {
fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
progname, path, strerror(errno));
exitcode = 1;
- } else
- printxattr(fsx.fsx_xflags, 0, 1, path, 0, 1);
+ return 0;
+ }
+
+ print_xflags(fa.fa_xflags, 0, 1, path, 0, 1);
- if (fd != -1)
- close(fd);
return 0;
}
static int
lsattr_f(
- int argc,
- char **argv)
+ int argc,
+ char **argv)
{
- struct fsxattr fsx;
- char *name = file->name;
- int c, aflag = 0, vflag = 0;
+ struct file_attr fa;
+ char *name = file->name;
+ int c, aflag = 0, vflag = 0;
+ struct stat st;
+ int error;
recurse_all = recurse_dir = 0;
while ((c = getopt(argc, argv, "DRav")) != EOF) {
@@ -211,17 +212,28 @@ lsattr_f(
if (recurse_all || recurse_dir) {
nftw(name, lsattr_callback,
100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
- } else if ((xfsctl(name, file->fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
+ return 0;
+ }
+
+ error = stat(name, &st);
+ if (error)
+ return error;
+
+ error = xfrog_file_getattr(AT_FDCWD, name, &st, &fa,
+ AT_SYMLINK_NOFOLLOW);
+ if (error) {
fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
progname, name, strerror(errno));
exitcode = 1;
- } else {
- printxattr(fsx.fsx_xflags, vflag, !aflag, name, vflag, !aflag);
- if (aflag) {
- fputs("/", stdout);
- printxattr(-1, 0, 1, name, 0, 1);
- }
+ return 0;
}
+
+ print_xflags(fa.fa_xflags, vflag, !aflag, name, vflag, !aflag);
+ if (aflag) {
+ fputs("/", stdout);
+ print_xflags(-1, 0, 1, name, 0, 1);
+ }
+
return 0;
}
@@ -232,44 +244,45 @@ chattr_callback(
int status,
struct FTW *data)
{
- struct fsxattr attr;
- int fd;
+ struct file_attr attr;
+ int error;
if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
- if ((fd = open(path, O_RDONLY)) == -1) {
- fprintf(stderr, _("%s: cannot open %s: %s\n"),
- progname, path, strerror(errno));
- exitcode = 1;
- } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &attr) < 0) {
+ error = xfrog_file_getattr(AT_FDCWD, path, stat, &attr,
+ AT_SYMLINK_NOFOLLOW);
+ if (error) {
fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
progname, path, strerror(errno));
exitcode = 1;
- } else {
- attr.fsx_xflags |= orflags;
- attr.fsx_xflags &= ~andflags;
- if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &attr) < 0) {
- fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
- progname, path, strerror(errno));
- exitcode = 1;
- }
+ return 0;
+ }
+
+ attr.fa_xflags |= orflags;
+ attr.fa_xflags &= ~andflags;
+ error = xfrog_file_setattr(AT_FDCWD, path, stat, &attr,
+ AT_SYMLINK_NOFOLLOW);
+ if (error) {
+ fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
+ progname, path, strerror(errno));
+ exitcode = 1;
}
- if (fd != -1)
- close(fd);
return 0;
}
static int
chattr_f(
- int argc,
- char **argv)
+ int argc,
+ char **argv)
{
- struct fsxattr attr;
- struct xflags *p;
- unsigned int i = 0;
- char *c, *name = file->name;
+ struct file_attr attr;
+ struct xflags *p;
+ unsigned int i = 0;
+ char *c, *name = file->name;
+ struct stat st;
+ int error;
orflags = andflags = 0;
recurse_all = recurse_dir = 0;
@@ -326,19 +339,32 @@ chattr_f(
if (recurse_all || recurse_dir) {
nftw(name, chattr_callback,
100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
- } else if (xfsctl(name, file->fd, FS_IOC_FSGETXATTR, &attr) < 0) {
+ return 0;
+ }
+
+ error = stat(name, &st);
+ if (error)
+ return error;
+
+ error = xfrog_file_getattr(AT_FDCWD, name, &st, &attr,
+ AT_SYMLINK_NOFOLLOW);
+ if (error) {
fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
progname, name, strerror(errno));
exitcode = 1;
- } else {
- attr.fsx_xflags |= orflags;
- attr.fsx_xflags &= ~andflags;
- if (xfsctl(name, file->fd, FS_IOC_FSSETXATTR, &attr) < 0) {
- fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
- progname, name, strerror(errno));
- exitcode = 1;
- }
+ return 0;
}
+
+ attr.fa_xflags |= orflags;
+ attr.fa_xflags &= ~andflags;
+ error = xfrog_file_setattr(AT_FDCWD, name, &st, &attr,
+ AT_SYMLINK_NOFOLLOW);
+ if (error) {
+ fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
+ progname, name, strerror(errno));
+ exitcode = 1;
+ }
+
return 0;
}
diff --git a/io/io.h b/io/io.h
index 259c034931b8..35fb8339eeb5 100644
--- a/io/io.h
+++ b/io/io.h
@@ -78,7 +78,7 @@ extern int openfile(char *, struct xfs_fsop_geom *, int, mode_t,
extern int addfile(char *, int , struct xfs_fsop_geom *, int,
struct fs_path *);
extern int closefile(void);
-extern void printxattr(uint, int, int, const char *, int, int);
+extern void print_xflags(uint, int, int, const char *, int, int);
extern unsigned int recurse_all;
extern unsigned int recurse_dir;
diff --git a/io/stat.c b/io/stat.c
index c257037aa8ee..c1085f14eade 100644
--- a/io/stat.c
+++ b/io/stat.c
@@ -112,7 +112,7 @@ print_extended_info(int verbose)
}
printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags);
- printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
+ print_xflags(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid);
printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize);
printf(_("fsxattr.cowextsize = %u\n"), fsx.fsx_cowextsize);
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 3/4] xfs_io: make ls/chattr work with special files
2025-08-27 15:15 ` [PATCH v2 3/4] xfs_io: make ls/chattr work with " Andrey Albershteyn
@ 2025-08-28 14:40 ` Darrick J. Wong
0 siblings, 0 replies; 18+ messages in thread
From: Darrick J. Wong @ 2025-08-28 14:40 UTC (permalink / raw)
To: Andrey Albershteyn; +Cc: aalbersh, linux-fsdevel, linux-xfs
On Wed, Aug 27, 2025 at 05:15:55PM +0200, Andrey Albershteyn wrote:
> From: Andrey Albershteyn <aalbersh@redhat.com>
>
> With new file_getattr/file_setattr syscalls we can now list/change file
> attributes on special files instead for ignoring them.
>
> Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
> ---
> io/attr.c | 138 +++++++++++++++++++++++++++++++++++++-------------------------
> io/io.h | 2 +-
> io/stat.c | 2 +-
> 3 files changed, 84 insertions(+), 58 deletions(-)
>
> diff --git a/io/attr.c b/io/attr.c
> index fd82a2e73801..1005450ac9f9 100644
> --- a/io/attr.c
> +++ b/io/attr.c
> @@ -8,6 +8,7 @@
> #include "input.h"
> #include "init.h"
> #include "io.h"
> +#include "libfrog/file_attr.h"
>
> static cmdinfo_t chattr_cmd;
> static cmdinfo_t lsattr_cmd;
> @@ -113,7 +114,7 @@ chattr_help(void)
> }
>
> void
> -printxattr(
> +print_xflags(
> uint flags,
> int verbose,
> int dofname,
> @@ -156,36 +157,36 @@ lsattr_callback(
> int status,
> struct FTW *data)
> {
> - struct fsxattr fsx;
> - int fd;
> + struct file_attr fa;
> + int error;
>
> if (recurse_dir && !S_ISDIR(stat->st_mode))
> return 0;
>
> - if ((fd = open(path, O_RDONLY)) == -1) {
> - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> - progname, path, strerror(errno));
> - exitcode = 1;
> - } else if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
> + error = xfrog_file_getattr(AT_FDCWD, path, stat, &fa,
> + AT_SYMLINK_NOFOLLOW);
> + if (error) {
^^^^^^ spaces not tabs for indentation
With the indentation problems all fixed (there are a few more here),
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> progname, path, strerror(errno));
> exitcode = 1;
> - } else
> - printxattr(fsx.fsx_xflags, 0, 1, path, 0, 1);
> + return 0;
> + }
> +
> + print_xflags(fa.fa_xflags, 0, 1, path, 0, 1);
>
> - if (fd != -1)
> - close(fd);
> return 0;
> }
>
> static int
> lsattr_f(
> - int argc,
> - char **argv)
> + int argc,
> + char **argv)
> {
> - struct fsxattr fsx;
> - char *name = file->name;
> - int c, aflag = 0, vflag = 0;
> + struct file_attr fa;
> + char *name = file->name;
> + int c, aflag = 0, vflag = 0;
> + struct stat st;
> + int error;
>
> recurse_all = recurse_dir = 0;
> while ((c = getopt(argc, argv, "DRav")) != EOF) {
> @@ -211,17 +212,28 @@ lsattr_f(
> if (recurse_all || recurse_dir) {
> nftw(name, lsattr_callback,
> 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
> - } else if ((xfsctl(name, file->fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
> + return 0;
> + }
> +
> + error = stat(name, &st);
> + if (error)
> + return error;
> +
> + error = xfrog_file_getattr(AT_FDCWD, name, &st, &fa,
> + AT_SYMLINK_NOFOLLOW);
> + if (error) {
> fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> progname, name, strerror(errno));
> exitcode = 1;
> - } else {
> - printxattr(fsx.fsx_xflags, vflag, !aflag, name, vflag, !aflag);
> - if (aflag) {
> - fputs("/", stdout);
> - printxattr(-1, 0, 1, name, 0, 1);
> - }
> + return 0;
> }
> +
> + print_xflags(fa.fa_xflags, vflag, !aflag, name, vflag, !aflag);
> + if (aflag) {
> + fputs("/", stdout);
> + print_xflags(-1, 0, 1, name, 0, 1);
> + }
> +
> return 0;
> }
>
> @@ -232,44 +244,45 @@ chattr_callback(
> int status,
> struct FTW *data)
> {
> - struct fsxattr attr;
> - int fd;
> + struct file_attr attr;
> + int error;
>
> if (recurse_dir && !S_ISDIR(stat->st_mode))
> return 0;
>
> - if ((fd = open(path, O_RDONLY)) == -1) {
> - fprintf(stderr, _("%s: cannot open %s: %s\n"),
> - progname, path, strerror(errno));
> - exitcode = 1;
> - } else if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &attr) < 0) {
> + error = xfrog_file_getattr(AT_FDCWD, path, stat, &attr,
> + AT_SYMLINK_NOFOLLOW);
> + if (error) {
> fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> progname, path, strerror(errno));
> exitcode = 1;
> - } else {
> - attr.fsx_xflags |= orflags;
> - attr.fsx_xflags &= ~andflags;
> - if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &attr) < 0) {
> - fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
> - progname, path, strerror(errno));
> - exitcode = 1;
> - }
> + return 0;
> + }
> +
> + attr.fa_xflags |= orflags;
> + attr.fa_xflags &= ~andflags;
> + error = xfrog_file_setattr(AT_FDCWD, path, stat, &attr,
> + AT_SYMLINK_NOFOLLOW);
> + if (error) {
> + fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
> + progname, path, strerror(errno));
> + exitcode = 1;
> }
>
> - if (fd != -1)
> - close(fd);
> return 0;
> }
>
> static int
> chattr_f(
> - int argc,
> - char **argv)
> + int argc,
> + char **argv)
> {
> - struct fsxattr attr;
> - struct xflags *p;
> - unsigned int i = 0;
> - char *c, *name = file->name;
> + struct file_attr attr;
> + struct xflags *p;
> + unsigned int i = 0;
> + char *c, *name = file->name;
> + struct stat st;
> + int error;
>
> orflags = andflags = 0;
> recurse_all = recurse_dir = 0;
> @@ -326,19 +339,32 @@ chattr_f(
> if (recurse_all || recurse_dir) {
> nftw(name, chattr_callback,
> 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
> - } else if (xfsctl(name, file->fd, FS_IOC_FSGETXATTR, &attr) < 0) {
> + return 0;
> + }
> +
> + error = stat(name, &st);
> + if (error)
> + return error;
> +
> + error = xfrog_file_getattr(AT_FDCWD, name, &st, &attr,
> + AT_SYMLINK_NOFOLLOW);
> + if (error) {
> fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
> progname, name, strerror(errno));
> exitcode = 1;
> - } else {
> - attr.fsx_xflags |= orflags;
> - attr.fsx_xflags &= ~andflags;
> - if (xfsctl(name, file->fd, FS_IOC_FSSETXATTR, &attr) < 0) {
> - fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
> - progname, name, strerror(errno));
> - exitcode = 1;
> - }
> + return 0;
> }
> +
> + attr.fa_xflags |= orflags;
> + attr.fa_xflags &= ~andflags;
> + error = xfrog_file_setattr(AT_FDCWD, name, &st, &attr,
> + AT_SYMLINK_NOFOLLOW);
> + if (error) {
> + fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
> + progname, name, strerror(errno));
> + exitcode = 1;
> + }
> +
> return 0;
> }
>
> diff --git a/io/io.h b/io/io.h
> index 259c034931b8..35fb8339eeb5 100644
> --- a/io/io.h
> +++ b/io/io.h
> @@ -78,7 +78,7 @@ extern int openfile(char *, struct xfs_fsop_geom *, int, mode_t,
> extern int addfile(char *, int , struct xfs_fsop_geom *, int,
> struct fs_path *);
> extern int closefile(void);
> -extern void printxattr(uint, int, int, const char *, int, int);
> +extern void print_xflags(uint, int, int, const char *, int, int);
>
> extern unsigned int recurse_all;
> extern unsigned int recurse_dir;
> diff --git a/io/stat.c b/io/stat.c
> index c257037aa8ee..c1085f14eade 100644
> --- a/io/stat.c
> +++ b/io/stat.c
> @@ -112,7 +112,7 @@ print_extended_info(int verbose)
> }
>
> printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags);
> - printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
> + print_xflags(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
> printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid);
> printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize);
> printf(_("fsxattr.cowextsize = %u\n"), fsx.fsx_cowextsize);
>
> --
> 2.49.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 4/4] xfs_db: use file_setattr to copy attributes on special files with rdump
2025-08-27 15:15 ` [PATCH v2 0/4] xfsprogs: utilize file_getattr() and file_setattr() Andrey Albershteyn
` (2 preceding siblings ...)
2025-08-27 15:15 ` [PATCH v2 3/4] xfs_io: make ls/chattr work with " Andrey Albershteyn
@ 2025-08-27 15:15 ` Andrey Albershteyn
2025-08-28 14:41 ` Darrick J. Wong
3 siblings, 1 reply; 18+ messages in thread
From: Andrey Albershteyn @ 2025-08-27 15:15 UTC (permalink / raw)
To: aalbersh, linux-fsdevel, linux-xfs
rdump just skipped file attributes on special files as copying wasn't
possible. Let's use new file_getattr/file_setattr syscalls to copy
attributes even for special files.
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
---
db/rdump.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/db/rdump.c b/db/rdump.c
index 9ff833553ccb..82520e37d713 100644
--- a/db/rdump.c
+++ b/db/rdump.c
@@ -17,6 +17,7 @@
#include "field.h"
#include "inode.h"
#include "listxattr.h"
+#include "libfrog/file_attr.h"
#include <sys/xattr.h>
#include <linux/xattr.h>
@@ -152,6 +153,12 @@ rdump_fileattrs_path(
const struct destdir *destdir,
const struct pathbuf *pbuf)
{
+ struct file_attr fa = {
+ .fa_extsize = ip->i_extsize,
+ .fa_projid = ip->i_projid,
+ .fa_cowextsize = ip->i_cowextsize,
+ .fa_xflags = xfs_ip2xflags(ip),
+ };
int ret;
ret = fchmodat(destdir->fd, pbuf->path, VFS_I(ip)->i_mode & ~S_IFMT,
@@ -181,7 +188,18 @@ rdump_fileattrs_path(
return 1;
}
- /* Cannot copy fsxattrs until setfsxattrat gets merged */
+ ret = xfrog_file_setattr(destdir->fd, pbuf->path, NULL, &fa,
+ AT_SYMLINK_NOFOLLOW);
+ if (ret) {
+ if (errno == EOPNOTSUPP || errno == EPERM || errno == ENOTTY)
+ lost_mask |= LOST_FSXATTR;
+ else
+ dbprintf(_("%s%s%s: xfrog_file_setattr %s\n"),
+ destdir->path, destdir->sep, pbuf->path,
+ strerror(errno));
+ if (strict_errors)
+ return 1;
+ }
return 0;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 4/4] xfs_db: use file_setattr to copy attributes on special files with rdump
2025-08-27 15:15 ` [PATCH v2 4/4] xfs_db: use file_setattr to copy attributes on special files with rdump Andrey Albershteyn
@ 2025-08-28 14:41 ` Darrick J. Wong
0 siblings, 0 replies; 18+ messages in thread
From: Darrick J. Wong @ 2025-08-28 14:41 UTC (permalink / raw)
To: Andrey Albershteyn; +Cc: aalbersh, linux-fsdevel, linux-xfs
On Wed, Aug 27, 2025 at 05:15:56PM +0200, Andrey Albershteyn wrote:
> rdump just skipped file attributes on special files as copying wasn't
> possible. Let's use new file_getattr/file_setattr syscalls to copy
> attributes even for special files.
>
> Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Looks good!
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> db/rdump.c | 20 +++++++++++++++++++-
> 1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/db/rdump.c b/db/rdump.c
> index 9ff833553ccb..82520e37d713 100644
> --- a/db/rdump.c
> +++ b/db/rdump.c
> @@ -17,6 +17,7 @@
> #include "field.h"
> #include "inode.h"
> #include "listxattr.h"
> +#include "libfrog/file_attr.h"
> #include <sys/xattr.h>
> #include <linux/xattr.h>
>
> @@ -152,6 +153,12 @@ rdump_fileattrs_path(
> const struct destdir *destdir,
> const struct pathbuf *pbuf)
> {
> + struct file_attr fa = {
> + .fa_extsize = ip->i_extsize,
> + .fa_projid = ip->i_projid,
> + .fa_cowextsize = ip->i_cowextsize,
> + .fa_xflags = xfs_ip2xflags(ip),
> + };
> int ret;
>
> ret = fchmodat(destdir->fd, pbuf->path, VFS_I(ip)->i_mode & ~S_IFMT,
> @@ -181,7 +188,18 @@ rdump_fileattrs_path(
> return 1;
> }
>
> - /* Cannot copy fsxattrs until setfsxattrat gets merged */
> + ret = xfrog_file_setattr(destdir->fd, pbuf->path, NULL, &fa,
> + AT_SYMLINK_NOFOLLOW);
> + if (ret) {
> + if (errno == EOPNOTSUPP || errno == EPERM || errno == ENOTTY)
> + lost_mask |= LOST_FSXATTR;
> + else
> + dbprintf(_("%s%s%s: xfrog_file_setattr %s\n"),
> + destdir->path, destdir->sep, pbuf->path,
> + strerror(errno));
> + if (strict_errors)
> + return 1;
> + }
>
> return 0;
> }
>
> --
> 2.49.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread