]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_quota: utilize file_setattr to set prjid on special files
authorAndrey Albershteyn <aalbersh@redhat.com>
Tue, 9 Sep 2025 15:24:37 +0000 (17:24 +0200)
committerAndrey Albershteyn <aalbersh@kernel.org>
Mon, 15 Sep 2025 09:10:05 +0000 (11:10 +0200)
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>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
quota/project.c

index adb26945fa57bd2cbc07c62dd2e3eb9ad823a3bb..5832e1474e2549d61c652de543f98d69e9c2b866 100644 (file)
@@ -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