All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] RFC: introduce extended inode owner identifier v10
@ 2012-07-09 15:28 Dmitry Monakhov
  2012-07-09 15:28 ` [PATCH 1/3] Add additional owner identifier Dmitry Monakhov
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Dmitry Monakhov @ 2012-07-09 15:28 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel; +Cc: jack, Dmitry Monakhov

Hi, Here is updated version subtree-quota pachset

*Feature description*
1) Inode may has a subtree identifier which has same meaning as uid/gid.
2) In general case Id is stored in inode's xattr named "system.subtree"
3) Id is inherent from parent inode on creation.
4) This id is cached in memory fs_inode structure and may be accessible
   via s_op->get_subtree(). This field it restricted by CONFIG_SUBTREE.
   So no wasting of memory happens.

5) Since id is cached in memory it may be used for different purposes
   such as:
5A) Implement additional quota id space orthogonal to uid/gid. This is
    useful in managing quota for some filesystem hierarchy(chroot or
    container over bindmount)

6) In comparison to XFS's project ID feature it does not affect
   rename(2)/link(2) in case of cross tries transfer

*User interface *
Subtree id is managed via generic xattr interface "system.subtree"
This good because
 1) We may use already existing interface.
 2) xattr already supported by generic utilities tar/rsync and etc

PATCH SET TOC:
1) generic subtree support
2) ext4: generic subtree support
3) ext4: subtree quota support
 NOTE:Ext4 quota is now managed via e2fsprogs, changes which add prjquota suppport for
 e2fsprogs will be submitted as separate patch-set.

Patch against next-20120605-1-g20a6ee4
Actually vfs part is really small, and most changes happen in fs/ext4/

Changes agains V9
 1) Change the name of the id from "project_id" to "subtree" accordings to Dave's
    comments.
 2) Fixes according to Jan's comments
   -  coalapse first and second patch
   -  get rid-of didicated mount point for subtree_id support
   -  code style changes
 3) Drop XFS stuff, since it require nontrivial changes in disk structures.

Changes against V7
 - Small fix for subtree switch error path
 - Remove usless macro expressions
Changes against v6
 - get rid of iattr stuff, current __dquot_transfer() provides sane interface
   for quota manipulation. i_prjid can must be changed only by fs-speciffic
   methods so only get() method is really necessery.
 - remove #ifdef tricks from generic code.
 - move i_prjid from vfs_inode to fs_inode, to prevent inode bloating.
 - get rid of isolation logic, because this feature confuse most users.
Changes against v5
 - convert dquota_transfer to struct iattr interface. Not it is possible
   to change i_prjid via notify_changes()
 - some bugfixes.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile b/Makefile
index 0d718ed..8dbcc39 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ VERSION = 3
 PATCHLEVEL = 5
 SUBLEVEL = 0
 EXTRAVERSION = -rc1
-NAME = Saber-toothed Squirrel
+NAME = Saber-toothed Squirrel-tree-quota
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 1/3] Add additional owner identifier
  2012-07-09 15:28 [PATCH 0/3] RFC: introduce extended inode owner identifier v10 Dmitry Monakhov
@ 2012-07-09 15:28 ` Dmitry Monakhov
  2012-07-09 15:28 ` [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem Dmitry Monakhov
  2012-07-09 15:28 ` [PATCH 3/3] ext4: add subtree quota support Dmitry Monakhov
  2 siblings, 0 replies; 9+ messages in thread
From: Dmitry Monakhov @ 2012-07-09 15:28 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel; +Cc: jack, Dmitry Monakhov

This patch add subtree inode identifier. Subtree ID may be used as
auxiliary owner specifier in addition to standard uid/gid.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/Kconfig            |    7 +++++++
 fs/quota/dquot.c      |   10 ++++++++++
 fs/quota/quotaio_v2.h |    6 ++++--
 include/linux/fs.h    |    1 +
 include/linux/quota.h |    9 ++++++++-
 include/linux/xattr.h |    3 +++
 6 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index c8554b5..54fc23a 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -60,6 +60,13 @@ config FILE_LOCKING
 	  This option enables standard file locking support, required
           for filesystems like NFS and for the flock() system
           call. Disabling this option saves about 11k.
+config SUBTREE
+	bool "Enable subtree inode identifier"
+	default y
+	help
+	  This option enables subtree inode identifier. Subtree id
+	  may be used as auxiliary owner specifier in addition to
+	  standard uid/gid.
 
 source "fs/notify/Kconfig"
 
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 10cbe84..ebc96c9 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -1141,6 +1141,11 @@ static int need_print_warning(struct dquot_warn *warn)
 			return current_fsuid() == warn->w_dq_id;
 		case GRPQUOTA:
 			return in_group_p(warn->w_dq_id);
+		case SBTRQUOTA:
+			/* XXX: Currently there is no way to understand
+			   which subtree this task belonges to, So print
+			   a warn message unconditionally. -dmon */
+			return 1;
 	}
 	return 0;
 }
@@ -1395,6 +1400,11 @@ static void __dquot_initialize(struct inode *inode, int type)
 		case GRPQUOTA:
 			id = inode->i_gid;
 			break;
+		case SBTRQUOTA:
+			if (!inode->i_sb->s_op->get_subtree)
+				continue;
+			id = inode->i_sb->s_op->get_subtree(inode);
+			break;
 		}
 		got[cnt] = dqget(sb, id, cnt);
 	}
diff --git a/fs/quota/quotaio_v2.h b/fs/quota/quotaio_v2.h
index f1966b4..a90bd18 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	/* SBTRQUOTA */\
 }
 
 #define V2_INITQVERSIONS {\
 	1,		/* USRQUOTA */\
-	1		/* GRPQUOTA */\
+	1,		/* GRPQUOTA */	\
+	1		/* SBTRQUOTA */\
 }
 
 /* First generic header */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b0a6d44..2eececc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1739,6 +1739,7 @@ struct super_operations {
 	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
 	int (*nr_cached_objects)(struct super_block *);
 	void (*free_cached_objects)(struct super_block *, int);
+	u32 (*get_subtree)(const struct inode *inode);
 };
 
 /*
diff --git a/include/linux/quota.h b/include/linux/quota.h
index c09fa04..042f45a 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -36,11 +36,17 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 
-#define __DQUOT_VERSION__	"dquot_6.5.2"
+#define __DQUOT_VERSION__	"dquot_6.6.0"
 
+#ifdef CONFIG_SUBTREE
+#define MAXQUOTAS 3
+#else
 #define MAXQUOTAS 2
+#endif
+
 #define USRQUOTA  0		/* element used for user quotas */
 #define GRPQUOTA  1		/* element used for group quotas */
+#define SBTRQUOTA 2		/* element used for subtree quotas */
 
 /*
  * Definitions for the default names of the quotas files.
@@ -48,6 +54,7 @@
 #define INITQFNAMES { \
 	"user",    /* USRQUOTA */ \
 	"group",   /* GRPQUOTA */ \
+	"subtree", /* SBTRQUOTA */ \
 	"undefined", \
 };
 
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index e5d1220..b0a4d78 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -61,6 +61,9 @@
 
 #include <linux/types.h>
 
+#define XATTR_SUBTREE "system.subtree"
+#define XATTR_SUBTREE_LEN (sizeof(XATTR_SUBTREE))
+
 struct inode;
 struct dentry;
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem
  2012-07-09 15:28 [PATCH 0/3] RFC: introduce extended inode owner identifier v10 Dmitry Monakhov
  2012-07-09 15:28 ` [PATCH 1/3] Add additional owner identifier Dmitry Monakhov
@ 2012-07-09 15:28 ` Dmitry Monakhov
  2012-07-09 21:04   ` Ted Ts'o
  2012-07-09 15:28 ` [PATCH 3/3] ext4: add subtree quota support Dmitry Monakhov
  2 siblings, 1 reply; 9+ messages in thread
From: Dmitry Monakhov @ 2012-07-09 15:28 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel; +Cc: jack, Dmitry Monakhov

* Abstract
  A subtree of a directory tree T is a tree consisting of a directory
  (the subtree root) in T and all of its descendants in T.

  *NOTE*: User is allowed to break pure subtree hierarchy via manual
          id manipulation.

  Subtree subtrees assumptions:
  (1) Each inode has an id. This id is persistently stored inside
      inode (xattr, usually inside ibody)
  (2) Subtree id is inherent from parent directory

  This feature is similar to project-id in XFS. One may assign some id to
  a subtree. Each entry from the subtree may be accounted in directory
  subtree quota. Will appear in later patches.

* Disk layout
  Subtree id is stored on disk inside xattr usually inside ibody.
  Xattr is used only as a data storage, It has not user visible xattr
  interface.

* User interface
  Subtree id is accessible via generic xattr interface "system.subtree"

* Notes
  ext4_setattr interface to subtreeid: Semantically subtree id must being changed
  similar to uid/gid, but subtree id is stored inside xattr so on-disk
  structures updates is not that trivial, so I've move subtree change
  logic to separate function.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/ext4/Kconfig   |   12 +++
 fs/ext4/Makefile  |    1 +
 fs/ext4/ext4.h    |    3 +
 fs/ext4/ialloc.c  |    6 ++
 fs/ext4/inode.c   |    4 +
 fs/ext4/subtree.c |  215 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ext4/subtree.h |   45 +++++++++++
 fs/ext4/super.c   |    7 ++
 fs/ext4/xattr.c   |    7 ++
 fs/ext4/xattr.h   |    2 +
 10 files changed, 302 insertions(+), 0 deletions(-)
 create mode 100644 fs/ext4/subtree.c
 create mode 100644 fs/ext4/subtree.h

diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index c22f170..f571168 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -77,6 +77,18 @@ config EXT4_FS_SECURITY
 	  If you are not using a security module that requires using
 	  extended attributes for file security labels, say N.
 
+config EXT4_SUBTREE
+	bool "Ext4 subtree id support"
+	select SUBTREE
+	depends on EXT4_FS_XATTR
+	help
+	  Enables subtree inode identifier support for ext4 filesystem.
+	  This feature allow to assign extended inode's identifier similar to
+	  uid/gid. Value is stored in xattr "system.subtree" and may be used
+	  as additional quota limit.
+
+	  If unsure, say N.
+
 config EXT4_DEBUG
 	bool "EXT4 debugging support"
 	depends on EXT4_FS
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 56fd8f8..df0a54c 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -12,3 +12,4 @@ ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
 ext4-$(CONFIG_EXT4_FS_XATTR)		+= xattr.o xattr_user.o xattr_trusted.o
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
 ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
+ext4-$(CONFIG_EXT4_SUBTREE)		+= subtree.o
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index cfc4e01..f831210 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -925,6 +925,9 @@ struct ext4_inode_info {
 
 	/* Precomputed uuid+inum+igen checksum for seeding inode checksums */
 	__u32 i_csum_seed;
+#ifdef CONFIG_EXT4_SUBTREE
+	__u32 i_subtree;
+#endif
 };
 
 /*
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index d48e8b1..ff73fea 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -28,6 +28,7 @@
 #include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
+#include "subtree.h"
 
 #include <trace/events/ext4.h>
 
@@ -898,6 +899,8 @@ got:
 
 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
 
+	ext4_set_subtree(inode, ext4_get_subtree(dir));
+
 	ret = inode;
 	dquot_initialize(inode);
 	err = dquot_alloc_inode(inode);
@@ -911,6 +914,9 @@ got:
 	err = ext4_init_security(handle, inode, dir, qstr);
 	if (err)
 		goto fail_free_drop;
+	err = ext4_subtree_init(handle, inode);
+	if (err)
+		goto fail_free_drop;
 
 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
 		/* set extent flag only for directory, file and normal symlink*/
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 02bc8cb..caf72f8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -42,6 +42,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "truncate.h"
+#include "subtree.h"
 
 #include <trace/events/ext4.h>
 
@@ -3870,6 +3871,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
 	}
 	if (ret)
 		goto bad_inode;
+	ret = ext4_subtree_read(inode);
+	if (ret)
+		goto bad_inode;
 
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext4_file_inode_operations;
diff --git a/fs/ext4/subtree.c b/fs/ext4/subtree.c
new file mode 100644
index 0000000..0486740
--- /dev/null
+++ b/fs/ext4/subtree.c
@@ -0,0 +1,215 @@
+/*
+ * linux/fs/ext4/subtree.c
+ *
+ * Copyright (C) 2012 Parallels Inc
+ * Dmitry Monakhov <dmonakhov@openvz.org>
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/quotaops.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
+#include "xattr.h"
+#include "subtree.h"
+
+/*
+ * Subtree assumptions:
+ * (1) Each inode has subtree id. This id is persistently stored inside
+ *     inode's xattr, usually inside ibody
+ * (2) Subtree id is inherent from parent directory
+ */
+
+/*
+ * Read subtree id from inode's xattr
+ * Locking: none
+ */
+int ext4_subtree_xattr_read(struct inode *inode, unsigned int *subtree)
+{
+	__le32 dsk_subtree;
+	int retval;
+
+	retval = ext4_xattr_get(inode, EXT4_XATTR_INDEX_SUBTREE, "",
+				&dsk_subtree, sizeof(dsk_subtree));
+	if (retval > 0) {
+		if (retval != sizeof(dsk_subtree))
+			return -EIO;
+		else
+			retval = 0;
+	}
+	*subtree = le32_to_cpu(dsk_subtree);
+	return retval;
+}
+
+/*
+ * Save subtree id to inode's xattr
+ * Locking: none
+ */
+int ext4_subtree_xattr_write(handle_t *handle, struct inode *inode,
+				unsigned int subtree, int xflags)
+{
+	__le32 dskid = cpu_to_le32(subtree);
+	int retval;
+
+	retval = ext4_xattr_set_handle(handle,
+				       inode, EXT4_XATTR_INDEX_SUBTREE, "",
+				       &dskid, sizeof(dskid), xflags);
+	if (retval > 0) {
+		if (retval != sizeof(dskid))
+			retval =  -EIO;
+		else
+			retval = 0;
+	}
+	return retval;
+}
+
+/*
+ * Change subtree id.
+ * Called under inode->i_mutex
+ */
+int ext4_subtree_change(struct inode *inode, unsigned int new_subtree)
+{
+	/*
+	 * One data_trans_blocks chunk for xattr update.
+	 * One quota_trans_blocks chunk for quota transfer, and one
+	 * quota_trans_block chunk for emergency quota rollback transfer,
+	 * because quota rollback may result new quota blocks allocation.
+	 */
+	unsigned credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) +
+		EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb) * 2;
+	int ret, ret2 = 0;
+	unsigned retries = 0;
+	handle_t *handle;
+	struct dquot *dquot[MAXQUOTAS] = {};
+	int old_id = ext4_get_subtree(inode);
+
+	dquot_initialize(inode);
+	dquot[SBTRQUOTA] = dqget(inode->i_sb, new_subtree, SBTRQUOTA);
+retry:
+	handle = ext4_journal_start(inode, credits);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		ext4_std_error(inode->i_sb, ret);
+		goto out;
+	}
+	/* Inode may not have subtree xattr yet. Create it explicitly */
+	ret = ext4_subtree_xattr_write(handle, inode, old_id, XATTR_CREATE);
+	if (ret == -EEXIST)
+		ret = 0;
+	if (ret) {
+		ret2 = ext4_journal_stop(handle);
+		if (ret2)
+			ret = ret2;
+		if (ret == -ENOSPC &&
+			ext4_should_retry_alloc(inode->i_sb, &retries))
+			goto retry;
+	}
+#ifdef CONFIG_QUOTA
+	ret = __dquot_transfer(inode, dquot);
+	if (ret)
+		return ret;
+#endif
+	ret = ext4_subtree_xattr_write(handle, inode, new_subtree,
+				       XATTR_REPLACE);
+	if (ret) {
+		/*
+		 * Function may fail only due to fatal error, Nor than less
+		 * we have try to rollback quota changes.
+		 */
+#ifdef CONFIG_QUOTA
+		__dquot_transfer(inode, dquot);
+#endif
+		ext4_std_error(inode->i_sb, ret);
+
+	} else
+		ext4_set_subtree(inode, new_subtree);
+
+	ret2 = ext4_journal_stop(handle);
+out:
+	dqput(dquot[SBTRQUOTA]);
+	if (ret2)
+		ret = ret2;
+	return ret;
+}
+
+int ext4_subtree_read(struct inode *inode)
+{
+	int ret = 0;
+	int subtree = 0;
+
+	ret = ext4_subtree_xattr_read(inode, &subtree);
+	if (ret == -ENODATA) {
+		subtree = 0;
+		ret = 0;
+	}
+	if (!ret)
+		ext4_set_subtree(inode, subtree);
+	return ret;
+}
+
+/*
+ * Initialize the subtree xattr of a new inode. Called from ext4_new_inode.
+ *
+ * dir->i_mutex: down
+ * inode->i_mutex: up (access to inode is still exclusive)
+ * Note: caller must assign correct subtree id to inode before.
+ */
+int ext4_subtree_init(handle_t *handle, struct inode *inode)
+{
+	return ext4_subtree_xattr_write(handle, inode, EXT4_I(inode)->i_subtree,
+				XATTR_CREATE);
+}
+
+static size_t
+ext4_xattr_subtree_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
+{
+	if (list && XATTR_SUBTREE_LEN <= list_size)
+		memcpy(list, XATTR_SUBTREE, XATTR_SUBTREE_LEN);
+	return XATTR_SUBTREE_LEN;
+}
+
+static int
+ext4_xattr_subtree_get(struct dentry *dentry, const char *name,
+		       void *buffer, size_t size, int type)
+{
+	int ret;
+	unsigned subtree;
+	char buf[32];
+
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	ret = ext4_subtree_xattr_read(dentry->d_inode, &subtree);
+	if (ret)
+		return ret;
+	snprintf(buf, sizeof(buf)-1, "%u", subtree);
+	buf[31] = '\0';
+	strncpy(buffer, buf, size);
+	return strlen(buf);
+}
+
+static int
+ext4_xattr_subtree_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
+{
+	unsigned int new_subtree;
+	int ret = 0;
+	char buf[11];
+	if (strcmp(name, "") != 0 || size + 1 > sizeof(buf))
+		return -EINVAL;
+	memcpy(buf, (char *)value, size);
+	buf[size] = '\0';
+	if (kstrtouint(buf, 10, &new_subtree))
+		return -EINVAL;
+	return ext4_subtree_change(dentry->d_inode, new_subtree);
+}
+
+const struct xattr_handler ext4_xattr_subtree_handler = {
+	.prefix	= XATTR_SUBTREE,
+	.list	= ext4_xattr_subtree_list,
+	.get	= ext4_xattr_subtree_get,
+	.set	= ext4_xattr_subtree_set,
+};
diff --git a/fs/ext4/subtree.h b/fs/ext4/subtree.h
new file mode 100644
index 0000000..362de80
--- /dev/null
+++ b/fs/ext4/subtree.h
@@ -0,0 +1,45 @@
+#include <linux/xattr.h>
+#include <linux/fs.h>
+
+#ifdef CONFIG_EXT4_SUBTREE
+extern int ext4_subtree_xattr_read(struct inode *inode, unsigned int *subtree);
+extern int ext4_subtree_xattr_write(handle_t *handle, struct inode *inode,
+				unsigned int subtree, int xflags);
+extern int ext4_subtree_init(handle_t *handle, struct inode *inode);
+extern int ext4_subtree_read(struct inode *inode);
+extern int ext4_subtree_change(struct inode *inode, unsigned int new_subtree);
+static inline u32 ext4_get_subtree(const struct inode *inode)
+{
+	const struct ext4_inode_info *ei =
+		container_of(inode, const struct ext4_inode_info, vfs_inode);
+	return ei->i_subtree;
+}
+static inline void ext4_set_subtree(struct inode *inode, u32 id)
+{
+	EXT4_I(inode)->i_subtree = id;
+}
+#else
+#define ext4_get_subtree(inode) do {} while (0)
+#define ext4_set_subtree(inode, id) do {} while (0)
+static inline int ext4_subtree_xattr_read(struct inode *inode, unsigned int *id)
+{
+	return -ENOTSUPP;
+}
+static inline int ext4_subtree_xattr_write(handle_t *h, struct inode *inode,
+				unsigned int subtree, int xflags)
+{
+	return -ENOTSUPP;
+}
+static inline int ext4_subtree_read(struct inode *inode)
+{
+	return 0;
+}
+static inline int ext4_subtree_change(struct inode *inode, unsigned int id)
+{
+	return -ENOTSUPP;
+}
+static inline int ext4_subtree_init(handle_t *handle, struct inode *inode)
+{
+	return 0;
+}
+#endif
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 84c7ba4..3599c95 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -50,6 +50,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "mballoc.h"
+#include "subtree.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/ext4.h>
@@ -1185,6 +1186,9 @@ static const struct super_operations ext4_sops = {
 	.quota_write	= ext4_quota_write,
 #endif
 	.bdev_try_to_free_page = bdev_try_to_free_page,
+#ifdef CONFIG_EXT4_SUBTREE
+	.get_subtree      = ext4_get_subtree,
+#endif
 };
 
 static const struct super_operations ext4_nojournal_sops = {
@@ -1204,6 +1208,9 @@ static const struct super_operations ext4_nojournal_sops = {
 	.quota_write	= ext4_quota_write,
 #endif
 	.bdev_try_to_free_page = bdev_try_to_free_page,
+#ifdef CONFIG_EXT4_SUBTREE
+	.get_subtree      = ext4_get_subtree,
+#endif
 };
 
 static const struct export_operations ext4_export_ops = {
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index e56c9ed..7466544 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -107,6 +107,10 @@ static const struct xattr_handler *ext4_xattr_handler_map[] = {
 #ifdef CONFIG_EXT4_FS_SECURITY
 	[EXT4_XATTR_INDEX_SECURITY]	     = &ext4_xattr_security_handler,
 #endif
+#ifdef CONFIG_EXT4_SUBTREE
+	[EXT4_XATTR_INDEX_SUBTREE]	     = &ext4_xattr_subtree_handler,
+#endif
+
 };
 
 const struct xattr_handler *ext4_xattr_handlers[] = {
@@ -119,6 +123,9 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
 #ifdef CONFIG_EXT4_FS_SECURITY
 	&ext4_xattr_security_handler,
 #endif
+#ifdef CONFIG_EXT4_SUBTREE
+	&ext4_xattr_subtree_handler,
+#endif
 	NULL
 };
 
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index 91f31ca..b207f35 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -21,6 +21,7 @@
 #define EXT4_XATTR_INDEX_TRUSTED		4
 #define	EXT4_XATTR_INDEX_LUSTRE			5
 #define EXT4_XATTR_INDEX_SECURITY	        6
+#define EXT4_XATTR_INDEX_SUBTREE	        7
 
 struct ext4_xattr_header {
 	__le32	h_magic;	/* magic number for identification */
@@ -72,6 +73,7 @@ extern const struct xattr_handler ext4_xattr_trusted_handler;
 extern const struct xattr_handler ext4_xattr_acl_access_handler;
 extern const struct xattr_handler ext4_xattr_acl_default_handler;
 extern const struct xattr_handler ext4_xattr_security_handler;
+extern const struct xattr_handler ext4_xattr_subtree_handler;
 
 extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] ext4: add subtree quota support
  2012-07-09 15:28 [PATCH 0/3] RFC: introduce extended inode owner identifier v10 Dmitry Monakhov
  2012-07-09 15:28 ` [PATCH 1/3] Add additional owner identifier Dmitry Monakhov
  2012-07-09 15:28 ` [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem Dmitry Monakhov
@ 2012-07-09 15:28 ` Dmitry Monakhov
  2 siblings, 0 replies; 9+ messages in thread
From: Dmitry Monakhov @ 2012-07-09 15:28 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel; +Cc: jack, Dmitry Monakhov

From: Dmitry Monakhov <dmonakhov@openvz.org>

Both regular and journaled quota are supported.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/ext4/ext4.h  |    1 +
 fs/ext4/super.c |   49 ++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f831210..ff41db8 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -955,6 +955,7 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_ERRORS_MASK		0x00070
 #define EXT4_MOUNT_MINIX_DF		0x00080	/* Mimics the Minix statfs */
 #define EXT4_MOUNT_NOLOAD		0x00100	/* Don't use existing journal*/
+#define EXT4_MOUNT_SBTRQUOTA		0x00200 /* Subtree quota support */
 #define EXT4_MOUNT_DATA_FLAGS		0x00C00	/* Mode for data writes: */
 #define EXT4_MOUNT_JOURNAL_DATA		0x00400	/* Write data to journal */
 #define EXT4_MOUNT_ORDERED_DATA		0x00800	/* Flush data before commit */
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 3599c95..6f5c1a7 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1128,8 +1128,8 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
 }
 
 #ifdef CONFIG_QUOTA
-#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
-#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
+static char *quotatypes[] = INITQFNAMES;
+#define QTYPE2NAME(t) (quotatypes[t])
 
 static int ext4_write_dquot(struct dquot *dquot);
 static int ext4_acquire_dquot(struct dquot *dquot);
@@ -1229,10 +1229,11 @@ enum {
 	Opt_journal_dev, Opt_journal_checksum, Opt_journal_async_commit,
 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
 	Opt_data_err_abort, Opt_data_err_ignore,
-	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+	Opt_usrjquota, Opt_grpjquota, Opt_sbtrjquota,
+	Opt_offusrjquota, Opt_offgrpjquota, Opt_offsbtrjquota,
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
 	Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
-	Opt_usrquota, Opt_grpquota, Opt_i_version,
+	Opt_usrquota, Opt_grpquota, Opt_sbtrquota, Opt_i_version,
 	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
 	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
 	Opt_inode_readahead_blks, Opt_journal_ioprio,
@@ -1281,10 +1282,13 @@ static const match_table_t tokens = {
 	{Opt_usrjquota, "usrjquota=%s"},
 	{Opt_offgrpjquota, "grpjquota="},
 	{Opt_grpjquota, "grpjquota=%s"},
+	{Opt_offsbtrjquota, "sbtrjquota="},
+	{Opt_sbtrjquota, "sbtrjquota=%s"},
 	{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
 	{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
 	{Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
 	{Opt_grpquota, "grpquota"},
+	{Opt_sbtrquota, "sbtrquota"},
 	{Opt_noquota, "noquota"},
 	{Opt_quota, "quota"},
 	{Opt_usrquota, "usrquota"},
@@ -1486,11 +1490,19 @@ static const struct mount_opts {
 		       EXT4_MOUNT_GRPQUOTA), MOPT_CLEAR | MOPT_Q},
 	{Opt_usrjquota, 0, MOPT_Q},
 	{Opt_grpjquota, 0, MOPT_Q},
+	{Opt_sbtrjquota, 0, MOPT_Q},
 	{Opt_offusrjquota, 0, MOPT_Q},
 	{Opt_offgrpjquota, 0, MOPT_Q},
+	{Opt_offsbtrjquota, 0, MOPT_Q},
 	{Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT},
 	{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
 	{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
+#ifdef CONFIG_EXT4_SUBTREE
+	{Opt_sbtrquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_SBTRQUOTA, (MOPT_SET |
+								  MOPT_Q)},
+#else
+	{Opt_sbtrquota, 0, MOPT_NOSUPPORT},
+#endif
 	{Opt_err, 0, 0}
 };
 
@@ -1513,6 +1525,17 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
 		return clear_qf_name(sb, USRQUOTA);
 	else if (token == Opt_offgrpjquota)
 		return clear_qf_name(sb, GRPQUOTA);
+#ifdef CONFIG_SUBTREE
+	else if (token == Opt_sbtrjquota)
+		return set_qf_name(sb, SBTRQUOTA, &args[0]);
+	else if (token == Opt_offsbtrjquota)
+		return clear_qf_name(sb, SBTRQUOTA);
+#else
+	else if (token == Opt_sbtrjquota || token == Opt_offsbtrjquota) {
+		ext4_msg(sb, KERN_ERR, "subtree quota options not supported");
+		return 0;
+	}
+#endif
 #endif
 	if (args->from && match_int(args, &arg))
 		return -1;
@@ -1685,13 +1708,17 @@ static int parse_options(char *options, struct super_block *sb,
 			return 0;
 	}
 #ifdef CONFIG_QUOTA
-	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA] ||
+		sbi->s_qf_names[SBTRQUOTA]) {
 		if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
 			clear_opt(sb, USRQUOTA);
 
 		if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA])
 			clear_opt(sb, GRPQUOTA);
 
+		if (test_opt(sb, SBTRQUOTA) && sbi->s_qf_names[SBTRQUOTA])
+			clear_opt(sb, SBTRQUOTA);
+
 		if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
 			ext4_msg(sb, KERN_ERR, "old and new quota "
 					"format mixing");
@@ -1743,12 +1770,19 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
 
 	if (sbi->s_qf_names[GRPQUOTA])
 		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
-
+#ifdef CONFIG_EXT4_SUBTREE
+	if (sbi->s_qf_names[SBTRQUOTA])
+		seq_printf(seq, ",sbtrjquota=%s", sbi->s_qf_names[SBTRQUOTA]);
+#endif
 	if (test_opt(sb, USRQUOTA))
 		seq_puts(seq, ",usrquota");
 
 	if (test_opt(sb, GRPQUOTA))
 		seq_puts(seq, ",grpquota");
+
+	if (test_opt(sb, SBTRQUOTA))
+		seq_puts(seq, ",sbtrquota");
+
 #endif
 }
 
@@ -4762,7 +4796,8 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot)
 {
 	/* Are we journaling quotas? */
 	if (EXT4_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
-	    EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
+	    EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA] ||
+	    EXT4_SB(dquot->dq_sb)->s_qf_names[SBTRQUOTA]) {
 		dquot_mark_dquot_dirty(dquot);
 		return ext4_write_dquot(dquot);
 	} else {
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem
  2012-07-09 15:28 ` [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem Dmitry Monakhov
@ 2012-07-09 21:04   ` Ted Ts'o
  2012-07-11 12:59     ` Dmitry Monakhov
  0 siblings, 1 reply; 9+ messages in thread
From: Ted Ts'o @ 2012-07-09 21:04 UTC (permalink / raw)
  To: Dmitry Monakhov; +Cc: linux-ext4, linux-fsdevel, jack

On Mon, Jul 09, 2012 at 07:28:44PM +0400, Dmitry Monakhov wrote:
> * Abstract
>   A subtree of a directory tree T is a tree consisting of a directory
>   (the subtree root) in T and all of its descendants in T.
> 
>   *NOTE*: User is allowed to break pure subtree hierarchy via manual
>           id manipulation.
> 
>   Subtree subtrees assumptions:
>   (1) Each inode has an id. This id is persistently stored inside
>       inode (xattr, usually inside ibody)
>   (2) Subtree id is inherent from parent directory
                      ^^^^^^^^ inherited

What really bothers me about this patch is that the abstraction is
extremely leaky.  In particular, it's not just "manual id
manipulation" that will break the abstraction.  If you rename a file
or directory across subtrees, it breaks the abstraction; so does hard
links.

When you get right down to it, this is effectively a secondary group
id, except it's not used for access control, but rather for quota
tracking.  You've used the name "subtree" id, but in fact there's no
guarantee subtrees has anything to do with it.  With a few renames,
any semblance of a subtree organization seems to disappear very
easily.

Another question which gets raised is is allowed to change the project
ownership?  Maybe I'm missing something, but I don't see any access
checking, so today it seems the answer is "anybody".  We could change
it so that only a root process can change project ownership, that
could raise other problems.

I also worry that this feature will have very limited applicability.
Will anyone other than parallels use it?

					- Ted

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem
  2012-07-09 21:04   ` Ted Ts'o
@ 2012-07-11 12:59     ` Dmitry Monakhov
  2012-07-11 13:24       ` Theodore Ts'o
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Monakhov @ 2012-07-11 12:59 UTC (permalink / raw)
  To: Ted Ts'o; +Cc: linux-ext4, linux-fsdevel, jack

On Mon, 9 Jul 2012 17:04:39 -0400, Ted Ts'o <tytso@mit.edu> wrote:
> On Mon, Jul 09, 2012 at 07:28:44PM +0400, Dmitry Monakhov wrote:
> > * Abstract
> >   A subtree of a directory tree T is a tree consisting of a directory
> >   (the subtree root) in T and all of its descendants in T.
> > 
> >   *NOTE*: User is allowed to break pure subtree hierarchy via manual
> >           id manipulation.
> > 
> >   Subtree subtrees assumptions:
> >   (1) Each inode has an id. This id is persistently stored inside
> >       inode (xattr, usually inside ibody)
> >   (2) Subtree id is inherent from parent directory
>                       ^^^^^^^^ inherited
> 
> What really bothers me about this patch is that the abstraction is
> extremely leaky.  In particular, it's not just "manual id
> manipulation" that will break the abstraction.  If you rename a file
> or directory across subtrees, it breaks the abstraction; so does hard
> links.
Yes this is my bad, bad name was chosen. When people hear about subtree they
do expect to see a true subtree (ADG). But the feature i want to add is
not about true subtree hierarchy, this is just an 3'rd inode's identifier
similar to uid/gid, subtree hierarchy is just one of most obvious
use-case. I just want to pick the best name for the feature

May be it would be better if i describe feature as "Namespace ID"
namespaces is well known abstraction in kernel, so misunderstanding
shouldn't happen.

Updated feature description:
1) Add XID (extension ID) the 3'rd inode's identifier similar to UID/GID
2) XID is stored inside xattr
3) XID is obtained from current task from current->cred->xid
4) XID is initialized on clone() according to namespace->xid

Obviously one can understand xid as "chroot id", "container id", or
"process-set id"
What do you think about that description?
> 
> When you get right down to it, this is effectively a secondary group
> id, except it's not used for access control, but rather for quota
> tracking.  You've used the name "subtree" id, but in fact there's no
> guarantee subtrees has anything to do with it.  With a few renames,
> any semblance of a subtree organization seems to disappear very
> easily.
> 
> Another question which gets raised is is allowed to change the project
> ownership?  Maybe I'm missing something, but I don't see any access
> checking, so today it seems the answer is "anybody".  We could change
> it so that only a root process can change project ownership, that
> could raise other problems.
Definitely, this should be restricted to CAP_SYS_ADMIN
> 
> I also worry that this feature will have very limited applicability.
> Will anyone other than parallels use it?
Off course no, this is very useful feature, but seems no one know
about this yet :). Third quota identifier should be usefully in following
cases:
1) Various containers implementation XLR and others
2) Chroot environments. For example I have an Android chroot environment
   and i want to prevent it from eat all space on my disk.
3) NFS: Per-mount quota. Server administrator is able to assign global
   disk limit for single nfs-share w/o limiting uid/gid quotas
> 
> 					- Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem
  2012-07-11 12:59     ` Dmitry Monakhov
@ 2012-07-11 13:24       ` Theodore Ts'o
  2012-07-11 15:26         ` Dmitry Monakhov
  0 siblings, 1 reply; 9+ messages in thread
From: Theodore Ts'o @ 2012-07-11 13:24 UTC (permalink / raw)
  To: Dmitry Monakhov; +Cc: linux-ext4, linux-fsdevel, jack

On Wed, Jul 11, 2012 at 04:59:24PM +0400, Dmitry Monakhov wrote:
> 
> May be it would be better if i describe feature as "Namespace ID"
> namespaces is well known abstraction in kernel, so misunderstanding
> shouldn't happen.

What if we call it a "quota group", with the rules that if a parent
directory has a quota group, any files or directories created in that
parent directory will inherit that quota group, and only processes
with CAP_SYS_ADMIN can change it.

And then what if we simply make the rule that if an inode has a quota
group, the quota is charged against two group id's; the group id named
in inode, and the quota group?

That is, do we really need to have a separate namespace for group ids
and "subtrees" or "namespaces"?  That means we don't have to change
the userspace quota tools and we can leverage the existing ways people
are used to managing group quotas.

						- Ted

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem
  2012-07-11 13:24       ` Theodore Ts'o
@ 2012-07-11 15:26         ` Dmitry Monakhov
  2012-07-11 17:17           ` Ted Ts'o
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Monakhov @ 2012-07-11 15:26 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: linux-ext4, linux-fsdevel, jack

On Wed, 11 Jul 2012 09:24:29 -0400, Theodore Ts'o <tytso@mit.edu> wrote:
> On Wed, Jul 11, 2012 at 04:59:24PM +0400, Dmitry Monakhov wrote:
> > 
> > May be it would be better if i describe feature as "Namespace ID"
> > namespaces is well known abstraction in kernel, so misunderstanding
> > shouldn't happen.
> 
> What if we call it a "quota group", with the rules that if a parent
> directory has a quota group, any files or directories created in that
> parent directory will inherit that quota group, and only processes
> with CAP_SYS_ADMIN can change it.
> 
> And then what if we simply make the rule that if an inode has a quota
> group, the quota is charged against two group id's; the group id named
> in inode, and the quota group?
Yes this looks reasonable, the only thing that we should aware of is id
collision. We have to reserve pool numbers to quota group id's.
This can be easily solved by changing disk structure of quota-file
to use u64 on uid.
> 
> That is, do we really need to have a separate namespace for group ids
> and "subtrees" or "namespaces"?  That means we don't have to change
> the userspace quota tools and we can leverage the existing ways people
> are used to managing group quotas.
> 
> 						- Ted
> --
P.S. You probably heard about tragedy in Krimsk due to water flood.
Tonight i'll go Krimsk to help as a volunteer, so i probably will be
out of Internet next 10-12days. Please excuse me, i'll send updated
version right after i'll back to Moscow.
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem
  2012-07-11 15:26         ` Dmitry Monakhov
@ 2012-07-11 17:17           ` Ted Ts'o
  0 siblings, 0 replies; 9+ messages in thread
From: Ted Ts'o @ 2012-07-11 17:17 UTC (permalink / raw)
  To: Dmitry Monakhov; +Cc: linux-ext4, linux-fsdevel, jack

On Wed, Jul 11, 2012 at 07:26:25PM +0400, Dmitry Monakhov wrote:
> Yes this looks reasonable, the only thing that we should aware of is id
> collision. We have to reserve pool numbers to quota group id's.
> This can be easily solved by changing disk structure of quota-file
> to use u64 on uid.

How many pool id's are you anticipating?  Is 32-bits really not
enough?  I'll note that uid_t and gid_t is only 32-bits today, and
part of my goal is to try to preserve compatibility with the existing
quota infrastructure.

							- Ted

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-07-11 17:17 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-09 15:28 [PATCH 0/3] RFC: introduce extended inode owner identifier v10 Dmitry Monakhov
2012-07-09 15:28 ` [PATCH 1/3] Add additional owner identifier Dmitry Monakhov
2012-07-09 15:28 ` [PATCH 2/3] ext4: Implement subtree ID support for ext4 filesystem Dmitry Monakhov
2012-07-09 21:04   ` Ted Ts'o
2012-07-11 12:59     ` Dmitry Monakhov
2012-07-11 13:24       ` Theodore Ts'o
2012-07-11 15:26         ` Dmitry Monakhov
2012-07-11 17:17           ` Ted Ts'o
2012-07-09 15:28 ` [PATCH 3/3] ext4: add subtree quota support Dmitry Monakhov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.