From b4dd0d87920d016d5d5a12d3990fc6560ec69e22 Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Wed, 6 Jan 2016 12:18:48 -0500 Subject: [PATCH] LU-4017 e2fsprogs: add [ch/ls]attr support for project quota You could use it like chattr -p file lsattr -p file Signed-off-by: Li Xi Signed-off-by: Wang Shilong Change-Id: I99ecf92b719c32135668f4dc7b11a85da52e0b2e Reviewed-on: http://review.whamcloud.com/18895 Tested-by: Jenkins Reviewed-by: Andreas Dilger Tested-by: Andreas Dilger --- lib/e2p/Makefile.in | 11 ++++++-- lib/e2p/e2p.h | 2 ++ lib/e2p/fgetproject.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ lib/e2p/fsetproject.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/e2p/project.h | 27 ++++++++++++++++++++ misc/chattr.1.in | 7 ++++++ misc/chattr.c | 33 ++++++++++++++++++++++-- misc/lsattr.1.in | 5 +++- misc/lsattr.c | 18 ++++++++++++-- 9 files changed, 228 insertions(+), 7 deletions(-) create mode 100644 lib/e2p/fgetproject.c create mode 100644 lib/e2p/fsetproject.c create mode 100644 lib/e2p/project.h diff --git a/lib/e2p/Makefile.in b/lib/e2p/Makefile.in index 1c71c1c..468898a 100644 --- a/lib/e2p/Makefile.in +++ b/lib/e2p/Makefile.in @@ -19,7 +19,7 @@ all:: e2p.pc OBJS= feature.o fgetflags.o fsetflags.o fgetversion.o fsetversion.o \ getflags.o getversion.o hashstr.o iod.o ls.o mntopts.o \ parse_num.o pe.o pf.o ps.o setflags.o setversion.o uuid.o \ - ostype.o percent.o + ostype.o percent.o fgetproject.o fsetproject.o SRCS= $(srcdir)/feature.c $(srcdir)/fgetflags.c \ $(srcdir)/fsetflags.c $(srcdir)/fgetversion.c \ @@ -28,7 +28,8 @@ SRCS= $(srcdir)/feature.c $(srcdir)/fgetflags.c \ $(srcdir)/ls.c $(srcdir)/mntopts.c $(srcdir)/parse_num.c \ $(srcdir)/pe.c $(srcdir)/pf.c $(srcdir)/ps.c \ $(srcdir)/setflags.c $(srcdir)/setversion.c $(srcdir)/uuid.c \ - $(srcdir)/ostype.c $(srcdir)/percent.c + $(srcdir)/ostype.c $(srcdir)/percent.c $(srcdir)/fgetproject.c \ + $(srcdir)/fsetproject.c HFILES= e2p.h LIBRARY= libe2p @@ -136,6 +137,12 @@ fgetversion.o: $(srcdir)/fgetversion.c $(top_builddir)/lib/config.h \ fsetversion.o: $(srcdir)/fsetversion.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/e2p.h \ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h +fsetproject.o: $(srcdir)/fsetproject.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2p.h $(srcdir)/project.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h +fgetproject.o: $(srcdir)/fgetproject.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2p.h $(srcdir)/project.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h getflags.o: $(srcdir)/getflags.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/e2p.h \ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h diff --git a/lib/e2p/e2p.h b/lib/e2p/e2p.h index 5fa41f4..66b83b4 100644 --- a/lib/e2p/e2p.h +++ b/lib/e2p/e2p.h @@ -32,6 +32,8 @@ int fgetflags (const char * name, unsigned long * flags); int fgetversion (const char * name, unsigned long * version); int fsetflags (const char * name, unsigned long flags); int fsetversion (const char * name, unsigned long version); +int fgetproject(const char *name, unsigned long *project); +int fsetproject(const char *name, unsigned long project); int getflags (int fd, unsigned long * flags); int getversion (int fd, unsigned long * version); int iterate_on_dir (const char * dir_name, diff --git a/lib/e2p/fgetproject.c b/lib/e2p/fgetproject.c new file mode 100644 index 0000000..12320b5 --- /dev/null +++ b/lib/e2p/fgetproject.c @@ -0,0 +1,63 @@ +/* + * fgetproject.c --- get project id + * + * Copyright (C) 1999 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#include +#include "project.h" +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fgetproject(const char *name, unsigned long *project) +{ +#ifndef FS_IOC_FSGETXATTR + errno = EOPNOTSUPP; + return -1; +#else + int fd, r, save_errno = 0; + struct fsxattr fsx; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx); + if (r == 0) + *project = fsx.fsx_projid; + save_errno = errno; + close (fd); + if (save_errno) + errno = save_errno; + return r; +#endif +} diff --git a/lib/e2p/fsetproject.c b/lib/e2p/fsetproject.c new file mode 100644 index 0000000..5df7090 --- /dev/null +++ b/lib/e2p/fsetproject.c @@ -0,0 +1,69 @@ +/* + * fgetproject.c --- get project id + * + * Copyright (C) 1999 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#include +#include "project.h" +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fsetproject(const char *name, unsigned long project) +{ +#ifndef FS_IOC_FSGETXATTR + errno = EOPNOTSUPP; + return -1; +#else + int fd, r, save_errno = 0; + struct fsxattr fsx; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx); + if (r == -1) { + save_errno = errno; + goto errout; + } + fsx.fsx_projid = project; + r = ioctl (fd, FS_IOC_FSSETXATTR, &fsx); + if (r == -1) + save_errno = errno; +errout: + close (fd); + if (save_errno) + errno = save_errno; + return r; +#endif +} diff --git a/lib/e2p/project.h b/lib/e2p/project.h new file mode 100644 index 0000000..253425a --- /dev/null +++ b/lib/e2p/project.h @@ -0,0 +1,27 @@ +/* + * project.h + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include + +#if defined(__linux__) && !defined(FS_IOC_FSGETXATTR) +#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr) +#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr) + +/* + * Structure for FS_IOC_FSGETXATTR and FS_IOC_FSSETXATTR. + */ +struct fsxattr { + __u32 fsx_xflags; /* xflags field value (get/set) */ + __u32 fsx_extsize; /* extsize field value (get/set)*/ + __u32 fsx_nextents; /* nextents field value (get) */ + __u32 fsx_projid; /* project identifier (get/set) */ + unsigned char fsx_pad[12]; +}; +#endif + diff --git a/misc/chattr.1.in b/misc/chattr.1.in index 75b3ed8..67f9a42 100644 --- a/misc/chattr.1.in +++ b/misc/chattr.1.in @@ -12,6 +12,10 @@ chattr \- change file attributes on a Linux file system .I version ] [ +.B \-p +.I project +] +[ .I mode ] .I files... @@ -71,6 +75,9 @@ Suppress most error messages. .TP .BI \-v " version" Set the file's version/generation number. +.TP +.BI \-p " project" +Set the file's project number. .SH ATTRIBUTES A file with the 'a' attribute set can only be open in append mode for writing. Only the superuser or a process possessing the CAP_LINUX_IMMUTABLE diff --git a/misc/chattr.c b/misc/chattr.c index f5fa397..2b7b01e 100644 --- a/misc/chattr.c +++ b/misc/chattr.c @@ -64,6 +64,9 @@ static int set_version; static unsigned long version; +static int set_project; +static unsigned long project; + static int recursive; static int verbose; static int silent; @@ -83,7 +86,7 @@ static unsigned long sf; static void usage(void) { fprintf(stderr, - _("Usage: %s [-RVf] [-+=aAcCdDeijPsStTu] [-v version] files...\n"), + _("Usage: %s [-RVf] [-+=aAcCdDeijPsStTu] [-v version] [-p project] files...\n"), program_name); exit(1); } @@ -146,6 +149,20 @@ static int decode_arg (int * i, int argc, char ** argv) silent = 1; continue; } + if (*p == 'p') { + (*i)++; + if (*i >= argc) + usage (); + project = strtol (argv[*i], &tmp, 0); + if (*tmp) { + com_err (program_name, 0, + _("bad project - %s\n"), + argv[*i]); + usage (); + } + set_project = 1; + continue; + } if (*p == 'v') { (*i)++; if (*i >= argc) @@ -249,6 +266,18 @@ static int change_attributes(const char * name) return -1; } } + if (set_project) { + if (verbose) + printf (_("Project of %s set as %lu\n"), name, version); + if (fsetproject (name, project) == -1) { + if (!silent) + com_err (program_name, errno, + _("while setting project on %s"), + name); + return -1; + } + + } if (S_ISDIR(st.st_mode) && recursive) return iterate_on_dir (name, chattr_dir_proc, NULL); return 0; @@ -312,7 +341,7 @@ int main (int argc, char ** argv) fputs("Can't both set and unset same flag.\n", stderr); exit (1); } - if (!(add || rem || set || set_version)) { + if (!(add || rem || set || set_version || set_project )) { fputs(_("Must use '-v', =, - or +\n"), stderr); exit (1); } diff --git a/misc/lsattr.1.in b/misc/lsattr.1.in index 7798a34..97a46d3 100644 --- a/misc/lsattr.1.in +++ b/misc/lsattr.1.in @@ -5,7 +5,7 @@ lsattr \- list file attributes on a Linux second extended file system .SH SYNOPSIS .B lsattr [ -.B \-RVadv +.B \-RVadvp ] [ .I files... @@ -31,6 +31,9 @@ List directories like other files, rather than listing their contents. .TP .B \-v List the file's version/generation number. +.TP +.B \-p +List the file's project number. .SH AUTHOR .B lsattr was written by Remy Card . It is currently being diff --git a/misc/lsattr.c b/misc/lsattr.c index e5e5969..879f94f 100644 --- a/misc/lsattr.c +++ b/misc/lsattr.c @@ -60,6 +60,7 @@ static unsigned pf_options; static int recursive; static int verbose; static int generation_opt; +static int project_opt; #ifdef _LFS64_LARGEFILE #define LSTAT lstat64 @@ -71,7 +72,7 @@ static int generation_opt; static void usage(void) { - fprintf(stderr, _("Usage: %s [-RVadlv] [files...]\n"), program_name); + fprintf(stderr, _("Usage: %s [-RVadlvp] [files...]\n"), program_name); exit(1); } @@ -79,12 +80,22 @@ static int list_attributes (const char * name) { unsigned long flags; unsigned long generation; + unsigned long project; if (fgetflags (name, &flags) == -1) { com_err (program_name, errno, _("While reading flags on %s"), name); return -1; } + if (project_opt) { + if (fgetproject(name, &project) == -1) { + com_err (program_name, errno, + _("While reading project on %s"), + name); + return -1; + } + printf ("%5lu ", project); + } if (generation_opt) { if (fgetversion (name, &generation) == -1) { com_err (program_name, errno, @@ -171,7 +182,7 @@ int main (int argc, char ** argv) #endif if (argc && *argv) program_name = *argv; - while ((c = getopt (argc, argv, "RVadlv")) != EOF) + while ((c = getopt (argc, argv, "RVadlvp")) != EOF) switch (c) { case 'R': @@ -192,6 +203,9 @@ int main (int argc, char ** argv) case 'v': generation_opt = 1; break; + case 'p': + project_opt = 1; + break; default: usage(); } -- 1.8.3.1