From 825cd3dd06309e680eb5fb8abf194457562e712c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 30 Jan 2008 01:06:34 -0500 Subject: [PATCH] Remove unused patches --- booked-page-flag.patch | 36 - ext2-unlocked-ioctl.patch | 253 ---- ext3-unlocked-ioctl.patch | 395 ------ ext4-block-reservation.patch | 300 ---- ext4-delalloc-extents-48bit.patch | 76 - ext4-delayed-allocation.patch | 1489 -------------------- ext4-unlocked-ioctl.patch | 403 ------ ext4_block_reservation_fix3.patch | 24 - ext4_delalloc_setpageprivate_fix.patch | 57 - ext4_nodelalloc_mount_opt.patch | 41 - ...alance_reservation_invariant_checking_fix.patch | 27 - ext4_reserve_global_return_error_fix.patch | 39 - 12 files changed, 3140 deletions(-) delete mode 100644 booked-page-flag.patch delete mode 100644 ext2-unlocked-ioctl.patch delete mode 100644 ext3-unlocked-ioctl.patch delete mode 100644 ext4-block-reservation.patch delete mode 100644 ext4-delalloc-extents-48bit.patch delete mode 100644 ext4-delayed-allocation.patch delete mode 100644 ext4-unlocked-ioctl.patch delete mode 100644 ext4_block_reservation_fix3.patch delete mode 100644 ext4_delalloc_setpageprivate_fix.patch delete mode 100644 ext4_nodelalloc_mount_opt.patch delete mode 100644 ext4_rebalance_reservation_invariant_checking_fix.patch delete mode 100644 ext4_reserve_global_return_error_fix.patch diff --git a/booked-page-flag.patch b/booked-page-flag.patch deleted file mode 100644 index 41c0a317..00000000 --- a/booked-page-flag.patch +++ /dev/null @@ -1,36 +0,0 @@ -[RFC] delayed allocation for ext4 - -From: Alex Tomas - -Adds PG_booked bit to page->flags. It's used in delayed allocation to -mark space is already reserved for page (including possible metadata) - -Signed-off-by: Alex Tomas ---- ---- - include/linux/page-flags.h | 5 +++++ - 1 file changed, 5 insertions(+) - -Index: linux-2.6.23-rc2/include/linux/page-flags.h -=================================================================== ---- linux-2.6.23-rc2.orig/include/linux/page-flags.h 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/include/linux/page-flags.h 2007-08-06 22:18:57.000000000 -0700 -@@ -89,6 +89,7 @@ - #define PG_mappedtodisk 16 /* Has blocks allocated on-disk */ - #define PG_reclaim 17 /* To be reclaimed asap */ - #define PG_buddy 19 /* Page is free, on buddy lists */ -+#define PG_booked 20 /* Has blocks reserved on-disk */ - - /* PG_readahead is only used for file reads; PG_reclaim is only for writes */ - #define PG_readahead PG_reclaim /* Reminder to do async read-ahead */ -@@ -211,6 +212,10 @@ static inline void SetPageUptodate(struc - #define SetPageReadahead(page) set_bit(PG_readahead, &(page)->flags) - #define ClearPageReadahead(page) clear_bit(PG_readahead, &(page)->flags) - -+#define PageBooked(page) test_bit(PG_booked, &(page)->flags) -+#define SetPageBooked(page) set_bit(PG_booked, &(page)->flags) -+#define ClearPageBooked(page) clear_bit(PG_booked, &(page)->flags) -+ - #define PageReclaim(page) test_bit(PG_reclaim, &(page)->flags) - #define SetPageReclaim(page) set_bit(PG_reclaim, &(page)->flags) - #define ClearPageReclaim(page) clear_bit(PG_reclaim, &(page)->flags) diff --git a/ext2-unlocked-ioctl.patch b/ext2-unlocked-ioctl.patch deleted file mode 100644 index 6d2010be..00000000 --- a/ext2-unlocked-ioctl.patch +++ /dev/null @@ -1,253 +0,0 @@ -Convert EXT2 to use unlocked_ioctl - -From: Mathieu Segaud - -Change ext2_ioctl() to be an unlocked_ioctl(), explicitly -exposing BKL's uses. - -Signed-off-by: Mathieu Segaud -Signed-off-by: "Theodore Ts'o" - ---- - fs/ext2/dir.c | 2 +- - fs/ext2/ext2.h | 3 +- - fs/ext2/file.c | 4 +- - fs/ext2/ioctl.c | 103 +++++++++++++++++++++++++++++++++++++------------------ - 4 files changed, 73 insertions(+), 39 deletions(-) - -diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c -index d868e26..dbee3c9 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..17fe628 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..0f18ac5 100644 ---- a/fs/ext2/ioctl.c -+++ b/fs/ext2/ioctl.c -@@ -17,12 +17,18 @@ - #include - - --int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, -+long ext2_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) - { -- struct ext2_inode_info *ei = EXT2_I(inode); -+ struct ext2_inode_info *ei; -+ struct inode *inode; - unsigned int flags; - unsigned short rsv_window_size; -+ long retval = 0; -+ -+ lock_kernel(); -+ inode = filp->f_path.dentry->d_inode; -+ ei = EXT2_I(inode); - - ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); - -@@ -30,18 +36,25 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - case EXT2_IOC_GETFLAGS: - ext2_get_inode_flags(ei); - flags = ei->i_flags & EXT2_FL_USER_VISIBLE; -- return put_user(flags, (int __user *) arg); -+ retval = put_user(flags, (int __user *) arg); -+ goto out; - case EXT2_IOC_SETFLAGS: { - unsigned int oldflags; - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if (!is_owner_or_cap(inode)) -- return -EACCES; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EACCES; -+ goto out; -+ } - -- if (get_user(flags, (int __user *) arg)) -- return -EFAULT; -+ if (get_user(flags, (int __user *) arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - if (!S_ISDIR(inode->i_mode)) - flags &= ~EXT2_DIRSYNC_FL; -@@ -50,7 +63,8 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - /* Is it quota file? Do not allow user to mess with it */ - if (IS_NOQUOTA(inode)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - oldflags = ei->i_flags; - -@@ -63,7 +77,8 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { - if (!capable(CAP_LINUX_IMMUTABLE)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - } - -@@ -75,41 +90,59 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - ext2_set_inode_flags(inode); - inode->i_ctime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); -- return 0; -+ goto out; - } - case EXT2_IOC_GETVERSION: -- return put_user(inode->i_generation, (int __user *) arg); -+ retval = put_user(inode->i_generation, (int __user *) arg); -+ goto out; - case EXT2_IOC_SETVERSION: -- if (!is_owner_or_cap(inode)) -- return -EPERM; -- if (IS_RDONLY(inode)) -- return -EROFS; -- if (get_user(inode->i_generation, (int __user *) arg)) -- return -EFAULT; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EPERM; -+ goto out; -+ } -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } -+ if (get_user(inode->i_generation, (int __user *) arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - inode->i_ctime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); -- return 0; -+ goto out; - case EXT2_IOC_GETRSVSZ: - if (test_opt(inode->i_sb, RESERVATION) - && S_ISREG(inode->i_mode) - && ei->i_block_alloc_info) { - rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size; -- return put_user(rsv_window_size, (int __user *)arg); -+ retval = put_user(rsv_window_size, (int __user *)arg); -+ goto out; - } -- return -ENOTTY; -+ retval = -ENOTTY; -+ goto out; - case EXT2_IOC_SETRSVSZ: { - -- if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) -- return -ENOTTY; -+ if (!test_opt(inode->i_sb, RESERVATION) || -+ !S_ISREG(inode->i_mode)) { -+ retval = -ENOTTY; -+ goto out; -+ } - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) -- return -EACCES; -+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) { -+ retval = -EACCES; -+ goto out; -+ } - -- if (get_user(rsv_window_size, (int __user *)arg)) -- return -EFAULT; -+ if (get_user(rsv_window_size, (int __user *)arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS) - rsv_window_size = EXT2_MAX_RESERVE_BLOCKS; -@@ -131,11 +164,15 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - rsv->rsv_goal_size = rsv_window_size; - } - mutex_unlock(&ei->truncate_mutex); -- return 0; -+ goto out; - } - default: -- return -ENOTTY; -+ retval = -ENOTTY; -+ goto out; - } -+out: -+ unlock_kernel(); -+ return retval; - } - - #ifdef CONFIG_COMPAT -@@ -161,9 +198,7 @@ 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; - } - #endif --- -1.5.3.8 diff --git a/ext3-unlocked-ioctl.patch b/ext3-unlocked-ioctl.patch deleted file mode 100644 index 7c2247b1..00000000 --- a/ext3-unlocked-ioctl.patch +++ /dev/null @@ -1,395 +0,0 @@ -Convert ext3_ioctl() to an unlocked_ioctl - -From: Mathieu Segaud - -Change ext3_ioctl() to be an unlocked_ioctl(), explicitly -exposing BKL's uses. - -Signed-off-by: Mathieu Segaud -Signed-off-by: "Theodore Ts'o" - ---- - fs/ext3/dir.c | 2 +- - fs/ext3/file.c | 2 +- - fs/ext3/ioctl.c | 161 ++++++++++++++++++++++++++++++++--------------- - include/linux/ext3_fs.h | 3 +- - 4 files changed, 113 insertions(+), 55 deletions(-) - -diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c -index 8ca3bfd..5ab6b88 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..49798ed 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..a7c480a 100644 ---- a/fs/ext3/ioctl.c -+++ b/fs/ext3/ioctl.c -@@ -17,12 +17,19 @@ - #include - #include - --int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, -+long ext3_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) - { -- struct ext3_inode_info *ei = EXT3_I(inode); -+ struct ext3_inode_info *ei; -+ struct inode *inode; - unsigned int flags; - unsigned short rsv_window_size; -+ long retval = 0; -+ -+ lock_kernel(); -+ -+ inode = filp->f_path.dentry->d_inode; -+ ei = EXT3_I(inode); - - ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg); - -@@ -30,7 +37,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - case EXT3_IOC_GETFLAGS: - ext3_get_inode_flags(ei); - flags = ei->i_flags & EXT3_FL_USER_VISIBLE; -- return put_user(flags, (int __user *) arg); -+ retval = put_user(flags, (int __user *) arg); -+ goto out; - case EXT3_IOC_SETFLAGS: { - handle_t *handle = NULL; - int err; -@@ -38,14 +46,20 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - unsigned int oldflags; - unsigned int jflag; - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if (!is_owner_or_cap(inode)) -- return -EACCES; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EACCES; -+ goto out; -+ } - -- if (get_user(flags, (int __user *) arg)) -- return -EFAULT; -+ if (get_user(flags, (int __user *) arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - if (!S_ISDIR(inode->i_mode)) - flags &= ~EXT3_DIRSYNC_FL; -@@ -54,7 +68,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - /* Is it quota file? Do not allow user to mess with it */ - if (IS_NOQUOTA(inode)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - oldflags = ei->i_flags; - -@@ -70,7 +85,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { - if (!capable(CAP_LINUX_IMMUTABLE)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - } - -@@ -81,7 +97,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { - if (!capable(CAP_SYS_RESOURCE)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - } - -@@ -89,7 +106,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - handle = ext3_journal_start(inode, 1); - if (IS_ERR(handle)) { - mutex_unlock(&inode->i_mutex); -- return PTR_ERR(handle); -+ retval = PTR_ERR(handle); -+ goto out; - } - if (IS_SYNC(inode)) - handle->h_sync = 1; -@@ -109,17 +127,20 @@ flags_err: - ext3_journal_stop(handle); - if (err) { - mutex_unlock(&inode->i_mutex); -- return err; -+ retval = err; -+ goto out; - } - - if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) - err = ext3_change_inode_journal_flag(inode, jflag); - mutex_unlock(&inode->i_mutex); -- return err; -+ retval = err; -+ goto out; - } - case EXT3_IOC_GETVERSION: - case EXT3_IOC_GETVERSION_OLD: -- return put_user(inode->i_generation, (int __user *) arg); -+ retval = put_user(inode->i_generation, (int __user *) arg); -+ goto out; - case EXT3_IOC_SETVERSION: - case EXT3_IOC_SETVERSION_OLD: { - handle_t *handle; -@@ -127,16 +148,24 @@ flags_err: - __u32 generation; - int err; - -- if (!is_owner_or_cap(inode)) -- return -EPERM; -- if (IS_RDONLY(inode)) -- return -EROFS; -- if (get_user(generation, (int __user *) arg)) -- return -EFAULT; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EPERM; -+ goto out; -+ } -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } -+ if (get_user(generation, (int __user *) arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - handle = ext3_journal_start(inode, 1); -- if (IS_ERR(handle)) -- return PTR_ERR(handle); -+ if (IS_ERR(handle)) { -+ retval = PTR_ERR(handle); -+ goto out; -+ } - err = ext3_reserve_inode_write(handle, inode, &iloc); - if (err == 0) { - inode->i_ctime = CURRENT_TIME_SEC; -@@ -144,7 +173,8 @@ flags_err: - err = ext3_mark_iloc_dirty(handle, inode, &iloc); - } - ext3_journal_stop(handle); -- return err; -+ retval = err; -+ goto out; - } - #ifdef CONFIG_JBD_DEBUG - case EXT3_IOC_WAIT_FOR_READONLY: -@@ -158,7 +188,7 @@ flags_err: - { - struct super_block *sb = inode->i_sb; - DECLARE_WAITQUEUE(wait, current); -- int ret = 0; -+ long ret = 0; - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait); -@@ -167,6 +197,7 @@ flags_err: - ret = 1; - } - remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait); -+ unlock_kernel(); - return ret; - } - #endif -@@ -175,22 +206,33 @@ flags_err: - && S_ISREG(inode->i_mode) - && ei->i_block_alloc_info) { - rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size; -- return put_user(rsv_window_size, (int __user *)arg); -+ retval = put_user(rsv_window_size, (int __user *)arg); -+ goto out; - } -- return -ENOTTY; -+ retval = -ENOTTY; -+ goto out; - case EXT3_IOC_SETRSVSZ: { - -- if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) -- return -ENOTTY; -+ if (!test_opt(inode->i_sb, RESERVATION) || -+ !S_ISREG(inode->i_mode)) { -+ retval = -ENOTTY; -+ goto out; -+ } - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if (!is_owner_or_cap(inode)) -- return -EACCES; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EACCES; -+ goto out; -+ } - -- if (get_user(rsv_window_size, (int __user *)arg)) -- return -EFAULT; -+ if (get_user(rsv_window_size, (int __user *)arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS) - rsv_window_size = EXT3_MAX_RESERVE_BLOCKS; -@@ -208,27 +250,34 @@ flags_err: - rsv->rsv_goal_size = rsv_window_size; - } - mutex_unlock(&ei->truncate_mutex); -- return 0; -+ goto out; - } - case EXT3_IOC_GROUP_EXTEND: { - ext3_fsblk_t n_blocks_count; - struct super_block *sb = inode->i_sb; - int err; - -- if (!capable(CAP_SYS_RESOURCE)) -- return -EPERM; -+ if (!capable(CAP_SYS_RESOURCE)) { -+ retval = -EPERM; -+ goto out; -+ } - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if (get_user(n_blocks_count, (__u32 __user *)arg)) -- return -EFAULT; -+ if (get_user(n_blocks_count, (__u32 __user *)arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count); - journal_lock_updates(EXT3_SB(sb)->s_journal); - journal_flush(EXT3_SB(sb)->s_journal); - journal_unlock_updates(EXT3_SB(sb)->s_journal); - -+ unlock_kernel(); - return err; - } - case EXT3_IOC_GROUP_ADD: { -@@ -236,28 +285,40 @@ flags_err: - struct super_block *sb = inode->i_sb; - int err; - -- if (!capable(CAP_SYS_RESOURCE)) -- return -EPERM; -+ if (!capable(CAP_SYS_RESOURCE)) { -+ retval = -EPERM; -+ goto out; -+ } - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - - if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg, -- sizeof(input))) -- return -EFAULT; -+ sizeof(input))) { -+ retval = -EFAULT; -+ goto out; -+ } - - err = ext3_group_add(sb, &input); - journal_lock_updates(EXT3_SB(sb)->s_journal); - journal_flush(EXT3_SB(sb)->s_journal); - journal_unlock_updates(EXT3_SB(sb)->s_journal); - -+ unlock_kernel(); - return err; - } - - - default: -+ unlock_kernel(); - return -ENOTTY; - } -+ -+out: -+ unlock_kernel(); -+ return retval; - } - - #ifdef CONFIG_COMPAT -@@ -305,9 +366,7 @@ 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; - } - #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 */ --- -1.5.3.8 - -- -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 - diff --git a/ext4-block-reservation.patch b/ext4-block-reservation.patch deleted file mode 100644 index c807320f..00000000 --- a/ext4-block-reservation.patch +++ /dev/null @@ -1,300 +0,0 @@ -ext4: [RFC] free space management for delayed allocation - -From: Alex Tomas - -ext4-block-reservation.patch - -this is scalable free space management. every time we -delay allocation of some page, a space (including metadata) -should be reserved - -Signed-off-by: Alex Tomas - ---- ---- - fs/ext4/balloc.c | 176 ++++++++++++++++++++++++++++++++++++++++++++- - fs/ext4/super.c | 2 - include/linux/ext4_fs.h | 5 + - include/linux/ext4_fs_sb.h | 5 + - 4 files changed, 185 insertions(+), 3 deletions(-) - -Index: linux-2.6.23-rc2/fs/ext4/balloc.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/balloc.c 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/balloc.c 2007-08-06 22:18:59.000000000 -0700 -@@ -630,8 +630,10 @@ void ext4_free_blocks(handle_t *handle, - return; - } - ext4_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks); -- if (dquot_freed_blocks) -+ if (dquot_freed_blocks) { -+ ext4_release_blocks(sb, dquot_freed_blocks); - DQUOT_FREE_BLOCK(inode, dquot_freed_blocks); -+ } - return; - } - -@@ -1440,7 +1442,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *h - struct ext4_sb_info *sbi; - struct ext4_reserve_window_node *my_rsv = NULL; - struct ext4_block_alloc_info *block_i; -- unsigned short windowsz = 0; -+ unsigned short windowsz = 0, reserved = 0; - #ifdef EXT4FS_DEBUG - static int goal_hits, goal_attempts; - #endif -@@ -1462,6 +1464,13 @@ ext4_fsblk_t ext4_new_blocks(handle_t *h - return 0; - } - -+ if (!(EXT4_I(inode)->i_state & EXT4_STATE_BLOCKS_RESERVED)) { -+ *errp = ext4_reserve_blocks(sb, num); -+ if (*errp) -+ return 0; -+ reserved = num; -+ } -+ - sbi = EXT4_SB(sb); - es = EXT4_SB(sb)->s_es; - ext4_debug("goal=%lu.\n", goal); -@@ -1674,8 +1683,11 @@ out: - /* - * Undo the block allocation - */ -- if (!performed_allocation) -+ if (!performed_allocation) { - DQUOT_FREE_BLOCK(inode, *count); -+ if (reserved) -+ ext4_release_blocks(sb, reserved); -+ } - brelse(bitmap_bh); - return 0; - } -@@ -1834,3 +1846,161 @@ unsigned long ext4_bg_num_gdb(struct sup - return ext4_bg_num_gdb_meta(sb,group); - - } -+ -+/* -+ * reservation.c contains routines to reserve blocks. -+ * we need this for delayed allocation, otherwise we -+ * could meet -ENOSPC at flush time -+ */ -+ -+/* -+ * as ->commit_write() where we're going to reserve -+ * non-allocated-yet blocks is well known hotpath, -+ * we have to make it scalable and avoid global -+ * data as much as possible -+ * -+ * there is per-sb array -+ */ -+ -+struct ext4_reservation_slot { -+ __u64 rs_reserved; -+ spinlock_t rs_lock; -+} ____cacheline_aligned; -+ -+ -+int ext4_reserve_local(struct super_block *sb, int blocks) -+{ -+ struct ext4_sb_info *sbi = EXT4_SB(sb); -+ struct ext4_reservation_slot *rs; -+ int rc = -ENOSPC; -+ -+ preempt_disable(); -+ rs = sbi->s_reservation_slots + smp_processor_id(); -+ -+ spin_lock(&rs->rs_lock); -+ if (likely(rs->rs_reserved >= blocks)) { -+ rs->rs_reserved -= blocks; -+ rc = 0; -+ } -+ spin_unlock(&rs->rs_lock); -+ -+ preempt_enable(); -+ return rc; -+} -+ -+ -+void ext4_rebalance_reservation(struct ext4_reservation_slot *rs, __u64 free) -+{ -+ int i, used_slots = 0; -+ __u64 chunk; -+ -+ /* let's know what slots have been used */ -+ for (i = 0; i < NR_CPUS; i++) -+ if (rs[i].rs_reserved || i == smp_processor_id()) -+ used_slots++; -+ -+ /* chunk is a number of block every used -+ * slot will get. make sure it isn't 0 */ -+ chunk = free + used_slots - 1; -+ do_div(chunk, used_slots); -+ -+ for (i = 0; i < NR_CPUS; i++) { -+ if (free < chunk) -+ chunk = free; -+ if (rs[i].rs_reserved || i == smp_processor_id()) { -+ rs[i].rs_reserved = chunk; -+ free -= chunk; -+ BUG_ON(free < 0); -+ } -+ } -+ BUG_ON(free); -+} -+ -+int ext4_reserve_global(struct super_block *sb, int blocks) -+{ -+ struct ext4_sb_info *sbi = EXT4_SB(sb); -+ struct ext4_reservation_slot *rs; -+ int i, rc = -ENOENT; -+ __u64 free = 0; -+ -+ rs = sbi->s_reservation_slots; -+ -+ /* lock all slots */ -+ for (i = 0; i < NR_CPUS; i++) { -+ spin_lock(&rs[i].rs_lock); -+ free += rs[i].rs_reserved; -+ } -+ -+ if (free >= blocks) { -+ free -= blocks; -+ ext4_rebalance_reservation(rs, free); -+ rc = 0; -+ } -+ -+ for (i = 0; i < NR_CPUS; i++) -+ spin_unlock(&rs[i].rs_lock); -+ -+ return rc; -+} -+ -+int ext4_reserve_blocks(struct super_block *sb, int blocks) -+{ -+ int ret; -+ -+ BUG_ON(blocks <= 0); -+ -+ ret = ext4_reserve_local(sb, blocks); -+ if (likely(ret == 0)) -+ return 0; -+ -+ return ext4_reserve_global(sb, blocks); -+} -+ -+void ext4_release_blocks(struct super_block *sb, int blocks) -+{ -+ struct ext4_sb_info *sbi = EXT4_SB(sb); -+ struct ext4_reservation_slot *rs; -+ -+ BUG_ON(blocks <= 0); -+ -+ preempt_disable(); -+ rs = sbi->s_reservation_slots + smp_processor_id(); -+ -+ spin_lock(&rs->rs_lock); -+ rs->rs_reserved += blocks; -+ spin_unlock(&rs->rs_lock); -+ -+ preempt_enable(); -+} -+ -+int ext4_reserve_init(struct super_block *sb) -+{ -+ struct ext4_sb_info *sbi = EXT4_SB(sb); -+ struct ext4_reservation_slot *rs; -+ int i; -+ -+ rs = kmalloc(sizeof(struct ext4_reservation_slot)*NR_CPUS, GFP_KERNEL); -+ if (rs == NULL) -+ return -ENOMEM; -+ sbi->s_reservation_slots = rs; -+ -+ for (i = 0; i < NR_CPUS; i++) { -+ spin_lock_init(&rs[i].rs_lock); -+ rs[i].rs_reserved = 0; -+ } -+ rs[0].rs_reserved = percpu_counter_sum(&sbi->s_freeblocks_counter); -+ -+ return 0; -+} -+ -+void ext4_reserve_release(struct super_block *sb) -+{ -+ struct ext4_sb_info *sbi = EXT4_SB(sb); -+ struct ext4_reservation_slot *rs; -+ -+ rs = sbi->s_reservation_slots; -+ BUG_ON(sbi->s_reservation_slots == NULL); -+ kfree(sbi->s_reservation_slots); -+ sbi->s_reservation_slots = NULL; -+} -+ -Index: linux-2.6.23-rc2/fs/ext4/super.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/super.c 2007-08-06 22:18:49.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/super.c 2007-08-06 22:18:59.000000000 -0700 -@@ -441,6 +441,7 @@ static void ext4_put_super (struct super - struct ext4_super_block *es = sbi->s_es; - int i; - -+ ext4_reserve_release(sb); - ext4_ext_release(sb); - ext4_xattr_put_super(sb); - jbd2_journal_destroy(sbi->s_journal); -@@ -1948,6 +1949,7 @@ static int ext4_fill_super (struct super - "writeback"); - - ext4_ext_init(sb); -+ ext4_reserve_init(sb); - - lock_kernel(); - return 0; -Index: linux-2.6.23-rc2/include/linux/ext4_fs.h -=================================================================== ---- linux-2.6.23-rc2.orig/include/linux/ext4_fs.h 2007-08-06 22:18:46.000000000 -0700 -+++ linux-2.6.23-rc2/include/linux/ext4_fs.h 2007-08-06 22:18:59.000000000 -0700 -@@ -203,6 +203,7 @@ struct ext4_group_desc - #define EXT4_STATE_NEW 0x00000002 /* inode is newly created */ - #define EXT4_STATE_XATTR 0x00000004 /* has in-inode xattrs */ - #define EXT4_STATE_NO_EXPAND 0x00000008 /* No space for expansion */ -+#define EXT4_STATE_BLOCKS_RESERVED 0x00000010 /* blocks reserved */ - - /* Used to pass group descriptor data when online resize is done */ - struct ext4_new_group_input { -@@ -912,6 +913,10 @@ extern struct ext4_group_desc * ext4_get - extern int ext4_should_retry_alloc(struct super_block *sb, int *retries); - extern void ext4_init_block_alloc_info(struct inode *); - extern void ext4_rsv_window_add(struct super_block *sb, struct ext4_reserve_window_node *rsv); -+int ext4_reserve_init(struct super_block *sb); -+void ext4_reserve_release(struct super_block *sb); -+void ext4_release_blocks(struct super_block *sb, int blocks); -+int ext4_reserve_blocks(struct super_block *sb, int blocks); - - /* dir.c */ - extern int ext4_check_dir_entry(const char *, struct inode *, -Index: linux-2.6.23-rc2/include/linux/ext4_fs_sb.h -=================================================================== ---- linux-2.6.23-rc2.orig/include/linux/ext4_fs_sb.h 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/include/linux/ext4_fs_sb.h 2007-08-06 22:18:59.000000000 -0700 -@@ -24,6 +24,8 @@ - #endif - #include - -+struct ext4_reservation_slot; -+ - /* - * third extended-fs super-block data in memory - */ -@@ -67,6 +69,9 @@ struct ext4_sb_info { - struct rb_root s_rsv_window_root; - struct ext4_reserve_window_node s_rsv_window_head; - -+ /* global reservation structures */ -+ struct ext4_reservation_slot *s_reservation_slots; -+ - /* Journaling */ - struct inode * s_journal_inode; - struct journal_s * s_journal; diff --git a/ext4-delalloc-extents-48bit.patch b/ext4-delalloc-extents-48bit.patch deleted file mode 100644 index d15f4f74..00000000 --- a/ext4-delalloc-extents-48bit.patch +++ /dev/null @@ -1,76 +0,0 @@ -ext4: Add basic delayed allocation support - -From: Alex Tomas - -Signed-off-by: Alex Tomas ---- ---- - fs/ext4/writeback.c | 20 ++++++++++++++------ - 1 file changed, 14 insertions(+), 6 deletions(-) - -Index: linux-2.6.23-rc3/fs/ext4/writeback.c -=================================================================== ---- linux-2.6.23-rc3.orig/fs/ext4/writeback.c 2007-08-14 16:37:58.000000000 -0700 -+++ linux-2.6.23-rc3/fs/ext4/writeback.c 2007-08-14 17:11:33.000000000 -0700 -@@ -275,7 +275,8 @@ static int ext4_wb_submit_extent(struct - struct inode *inode = wc->mapping->host; - int blkbits = inode->i_blkbits; - struct page *page; -- unsigned long blk, off, len, remain; -+ ext4_fsblk_t off; -+ unsigned long blk, len, remain; - unsigned long pstart, plen, prev; - struct bio *bio = NULL; - int nr_pages; -@@ -336,6 +337,8 @@ alloc_new_bio: - nr_pages = (nr_pages >> (PAGE_CACHE_SHIFT - blkbits)); - off = le32_to_cpu(ex->ee_start) + - (blk - le32_to_cpu(ex->ee_block)); -+ off |= (ext4_fsblk_t) -+ le16_to_cpu(ex->ee_start_hi) << 32; - bio = ext4_wb_bio_alloc(inode, off, nr_pages + 2); - if (bio == NULL) - return -ENOMEM; -@@ -383,7 +386,9 @@ ext4_wb_find_goal(struct inode *inode, s - /* try to predict block placement */ - ex = path[depth].p_ext; - if (ex) -- return le32_to_cpu(ex->ee_start) + -+ return (le32_to_cpu(ex->ee_start) | -+ ((ext4_fsblk_t) -+ le16_to_cpu(ex->ee_start_hi) << 32)) + - (block - le32_to_cpu(ex->ee_block)); - - /* it looks index is empty -@@ -423,7 +428,8 @@ static int ext4_wb_handle_extent(struct - (unsigned) ec->ec_block, - (unsigned) ec->ec_len, - (unsigned) ec->ec_start); -- nex.ee_start = cpu_to_le32(ec->ec_start); -+ nex.ee_start = cpu_to_le32(ec->ec_start & 0xffffffff); -+ nex.ee_start_hi = cpu_to_le16((ec->ec_start >> 32) & 0xffff); - nex.ee_block = cpu_to_le32(ec->ec_block); - nex.ee_len = cpu_to_le16(ec->ec_len); - err = ext4_wb_submit_extent(wc, NULL, &nex, 0); -@@ -497,8 +503,8 @@ static int ext4_wb_handle_extent(struct - pblock, count, inode->i_ino, ec->ec_len); - - /* insert new extent */ -- nex.ee_start = cpu_to_le32(pblock); -- nex.ee_start_hi = 0; -+ nex.ee_start = cpu_to_le32(pblock & 0xffffffff); -+ nex.ee_start_hi = cpu_to_le16((pblock >> 32) & 0xffff); - nex.ee_len = cpu_to_le16(count); - nex.ee_block = cpu_to_le32(ec->ec_block); - err = ext4_ext_insert_extent(handle, inode, path, &nex); -@@ -533,7 +539,9 @@ static int ext4_wb_handle_extent(struct - * in correspondend buffer_heads to prevent corruptions */ - for (i = 0; i < le16_to_cpu(nex.ee_len); i++) - unmap_underlying_metadata(sb->s_bdev, -- le32_to_cpu(nex.ee_start) + i); -+ ((ext4_fsblk_t) -+ le16_to_cpu(nex.ee_start_hi) << 32) + -+ le32_to_cpu(nex.ee_start) + i); - - /* correct on-disk inode size */ - if (le16_to_cpu(nex.ee_len) > 0) { diff --git a/ext4-delayed-allocation.patch b/ext4-delayed-allocation.patch deleted file mode 100644 index 1a447dac..00000000 --- a/ext4-delayed-allocation.patch +++ /dev/null @@ -1,1489 +0,0 @@ -ext4: [RFC] delayed allocation for ext4 - -From: Alex Tomas - -delayed allocation itself, enabled by "delalloc" mount option. -extents support is also required. currently it works only -with blocksize=pagesize. - -Shaggy fixed a lot of endian errors reported by sparse - -Signed-off-by: Alex Tomas ---- - - fs/ext4/Makefile | 2 - fs/ext4/extents.c | 30 + - fs/ext4/file.c | 4 - fs/ext4/inode.c | 34 + - fs/ext4/super.c | 14 - fs/ext4/writeback.c | 1185 ++++++++++++++++++++++++++++++++++++++++ - include/linux/ext4_fs.h | 17 - include/linux/ext4_fs_extents.h | 1 - include/linux/ext4_fs_i.h | 4 - include/linux/ext4_fs_sb.h | 11 - 10 files changed, 1297 insertions(+), 5 deletions(-) - -Index: linux-2.6.23-rc2/fs/ext4/Makefile -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/Makefile 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/Makefile 2007-08-06 22:19:05.000000000 -0700 -@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o - - ext4dev-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ -- ext4_jbd2.o -+ ext4_jbd2.o writeback.o - - ext4dev-$(CONFIG_EXT4DEV_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o - ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o -Index: linux-2.6.23-rc2/fs/ext4/extents.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/extents.c 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/extents.c 2007-08-06 22:19:05.000000000 -0700 -@@ -2508,6 +2508,36 @@ int ext4_ext_writepage_trans_blocks(stru - return needed; - } - -+int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks) -+{ -+ int lcap, icap, rcap, leafs, idxs, num; -+ -+ rcap = ext4_ext_space_root(inode); -+ if (blocks <= rcap) { -+ /* all extents fit to the root */ -+ return 0; -+ } -+ -+ rcap = ext4_ext_space_root_idx(inode); -+ lcap = ext4_ext_space_block(inode); -+ icap = ext4_ext_space_block_idx(inode); -+ -+ num = leafs = (blocks + lcap - 1) / lcap; -+ if (leafs <= rcap) { -+ /* all pointers to leafs fit to the root */ -+ return leafs; -+ } -+ -+ /* ok. we need separate index block(s) to link all leaf blocks */ -+ idxs = (leafs + icap - 1) / icap; -+ do { -+ num += idxs; -+ idxs = (idxs + icap - 1) / icap; -+ } while (idxs > rcap); -+ -+ return num; -+} -+ - /* - * preallocate space for a file. This implements ext4's fallocate inode - * operation, which gets called from sys_fallocate system call. -Index: linux-2.6.23-rc2/fs/ext4/file.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/file.c 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/file.c 2007-08-06 22:19:05.000000000 -0700 -@@ -35,8 +35,8 @@ static int ext4_release_file (struct ino - { - /* if we are the last writer on the inode, drop the block reservation */ - if ((filp->f_mode & FMODE_WRITE) && -- (atomic_read(&inode->i_writecount) == 1)) -- { -+ (atomic_read(&inode->i_writecount) == 1) && -+ EXT4_I(inode)->i_blocks_reserved == 0) { - mutex_lock(&EXT4_I(inode)->truncate_mutex); - ext4_discard_reservation(inode); - mutex_unlock(&EXT4_I(inode)->truncate_mutex); -Index: linux-2.6.23-rc2/fs/ext4/inode.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/inode.c 2007-08-06 22:18:49.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/inode.c 2007-08-06 22:19:05.000000000 -0700 -@@ -942,7 +942,7 @@ out: - - #define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32) - --static int ext4_get_block(struct inode *inode, sector_t iblock, -+int ext4_get_block(struct inode *inode, sector_t iblock, - struct buffer_head *bh_result, int create) - { - handle_t *handle = ext4_journal_current_handle(); -@@ -1741,9 +1741,34 @@ static const struct address_space_operat - .releasepage = ext4_releasepage, - }; - -+static int ext4_wb_set_page_dirty(struct page *page) -+{ -+ return __set_page_dirty_nobuffers(page); -+} -+ -+static struct address_space_operations ext4_writeback_da_aops = { -+ .readpage = ext4_readpage, -+ .readpages = ext4_readpages, -+ .writepage = ext4_wb_writepage, -+ .writepages = ext4_wb_writepages, -+ .sync_page = block_sync_page, -+ .prepare_write = ext4_wb_prepare_write, -+ .commit_write = ext4_wb_commit_write, -+ .bmap = ext4_bmap, -+ .invalidatepage = ext4_wb_invalidatepage, -+ .releasepage = ext4_wb_releasepage, -+ .set_page_dirty = ext4_wb_set_page_dirty, -+ .direct_IO = ext4_direct_IO, -+}; -+ - void ext4_set_aops(struct inode *inode) - { -- if (ext4_should_order_data(inode)) -+ if (S_ISREG(inode->i_mode) && -+ (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) && -+ test_opt(inode->i_sb, EXTENTS) && -+ test_opt(inode->i_sb, DELAYED_ALLOC)) -+ inode->i_mapping->a_ops = &ext4_writeback_da_aops; -+ else if (ext4_should_order_data(inode)) - inode->i_mapping->a_ops = &ext4_ordered_aops; - else if (ext4_should_writeback_data(inode)) - inode->i_mapping->a_ops = &ext4_writeback_aops; -@@ -1767,6 +1792,11 @@ int ext4_block_truncate_page(handle_t *h - struct buffer_head *bh; - int err = 0; - -+ if ((EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) && -+ test_opt(inode->i_sb, EXTENTS) && -+ test_opt(inode->i_sb, DELAYED_ALLOC)) -+ return ext4_wb_block_truncate_page(handle, page, mapping, from); -+ - blocksize = inode->i_sb->s_blocksize; - length = blocksize - (offset & (blocksize - 1)); - iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); -Index: linux-2.6.23-rc2/fs/ext4/super.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/super.c 2007-08-06 22:18:59.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/super.c 2007-08-06 22:19:05.000000000 -0700 -@@ -441,6 +441,7 @@ static void ext4_put_super (struct super - struct ext4_super_block *es = sbi->s_es; - int i; - -+ ext4_wb_release(sb); - ext4_reserve_release(sb); - ext4_ext_release(sb); - ext4_xattr_put_super(sb); -@@ -508,6 +509,13 @@ static struct inode *ext4_alloc_inode(st - ei->i_block_alloc_info = NULL; - ei->vfs_inode.i_version = 1; - memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); -+ -+ /* FIXME: these wb-related fields could be initialized once */ -+ ei->i_blocks_reserved = 0; -+ ei->i_md_reserved = 0; -+ atomic_set(&ei->i_wb_writers, 0); -+ spin_lock_init(&ei->i_wb_reserved_lock); -+ - return &ei->vfs_inode; - } - -@@ -738,6 +746,7 @@ enum { - Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, - Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, - Opt_grpquota, Opt_extents, Opt_noextents, -+ Opt_delayed_alloc, - }; - - static match_table_t tokens = { -@@ -791,6 +800,7 @@ static match_table_t tokens = { - {Opt_barrier, "barrier=%u"}, - {Opt_extents, "extents"}, - {Opt_noextents, "noextents"}, -+ {Opt_delayed_alloc, "delalloc"}, - {Opt_err, NULL}, - {Opt_resize, "resize"}, - }; -@@ -1112,6 +1122,9 @@ clear_qf_name: - else - clear_opt(sbi->s_mount_opt, BARRIER); - break; -+ case Opt_delayed_alloc: -+ set_opt(sbi->s_mount_opt, DELAYED_ALLOC); -+ break; - case Opt_ignore: - break; - case Opt_resize: -@@ -1950,6 +1963,7 @@ static int ext4_fill_super (struct super - - ext4_ext_init(sb); - ext4_reserve_init(sb); -+ ext4_wb_init(sb); - - lock_kernel(); - return 0; -Index: linux-2.6.23-rc2/fs/ext4/writeback.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc2/fs/ext4/writeback.c 2007-08-06 22:19:05.000000000 -0700 -@@ -0,0 +1,1185 @@ -+/* -+ * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+/* -+ * TODO: -+ * MUST: -+ * - flush dirty pages in -ENOSPC case in order to free reserved blocks -+ * - direct I/O support -+ * - blocksize != PAGE_CACHE_SIZE support -+ * - store last unwritten page in ext4_wb_writepages() and -+ * continue from it in a next run -+ * WISH: -+ * - should ext4_wb_writepage() try to flush neighbours? -+ * - ext4_wb_block_truncate_page() must flush partial truncated pages -+ * - reservation can be done per write-request in ext4_file_write() -+ * rather than per-page in ext4_wb_commit_write() -- it's quite -+ * expensive to recalculate amount of required metadata for evey page -+ * - re-allocation to improve layout -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * If EXT4_WB_STATS is defined, then some stats are collected. -+ * It will be showed upont umount time. -+ */ -+#define EXT4_WB_STATS -+ -+ -+/* -+ * With EXT4_WB_SKIP_SMALL defined the patch will try to avoid -+ * small I/Os ignoring ->writepages() if mapping hasn't enough -+ * contig. dirty pages -+ */ -+#define EXT4_WB_SKIP_SMALL__ -+ -+#define WB_ASSERT(__x__) if (!(__x__)) BUG(); -+ -+#define WB_DEBUG__ -+#ifdef WB_DEBUG -+#define wb_debug(fmt, a...) printk(fmt, ##a); -+#else -+#define wb_debug(fmt, a...) -+#endif -+ -+#define WB_MAX_PAGES_PER_EXTENT 32768 -+ -+#define WB_PAGES_PER_ARRAY 60 -+ -+struct ext4_wb_pages { -+ struct list_head list; -+ struct page *pages[WB_PAGES_PER_ARRAY]; -+ unsigned short num, start; -+}; -+ -+struct ext4_wb_control { -+ pgoff_t start; -+ int len, extents; -+ int blocks_to_release; -+ struct ext4_wb_pages *pages; -+ struct list_head list; -+ struct address_space *mapping; -+}; -+ -+ -+void ext4_wb_invalidatepage(struct page *, unsigned long); -+int ext4_get_block(struct inode *inode, sector_t iblock, -+ struct buffer_head *bh_result, int create); -+ -+ -+static struct page *ext4_wb_pull_page(struct ext4_wb_control *wc) -+{ -+ struct ext4_wb_pages *wp = wc->pages; -+ -+ BUG_ON(wp == NULL); -+ BUG_ON(list_empty(&wc->list)); -+ BUG_ON(list_empty(&wp->list)); -+ if (wp->start == wp->num) { -+ list_del(&wp->list); -+ kfree(wp); -+ if (list_empty(&wc->list)) -+ return NULL; -+ wp = list_entry(wc->list.next, struct ext4_wb_pages, list); -+ wc->pages = wp; -+ } -+ BUG_ON(list_empty(&wp->list)); -+ return wp->pages[wp->start++]; -+} -+ -+static struct bio *ext4_wb_bio_alloc(struct inode *inode, -+ sector_t first_block, int nr_vecs) -+{ -+ gfp_t gfp_flags = GFP_NOFS | __GFP_HIGH; -+ struct bio *bio; -+ int maxreq; -+ -+ maxreq = bio_get_nr_vecs(inode->i_sb->s_bdev); -+ if (maxreq < nr_vecs) -+ nr_vecs = maxreq; -+ -+ bio = bio_alloc(gfp_flags, nr_vecs); -+ -+ if (bio == NULL && (current->flags & PF_MEMALLOC)) { -+ while (!bio && (nr_vecs /= 2)) -+ bio = bio_alloc(gfp_flags, nr_vecs); -+ } -+ -+ if (bio) { -+ bio->bi_bdev = inode->i_sb->s_bdev; -+ bio->bi_sector = first_block << (inode->i_blkbits - 9); -+ } -+ return bio; -+} -+ -+static int ext4_wb_end_io(struct bio *bio, unsigned int bytes, int err) -+{ -+ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); -+ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; -+ -+ if (bio->bi_size) -+ return 1; -+ -+ do { -+ struct page *page = bvec->bv_page; -+ -+ if (--bvec >= bio->bi_io_vec) -+ prefetchw(&bvec->bv_page->flags); -+ -+ if (!uptodate) -+ SetPageError(page); -+ end_page_writeback(page); -+ } while (bvec >= bio->bi_io_vec); -+ bio_put(bio); -+ return 0; -+} -+ -+static struct bio *ext4_wb_bio_submit(struct bio *bio, handle_t *handle) -+{ -+ bio->bi_end_io = ext4_wb_end_io; -+ submit_bio(WRITE, bio); -+ return NULL; -+} -+ -+int inline ext4_wb_reserve_space_page(struct page *page, int blocks) -+{ -+ struct inode *inode = page->mapping->host; -+ int total, mdb, err; -+ -+ wb_debug("reserve %d blocks for page %lu from inode %lu\n", -+ blocks, page->index, inode->i_ino); -+ -+ /* user wants us to reserve blocks for his file. reserving space -+ * for his (data) blocks isn't enough because adding block may -+ * involve allocation index/leaf blocks for tree/blockmap. -+ * so, we need to calculate numbers of needed metadata for worst -+ * case: block per extent */ -+ -+ spin_lock(&EXT4_I(inode)->i_wb_reserved_lock); -+ total = EXT4_I(inode)->i_blocks_reserved + blocks; -+ mdb = ext4_ext_calc_metadata_amount(inode, total); -+ -+ /* if blockmap needs more metadata, we have to reserve difference */ -+ BUG_ON(mdb < EXT4_I(inode)->i_md_reserved); -+ mdb = mdb - EXT4_I(inode)->i_md_reserved; -+ -+ err = ext4_reserve_blocks(inode->i_sb, mdb + blocks); -+ if (err) { -+ /* blocks are exhausted? */ -+ spin_unlock(&EXT4_I(inode)->i_wb_reserved_lock); -+ return err; -+ } -+ -+ /* blocks have been reserved, account this. I believe -+ * inode's fields are protected by inode->i_sem */ -+ EXT4_I(inode)->i_blocks_reserved += blocks; -+ EXT4_I(inode)->i_md_reserved += mdb; -+ spin_unlock(&EXT4_I(inode)->i_wb_reserved_lock); -+ -+ /* we have reserved space on a disk for the page */ -+ SetPageBooked(page); -+ return 0; -+} -+ -+/* -+ * release space reserved for @blocks of data -+ * @used signals that @blocks got really allocated and we just -+ * need to release corresponded over-reserved metadata -+ */ -+int inline ext4_wb_release_space(struct inode *inode, int blocks, int used) -+{ -+ int total, mdb, release; -+ -+ spin_lock(&EXT4_I(inode)->i_wb_reserved_lock); -+ -+ total = EXT4_I(inode)->i_blocks_reserved - blocks; -+ mdb = ext4_ext_calc_metadata_amount(inode, total); -+ -+ /* if blockmap needs lesser metadata, we may release difference */ -+ BUG_ON(mdb > EXT4_I(inode)->i_md_reserved); -+ mdb = EXT4_I(inode)->i_md_reserved - mdb; -+ -+ release = mdb; -+ /* drop reservation only for non-used blocks */ -+ if (!used) -+ release += blocks; -+ wb_debug("%u %s: release %d/%d blocks from %u/%u reserved" -+ " for inode %lu\n", blocks, -+ used ? "allocated" : "dropped", used ? 0 : blocks, -+ mdb, EXT4_I(inode)->i_blocks_reserved, -+ EXT4_I(inode)->i_md_reserved, inode->i_ino); -+ if (release) -+ ext4_release_blocks(inode->i_sb, release); -+ -+ /* update per-inode reservations */ -+ BUG_ON(blocks > EXT4_I(inode)->i_blocks_reserved); -+ EXT4_I(inode)->i_blocks_reserved -= blocks; -+ BUG_ON(mdb > EXT4_I(inode)->i_md_reserved); -+ EXT4_I(inode)->i_md_reserved -= mdb; -+ -+ spin_unlock(&EXT4_I(inode)->i_wb_reserved_lock); -+ -+ return 0; -+} -+ -+static inline int ext4_wb_drop_page_reservation(struct page *page) -+{ -+ /* we just allocated blocks for this page. those blocks (and -+ * probably metadata for them) were reserved before. now we -+ * should drop reservation mark from the page. if we didn't -+ * do that then ->invalidatepage() may think page still holds -+ * reserved blocks. we could release reserved blocks right -+ * now, but I'd prefer to make this once per several blocks */ -+ wb_debug("drop reservation from page %lu from inode %lu\n", -+ page->index, page->mapping->host->i_ino); -+ BUG_ON(!PageBooked(page)); -+ ClearPageBooked(page); -+ return 0; -+} -+ -+static int ext4_wb_submit_extent(struct ext4_wb_control *wc, handle_t *handle, -+ struct ext4_extent *ex, int new) -+{ -+ struct inode *inode = wc->mapping->host; -+ int blkbits = inode->i_blkbits; -+ struct page *page; -+ unsigned long blk, off, len, remain; -+ unsigned long pstart, plen, prev; -+ struct bio *bio = NULL; -+ int nr_pages; -+ -+ /* -+ * we have list of pages in wc and block numbers in ex -+ * let's cook bios from them and start real I/O -+ */ -+ -+ BUG_ON(PAGE_CACHE_SHIFT < blkbits); -+ BUG_ON(list_empty(&wc->list)); -+ -+ wb_debug("cook and submit bios for %u/%u/%u for %lu/%u\n", -+ le32_to_cpu(ex->ee_block), le16_to_cpu(ex->ee_len), -+ le32_to_cpu(ex->ee_start), wc->start, wc->len); -+ -+ blk = le32_to_cpu(ex->ee_block); -+ remain = le16_to_cpu(ex->ee_len); -+ wc->extents++; -+ -+ while (remain) { -+ page = ext4_wb_pull_page(wc); -+ if (page == NULL) -+ break; -+ -+ pstart = page->index << (PAGE_CACHE_SHIFT - blkbits); -+ plen = PAGE_SIZE >> blkbits; -+ if (pstart > blk) { -+ /* probably extent covers long space and page -+ * to be written in the middle of it */ -+ BUG_ON(pstart - blk >= remain); -+ remain -= pstart - blk; -+ blk = pstart; -+ } -+ BUG_ON(blk < pstart || blk >= pstart + plen); -+ -+ BUG_ON(!PageUptodate(page)); -+ /* page can get here via mmap(2) -+ * BUG_ON(!PagePrivate(page));*/ -+ BUG_ON(new && PageMappedToDisk(page)); -+ BUG_ON(!new && !PageMappedToDisk(page)); -+ SetPageMappedToDisk(page); -+ if (new && PagePrivate(page)) { -+ /* space is just allocated and it was reserved in -+ * ->commit_write(). time to release reservation. -+ * space may not be reserved if page gets dirty -+ * via mmap. should we reserve it in ->mmap() ? */ -+ prev = min(plen, remain); -+ ext4_wb_drop_page_reservation(page); -+ wc->blocks_to_release += prev; -+ } -+ -+alloc_new_bio: -+ if (bio == NULL) { -+ /* +2 because head/tail may belong to different pages */ -+ nr_pages = (le16_to_cpu(ex->ee_len) - -+ (blk - le32_to_cpu(ex->ee_block))); -+ nr_pages = (nr_pages >> (PAGE_CACHE_SHIFT - blkbits)); -+ off = le32_to_cpu(ex->ee_start) + -+ (blk - le32_to_cpu(ex->ee_block)); -+ bio = ext4_wb_bio_alloc(inode, off, nr_pages + 2); -+ if (bio == NULL) -+ return -ENOMEM; -+ } -+ -+ off = (blk - pstart) << blkbits; -+ prev = min(plen, remain); -+ len = prev << blkbits; -+ if (bio_add_page(bio, page, len, off) < len) { -+ bio = ext4_wb_bio_submit(bio, handle); -+ goto alloc_new_bio; -+ } -+ remain -= prev; -+ blk += prev; -+ if (blk < pstart + plen) { -+ /* extent covers part of the page only. -+ * it's possible that next extent covers -+ * the tail. so, we leave page */ -+ printk("blk %lu pstart %lu plen %lu remain" -+ " %lu prev %lu\n", -+ blk, pstart, plen, remain, prev); -+ wc->pages->start--; -+ BUG_ON(remain != 0); -+ } -+ } -+ if (bio) -+ ext4_wb_bio_submit(bio, handle); -+ BUG_ON(new && remain != 0); -+ return 0; -+} -+ -+static ext4_fsblk_t -+ext4_wb_find_goal(struct inode *inode, struct ext4_ext_path *path, -+ ext4_fsblk_t block) -+{ -+ struct ext4_inode_info *ei = EXT4_I(inode); -+ ext4_fsblk_t bg_start; -+ unsigned long colour; -+ int depth; -+ -+ if (path) { -+ struct ext4_extent *ex; -+ depth = path->p_depth; -+ -+ /* try to predict block placement */ -+ ex = path[depth].p_ext; -+ if (ex) -+ return le32_to_cpu(ex->ee_start) + -+ (block - le32_to_cpu(ex->ee_block)); -+ -+ /* it looks index is empty -+ * try to find starting from index itself */ -+ if (path[depth].p_bh) -+ return path[depth].p_bh->b_blocknr; -+ } -+ -+ /* OK. use inode's group */ -+ bg_start = (ei->i_block_group * EXT4_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ return bg_start + colour + block; -+} -+ -+static int ext4_wb_handle_extent(struct inode *inode, -+ struct ext4_ext_path *path, -+ struct ext4_ext_cache *ec, -+ void *cbdata) -+{ -+ struct ext4_wb_control *wc = cbdata; -+ struct super_block *sb = inode->i_sb; -+ ext4_fsblk_t goal, pblock; -+ unsigned long tgen, count; -+ struct ext4_extent nex; -+ loff_t new_i_size; -+ handle_t *handle; -+ int i, err; -+ -+ if (ec->ec_type == EXT4_EXT_CACHE_EXTENT) { -+ /* -+ * The extent is already allocated. The only thing -+ * we have to do is to flush correspondend pages. -+ */ -+ wb_debug("extent %u/%u/%u exist\n", -+ (unsigned) ec->ec_block, -+ (unsigned) ec->ec_len, -+ (unsigned) ec->ec_start); -+ nex.ee_start = cpu_to_le32(ec->ec_start); -+ nex.ee_block = cpu_to_le32(ec->ec_block); -+ nex.ee_len = cpu_to_le16(ec->ec_len); -+ err = ext4_wb_submit_extent(wc, NULL, &nex, 0); -+ -+ /* correct on-disk size, if we grow within -+ * already allocated block */ -+ new_i_size = (loff_t) le32_to_cpu(nex.ee_block) + -+ le16_to_cpu(nex.ee_len); -+ new_i_size = new_i_size << inode->i_blkbits; -+ if (new_i_size > i_size_read(inode)) -+ new_i_size = i_size_read(inode); -+ if (new_i_size > EXT4_I(inode)->i_disksize) { -+ EXT4_I(inode)->i_disksize = new_i_size; -+ mutex_unlock(&EXT4_I(inode)->truncate_mutex); -+ ext4_dirty_inode(inode); -+ mutex_lock(&EXT4_I(inode)->truncate_mutex); -+ } -+ return err; -+ } -+ -+ wb_debug("extent %u/%u DOES NOT exist\n", ec->ec_block, ec->ec_len); -+ -+ /* space for some pages we want to flush hasn't allocated -+ * yet. so, it's time to allocate space */ -+ tgen = EXT4_I(inode)->i_ext_generation; -+ count = ext4_ext_calc_credits_for_insert(inode, path); -+ mutex_unlock(&EXT4_I(inode)->truncate_mutex); -+ -+ handle = ext4_journal_start(inode, -+ count + EXT4_DATA_TRANS_BLOCKS(sb) + 1); -+ if (IS_ERR(handle)) { -+ mutex_lock(&EXT4_I(inode)->truncate_mutex); -+ return PTR_ERR(handle); -+ } -+ -+ /* FIXME: we could analyze current path and advice allocator -+ * to find additional blocks if goal can't be allocated -+ * this is for better interaction between extents and mballoc -+ * plus this should improve overall performance */ -+ -+ mutex_lock(&EXT4_I(inode)->truncate_mutex); -+ if (tgen != EXT4_I(inode)->i_ext_generation) { -+ /* the tree has changed. so path can be invalid at moment */ -+ ext4_journal_stop(handle); -+ return EXT_REPEAT; -+ } -+ -+ goal = ext4_wb_find_goal(inode, path, ec->ec_block); -+ count = ec->ec_len; -+ -+ /* if this is a tail of closed file, ask allocator don't preallocate */ -+ new_i_size = i_size_read(inode) + sb->s_blocksize - 1; -+ new_i_size = new_i_size >> inode->i_blkbits; -+ if (ec->ec_block + count == new_i_size && -+ !atomic_read(&inode->i_writecount)) { -+ /* XXX: disable preallocation for tail */ -+ } -+ -+ /* this is a hack to tell the allocator that blocks -+ * we are going to allocated are already reserved */ -+ EXT4_I(inode)->i_state |= EXT4_STATE_BLOCKS_RESERVED; -+ pblock = ext4_new_blocks(handle, inode, goal, &count, &err); -+ EXT4_I(inode)->i_state &= ~EXT4_STATE_BLOCKS_RESERVED; -+ -+ if (!pblock) -+ goto out; -+ -+ BUG_ON(count > ec->ec_len); -+ BUG_ON(count == 0); -+ wb_debug("allocated %llu/%lu for %lu (asked %u)\n", -+ pblock, count, inode->i_ino, ec->ec_len); -+ -+ /* insert new extent */ -+ nex.ee_start = cpu_to_le32(pblock); -+ nex.ee_start_hi = 0; -+ nex.ee_len = cpu_to_le16(count); -+ nex.ee_block = cpu_to_le32(ec->ec_block); -+ err = ext4_ext_insert_extent(handle, inode, path, &nex); -+ if (err) -+ goto out; -+ -+ /* -+ * Putting len of the actual extent we just inserted, -+ * we are asking ext4_ext_walk_space() to continue -+ * scaning after that block -+ */ -+ ec->ec_len = le16_to_cpu(nex.ee_len); -+ BUG_ON(nex.ee_len == 0); -+ -+#ifdef EXT4_WB_STATS -+ atomic_add(le16_to_cpu(nex.ee_len), -+ &EXT4_SB(inode->i_sb)->s_wb_allocated); -+#endif -+ -+ wb_debug("inserted %lu/%lu/%lu for %lu (asked %u)\n", -+ (unsigned long) le32_to_cpu(nex.ee_block), -+ (unsigned long) le16_to_cpu(nex.ee_len), -+ (unsigned long) le32_to_cpu(nex.ee_start), -+ inode->i_ino, ec->ec_len); -+ -+ /* -+ * Important! The nex can change after insert. So do not -+ * use ec for following -+ */ -+ -+ /* block have been allocated for data, so time to drop dirty -+ * in correspondend buffer_heads to prevent corruptions */ -+ for (i = 0; i < le16_to_cpu(nex.ee_len); i++) -+ unmap_underlying_metadata(sb->s_bdev, -+ le32_to_cpu(nex.ee_start) + i); -+ -+ /* correct on-disk inode size */ -+ if (le16_to_cpu(nex.ee_len) > 0) { -+ new_i_size = (loff_t) le32_to_cpu(nex.ee_block) + -+ le16_to_cpu(nex.ee_len); -+ new_i_size = new_i_size << inode->i_blkbits; -+ if (new_i_size > i_size_read(inode)) -+ new_i_size = i_size_read(inode); -+ if (new_i_size > EXT4_I(inode)->i_disksize) { -+ EXT4_I(inode)->i_disksize = new_i_size; -+ err = ext4_mark_inode_dirty(handle, inode); -+ } -+ } -+ -+ if (ext4_should_order_data(inode)) -+ err = ext4_wb_submit_extent(wc, handle, &nex, 1); -+ else -+ err = ext4_wb_submit_extent(wc, NULL, &nex, 1); -+ -+ /* we don't want to recalculate needed reservation for -+ * each page. we may do this for each new extent */ -+ ext4_wb_release_space(inode, wc->blocks_to_release, 1); -+ wc->blocks_to_release = 0; -+ -+out: -+ ext4_journal_stop(handle); -+ if (err) -+ printk("EXT4-fs: writeback error = %d\n", err); -+ return err; -+} -+ -+static int ext4_wb_flush(struct ext4_wb_control *wc) -+{ -+ struct list_head *cur, *tmp; -+ struct inode *inode; -+ int err, num = 0; -+ -+ if (wc->len == 0) -+ return 0; -+ -+ inode = wc->mapping->host; -+ wb_debug("start flushing %lu/%u from inode %lu\n", -+ wc->start, wc->len, inode->i_ino); -+ -+ wc->pages = list_entry(wc->list.next, struct ext4_wb_pages, list); -+ wc->extents = 0; -+ -+ mutex_lock(&EXT4_I(inode)->truncate_mutex); -+ /* FIXME: last page may be partial */ -+ err = ext4_ext_walk_space(inode, wc->start, wc->len, -+ ext4_wb_handle_extent, wc); -+ mutex_unlock(&EXT4_I(inode)->truncate_mutex); -+ -+ list_for_each_safe(cur, tmp, &wc->list) { -+ struct ext4_wb_pages *wp; -+ wp = list_entry(cur, struct ext4_wb_pages, list); -+ if (err) { -+ while (wp->start < wp->num) { -+ struct page *page = wp->pages[wp->start]; -+ BUG_ON(!PageWriteback(page)); -+ end_page_writeback(page); -+ __set_page_dirty_nobuffers(page); -+ wp->start++; -+ } -+ } else { -+ BUG_ON(num != 0); -+ BUG_ON(wp->start != wp->num - 1 && -+ wp->start != wp->num); -+ } -+ list_del(&wp->list); -+ kfree(wp); -+ num++; -+ } -+ wc->pages = NULL; -+ wc->len = 0; -+ wc->extents = 0; -+ -+ return err; -+} -+ -+static int ext4_wb_add_page(struct ext4_wb_control *wc, struct page *page) -+{ -+ struct ext4_wb_pages *wp = wc->pages; -+ -+ if (wp == NULL || wp->num == WB_PAGES_PER_ARRAY) { -+ wp = kmalloc(sizeof(struct ext4_wb_pages), GFP_NOFS); -+ if (wp == NULL) { -+ printk("no mem for ext4_wb_pages!\n"); -+ return -ENOMEM; -+ } -+ wp->num = 0; -+ wp->start = 0; -+ list_add_tail(&wp->list, &wc->list); -+ wc->pages = wp; -+ } -+ -+ wp->pages[wp->num] = page; -+ wp->num++; -+ -+ return 0; -+} -+ -+static inline void -+ext4_wb_init_control(struct ext4_wb_control *wc, struct address_space *mapping) -+{ -+ wc->mapping = mapping; -+ wc->len = 0; -+ wc->blocks_to_release = 0; -+ INIT_LIST_HEAD(&wc->list); -+ wc->pages = NULL; -+} -+ -+static inline int -+ext4_wb_can_merge(struct ext4_wb_control *wc, unsigned long next) -+{ -+ if (wc->start + wc->len == next && -+ wc->len <= WB_MAX_PAGES_PER_EXTENT) -+ return 1; -+ return 0; -+} -+ -+int ext4_wb_writepages(struct address_space *mapping, -+ struct writeback_control *wbc) -+{ -+ struct backing_dev_info *bdi = mapping->backing_dev_info; -+ struct inode *inode = mapping->host; -+ int nr_pages, i, err = 0, done = 0; -+ struct ext4_wb_control wc; -+ struct pagevec pvec; -+ pgoff_t index = 0; -+ int written = 0; -+ int extents = 0; -+ pgoff_t pindex = 0; -+ -+ wb_debug("->writepages on inode %lu (%u reserved)\n", -+ inode->i_ino, EXT4_I(inode)->i_blocks_reserved); -+#ifdef EXT4_WB_SKIP_SMALL -+ if (wbc->nr_to_write <= 64 && wbc->sync_mode == WB_SYNC_NONE) -+ return 0; -+#endif -+ atomic_inc(&EXT4_I(inode)->i_wb_writers); -+#ifdef EXT4_WB_STATS -+ atomic_inc(&EXT4_SB(inode->i_sb)->s_wb_reqs); -+ atomic_add(wbc->nr_to_write, &EXT4_SB(inode->i_sb)->s_wb_nr_to_write); -+ if (atomic_read(&EXT4_I(inode)->i_wb_writers) != 1) -+ atomic_inc(&EXT4_SB(inode->i_sb)->s_wb_collisions); -+#endif -+ -+ /* skip opened-for-write small files -+ * XXX: what do we do if most of files hit the condition? */ -+ if (wbc->sync_mode == WB_SYNC_NONE && -+ atomic_read(&inode->i_writecount) && -+ i_size_read(inode) <= 64*1024) { -+ return 0; -+ } -+ -+ ext4_wb_init_control(&wc, mapping); -+ -+ pagevec_init(&pvec, 0); -+ while (!done && (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, -+ PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE))) { -+ for (i = 0; i < nr_pages; i++) { -+ struct page *page = pvec.pages[i]; -+ -+ lock_page(page); -+ -+ if (wbc->sync_mode != WB_SYNC_NONE) -+ wait_on_page_writeback(page); -+ -+ if (page->mapping != mapping) { -+ unlock_page(page); -+ continue; -+ } -+ if (PageWriteback(page)) { -+ unlock_page(page); -+ continue; -+ } -+ -+ if (wc.len && ext4_wb_can_merge(&wc, page->index) && -+ wbc->nr_to_write <= 0) { -+ /* -+ * If we already exhausted blocks we got -+ * to write and new extent starts, stop -+ * writeback -+ */ -+ unlock_page(page); -+ done = 1; -+ break; -+ -+ } -+ -+ if (!clear_page_dirty_for_io(page)) { -+ unlock_page(page); -+ continue; -+ } -+ -+ set_page_writeback(page); -+ unlock_page(page); -+ -+ if (wc.len == 0) { -+ wc.start = page->index; -+ wc.len = 1; -+ extents++; -+ } else if (ext4_wb_can_merge(&wc, page->index)) { -+ wc.len++; -+ } else { -+ /* end of current extent: flush it ... */ -+#if 0 -+ if (wc.len < 64 && wc.len > 0) { -+ printk("#%u: wow! short extent %d for flush on #%lu\n", -+ (unsigned) current->pid, wc.len, inode->i_ino); -+ printk("#%u: done = %d, nr_to_write %ld, sync = %d\n", -+ (unsigned) current->pid, done, wbc->nr_to_write, -+ wbc->sync_mode); -+ printk("#%u: written %d, extents %d\n", -+ (unsigned) current->pid, written, extents); -+ printk("#%u: cur %lu, prev %lu\n", -+ (unsigned) current->pid, -+ (unsigned long) page->index, -+ (unsigned long) pindex); -+ } -+#endif -+ err = ext4_wb_flush(&wc); -+ if (err) { -+ done = 1; -+ end_page_writeback(page); -+ break; -+ } -+ -+ /* ... and start new one */ -+ BUG_ON(!PageWriteback(page)); -+ wc.start = page->index; -+ wc.len = 1; -+ extents++; -+ } -+ -+ pindex = page->index; -+ err = ext4_wb_add_page(&wc, page); -+ if (err) { -+ done = 1; -+ end_page_writeback(page); -+ break; -+ } -+ written++; -+ -+ wbc->nr_to_write--; -+#if 0 -+ if ((--(wbc->nr_to_write) <= 0)) -+ done = 1; -+#endif -+ if (wbc->nonblocking && bdi_write_congested(bdi)) { -+#ifdef EXT4_WB_STATS -+ atomic_inc(&EXT4_SB(inode->i_sb)->s_wb_congested); -+#endif -+ wbc->encountered_congestion = 1; -+ done = 1; -+ } -+ } -+ pagevec_release(&pvec); -+ } -+ if (!err) { -+#ifdef EXT4_WB_SKIP_SMALL -+ if (wc.len > 0 && wc.len < 64 -+ && wbc->sync_mode == WB_SYNC_NONE) { -+ struct list_head *cur, *tmp; -+ list_for_each_safe(cur, tmp, &wc.list) { -+ struct ext4_wb_pages *wp; -+ wp = list_entry(cur, struct ext4_wb_pages, -+ list); -+ for (i = wp->start; i < wp->num; i++) { -+ struct page *page = wp->pages[i]; -+ BUG_ON(!PageWriteback(page)); -+ end_page_writeback(page); -+ __set_page_dirty_nobuffers(page); -+ } -+ wbc->nr_to_write += i; -+ list_del(&wp->list); -+ kfree(wp); -+ } -+ } else -+#endif -+ ext4_wb_flush(&wc); -+ } -+ -+ atomic_dec(&EXT4_I(inode)->i_wb_writers); -+ -+#ifdef EXT4_WB_STATS -+ atomic_add(written, &EXT4_SB(inode->i_sb)->s_wb_blocks); -+ atomic_add(extents, &EXT4_SB(inode->i_sb)->s_wb_extents); -+#endif -+ return 0; -+} -+ -+static void ext4_wb_clear_page(struct page *page, int from, int to) -+{ -+ void *kaddr; -+ -+ if (to < PAGE_CACHE_SIZE || from > 0) { -+ kaddr = kmap_atomic(page, KM_USER0); -+ if (PAGE_CACHE_SIZE > to) -+ memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); -+ if (0 < from) -+ memset(kaddr, 0, from); -+ flush_dcache_page(page); -+ kunmap_atomic(kaddr, KM_USER0); -+ } -+} -+ -+int ext4_wb_prepare_write(struct file *file, struct page *page, -+ unsigned from, unsigned to) -+{ -+ struct inode *inode = page->mapping->host; -+ struct buffer_head bh, *bhw = &bh; -+ int err = 0; -+ -+ wb_debug("prepare page %lu (%u-%u) for inode %lu\n", -+ page->index, from, to, page->mapping->host->i_ino); -+ -+ /* if page is uptodate this means that ->prepare_write() has -+ * been called on page before and page is mapped to disk or -+ * we did reservation. page is protected and nobody can -+ * access it. hence, it safe to use page->private to pass -+ * flag that ->commit_write() has to reserve blocks. because -+ * an error may occur after ->prepare_write() we should not -+ * reserve block here. it's better to do in ->commit_write() -+ * when we're sure page is to be written */ -+ page->private = 0; -+ if (!PageUptodate(page)) { -+ /* first write to this page */ -+ bh.b_state = 0; -+ err = ext4_get_block(inode, page->index, bhw, 0); -+ if (err) -+ return err; -+ if (!buffer_mapped(bhw)) { -+ /* this block isn't allocated yet, reserve space */ -+ wb_debug("reserve space for new block\n"); -+ page->private = 1; -+ ext4_wb_clear_page(page, from, to); -+ ClearPageMappedToDisk(page); -+ } else { -+ /* block is already mapped, so no need to reserve */ -+ BUG_ON(PagePrivate(page)); -+ if (to - from < PAGE_CACHE_SIZE) { -+ wb_debug("read block %u\n", -+ (unsigned) bhw->b_blocknr); -+ set_bh_page(bhw, page, 0); -+ bhw->b_this_page = NULL; -+ bhw->b_size = 1 << inode->i_blkbits; -+ atomic_set(&bhw->b_count, 1); -+ ll_rw_block(READ, 1, &bhw); -+ wait_on_buffer(bhw); -+ if (!buffer_uptodate(bhw)) -+ return -EIO; -+ } -+ SetPageMappedToDisk(page); -+ } -+ } else if (!PageMappedToDisk(page) && !PagePrivate(page)) { -+ /* this page was a hole at time of mmap() calling -+ * now someone wants to modify it by sys_write() */ -+ wb_debug("reserve block for hole\n"); -+ page->private = 1; -+ } -+ -+ return 0; -+} -+ -+int ext4_wb_commit_write(struct file *file, struct page *page, -+ unsigned from, unsigned to) -+{ -+ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; -+ struct inode *inode = page->mapping->host; -+ int err = 0; -+ -+ wb_debug("commit page %lu (%u-%u) for inode %lu\n", -+ page->index, from, to, inode->i_ino); -+ -+ /* mark page private so that we get -+ * called to invalidate/release page */ -+ SetPagePrivate(page); -+ -+ if (!PageBooked(page) && !PageMappedToDisk(page)) { -+ /* ->prepare_write() observed that block for this -+ * page hasn't been allocated yet. there fore it -+ * asked to reserve block for later allocation */ -+ BUG_ON(page->private == 0); -+ page->private = 0; -+ err = ext4_wb_reserve_space_page(page, 1); -+ if (err) -+ return err; -+ } -+ -+ /* ok. block for this page is allocated already or it has -+ * been reserved succesfully. so, user may use it */ -+ __set_page_dirty_nobuffers(page); -+ -+ SetPageUptodate(page); -+ -+ /* correct in-core size, on-disk size will -+ * be corrected upon allocation */ -+ if (pos > inode->i_size) { -+ i_size_write(inode, pos); -+ mark_inode_dirty(inode); -+ } -+ -+ return err; -+} -+ -+int ext4_wb_write_single_page(struct page *page, -+ struct writeback_control *wbc) -+{ -+ struct inode *inode = page->mapping->host; -+ struct ext4_wb_control wc; -+ int err; -+ -+ atomic_inc(&EXT4_I(inode)->i_wb_writers); -+ -+#ifdef EXT4_WB_STATS -+ atomic_inc(&EXT4_SB(inode->i_sb)->s_wb_single_pages); -+ if (atomic_read(&EXT4_I(inode)->i_wb_writers) != 1) -+ atomic_inc(&EXT4_SB(inode->i_sb)->s_wb_collisions_sp); -+#endif -+ -+ ext4_wb_init_control(&wc, page->mapping); -+ -+ BUG_ON(PageWriteback(page)); -+ set_page_writeback(page); -+ unlock_page(page); -+ -+ wc.start = page->index; -+ wc.len = 1; -+ -+ err = ext4_wb_add_page(&wc, page); -+ if (err) { -+ printk(KERN_ERR "EXT4-fs: cant add page at %s:%d - %d\n", -+ __FILE__, __LINE__, err); -+ end_page_writeback(page); -+ return err; -+ } -+ err = ext4_wb_flush(&wc); -+ atomic_dec(&EXT4_I(inode)->i_wb_writers); -+ -+ return err; -+} -+ -+int ext4_wb_writepage(struct page *page, struct writeback_control *wbc) -+{ -+ struct inode *inode = page->mapping->host; -+ loff_t i_size = i_size_read(inode); -+ pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; -+ unsigned offset; -+ void *kaddr; -+ -+ wb_debug("writepage %lu from inode %lu\n", page->index, inode->i_ino); -+ -+ /* -+ * FIXME: just to play ... -+ * If another thread is writing inode's data and the page -+ * hasn't space on a disk yet, leave it for that thread -+ */ -+#if 1 -+ if (atomic_read(&EXT4_I(page->mapping->host)->i_wb_writers) -+ && !PageMappedToDisk(page)) { -+ __set_page_dirty_nobuffers(page); -+ unlock_page(page); -+ return 0; -+ } -+#endif -+ -+ /* we give up here if we're reentered, because -+ * it might be for a different filesystem */ -+ if (ext4_journal_current_handle()) { -+ __set_page_dirty_nobuffers(page); -+ unlock_page(page); -+ return 0; -+ } -+ -+ /* Is the page fully inside i_size? */ -+ if (page->index < end_index) -+ return ext4_wb_write_single_page(page, wbc); -+ -+ /* Is the page fully outside i_size? (truncate in progress) */ -+ offset = i_size & (PAGE_CACHE_SIZE-1); -+ if (page->index >= end_index + 1 || !offset) { -+ /* -+ * The page may have dirty, unmapped buffers. For example, -+ * they may have been added in ext4_writepage(). Make them -+ * freeable here, so the page does not leak. -+ */ -+ ext4_wb_invalidatepage(page, 0); -+ unlock_page(page); -+ return 0; /* don't care */ -+ } -+ -+ /* -+ * The page straddles i_size. It must be zeroed out on each and every -+ * writepage invocation because it may be mmapped. "A file is mapped -+ * in multiples of the page size. For a file that is not a multiple of -+ * the page size, the remaining memory is zeroed when mapped, and -+ * writes to that region are not written out to the file." -+ */ -+ kaddr = kmap_atomic(page, KM_USER0); -+ memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); -+ flush_dcache_page(page); -+ kunmap_atomic(kaddr, KM_USER0); -+ return ext4_wb_write_single_page(page, wbc); -+} -+ -+int ext4_wb_releasepage(struct page *page, gfp_t wait) -+{ -+ wb_debug("release %sM%sR page %lu from inode %lu (wait %d)\n", -+ PageMappedToDisk(page) ? "" : "!", -+ PageBooked(page) ? "" : "!", -+ page->index, page->mapping->host->i_ino, wait); -+ -+ if (PageWriteback(page)) -+ return 0; -+ -+ if (PagePrivate(page)) -+ ClearPagePrivate(page); -+ return 0; -+} -+ -+void ext4_wb_invalidatepage(struct page *page, unsigned long offset) -+{ -+ struct inode *inode = page->mapping->host; -+ int ret = 0; -+ -+ /* ->invalidatepage() is called when page is marked Private. -+ * for our page being Private mean that space has been -+ * reserved for this page and it is being truncated. so, -+ * it's time to drop reservation */ -+ wb_debug("invalidate %sM%sR page %lu from inode %lu (offset %lu)\n", -+ PageMappedToDisk(page) ? "" : "!", -+ PageBooked(page) ? "" : "!", -+ page->index, inode->i_ino, offset); -+ -+ if (offset == 0) { -+ if (PageBooked(page)) { -+ atomic_inc(&EXT4_SB(inode->i_sb)->s_wb_dropped); -+ ext4_wb_release_space(inode, 1, 0); -+ ext4_wb_drop_page_reservation(page); -+ } -+ ret = try_to_release_page(page, 0); -+ } -+ return; -+} -+ -+int ext4_wb_block_truncate_page(handle_t *handle, struct page *page, -+ struct address_space *mapping, loff_t from) -+{ -+ unsigned offset = from & (PAGE_CACHE_SIZE-1); -+ struct inode *inode = mapping->host; -+ struct buffer_head bh, *bhw = &bh; -+ unsigned blocksize, length; -+ void *kaddr; -+ int err = 0; -+ -+ wb_debug("partial truncate from %lu on page %lu from inode %lu\n", -+ (unsigned long) from, page->index, inode->i_ino); -+ -+ blocksize = inode->i_sb->s_blocksize; -+ length = blocksize - (offset & (blocksize - 1)); -+ -+ /* if page isn't uptodate we have to check has it assigned block -+ * if it has then that block is to be read before memset() */ -+ if (!PageUptodate(page)) { -+ BUG_ON(PageMappedToDisk(page)); -+ bh.b_state = 0; -+ err = ext4_get_block(inode, page->index, bhw, 0); -+ if (err) -+ goto err_out; -+ BUG_ON(buffer_new(bhw)); -+ if (buffer_mapped(bhw)) { -+ /* time to retrieve data from a disk */ -+ wb_debug("read block %u for part.trunc on %lu\n", -+ (unsigned) bhw->b_blocknr, page->index); -+ set_bh_page(bhw, page, 0); -+ bhw->b_this_page = NULL; -+ bhw->b_size = 1 << inode->i_blkbits; -+ atomic_set(&bhw->b_count, 1); -+ ll_rw_block(READ, 1, &bhw); -+ wait_on_buffer(bhw); -+ err = -EIO; -+ if (!buffer_uptodate(bhw)) -+ goto err_out; -+ SetPageMappedToDisk(page); -+ } else { -+ wb_debug("zero page %lu (part.trunc)\n", page->index); -+ offset = 0; -+ length = blocksize; -+ } -+ } -+ -+ kaddr = kmap_atomic(page, KM_USER0); -+ memset(kaddr + offset, 0, length); -+ flush_dcache_page(page); -+ kunmap_atomic(kaddr, KM_USER0); -+ SetPageUptodate(page); -+ __set_page_dirty_nobuffers(page); -+ -+err_out: -+ unlock_page(page); -+ page_cache_release(page); -+ return err; -+} -+ -+void ext4_wb_init(struct super_block *sb) -+{ -+ if (!test_opt(sb, DELAYED_ALLOC)) -+ return; -+ -+ if (PAGE_CACHE_SHIFT != sb->s_blocksize_bits) { -+ printk(KERN_ERR "EXT4-fs: delayed allocation isn't" -+ "supported for PAGE_CACHE_SIZE != blocksize yet\n"); -+ clear_opt (EXT4_SB(sb)->s_mount_opt, DELAYED_ALLOC); -+ return; -+ } -+ printk("EXT4-fs: delayed allocation enabled\n"); -+} -+ -+void ext4_wb_release(struct super_block *sb) -+{ -+ struct ext4_sb_info *sbi = EXT4_SB(sb); -+ -+ if (!test_opt(sb, DELAYED_ALLOC)) -+ return; -+ -+#ifdef EXT4_WB_STATS -+ if (atomic_read(&sbi->s_wb_reqs) == 0) -+ return; -+ -+ printk("EXT4-fs: writeback: %d blocks %d extents in %d reqs (%d ave)\n", -+ atomic_read(&sbi->s_wb_blocks), -+ atomic_read(&sbi->s_wb_extents), -+ atomic_read(&sbi->s_wb_reqs), -+ atomic_read(&sbi->s_wb_blocks) / atomic_read(&sbi->s_wb_reqs)); -+ printk("EXT4-fs: writeback: %d nr_to_write, %d congestions, %d singles\n", -+ atomic_read(&sbi->s_wb_nr_to_write), -+ atomic_read(&sbi->s_wb_congested), -+ atomic_read(&sbi->s_wb_single_pages)); -+ printk("EXT4-fs: writeback: %d collisions, %d single-page collisions\n", -+ atomic_read(&sbi->s_wb_collisions), -+ atomic_read(&sbi->s_wb_collisions_sp)); -+ printk("EXT4-fs: writeback: %d allocated, %d dropped\n", -+ atomic_read(&sbi->s_wb_allocated), -+ atomic_read(&sbi->s_wb_dropped)); -+#endif -+} -+ -Index: linux-2.6.23-rc2/include/linux/ext4_fs.h -=================================================================== ---- linux-2.6.23-rc2.orig/include/linux/ext4_fs.h 2007-08-06 22:18:59.000000000 -0700 -+++ linux-2.6.23-rc2/include/linux/ext4_fs.h 2007-08-06 22:19:05.000000000 -0700 -@@ -488,6 +488,8 @@ do { \ - #define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */ - #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ - #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ -+#define EXT4_MOUNT_DELAYED_ALLOC 0x2000000/* Delayed allocation support*/ -+ - /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H - #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt -@@ -1101,6 +1103,21 @@ ext4_get_blocks_wrap(handle_t *handle, s - } - - -+/* writeback.c */ -+extern int ext4_wb_writepages(struct address_space *, -+ struct writeback_control *); -+extern int ext4_wb_prepare_write(struct file *file, struct page *page, -+ unsigned from, unsigned to); -+extern int ext4_wb_commit_write(struct file *, struct page *, unsigned, -+ unsigned); -+extern int ext4_wb_writepage(struct page *, struct writeback_control *); -+extern void ext4_wb_invalidatepage(struct page *, unsigned long); -+extern int ext4_wb_releasepage(struct page *, gfp_t); -+extern int ext4_wb_block_truncate_page(handle_t *, struct page *, -+ struct address_space *, loff_t); -+extern void ext4_wb_init(struct super_block *); -+extern void ext4_wb_release(struct super_block *); -+ - #endif /* __KERNEL__ */ - - #endif /* _LINUX_EXT4_FS_H */ -Index: linux-2.6.23-rc2/include/linux/ext4_fs_extents.h -=================================================================== ---- linux-2.6.23-rc2.orig/include/linux/ext4_fs_extents.h 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/include/linux/ext4_fs_extents.h 2007-08-06 22:19:05.000000000 -0700 -@@ -235,6 +235,7 @@ extern unsigned int ext4_ext_check_overl - extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *); - extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *); - extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *); -+int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks); - - #endif /* _LINUX_EXT4_EXTENTS */ - -Index: linux-2.6.23-rc2/include/linux/ext4_fs_i.h -=================================================================== ---- linux-2.6.23-rc2.orig/include/linux/ext4_fs_i.h 2007-08-06 22:18:09.000000000 -0700 -+++ linux-2.6.23-rc2/include/linux/ext4_fs_i.h 2007-08-06 22:19:05.000000000 -0700 -@@ -158,6 +158,10 @@ struct ext4_inode_info { - * struct timespec i_{a,c,m}time in the generic inode. - */ - struct timespec i_crtime; -+ __u32 i_blocks_reserved; -+ __u32 i_md_reserved; -+ spinlock_t i_wb_reserved_lock; /* to protect i_md_reserved */ -+ atomic_t i_wb_writers; - }; - - #endif /* _LINUX_EXT4_FS_I */ -Index: linux-2.6.23-rc2/include/linux/ext4_fs_sb.h -=================================================================== ---- linux-2.6.23-rc2.orig/include/linux/ext4_fs_sb.h 2007-08-06 22:18:59.000000000 -0700 -+++ linux-2.6.23-rc2/include/linux/ext4_fs_sb.h 2007-08-06 22:19:05.000000000 -0700 -@@ -97,6 +97,17 @@ struct ext4_sb_info { - unsigned long s_ext_blocks; - unsigned long s_ext_extents; - #endif -+ -+ atomic_t s_wb_congested; -+ atomic_t s_wb_single_pages; -+ atomic_t s_wb_collisions_sp; -+ atomic_t s_wb_allocated; -+ atomic_t s_wb_reqs; -+ atomic_t s_wb_nr_to_write; -+ atomic_t s_wb_collisions; -+ atomic_t s_wb_blocks; -+ atomic_t s_wb_extents; -+ atomic_t s_wb_dropped; - }; - - #endif /* _LINUX_EXT4_FS_SB */ diff --git a/ext4-unlocked-ioctl.patch b/ext4-unlocked-ioctl.patch deleted file mode 100644 index 0b92b74b..00000000 --- a/ext4-unlocked-ioctl.patch +++ /dev/null @@ -1,403 +0,0 @@ -Convert ext4_ioctl to an unlocked_ioctl - -From: Mathieu Segaud - -Change ext4_ioctl() to be an unlocked_ioctl(), explicitly -exposing BKL's uses. - -Signed-off-by: Mathieu Segaud -Signed-off-by: "Theodore Ts'o" - -diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c -index 33888bb..56e6608 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..c586a81 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 2ed7c37..7689d2e 100644 ---- a/fs/ext4/ioctl.c -+++ b/fs/ext4/ioctl.c -@@ -17,12 +17,18 @@ - #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 ext4_inode_info *ei = EXT4_I(inode); -+ struct ext4_inode_info *ei; -+ struct inode *inode; - unsigned int flags; - unsigned short rsv_window_size; -+ long retval = 0; -+ -+ lock_kernel(); -+ -+ inode = filp->f_path.dentry->d_inode; -+ ei = EXT4_I(inode); - - ext4_debug ("cmd = %u, arg = %lu\n", cmd, arg); - -@@ -30,22 +36,28 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - case EXT4_IOC_GETFLAGS: - ext4_get_inode_flags(ei); - flags = ei->i_flags & EXT4_FL_USER_VISIBLE; -- return put_user(flags, (int __user *) arg); -+ retval = put_user(flags, (int __user *) arg); -+ goto out; - case EXT4_IOC_SETFLAGS: { - handle_t *handle = NULL; -- int err; - struct ext4_iloc iloc; - unsigned int oldflags; - unsigned int jflag; - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if (!is_owner_or_cap(inode)) -- return -EACCES; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EACCES; -+ goto out; -+ } - -- if (get_user(flags, (int __user *) arg)) -- return -EFAULT; -+ if (get_user(flags, (int __user *) arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - if (!S_ISDIR(inode->i_mode)) - flags &= ~EXT4_DIRSYNC_FL; -@@ -54,7 +66,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - /* Is it quota file? Do not allow user to mess with it */ - if (IS_NOQUOTA(inode)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - oldflags = ei->i_flags; - -@@ -70,7 +83,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { - if (!capable(CAP_LINUX_IMMUTABLE)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - } - -@@ -81,7 +95,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { - if (!capable(CAP_SYS_RESOURCE)) { - mutex_unlock(&inode->i_mutex); -- return -EPERM; -+ retval = -EPERM; -+ goto out; - } - } - -@@ -89,12 +104,13 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - handle = ext4_journal_start(inode, 1); - if (IS_ERR(handle)) { - mutex_unlock(&inode->i_mutex); -- return PTR_ERR(handle); -+ retval = PTR_ERR(handle); -+ goto out; - } - if (IS_SYNC(inode)) - handle->h_sync = 1; -- err = ext4_reserve_inode_write(handle, inode, &iloc); -- if (err) -+ retval = ext4_reserve_inode_write(handle, inode, &iloc); -+ if (retval) - goto flags_err; - - flags = flags & EXT4_FL_USER_MODIFIABLE; -@@ -104,47 +120,55 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - ext4_set_inode_flags(inode); - inode->i_ctime = ext4_current_time(inode); - -- err = ext4_mark_iloc_dirty(handle, inode, &iloc); -+ retval = ext4_mark_iloc_dirty(handle, inode, &iloc); - flags_err: - ext4_journal_stop(handle); -- if (err) { -+ if (retval) { - mutex_unlock(&inode->i_mutex); -- return err; -+ goto out; - } - - if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) -- err = ext4_change_inode_journal_flag(inode, jflag); -+ retval = ext4_change_inode_journal_flag(inode, jflag); - mutex_unlock(&inode->i_mutex); -- return err; -+ goto out; - } - case EXT4_IOC_GETVERSION: - case EXT4_IOC_GETVERSION_OLD: -- return put_user(inode->i_generation, (int __user *) arg); -+ retval = put_user(inode->i_generation, (int __user *) arg); -+ goto out; - case EXT4_IOC_SETVERSION: - case EXT4_IOC_SETVERSION_OLD: { - handle_t *handle; - struct ext4_iloc iloc; - __u32 generation; -- int err; - -- if (!is_owner_or_cap(inode)) -- return -EPERM; -- if (IS_RDONLY(inode)) -- return -EROFS; -- if (get_user(generation, (int __user *) arg)) -- return -EFAULT; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EPERM; -+ goto out; -+ } -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } -+ if (get_user(generation, (int __user *) arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - handle = ext4_journal_start(inode, 1); -- if (IS_ERR(handle)) -- return PTR_ERR(handle); -- err = ext4_reserve_inode_write(handle, inode, &iloc); -- if (err == 0) { -+ if (IS_ERR(handle)) { -+ retval = PTR_ERR(handle); -+ goto out; -+ } -+ retval = ext4_reserve_inode_write(handle, inode, &iloc); -+ if (retval == 0) { - inode->i_ctime = ext4_current_time(inode); - inode->i_generation = generation; -- err = ext4_mark_iloc_dirty(handle, inode, &iloc); -+ retval = ext4_mark_iloc_dirty(handle, inode, &iloc); - } - ext4_journal_stop(handle); -- return err; -+ goto out; - } - #ifdef CONFIG_JBD2_DEBUG - case EXT4_IOC_WAIT_FOR_READONLY: -@@ -158,16 +182,15 @@ flags_err: - { - struct super_block *sb = inode->i_sb; - DECLARE_WAITQUEUE(wait, current); -- int ret = 0; - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait); - if (timer_pending(&EXT4_SB(sb)->turn_ro_timer)) { - schedule(); -- ret = 1; -+ retval = 1; - } - remove_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait); -- return ret; -+ goto out; - } - #endif - case EXT4_IOC_GETRSVSZ: -@@ -175,22 +198,33 @@ flags_err: - && S_ISREG(inode->i_mode) - && ei->i_block_alloc_info) { - rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size; -- return put_user(rsv_window_size, (int __user *)arg); -+ retval = put_user(rsv_window_size, (int __user *)arg); -+ goto out; - } -- return -ENOTTY; -+ retval = -ENOTTY; -+ goto out; - case EXT4_IOC_SETRSVSZ: { - -- if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) -- return -ENOTTY; -+ if (!test_opt(inode->i_sb, RESERVATION) || -+ !S_ISREG(inode->i_mode)) { -+ retval = -ENOTTY; -+ goto out; -+ } - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if (!is_owner_or_cap(inode)) -- return -EACCES; -+ if (!is_owner_or_cap(inode)) { -+ retval = -EACCES; -+ goto out; -+ } - -- if (get_user(rsv_window_size, (int __user *)arg)) -- return -EFAULT; -+ if (get_user(rsv_window_size, (int __user *)arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - - if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS) - rsv_window_size = EXT4_MAX_RESERVE_BLOCKS; -@@ -208,58 +242,75 @@ flags_err: - rsv->rsv_goal_size = rsv_window_size; - } - up_write(&ei->i_data_sem); -- return 0; -+ goto out; - } - case EXT4_IOC_GROUP_EXTEND: { - ext4_fsblk_t n_blocks_count; - struct super_block *sb = inode->i_sb; - int err; - -- if (!capable(CAP_SYS_RESOURCE)) -- return -EPERM; -+ if (!capable(CAP_SYS_RESOURCE)) { -+ retval = -EPERM; -+ goto out; -+ } - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - -- if (get_user(n_blocks_count, (__u32 __user *)arg)) -- return -EFAULT; -+ if (get_user(n_blocks_count, (__u32 __user *)arg)) { -+ retval = -EFAULT; -+ goto out; -+ } - -- err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); -+ retval = ext4_group_extend(sb, EXT4_SB(sb)->s_es, -+ n_blocks_count); - jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); - jbd2_journal_flush(EXT4_SB(sb)->s_journal); - jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); - -- return err; -+ goto out; - } - case EXT4_IOC_GROUP_ADD: { - struct ext4_new_group_data input; - struct super_block *sb = inode->i_sb; - int err; - -- if (!capable(CAP_SYS_RESOURCE)) -- return -EPERM; -+ if (!capable(CAP_SYS_RESOURCE)) { -+ retval = -EPERM; -+ goto out; -+ } - -- if (IS_RDONLY(inode)) -- return -EROFS; -+ if (IS_RDONLY(inode)) { -+ retval = -EROFS; -+ goto out; -+ } - - if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, -- sizeof(input))) -- return -EFAULT; -+ sizeof(input))) { -+ retval = -EFAULT; -+ goto out; -+ } - -- err = ext4_group_add(sb, &input); -+ retval = ext4_group_add(sb, &input); - jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); - jbd2_journal_flush(EXT4_SB(sb)->s_journal); - jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); - -- return err; -+ goto out; - } - - case EXT4_IOC_MIGRATE: -- return ext4_ext_migrate(inode, filp, cmd, arg); -+ retval = ext4_ext_migrate(inode, filp, cmd, arg); -+ goto out; - - default: -- return -ENOTTY; -+ retval = -ENOTTY; - } -+out: -+ unlock_kernel(); -+ return retval; - } - - #ifdef CONFIG_COMPAT -@@ -307,9 +358,7 @@ 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; - } - #endif -diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h -index 1852313..0eb31e3 100644 ---- a/include/linux/ext4_fs.h -+++ b/include/linux/ext4_fs.h -@@ -1042,8 +1042,7 @@ extern int ext4_block_truncate_page(handle_t *handle, struct page *page, - struct address_space *mapping, loff_t from); - - /* 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/ext4_block_reservation_fix3.patch b/ext4_block_reservation_fix3.patch deleted file mode 100644 index 50e29f97..00000000 --- a/ext4_block_reservation_fix3.patch +++ /dev/null @@ -1,24 +0,0 @@ -If ext4_reserve_block has failed we have to drop quota. - -From: Dmitry Monakhov - -Signed-off-by: Dmitry Monakhov -Acked-by: Alex Tomas -Signed-off-by: Dave Kleikamp ---- - fs/ext4/balloc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: linux-2.6.23-rc2/fs/ext4/balloc.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/balloc.c 2007-08-06 22:18:59.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/balloc.c 2007-08-06 22:19:02.000000000 -0700 -@@ -1467,7 +1467,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *h - if (!(EXT4_I(inode)->i_state & EXT4_STATE_BLOCKS_RESERVED)) { - *errp = ext4_reserve_blocks(sb, num); - if (*errp) -- return 0; -+ goto out; - reserved = num; - } - diff --git a/ext4_delalloc_setpageprivate_fix.patch b/ext4_delalloc_setpageprivate_fix.patch deleted file mode 100644 index 7274ebcc..00000000 --- a/ext4_delalloc_setpageprivate_fix.patch +++ /dev/null @@ -1,57 +0,0 @@ -ext4: delalloc setpageprivate fix (XXX fix comments, fold? in patch series?) - -From: Mingming Cao - -On 16:46 Срд 20 Июн , Mingming Cao wrote: -> On Wed, 2007-06-20 at 12:15 +0400, Alex Tomas wrote: -> > Mingming Cao wrote: -> > > Hmm, PageMappedToDisk is probably not sufficient enough for pagesize! -> > > =blocksize. Is that the reason we need page->private to pass the -> > > request? -> > -> > PageMappedToDisk isn't enough in that case, definitely. bh is the way -> > to track state of each block (this is what i'm implementing now), but -> > I think current nobh version (per-page flags are used) is valuable. -> > -> > > That's good to know, thanks for the update. So probably above error case -> > > handling will be addressed in the new version? -> > -> > well, you actually can move that SetPagePrivate() few lines above -> > (Dmitriy already tested this). -> -> Like this? -Of course not, we may set page private bit only if -space was successfully reserved by ext4_wb_reserve_space_page(). -So patch looks like this: - -Signed-off-by: Mingming Cao -Signed-off-by: Alex Tomas - ---- - fs/ext4/writeback.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -Index: linux-2.6.23-rc2/fs/ext4/writeback.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/writeback.c 2007-08-06 22:19:08.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/writeback.c 2007-08-06 22:19:19.000000000 -0700 -@@ -918,9 +918,6 @@ int ext4_wb_commit_write(struct file *fi - wb_debug("commit page %lu (%u-%u) for inode %lu\n", - page->index, from, to, inode->i_ino); - -- /* mark page private so that we get -- * called to invalidate/release page */ -- SetPagePrivate(page); - - if (!PageBooked(page) && !PageMappedToDisk(page)) { - /* ->prepare_write() observed that block for this -@@ -932,6 +929,9 @@ int ext4_wb_commit_write(struct file *fi - if (err) - return err; - } -+ /* mark page private so that we get -+ * called to invalidate/release page */ -+ SetPagePrivate(page); - - /* ok. block for this page is allocated already or it has - * been reserved succesfully. so, user may use it */ diff --git a/ext4_nodelalloc_mount_opt.patch b/ext4_nodelalloc_mount_opt.patch deleted file mode 100644 index bdafc88b..00000000 --- a/ext4_nodelalloc_mount_opt.patch +++ /dev/null @@ -1,41 +0,0 @@ -Add a mount option to turn off delayed allocation. - -From: Mingming Cao - -Signed-off-by: Mingming Cao ---- ---- - fs/ext4/super.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -Index: linux-2.6.23-rc2/fs/ext4/super.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/super.c 2007-08-06 22:19:05.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/super.c 2007-08-06 22:19:11.000000000 -0700 -@@ -746,7 +746,7 @@ enum { - Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, - Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, - Opt_grpquota, Opt_extents, Opt_noextents, -- Opt_delayed_alloc, -+ Opt_delayed_alloc, Opt_nodelayed_alloc, - }; - - static match_table_t tokens = { -@@ -801,6 +801,7 @@ static match_table_t tokens = { - {Opt_extents, "extents"}, - {Opt_noextents, "noextents"}, - {Opt_delayed_alloc, "delalloc"}, -+ {Opt_nodelayed_alloc, "nodelalloc"}, - {Opt_err, NULL}, - {Opt_resize, "resize"}, - }; -@@ -1125,6 +1126,9 @@ clear_qf_name: - case Opt_delayed_alloc: - set_opt(sbi->s_mount_opt, DELAYED_ALLOC); - break; -+ case Opt_nodelayed_alloc: -+ clear_opt(sbi->s_mount_opt, DELAYED_ALLOC); -+ break; - case Opt_ignore: - break; - case Opt_resize: diff --git a/ext4_rebalance_reservation_invariant_checking_fix.patch b/ext4_rebalance_reservation_invariant_checking_fix.patch deleted file mode 100644 index 1661ea81..00000000 --- a/ext4_rebalance_reservation_invariant_checking_fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -ext4: Rebalance reservation invariant checking fix - -From: Dmitry Monakhov - -Variable "free" was declarated as __u64 so conidition (free < 0) always -false, even if free was overflowed during substraction. - -Singed-off-by: Mingming Cao -Signed-off-by: Dmitry Monakhov ---- - fs/ext4/balloc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: linux-2.6.23-rc2/fs/ext4/balloc.c -=================================================================== ---- linux-2.6.23-rc2.orig/fs/ext4/balloc.c 2007-08-06 22:19:13.000000000 -0700 -+++ linux-2.6.23-rc2/fs/ext4/balloc.c 2007-08-06 22:19:16.000000000 -0700 -@@ -1909,8 +1909,8 @@ void ext4_rebalance_reservation(struct e - chunk = free; - if (rs[i].rs_reserved || i == smp_processor_id()) { - rs[i].rs_reserved = chunk; -+ BUG_ON(free < chunk); - free -= chunk; -- BUG_ON(free < 0); - } - } - BUG_ON(free); diff --git a/ext4_reserve_global_return_error_fix.patch b/ext4_reserve_global_return_error_fix.patch deleted file mode 100644 index 443f1d0c..00000000 --- a/ext4_reserve_global_return_error_fix.patch +++ /dev/null @@ -1,39 +0,0 @@ -ext4: Reserve global return error fix - -From: Dmitriy Monakhov - -simple test: strace dd if=/dev/zero of=/mnt/file - -open("/dev/zero", O_RDONLY) = 0 -close(1) = 0 -open("/mnt/test/file", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 1 -read(0, "\0\0\0\0\0\0\0\0\0"..., 512) = 512 -write(1, "\0\0\0\0\0\0\0\0"..., 512) = 512 -read(0, "\0\0\0\0\0\0\0\0\0"..., 512) = 512 -write(1, "\0\0\0\0\0\0\0\0"..., 512) = -1 ENOENT (No such fil -e or directory) - -This strange error returned from ext4_reserve_global(). -It's just typo because: -a) In fact this is 100% ENOSPC situation -b) simular function ext4_reserve_local() returns -ENOSPC - -Signed-off-by: Mingming Cao -Signed-off-by: Dmitriy Monakhov ---- - fs/ext4/balloc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: linux-2.6.23-rc3/fs/ext4/balloc.c -=================================================================== ---- linux-2.6.23-rc3.orig/fs/ext4/balloc.c 2007-08-14 16:37:58.000000000 -0700 -+++ linux-2.6.23-rc3/fs/ext4/balloc.c 2007-08-14 17:11:34.000000000 -0700 -@@ -1920,7 +1920,7 @@ int ext4_reserve_global(struct super_blo - { - struct ext4_sb_info *sbi = EXT4_SB(sb); - struct ext4_reservation_slot *rs; -- int i, rc = -ENOENT; -+ int i, rc = -ENOSPC; - __u64 free = 0; - - rs = sbi->s_reservation_slots; -- 2.11.4.GIT