--- /dev/null
+From 611406e29293c37b4a8771073030ccdaf0bd4fa5 Mon Sep 17 00:00:00 2001
+From: Li Xi <pkuelelixi@gmail.com>
+Subject: [PATCH] vfs: Add general support to enforce project quota limits
+
+This patch adds support for a new quota type PRJQUOTA for project quota
+enforcement. Also a new method get_projid() is added into dquot_operations
+structure.
+
+Signed-off-by: Li Xi <lixi@ddn.com>
+Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jan Kara <jack@suse.cz>
+----
+
+diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
+index d7d5a0a..6b80f11 100644
+--- a/fs/quota/dquot.c
++++ b/fs/quota/dquot.c
+@@ -1152,8 +1152,8 @@ static int need_print_warning(struct dquot_warn *warn)
+ return uid_eq(current_fsuid(), warn->w_dq_id.uid);
+ case GRPQUOTA:
+ return in_group_p(warn->w_dq_id.gid);
+- case PRJQUOTA: /* Never taken... Just make gcc happy */
+- return 0;
++ case PRJQUOTA:
++ return 1;
+ }
+ return 0;
+ }
+@@ -1392,6 +1392,9 @@ static void __dquot_initialize(struct inode *inode, int type)
+ /* First get references to structures we might need. */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ struct kqid qid;
++ kprojid_t projid;
++ int rc;
++
+ got[cnt] = NULL;
+ if (type != -1 && cnt != type)
+ continue;
+@@ -1402,6 +1405,10 @@ static void __dquot_initialize(struct inode *inode, int type)
+ */
+ if (inode->i_dquot[cnt])
+ continue;
++
++ if (!sb_has_quota_active(sb, cnt))
++ continue;
++
+ init_needed = 1;
+
+ switch (cnt) {
+@@ -1411,6 +1418,12 @@ static void __dquot_initialize(struct inode *inode, int type)
+ case GRPQUOTA:
+ qid = make_kqid_gid(inode->i_gid);
+ break;
++ case PRJQUOTA:
++ rc = inode->i_sb->dq_op->get_projid(inode, &projid);
++ if (rc)
++ continue;
++ qid = make_kqid_projid(projid);
++ break;
+ }
+ got[cnt] = dqget(sb, qid);
+ }
+@@ -2154,7 +2167,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
+ error = -EROFS;
+ goto out_fmt;
+ }
+- if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
++ if (!sb->s_op->quota_write || !sb->s_op->quota_read ||
++ (type == PRJQUOTA && sb->dq_op->get_projid == NULL)) {
+ error = -EINVAL;
+ goto out_fmt;
+ }
+diff --git a/fs/quota/quotaio_v2.h b/fs/quota/quotaio_v2.h
+index f1966b4..4e95430 100644
+--- a/fs/quota/quotaio_v2.h
++++ b/fs/quota/quotaio_v2.h
+@@ -13,12 +13,14 @@
+ */
+ #define V2_INITQMAGICS {\
+ 0xd9c01f11, /* USRQUOTA */\
+- 0xd9c01927 /* GRPQUOTA */\
++ 0xd9c01927, /* GRPQUOTA */\
++ 0xd9c03f14, /* PRJQUOTA */\
+ }
+
+ #define V2_INITQVERSIONS {\
+ 1, /* USRQUOTA */\
+- 1 /* GRPQUOTA */\
++ 1, /* GRPQUOTA */\
++ 1, /* PRJQUOTA */\
+ }
+
+ /* First generic header */
+diff --git a/include/linux/quota.h b/include/linux/quota.h
+index 99932a5..0d20c39 100644
+--- a/include/linux/quota.h
++++ b/include/linux/quota.h
+@@ -52,6 +52,7 @@
+
+ #undef USRQUOTA
+ #undef GRPQUOTA
++#undef PRJQUOTA
+ enum quota_type {
+ USRQUOTA = 0, /* element used for user quotas */
+ GRPQUOTA = 1, /* element used for group quotas */
+@@ -314,6 +315,7 @@ struct dquot_operations {
+ /* get reserved quota for delayed alloc, value returned is managed by
+ * quota code only */
+ qsize_t *(*get_reserved_space) (struct inode *);
++ int (*get_projid) (struct inode *, kprojid_t *);/* Get project ID */
+ };
+
+ struct path;
+diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
+index 83d19df..418e9dd 100644
+--- a/include/uapi/linux/fs.h
++++ b/include/uapi/linux/fs.h
+@@ -58,6 +58,36 @@ struct inodes_stat_t {
+ int dummy[5]; /* padding for sysctl ABI compatibility */
+ };
+
++/*
++ * 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];
++};
++#define HAVE_FSXATTR 1
++
++/*
++ * Flags for the fsx_xflags field
++ */
++#define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */
++#define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */
++#define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */
++#define FS_XFLAG_APPEND 0x00000010 /* all writes append */
++#define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */
++#define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */
++#define FS_XFLAG_NODUMP 0x00000080 /* do not include in backups */
++#define FS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */
++#define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */
++#define FS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */
++#define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
++#define FS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
++#define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
++#define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */
++#define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
+
+ #define NR_FILE 8192 /* this can well be larger on a larger system */
+
+@@ -163,6 +193,8 @@ struct inodes_stat_t {
+ #define FS_IOC_GETVERSION _IOR('v', 1, long)
+ #define FS_IOC_SETVERSION _IOW('v', 2, long)
+ #define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
++#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr)
++#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
+ #define FS_IOC32_GETFLAGS _IOR('f', 1, int)
+ #define FS_IOC32_SETFLAGS _IOW('f', 2, int)
+ #define FS_IOC32_GETVERSION _IOR('v', 1, int)
+@@ -195,6 +227,7 @@ struct inodes_stat_t {
+ #define FS_EXTENT_FL 0x00080000 /* Extents */
+ #define FS_DIRECTIO_FL 0x00100000 /* Use direct i/o */
+ #define FS_NOCOW_FL 0x00800000 /* Do not cow file */
++#define FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
+ #define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
+
+ #define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
+diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h
+index 3b6cfbe..b2d9486 100644
+--- a/include/uapi/linux/quota.h
++++ b/include/uapi/linux/quota.h
+@@ -36,11 +36,12 @@
+ #include <linux/errno.h>
+ #include <linux/types.h>
+
+-#define __DQUOT_VERSION__ "dquot_6.5.2"
++#define __DQUOT_VERSION__ "dquot_6.6.0"
+
+-#define MAXQUOTAS 2
++#define MAXQUOTAS 3
+ #define USRQUOTA 0 /* element used for user quotas */
+ #define GRPQUOTA 1 /* element used for group quotas */
++#define PRJQUOTA 2 /* element used for project quotas */
+
+ /*
+ * Definitions for the default names of the quotas files.
+@@ -48,6 +49,7 @@
+ #define INITQFNAMES { \
+ "user", /* USRQUOTA */ \
+ "group", /* GRPQUOTA */ \
++ "project", /* PRJQUOTA */ \
+ "undefined", \
+ };
+