From: Dmitry Monakhov <dmonakhov@openvz.org>
To: linux-fsdevel@vger.kernel.org
Cc: Dmitry Monakhov <dmonakhov@openvz.org>
Subject: [PATCH 6/6] ext4: Implement metagroup support for ext4 filesystem
Date: Thu, 18 Feb 2010 19:45:30 +0300 [thread overview]
Message-ID: <1266511530-10533-7-git-send-email-dmonakhov@openvz.org> (raw)
In-Reply-To: <1266511530-10533-6-git-send-email-dmonakhov@openvz.org>
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
fs/ext4/Kconfig | 8 +++
fs/ext4/Makefile | 1 +
fs/ext4/ext4.h | 8 ++-
fs/ext4/ialloc.c | 5 +-
fs/ext4/inode.c | 13 ++++-
fs/ext4/super.c | 9 +++-
fs/ext4/xattr.c | 7 ++
fs/ext4/xattr.h | 11 +++
fs/ext4/xattr_metagroup.c | 153 +++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 211 insertions(+), 4 deletions(-)
create mode 100644 fs/ext4/xattr_metagroup.c
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index 9ed1bb1..e3365db 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -74,6 +74,14 @@ 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_METAGROUP
+ bool "Ext4 metagroup support"
+ depends on METAGROUP
+ depends on EXT4_FS_XATTR
+ help
+ Enables metagroup inode identifier support for ext4 filesystem.
+ This feature allow to assign some id to inodes similar to
+ uid/gid.
config EXT4_DEBUG
bool "EXT4 debugging support"
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 8867b2a..62f75b8 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -11,3 +11,4 @@ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.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_METAGROUP) += xattr_metagroup.o
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index b2c01a2..c3f95e7 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -719,6 +719,10 @@ struct ext4_inode_info {
*/
tid_t i_sync_tid;
tid_t i_datasync_tid;
+#ifdef CONFIG_EXT4_METAGROUP
+ /* metagroup id, additional owner identifier similar to uid/gid */
+ unsigned int i_mid;
+#endif
};
/*
@@ -766,7 +770,9 @@ struct ext4_inode_info {
#define EXT4_MOUNT_DELALLOC 0x8000000LL /* Delalloc support */
#define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000LL /* Abort on file data write */
#define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000LL /* Block validity checking */
-#define EXT4_MOUNT_DISCARD 0x40000000LL /* Issue DISCARD requests */
+#define EXT4_MOUNT_DISCARD 0x40000000LL /* Issue DISCARD requests
+*/
+#define EXT4_MOUNT_METAGROUP 0x80000000LL /* extended owner id */
#define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt
#define set_opt(o, opt) o |= EXT4_MOUNT_##opt
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index f3624ea..535b905 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1032,7 +1032,10 @@ got:
ei->i_state = EXT4_STATE_NEW;
ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
-
+#ifdef CONFIG_EXT4_METAGROUP
+ // XXX: move this to generic inode init helper
+ EXT4_I(inode)->i_mid = EXT4_I(dir)->i_mid;
+#endif
ret = inode;
if (vfs_dq_alloc_inode(inode)) {
err = -EDQUOT;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e119524..b1b5fdc 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4936,7 +4936,18 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
}
if (ret)
goto bad_inode;
-
+#ifdef CONFIG_EXT4_METAGROUP
+ if(test_opt(inode->i_sb, METAGROUP)) {
+ ret = ext4_metagroup_read(inode, &ei->i_mid);
+ if (ret == -ENODATA) {
+ ei->i_mid = 0;
+ ret = 0;
+ }
+ if (ret)
+ goto bad_inode;
+ } else
+ ei->i_mid = 0;
+#endif
if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext4_file_inode_operations;
inode->i_fop = &ext4_file_operations;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 80d6c14..cb169f8 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -923,6 +923,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
if (test_opt(sb, DISCARD))
seq_puts(seq, ",discard");
+ if (test_opt(sb, METAGROUP))
+ seq_puts(seq, ",metagroup");
+
if (test_opt(sb, NOLOAD))
seq_puts(seq, ",norecovery");
@@ -1112,7 +1115,7 @@ enum {
Opt_stripe, Opt_delalloc, Opt_nodelalloc,
Opt_block_validity, Opt_noblock_validity,
Opt_inode_readahead_blks, Opt_journal_ioprio,
- Opt_discard, Opt_nodiscard,
+ Opt_discard, Opt_nodiscard, Opt_metagroup,
};
static const match_table_t tokens = {
@@ -1181,6 +1184,7 @@ static const match_table_t tokens = {
{Opt_noauto_da_alloc, "noauto_da_alloc"},
{Opt_discard, "discard"},
{Opt_nodiscard, "nodiscard"},
+ {Opt_metagroup, "metagroup"},
{Opt_err, NULL},
};
@@ -1612,6 +1616,9 @@ set_qf_format:
case Opt_nodiscard:
clear_opt(sbi->s_mount_opt, DISCARD);
break;
+ case Opt_metagroup:
+ set_opt(sbi->s_mount_opt, METAGROUP);
+ break;
default:
ext4_msg(sb, KERN_ERR,
"Unrecognized mount option \"%s\" "
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index f3a2f7e..a97294b 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -107,6 +107,10 @@ static struct xattr_handler *ext4_xattr_handler_map[] = {
#ifdef CONFIG_EXT4_FS_SECURITY
[EXT4_XATTR_INDEX_SECURITY] = &ext4_xattr_security_handler,
#endif
+#ifdef CONFIG_EXT4_METAGROUP
+ [EXT4_XATTR_INDEX_METAGROUP] = &ext4_xattr_metagroup_handler,
+#endif
+
};
struct xattr_handler *ext4_xattr_handlers[] = {
@@ -119,6 +123,9 @@ struct xattr_handler *ext4_xattr_handlers[] = {
#ifdef CONFIG_EXT4_FS_SECURITY
&ext4_xattr_security_handler,
#endif
+#ifdef CONFIG_EXT4_METAGROUP
+ &ext4_xattr_metagroup_handler,
+#endif
NULL
};
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index 8ede88b..46b8369 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_METAGROUP 7
struct ext4_xattr_header {
__le32 h_magic; /* magic number for identification */
@@ -70,6 +71,7 @@ extern struct xattr_handler ext4_xattr_trusted_handler;
extern struct xattr_handler ext4_xattr_acl_access_handler;
extern struct xattr_handler ext4_xattr_acl_default_handler;
extern struct xattr_handler ext4_xattr_security_handler;
+extern struct xattr_handler ext4_xattr_metagroup_handler;
extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
@@ -153,3 +155,12 @@ static inline int ext4_init_security(handle_t *handle, struct inode *inode,
return 0;
}
#endif
+
+#ifdef CONFIG_EXT4_METAGROUP
+extern int ext4_metagroup_read(struct inode *inode, unsigned int *mid);
+#else
+inline int ext4_metagroup_read(struct inode *inode, unsigned int *mid)
+{
+ return -ENOTSUPP;
+}
+#endif
diff --git a/fs/ext4/xattr_metagroup.c b/fs/ext4/xattr_metagroup.c
new file mode 100644
index 0000000..5585d4d
--- /dev/null
+++ b/fs/ext4/xattr_metagroup.c
@@ -0,0 +1,153 @@
+/*
+ * linux/fs/ext4/xattr_metagroup.c
+ *
+ * Copyright (C) 2010 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"
+
+/*
+ * Read metagroup id from inode's xattr
+ * Locking: none
+ */
+int ext4_metagroup_read(struct inode *inode, unsigned int *mid)
+{
+ __le32 dsk_mid;
+ int retval;
+ retval = ext4_xattr_get(inode, EXT4_XATTR_INDEX_METAGROUP, "",
+ &dsk_mid, sizeof (dsk_mid));
+ if (retval > 0 && retval != sizeof(dsk_mid))
+ return -EIO;
+ *mid = le32_to_cpu(dsk_mid);
+ return retval;
+
+}
+
+/*
+ * Save metagroup id to inode's xattr
+ * Locking: none
+ */
+static int ext4_metagroup_write(handle_t *handle, struct inode *inode,
+ unsigned int mid, int xflags)
+{
+ __le32 dsk_mid;
+ int retval;
+ retval = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_METAGROUP, "",
+ &dsk_mid, sizeof (dsk_mid), xflags);
+ if (retval > 0 && retval != sizeof(dsk_mid))
+ return -EIO;
+ return retval;
+}
+
+/*
+ * Change metagroup id.
+ * Called under inode->i_mutex
+ */
+static int ext4_metagroup_change(struct inode *inode, unsigned int new_mid)
+{
+ /*
+ * 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;
+ qid_t qid[MAXQUOTAS];
+ int ret, ret2 = 0;
+ unsigned retries = 0;
+ handle_t *handle;
+
+ vfs_dq_init(inode);
+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 metagroup xattr yet. Create it explicitly */
+ ret = ext4_metagroup_write(handle, inode, EXT4_I(inode)->i_mid,
+ 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
+ qid[MGRQUOTA] = new_mid;
+ if (inode->i_sb->dq_op->transfer(inode, qid, 1 << MGRQUOTA))
+ ret = -EDQUOT;
+#endif
+ ret = ext4_metagroup_write(handle, inode, new_mid, 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
+ qid[MGRQUOTA] = EXT4_I(inode)->i_mid;
+ if (inode->i_sb->dq_op->transfer(inode, qid, 1 << MGRQUOTA))
+ ret = -EDQUOT;
+#endif
+ ext4_std_error(inode->i_sb, ret);
+
+ }
+ EXT4_I(inode)->i_mid = new_mid;
+ ret2 = ext4_journal_stop(handle);
+out:
+ if (ret2)
+ ret = ret2;
+ return ret;
+}
+static size_t
+ext4_xattr_metagroup_list(struct dentry *dentry, char *list, size_t list_size,
+ const char *name, size_t name_len, int type)
+{
+ if (list && XATTR_METAGROUP_LEN <= list_size)
+ memcpy(list, XATTR_METAGROUP_PREFIX, XATTR_METAGROUP_LEN);
+ return XATTR_METAGROUP_LEN;
+
+}
+
+static int
+ext4_xattr_metagroup_get(struct dentry *dentry, const char *name,
+ void *buffer, size_t size, int type)
+{
+ if (strcmp(name, "") != 0)
+ return -EINVAL;
+ return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_METAGROUP,
+ name, buffer, size);
+}
+
+static int
+ext4_xattr_metagroup_set(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags, int type)
+{
+ unsigned int new_mid;
+ if (strcmp(name, "") != 0)
+ return -EINVAL;
+ new_mid = simple_strtoul(value, (char **)&value, 0);
+ return ext4_metagroup_change(dentry->d_inode, new_mid);
+}
+
+struct xattr_handler ext4_xattr_metagroup_handler = {
+ .prefix = XATTR_METAGROUP,
+ .list = ext4_xattr_metagroup_list,
+ .get = ext4_xattr_metagroup_get,
+ .set = ext4_xattr_metagroup_set,
+};
--
1.6.6
next prev parent reply other threads:[~2010-02-18 16:54 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-18 16:45 [PATCH 0/6] RFC: introduce extended inode owner identifier v4 Dmitry Monakhov
2010-02-18 16:45 ` [PATCH 1/6] vfs: add per-sb auxiliary inode attribute table Dmitry Monakhov
2010-02-18 16:45 ` [PATCH 2/6] quota: switch reservation space management to aux_attribute Dmitry Monakhov
2010-02-18 16:45 ` [PATCH 3/6] vfs: Add additional owner identifier Dmitry Monakhov
2010-02-18 16:45 ` [PATCH 4/6] quota: Implement metagroup support for quota Dmitry Monakhov
2010-02-18 16:45 ` [PATCH 5/6] ext4: enlarge mount option field Dmitry Monakhov
2010-02-18 16:45 ` Dmitry Monakhov [this message]
2010-02-18 19:00 ` [PATCH 1/6] vfs: add per-sb auxiliary inode attribute table Brad Boyer
2010-02-18 19:34 ` Dmitry Monakhov
2010-02-18 23:31 ` [PATCH 0/6] RFC: introduce extended inode owner identifier v4 Dave Chinner
2010-02-19 10:16 ` Dmitry Monakhov
2010-02-19 23:31 ` Dave Chinner
2010-02-20 10:58 ` Dmitry Monakhov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1266511530-10533-7-git-send-email-dmonakhov@openvz.org \
--to=dmonakhov@openvz.org \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).