All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Andrey Albershteyn <aalbersh@redhat.com>
Cc: aalbersh@kernel.org, linux-fsdevel@vger.kernel.org,
	linux-xfs@vger.kernel.org
Subject: Re: [PATCH 1/4] libfrog: add wrappers for file_getattr/file_setattr syscalls
Date: Tue, 12 Aug 2025 07:53:18 -0700	[thread overview]
Message-ID: <20250812145318.GE7942@frogsfrogsfrogs> (raw)
In-Reply-To: <echftqsxxxecifnok2j3tbel377ds7cud2cm5kjc5qbtwszn2m@retzo6pcntfv>

On Mon, Aug 11, 2025 at 07:44:14PM +0200, Andrey Albershteyn wrote:
> On 2025-08-11 08:02:42, Darrick J. Wong wrote:
> > On Fri, Aug 08, 2025 at 09:30:16PM +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   | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  libfrog/file_attr.h   |  35 +++++++++++++++++
> > >  m4/package_libcdev.m4 |  19 +++++++++
> > >  7 files changed, 187 insertions(+)
> > > 
> > > diff --git a/configure.ac b/configure.ac
> > > index 9a3309bcdfd1..40a44c571e7b 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..018cc78960e3 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 __NR_file_getattr 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 __NR_file_getattr
> > 
> > Seeing as uapi fs.h now has:
> > 
> > #define FILE_ATTR_SIZE_VER0 24
> > #define FILE_ATTR_SIZE_LATEST FILE_ATTR_SIZE_VER0
> > 
> > I wonder if you'd be better off gating on one of those defines rather
> > than the presence of the syscall number?
> 
> Hmm, yeah, should work
> 
> > 
> > > +/*
> > > + * 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 b64ca4597f4e..7d49fd0fe6cc 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..8592d775f554
> > > --- /dev/null
> > > +++ b/libfrog/file_attr.c
> > > @@ -0,0 +1,105 @@
> > > +// 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
> > > +file_getattr(
> > > +	const int		dfd,
> > > +	const char		*path,
> > > +	const struct stat	*stat,
> > > +	struct file_attr	*fa,
> > > +	const unsigned int	at_flags)
> > > +{
> > 
> > Will this cause a naming conflict when libc wraps the new syscall?
> 
> xfrog_file_getattr?
> 
> > 
> > > +	int			error;
> > > +	int			fd;
> > > +	struct fsxattr		fsxa;
> > > +
> > > +#ifdef HAVE_FILE_ATTR
> > > +	return syscall(__NR_file_getattr, dfd, path, fa,
> > > +			sizeof(struct file_attr), at_flags);
> > 
> > What happens if we build xfsprogs on new userspace but it then gets run
> > on an old kernel that doesn't support file_getattr(2)?  Shouldn't we
> > fall back to the old ioctl on ENOSYS?
> 
> oh right, missed that. I can add this check.
> 
> Is it something common in general? I suppose booting into older
> kernel when xfsprogs was compiled with the "current" one is one case
> but it's expected that kernel can miss some features

I don't think it's common among packaged distributions, but developers
(or at least myself) regularly do things like that.

> > 
> > > +#else
> > > +	if (SPECIAL_FILE(stat->st_mode))
> > > +		return 0;
> > 
> > Why does it return 0 without filling out @fa?  Shouldn't this be
> > EOPNOTSUPP or something?
> > 
> > > +#endif
> > > +
> > > +	fd = open(path, O_RDONLY|O_NOCTTY);
> > > +	if (fd == -1)
> > > +		return errno;
> > > +
> > > +	error = ioctl(fd, FS_IOC_FSGETXATTR, &fsxa);
> > > +	close(fd);
> > > +
> > > +	fsxattr_to_file_attr(&fsxa, fa);
> > 
> > Er... if the ioctl errors out, fsxa will still be uninitialized stack
> > garbage, which is (pointlessly) copied to the caller's fa structure.
> > 
> > > +
> > > +	return error;
> > 
> > I'm confused about the return value of this function.  If the syscall
> > or the ioctl fail we'll pass the -1 to the caller and let them access
> > errno, but if the open fails we return errno directly?
> 
> I was trying to just wrap the old code without changing the output,
> I haven't thought too hard about design of this function. I will
> apply your suggestion including EOPNOSUPP mentioned in other mail.

<nod>

--D

> > 
> > > +}
> > > +
> > > +int
> > > +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
> > > +	return syscall(__NR_file_setattr, dfd, path, fa,
> > > +			sizeof(struct file_attr), at_flags);
> > > +#else
> > > +	if (SPECIAL_FILE(stat->st_mode))
> > > +		return 0;
> > > +#endif
> > > +
> > > +	fd = open(path, O_RDONLY|O_NOCTTY);
> > > +	if (fd == -1)
> > > +		return errno;
> > 
> > Same comments that I had about file_getattr.
> > 
> > > +
> > > +	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..3e56e80a6f95
> > > --- /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_IXATTR_H__
> > > +#define __LIBFROG_IXATTR_H__
> > 
> > __LIBFROG_FILE_ATTR_H__ ?
> 
> ops, right
> 
> > 
> > --D
> > 
> > > +
> > > +#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
> > > +file_getattr(
> > > +	const int		dfd,
> > > +	const char		*path,
> > > +	const struct stat	*stat,
> > > +	struct file_attr	*fa,
> > > +	const unsigned int	at_flags);
> > > +
> > > +int
> > > +file_setattr(
> > > +	const int		dfd,
> > > +	const char		*path,
> > > +	const struct stat	*stat,
> > > +	struct file_attr	*fa,
> > > +	const unsigned int	at_flags);
> > > +
> > > +#endif /* __LIBFROG_IXATTR_H__ */
> > > diff --git a/m4/package_libcdev.m4 b/m4/package_libcdev.m4
> > > index 61353d0aa9d5..cb8ff1576d01 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
> > > 
> > > 
> > 
> 
> -- 
> - Andrey
> 
> 

  reply	other threads:[~2025-08-12 14:53 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-08 19:28 Tests for file_getattr()/file_setattr() and xfsprogs update Andrey Albershteyn
2025-08-08 19:30 ` [PATCH 0/4] xfsprogs: utilize file_getattr() and file_setattr() Andrey Albershteyn
2025-08-08 19:30   ` [PATCH 1/4] libfrog: add wrappers for file_getattr/file_setattr syscalls Andrey Albershteyn
2025-08-11 15:02     ` Darrick J. Wong
2025-08-11 17:44       ` Andrey Albershteyn
2025-08-12 14:53         ` Darrick J. Wong [this message]
2025-08-08 19:30   ` [PATCH 2/4] xfs_quota: utilize file_setattr to set prjid on special files Andrey Albershteyn
2025-08-11 15:07     ` Darrick J. Wong
2025-08-11 17:51       ` Andrey Albershteyn
2025-08-08 19:30   ` [PATCH 3/4] xfs_io: make ls/chattr work with " Andrey Albershteyn
2025-08-11 15:12     ` Darrick J. Wong
2025-08-11 17:57       ` Andrey Albershteyn
2025-08-12 17:28         ` Darrick J. Wong
2025-08-08 19:30   ` [PATCH 4/4] xfs_db: use file_setattr to copy attributes on special files with rdump Andrey Albershteyn
2025-08-11 15:14     ` Darrick J. Wong
2025-08-11 17:59       ` Andrey Albershteyn
2025-08-08 19:31 ` [PATCH 0/3] Test file_getattr and file_setattr syscalls Andrey Albershteyn
2025-08-08 19:31   ` [PATCH 1/3] file_attr: introduce program to set/get fsxattr Andrey Albershteyn
2025-08-11 15:23     ` Darrick J. Wong
2025-08-11 18:06       ` Andrey Albershteyn
2025-08-11 17:51     ` Zorro Lang
2025-08-11 18:12       ` Andrey Albershteyn
2025-08-08 19:31   ` [PATCH 2/3] generic: introduce test to test file_getattr/file_setattr syscalls Andrey Albershteyn
2025-08-11 15:17     ` Darrick J. Wong
2025-08-11 18:13       ` Andrey Albershteyn
2025-08-11 17:55     ` Zorro Lang
2025-08-11 18:18       ` Andrey Albershteyn
2025-08-11 18:43         ` Zorro Lang
2025-08-08 19:31   ` [PATCH 3/3] xfs: test quota's project ID on special files Andrey Albershteyn
2025-08-11 15:21     ` Darrick J. Wong
2025-08-11 18:21       ` Andrey Albershteyn
2025-08-11 17:46     ` Zorro Lang
2025-08-11 18:20       ` Andrey Albershteyn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250812145318.GE7942@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=aalbersh@kernel.org \
    --cc=aalbersh@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.