From 7e71d8dd6be44e11b0c45508d8bc9f3619b3a206 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 30 Jan 2008 01:24:48 -0500 Subject: [PATCH] Add Andi Kleen's ioctl patches and Eric's allow in-inode EA patch --- allow_in-inode_eas_on_ext4_root_inode | 52 ++++++++++++ convert_ext2_over_to_use_unlocked_ioctl | 96 ++++++++++++++++++++++ convert_ext3_to_use_unlocked_ioctl_v2 | 90 ++++++++++++++++++++ convert_ext4_to_use_unlocked_ioctl_v2 | 89 ++++++++++++++++++++ ext3__remove_incorrect_bkl_comment | 22 +++++ remove_incorrect_bkl_comment_in_ext2 | 21 +++++ remove_incorrect_bkl_comments_in_ext4 | 32 ++++++++ ...t_comment_refering_to_lock_kernel_from_jbd-jbd2 | 36 ++++++++ series | 8 ++ 9 files changed, 446 insertions(+) create mode 100644 allow_in-inode_eas_on_ext4_root_inode create mode 100644 convert_ext2_over_to_use_unlocked_ioctl create mode 100644 convert_ext3_to_use_unlocked_ioctl_v2 create mode 100644 convert_ext4_to_use_unlocked_ioctl_v2 create mode 100644 ext3__remove_incorrect_bkl_comment create mode 100644 remove_incorrect_bkl_comment_in_ext2 create mode 100644 remove_incorrect_bkl_comments_in_ext4 create mode 100644 remove_incorrect_comment_refering_to_lock_kernel_from_jbd-jbd2 diff --git a/allow_in-inode_eas_on_ext4_root_inode b/allow_in-inode_eas_on_ext4_root_inode new file mode 100644 index 00000000..58d4cf42 --- /dev/null +++ b/allow_in-inode_eas_on_ext4_root_inode @@ -0,0 +1,52 @@ +allow in-inode EAs on ext4 root inode + +From: Eric Sandeen + +The ext3 root inode was treated specially with respect +to in-inode extended attributes, for reasons detailed +in the removed comment below. The first mkfs-created +inodes would not get extra_i_size or the EXT3_STATE_XATTR +flag set in ext3_read_inode, which disallowed reading or +setting in-inode EAs on the root. + +However, in ext4, ext4_mark_inode_dirty calls +ext4_expand_extra_isize for all inodes; once this is done +EAs may be placed in the root ext4 inode body. + +But for reasons above, it won't be found after a reboot. + +testcase: + +setfattr -n user.name -v value mntpt/ +setfattr -n user.name2 -v value2 mntpt/ +umount mntpt/; remount mntpt/ +getfattr -d mntpt/ + +name2/value2 has gone missing; debugfs shows it in the +inode body, but it is not found there by getattr. + +The following fixes it up; newer mkfs appears to properly +zero the inodes, so this workaround isn't needed for ext4. + +Signed-off-by: Eric Sandeen +Signed-off-by: Theodore Ts'o + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index e7e10df..4fed498 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2908,13 +2908,7 @@ void ext4_read_inode(struct inode * inode) + ei->i_data[block] = raw_inode->i_block[block]; + INIT_LIST_HEAD(&ei->i_orphan); + +- if (inode->i_ino >= EXT4_FIRST_INO(inode->i_sb) + 1 && +- EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { +- /* +- * When mke2fs creates big inodes it does not zero out +- * the unused bytes above EXT4_GOOD_OLD_INODE_SIZE, +- * so ignore those first few inodes. +- */ ++ if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { + ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); + if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > + EXT4_INODE_SIZE(inode->i_sb)) { diff --git a/convert_ext2_over_to_use_unlocked_ioctl b/convert_ext2_over_to_use_unlocked_ioctl new file mode 100644 index 00000000..05c1198f --- /dev/null +++ b/convert_ext2_over_to_use_unlocked_ioctl @@ -0,0 +1,96 @@ +Convert ext2 over to use unlocked_ioctl + +From: Andi Kleen + +I checked ext2_ioctl and could not find anything in there that would +need the BKL. So convert it over to use unlocked_ioctl + +Signed-off-by: Andi Kleen +Signed-off-by: Theodore Ts'o + +diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c +index d868e26..8dededd 100644 +--- a/fs/ext2/dir.c ++++ b/fs/ext2/dir.c +@@ -703,7 +703,7 @@ const struct file_operations ext2_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .readdir = ext2_readdir, +- .ioctl = ext2_ioctl, ++ .unlocked_ioctl = ext2_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ext2_compat_ioctl, + #endif +diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h +index c87ae29..bb9948c 100644 +--- a/fs/ext2/ext2.h ++++ b/fs/ext2/ext2.h +@@ -139,8 +139,7 @@ int __ext2_write_begin(struct file *file, struct address_space *mapping, + struct page **pagep, void **fsdata); + + /* ioctl.c */ +-extern int ext2_ioctl (struct inode *, struct file *, unsigned int, +- unsigned long); ++extern long ext2_ioctl(struct file *, unsigned int, unsigned long); + extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long); + + /* namei.c */ +diff --git a/fs/ext2/file.c b/fs/ext2/file.c +index c051798..5f2fa9c 100644 +--- a/fs/ext2/file.c ++++ b/fs/ext2/file.c +@@ -48,7 +48,7 @@ const struct file_operations ext2_file_operations = { + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = generic_file_aio_write, +- .ioctl = ext2_ioctl, ++ .unlocked_ioctl = ext2_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ext2_compat_ioctl, + #endif +@@ -65,7 +65,7 @@ const struct file_operations ext2_xip_file_operations = { + .llseek = generic_file_llseek, + .read = xip_file_read, + .write = xip_file_write, +- .ioctl = ext2_ioctl, ++ .unlocked_ioctl = ext2_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ext2_compat_ioctl, + #endif +diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c +index 320b2cb..b8ea11f 100644 +--- a/fs/ext2/ioctl.c ++++ b/fs/ext2/ioctl.c +@@ -17,9 +17,9 @@ + #include + + +-int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, +- unsigned long arg) ++long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { ++ struct inode *inode = filp->f_dentry->d_inode; + struct ext2_inode_info *ei = EXT2_I(inode); + unsigned int flags; + unsigned short rsv_window_size; +@@ -141,9 +141,6 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, + #ifdef CONFIG_COMPAT + long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +- struct inode *inode = file->f_path.dentry->d_inode; +- int ret; +- + /* These are just misnamed, they actually get/put from/to user an int */ + switch (cmd) { + case EXT2_IOC32_GETFLAGS: +@@ -161,9 +158,6 @@ long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + default: + return -ENOIOCTLCMD; + } +- lock_kernel(); +- ret = ext2_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); +- unlock_kernel(); +- return ret; ++ return ext2_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); + } + #endif diff --git a/convert_ext3_to_use_unlocked_ioctl_v2 b/convert_ext3_to_use_unlocked_ioctl_v2 new file mode 100644 index 00000000..f1b51aa5 --- /dev/null +++ b/convert_ext3_to_use_unlocked_ioctl_v2 @@ -0,0 +1,90 @@ +Convert ext3 to use unlocked_ioctl v2 + +From: Andi Kleen + +I checked ext3_ioctl and it looked largely safe to not be used +without BKL. So convert it over to unlocked_ioctl. + +Signed-off-by: Andi Kleen + +v1->v2: drop lock kernel for online growth. resize.c seems to do enough +locking +Signed-off-by: Theodore Ts'o + +diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c +index 8ca3bfd..77a6962 100644 +--- a/fs/ext3/dir.c ++++ b/fs/ext3/dir.c +@@ -42,7 +42,7 @@ const struct file_operations ext3_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .readdir = ext3_readdir, /* we take BKL. needed?*/ +- .ioctl = ext3_ioctl, /* BKL held */ ++ .unlocked_ioctl = ext3_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ext3_compat_ioctl, + #endif +diff --git a/fs/ext3/file.c b/fs/ext3/file.c +index acc4913..2da795e 100644 +--- a/fs/ext3/file.c ++++ b/fs/ext3/file.c +@@ -112,7 +112,7 @@ const struct file_operations ext3_file_operations = { + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = ext3_file_write, +- .ioctl = ext3_ioctl, ++ .unlocked_ioctl = ext3_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ext3_compat_ioctl, + #endif +diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c +index 023a070..0f177d2 100644 +--- a/fs/ext3/ioctl.c ++++ b/fs/ext3/ioctl.c +@@ -17,9 +17,9 @@ + #include + #include + +-int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, +- unsigned long arg) ++long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { ++ struct inode *inode = filp->f_dentry->d_inode; + struct ext3_inode_info *ei = EXT3_I(inode); + unsigned int flags; + unsigned short rsv_window_size; +@@ -263,9 +263,6 @@ flags_err: + #ifdef CONFIG_COMPAT + long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +- struct inode *inode = file->f_path.dentry->d_inode; +- int ret; +- + /* These are just misnamed, they actually get/put from/to user an int */ + switch (cmd) { + case EXT3_IOC32_GETFLAGS: +@@ -305,9 +302,6 @@ long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + default: + return -ENOIOCTLCMD; + } +- lock_kernel(); +- ret = ext3_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); +- unlock_kernel(); +- return ret; ++ return ext3_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); + } + #endif +diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h +index 241c01c..1c925eb 100644 +--- a/include/linux/ext3_fs.h ++++ b/include/linux/ext3_fs.h +@@ -838,8 +838,7 @@ extern void ext3_get_inode_flags(struct ext3_inode_info *); + extern void ext3_set_aops(struct inode *inode); + + /* ioctl.c */ +-extern int ext3_ioctl (struct inode *, struct file *, unsigned int, +- unsigned long); ++extern long ext3_ioctl(struct file *, unsigned int, unsigned long); + extern long ext3_compat_ioctl (struct file *, unsigned int, unsigned long); + + /* namei.c */ diff --git a/convert_ext4_to_use_unlocked_ioctl_v2 b/convert_ext4_to_use_unlocked_ioctl_v2 new file mode 100644 index 00000000..046554e3 --- /dev/null +++ b/convert_ext4_to_use_unlocked_ioctl_v2 @@ -0,0 +1,89 @@ +Convert ext4 to use unlocked_ioctl v2 + +From: Andi Kleen + +I checked ext4_ioctl and it looked largely safe to not be used +without BKL. So convert it over to unlocked_ioctl. + +Signed-off-by: Andi Kleen + +v1->v2: drop BKL for online grow. resize.c seems to do enough locking +Signed-off-by: Theodore Ts'o + +diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c +index 33888bb..d9c81ce 100644 +--- a/fs/ext4/dir.c ++++ b/fs/ext4/dir.c +@@ -42,7 +42,7 @@ const struct file_operations ext4_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .readdir = ext4_readdir, /* we take BKL. needed?*/ +- .ioctl = ext4_ioctl, /* BKL held */ ++ .unlocked_ioctl = ext4_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ext4_compat_ioctl, + #endif +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index ac35ec5..20507a2 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -129,7 +129,7 @@ const struct file_operations ext4_file_operations = { + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = ext4_file_write, +- .ioctl = ext4_ioctl, ++ .unlocked_ioctl = ext4_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ext4_compat_ioctl, + #endif +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index f362025..2f7524f 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -17,9 +17,9 @@ + #include + #include + +-int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, +- unsigned long arg) ++long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { ++ struct inode *inode = filp->f_dentry->d_inode; + struct ext4_inode_info *ei = EXT4_I(inode); + unsigned int flags; + unsigned short rsv_window_size; +@@ -278,9 +278,6 @@ flags_err: + #ifdef CONFIG_COMPAT + long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +- struct inode *inode = file->f_path.dentry->d_inode; +- int ret; +- + /* These are just misnamed, they actually get/put from/to user an int */ + switch (cmd) { + case EXT4_IOC32_GETFLAGS: +@@ -320,9 +317,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + default: + return -ENOIOCTLCMD; + } +- lock_kernel(); +- ret = ext4_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); +- unlock_kernel(); +- return ret; ++ return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); + } + #endif +diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h +index d203543..ba146b0 100644 +--- a/include/linux/ext4_fs.h ++++ b/include/linux/ext4_fs.h +@@ -1124,8 +1124,7 @@ extern int ext4_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create); + + /* ioctl.c */ +-extern int ext4_ioctl (struct inode *, struct file *, unsigned int, +- unsigned long); ++extern long ext4_ioctl(struct file *, unsigned int, unsigned long); + extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long); + + /* migrate.c */ diff --git a/ext3__remove_incorrect_bkl_comment b/ext3__remove_incorrect_bkl_comment new file mode 100644 index 00000000..b7e88e0a --- /dev/null +++ b/ext3__remove_incorrect_bkl_comment @@ -0,0 +1,22 @@ +ext3: Remove incorrect BKL comment + +From: Andi Kleen + +There is no BKL held on entry in ->fsync nor in the low level ext3_sync_file. + +Signed-off-by: Andi Kleen +Signed-off-by: Theodore Ts'o + +diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c +index 77a6962..9fee14c 100644 +--- a/fs/ext3/dir.c ++++ b/fs/ext3/dir.c +@@ -46,7 +46,7 @@ const struct file_operations ext3_dir_operations = { + #ifdef CONFIG_COMPAT + .compat_ioctl = ext3_compat_ioctl, + #endif +- .fsync = ext3_sync_file, /* BKL held */ ++ .fsync = ext3_sync_file, + .release = ext3_release_dir, + }; + diff --git a/remove_incorrect_bkl_comment_in_ext2 b/remove_incorrect_bkl_comment_in_ext2 new file mode 100644 index 00000000..d771b4e0 --- /dev/null +++ b/remove_incorrect_bkl_comment_in_ext2 @@ -0,0 +1,21 @@ +Remove incorrect BKL comment in ext2 + +From: Andi Kleen + +No BKL used anywhere, so don't mention it. + +Signed-off-by: Andi Kleen +Signed-off-by: Theodore Ts'o + +diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c +index b1ab32a..7a1fcc9 100644 +--- a/fs/ext2/inode.c ++++ b/fs/ext2/inode.c +@@ -569,7 +569,6 @@ static void ext2_splice_branch(struct inode *inode, + * + * `handle' can be NULL if create == 0. + * +- * The BKL may not be held on entry here. Be sure to take it early. + * return > 0, # of blocks mapped or allocated. + * return = 0, if plain lookup failed. + * return < 0, error case. diff --git a/remove_incorrect_bkl_comments_in_ext4 b/remove_incorrect_bkl_comments_in_ext4 new file mode 100644 index 00000000..4a274a79 --- /dev/null +++ b/remove_incorrect_bkl_comments_in_ext4 @@ -0,0 +1,32 @@ +Remove incorrect BKL comments in ext4 + +From: Andi Kleen + +Signed-off-by: Andi Kleen +Signed-off-by: Theodore Ts'o + +diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c +index d9c81ce..88c97f7 100644 +--- a/fs/ext4/dir.c ++++ b/fs/ext4/dir.c +@@ -46,7 +46,7 @@ const struct file_operations ext4_dir_operations = { + #ifdef CONFIG_COMPAT + .compat_ioctl = ext4_compat_ioctl, + #endif +- .fsync = ext4_sync_file, /* BKL held */ ++ .fsync = ext4_sync_file, + .release = ext4_release_dir, + }; + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index fb250bd..e7e10df 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -773,7 +773,6 @@ err_out: + * + * `handle' can be NULL if create == 0. + * +- * The BKL may not be held on entry here. Be sure to take it early. + * return > 0, # of blocks mapped or allocated. + * return = 0, if plain lookup failed. + * return < 0, error case. diff --git a/remove_incorrect_comment_refering_to_lock_kernel_from_jbd-jbd2 b/remove_incorrect_comment_refering_to_lock_kernel_from_jbd-jbd2 new file mode 100644 index 00000000..f064c777 --- /dev/null +++ b/remove_incorrect_comment_refering_to_lock_kernel_from_jbd-jbd2 @@ -0,0 +1,36 @@ +Remove incorrect comment refering to lock_kernel() from jbd/jbd2 + +From: Andi Kleen + +None of the callers of this function does actually take the BKL +as far as I can see. So remove the comment refering to the BKL. + +Signed-off-by: Andi Kleen +Signed-off-by: Theodore Ts'o + +diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c +index c5d9694..2b8edf4 100644 +--- a/fs/jbd/recovery.c ++++ b/fs/jbd/recovery.c +@@ -354,7 +354,7 @@ static int do_one_pass(journal_t *journal, + struct buffer_head * obh; + struct buffer_head * nbh; + +- cond_resched(); /* We're under lock_kernel() */ ++ cond_resched(); + + /* If we already know where to stop the log traversal, + * check right now that we haven't gone past the end of +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index 9216806..d36356f 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -397,7 +397,7 @@ static int do_one_pass(journal_t *journal, + struct buffer_head * obh; + struct buffer_head * nbh; + +- cond_resched(); /* We're under lock_kernel() */ ++ cond_resched(); + + /* If we already know where to stop the log traversal, + * check right now that we haven't gone past the end of diff --git a/series b/series index ae0cfe4a..5a7971ce 100644 --- a/series +++ b/series @@ -34,5 +34,13 @@ ext4-online-defrag-header-changes.patch ext4-online-defrag-alloc-contiguous-blks.patch ext4-online-defrag-relocate-file-data.patch ext4-online-defrag-free-space-fragmentation.patch +convert_ext2_over_to_use_unlocked_ioctl +remove_incorrect_bkl_comment_in_ext2 +convert_ext3_to_use_unlocked_ioctl_v2 +ext3__remove_incorrect_bkl_comment +remove_incorrect_comment_refering_to_lock_kernel_from_jbd-jbd2 +convert_ext4_to_use_unlocked_ioctl_v2 +remove_incorrect_bkl_comments_in_ext4 +allow_in-inode_eas_on_ext4_root_inode #command to use defrag #ext4-online-defrag-defrag-command.c -- 2.11.4.GIT