From: Andrey Albershteyn <aalbersh@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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