lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-id: <1265635693-12182-11-git-send-email-dmonakhov@openvz.org>
Date:	Mon, 08 Feb 2010 16:28:12 +0300
From:	Dmitry Monakhov <dmonakhov@...nvz.org>
To:	linux-ext4@...r.kernel.org
Cc:	Jan Kara <jack@...e.cz>, Dmitry Monakhov <dmonakhov@...nvz.org>
Subject: [PATCH 10/11] ext4: add subtree support

After this patch ext4 has basic subtree support.
* User visiable changes
  mount option:	       "subtree"
  mount flag: 	       EXT4_MOUNT_SUBTREE
  ioctl	   	       EXT4_IOC_GET_TREEID / EXT4_IOC_SET_TREEID

Signed-off-by: Dmitry Monakhov <dmonakhov@...nvz.org>
---
 fs/ext4/ext4.h   |    6 ++++++
 fs/ext4/ialloc.c |    6 ++++++
 fs/ext4/inode.c  |    5 +++++
 fs/ext4/ioctl.c  |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ext4/namei.c  |    9 ++++++++-
 fs/ext4/super.c  |   18 +++++++++++++++++-
 6 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 55f1034..c707c7c 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -390,6 +390,8 @@ struct ext4_new_group_data {
  /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
 #define EXT4_IOC_ALLOC_DA_BLKS		_IO('f', 12)
 #define EXT4_IOC_MOVE_EXT		_IOWR('f', 15, struct move_extent)
+#define EXT4_IOC_GET_SUBTREE		_IOR('f', 16, unsigned int)
+#define EXT4_IOC_SET_SUBTREE		_IOW('f', 17, unsigned int)
 
 /*
  * ioctl commands in 32 bit emulation
@@ -711,6 +713,9 @@ struct ext4_inode_info {
 	 */
 	tid_t i_sync_tid;
 	tid_t i_datasync_tid;
+#ifdef CONFIG_EXT4_SUBTREE
+	unsigned i_subtree;
+#endif
 };
 
 /*
@@ -760,6 +765,7 @@ struct ext4_inode_info {
 #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_SUBTREE		0x80000000LL /* Dedicated subtree */
 
 #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 2fab5ad..d527a0c 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>
 
@@ -1033,6 +1034,7 @@ got:
 	ext4_set_inode_state(inode, EXT4_STATE_NEW);
 
 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
+	ext4_st_inherent_subtree(inode, dir);
 
 	ret = inode;
 	if (vfs_dq_alloc_inode(inode)) {
@@ -1048,6 +1050,10 @@ got:
 	if (err)
 		goto fail_free_drop;
 
+	err = ext4_st_init(handle, inode, dir);
+	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*/
 		if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) {
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 218ea0b..2a31b0f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -44,6 +44,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "ext4_extents.h"
+#include "subtree.h"
 
 #include <trace/events/ext4.h>
 
@@ -5053,6 +5054,10 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
 	if (ret)
 		goto bad_inode;
 
+	ret = ext4_st_read(inode);
+	if (ret)
+		goto bad_inode;
+
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext4_file_inode_operations;
 		inode->i_fop = &ext4_file_operations;
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index b63d193..135d059 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -17,6 +17,7 @@
 #include <asm/uaccess.h>
 #include "ext4_jbd2.h"
 #include "ext4.h"
+#include "subtree.h"
 
 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
@@ -164,6 +165,57 @@ setversion_out:
 		mnt_drop_write(filp->f_path.mnt);
 		return err;
 	}
+#ifdef CONFIG_EXT4_SUBTREE
+	case EXT4_IOC_GET_SUBTREE:
+		if (test_opt(inode->i_sb, SUBTREE))
+			return put_user(EXT4_I(inode)->i_subtree,
+					(unsigned int __user*) arg);
+		else
+			return -EINVAL;
+	case EXT4_IOC_SET_SUBTREE: {
+		int err;
+		unsigned int subtree;
+		struct inode *dir = IS_ROOT(filp->f_dentry) ?
+			NULL : filp->f_dentry->d_parent->d_inode;
+
+		if (!test_opt(inode->i_sb, SUBTREE))
+			return -EINVAL;
+
+		if (!is_owner_or_cap(inode))
+			return -EACCES;
+
+		if (get_user(subtree, (unsigned int __user *) arg))
+			return -EFAULT;
+
+		err = mnt_want_write(filp->f_path.mnt);
+		if (err)
+			return err;
+		/*
+		 * Nested  subtrees are not allowed! We have to hold
+		 * dir->i_mutex for entire operation in order to prevent
+		 * from races with parent's ioctl.
+		 */
+		if (dir)
+			mutex_lock(&dir->i_mutex);
+		mutex_lock(&inode->i_mutex);
+
+		err = -EPERM;
+		/* Is it quota file? Do not allow user to mess with it */
+		if (IS_NOQUOTA(inode))
+			goto settree_out;
+
+		if (!capable(CAP_SYS_RESOURCE))
+			goto settree_out;
+
+		err = ext4_st_change(inode, dir, subtree);
+settree_out:
+		if (dir)
+			mutex_unlock(&dir->i_mutex);
+		mutex_unlock(&inode->i_mutex);
+		mnt_drop_write(filp->f_path.mnt);
+		return err;
+	}
+#endif
 #ifdef CONFIG_JBD2_DEBUG
 	case EXT4_IOC_WAIT_FOR_READONLY:
 		/*
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 17a17e1..4b1ac37 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -39,6 +39,7 @@
 
 #include "xattr.h"
 #include "acl.h"
+#include "subtree.h"
 
 /*
  * define how far ahead to read directories while searching them.
@@ -1086,6 +1087,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
 				return ERR_CAST(inode);
 			}
 		}
+		ext4_st_check_parent(dir, inode);
 	}
 	return d_splice_alias(inode, dentry);
 }
@@ -2314,7 +2316,8 @@ static int ext4_link(struct dentry *old_dentry,
 	 */
 	if (inode->i_nlink == 0)
 		return -ENOENT;
-
+	if (!ext4_st_may_link(dir, inode))
+		return -EXDEV;
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS);
@@ -2364,6 +2367,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 	 * in separate transaction */
 	if (new_dentry->d_inode)
 		vfs_dq_init(new_dentry->d_inode);
+
+	if (!ext4_st_may_rename(new_dir, old_dentry->d_inode))
+		return -EXDEV;
+
 	handle = ext4_journal_start(old_dir, 2 *
 					EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 93ba5e2..2684453 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -46,6 +46,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "mballoc.h"
+#include "subtree.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/ext4.h>
@@ -853,6 +854,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
 		seq_puts(seq, ",debug");
 	if (test_opt(sb, OLDALLOC))
 		seq_puts(seq, ",oldalloc");
+	if (test_opt(sb, SUBTREE))
+		seq_puts(seq, ",subtree");
 #ifdef CONFIG_EXT4_FS_XATTR
 	if (test_opt(sb, XATTR_USER) &&
 		!(def_mount_opts & EXT4_DEFM_XATTR_USER))
@@ -1115,7 +1118,7 @@ enum {
 	Opt_block_validity, Opt_noblock_validity,
 	Opt_inode_readahead_blks, Opt_journal_ioprio,
 	Opt_dioread_nolock, Opt_dioread_lock,
-	Opt_discard, Opt_nodiscard,
+	Opt_discard, Opt_nodiscard, Opt_subtree, Opt_nosubtree,
 };
 
 static const match_table_t tokens = {
@@ -1186,6 +1189,8 @@ static const match_table_t tokens = {
 	{Opt_dioread_lock, "dioread_lock"},
 	{Opt_discard, "discard"},
 	{Opt_nodiscard, "nodiscard"},
+	{Opt_subtree, "subtree"},
+	{Opt_nosubtree, "nosubtree"},
 	{Opt_err, NULL},
 };
 
@@ -1612,6 +1617,17 @@ set_qf_format:
 			*journal_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE,
 							    option);
 			break;
+		case Opt_subtree:
+			if (is_remount && !test_opt(sb, SUBTREE)) {
+				ext4_msg(sb, KERN_ERR,
+					 "Cannot toggle subtree support on remount");
+				return 0;
+			}
+			set_opt(sbi->s_mount_opt, SUBTREE);
+			break;
+		case Opt_nosubtree:
+			clear_opt(sbi->s_mount_opt, SUBTREE);
+			break;
 		case Opt_noauto_da_alloc:
 			set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
 			break;
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ