Whamcloud - gitweb
LU-4017 e2fsprogs: add [ch/ls]attr support for project quota 95/18895/16
authorWang Shilong <wshilong@ddn.com>
Wed, 6 Jan 2016 17:18:48 +0000 (12:18 -0500)
committerAndreas Dilger <andreas.dilger@intel.com>
Tue, 9 Aug 2016 09:37:21 +0000 (09:37 +0000)
You could use it like
chattr -p <project id> file
lsattr -p file

Signed-off-by: Li Xi <lixi@ddn.com>
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Change-Id: I99ecf92b719c32135668f4dc7b11a85da52e0b2e
Reviewed-on: http://review.whamcloud.com/18895
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Andreas Dilger <andreas.dilger@intel.com>
lib/e2p/Makefile.in
lib/e2p/e2p.h
lib/e2p/fgetproject.c [new file with mode: 0644]
lib/e2p/fsetproject.c [new file with mode: 0644]
lib/e2p/project.h [new file with mode: 0644]
misc/chattr.1.in
misc/chattr.c
misc/lsattr.1.in
misc/lsattr.c

index 1c71c1c..468898a 100644 (file)
@@ -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
index 5fa41f4..66b83b4 100644 (file)
@@ -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 (file)
index 0000000..12320b5
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * fgetproject.c --- get project id
+ *
+ * Copyright (C) 1999  Theodore Ts'o <tytso@mit.edu>
+ *
+ * %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 <errno.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#if HAVE_EXT2_IOCTLS
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#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 (file)
index 0000000..5df7090
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * fgetproject.c --- get project id
+ *
+ * Copyright (C) 1999  Theodore Ts'o <tytso@mit.edu>
+ *
+ * %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 <errno.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#if HAVE_EXT2_IOCTLS
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#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 (file)
index 0000000..253425a
--- /dev/null
@@ -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 <ext2fs/ext2_fs.h>
+
+#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
+
index 75b3ed8..67f9a42 100644 (file)
@@ -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
index f5fa397..2b7b01e 100644 (file)
@@ -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);
        }
index 7798a34..97a46d3 100644 (file)
@@ -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 <Remy.Card@linux.org>.  It is currently being
index e5e5969..879f94f 100644 (file)
@@ -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();
                }