]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Jan 2015 00:23:45 +0000 (16:23 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Jan 2015 00:23:45 +0000 (16:23 -0800)
added patches:
ext4-fix-warning-in-ext4_da_update_reserve_space.patch
quota-provide-interface-for-readding-allocated-space-into-reserved-space.patch

queue-3.10/ext4-fix-warning-in-ext4_da_update_reserve_space.patch [new file with mode: 0644]
queue-3.10/quota-provide-interface-for-readding-allocated-space-into-reserved-space.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/ext4-fix-warning-in-ext4_da_update_reserve_space.patch b/queue-3.10/ext4-fix-warning-in-ext4_da_update_reserve_space.patch
new file mode 100644 (file)
index 0000000..f170d0c
--- /dev/null
@@ -0,0 +1,106 @@
+From 7d7345322d60edb0fa49a64a89b31360f01d09cb Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Sat, 17 Aug 2013 09:36:54 -0400
+Subject: ext4: fix warning in ext4_da_update_reserve_space()
+
+From: Jan Kara <jack@suse.cz>
+
+commit 7d7345322d60edb0fa49a64a89b31360f01d09cb upstream.
+
+reaim workfile.dbase test easily triggers warning in
+ext4_da_update_reserve_space():
+
+EXT4-fs warning (device ram0): ext4_da_update_reserve_space:365:
+ino 12, allocated 1 with only 0 reserved metadata blocks (releasing 1
+blocks with reserved 9 data blocks)
+
+The problem is that (one of) tests creates file and then randomly writes
+to it with O_SYNC. That results in writing back pages of the file in
+random order so we create extents for written blocks say 0, 2, 4, 6, 8
+- this last allocation also allocates new block for extents. Then we
+writeout block 1 so we have extents 0-2, 4, 6, 8 and we release
+indirect extent block because extents fit in the inode again. Then we
+writeout block 10 and we need to allocate indirect extent block again
+which triggers the warning because we don't have the reservation
+anymore.
+
+Fix the problem by giving back freed metadata blocks resulting from
+extent merging into inode's reservation pool.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Cc: Josh Hunt <johunt@akamai.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h    |    1 +
+ fs/ext4/extents.c |    3 ++-
+ fs/ext4/mballoc.c |   21 +++++++++++++++++----
+ 3 files changed, 20 insertions(+), 5 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -589,6 +589,7 @@ enum {
+ #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE       0x0008
+ #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010
+ #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER  0x0020
++#define EXT4_FREE_BLOCKS_RESERVE              0x0040
+ /*
+  * Flags used by ext4_discard_partial_page_buffers
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1722,7 +1722,8 @@ static void ext4_ext_try_to_merge_up(han
+       brelse(path[1].p_bh);
+       ext4_free_blocks(handle, inode, NULL, blk, 1,
+-                       EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
++                       EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET |
++                       EXT4_FREE_BLOCKS_RESERVE);
+ }
+ /*
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4610,6 +4610,7 @@ void ext4_free_blocks(handle_t *handle,
+       struct buffer_head *gd_bh;
+       ext4_group_t block_group;
+       struct ext4_sb_info *sbi;
++      struct ext4_inode_info *ei = EXT4_I(inode);
+       struct ext4_buddy e4b;
+       unsigned int count_clusters;
+       int err = 0;
+@@ -4808,7 +4809,6 @@ do_more:
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh);
+       ext4_group_desc_csum_set(sb, block_group, gdp);
+       ext4_unlock_group(sb, block_group);
+-      percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
+       if (sbi->s_log_groups_per_flex) {
+               ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+@@ -4816,10 +4816,23 @@ do_more:
+                            &sbi->s_flex_groups[flex_group].free_clusters);
+       }
+-      ext4_mb_unload_buddy(&e4b);
+-
+-      if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
++      if (flags & EXT4_FREE_BLOCKS_RESERVE && ei->i_reserved_data_blocks) {
++              percpu_counter_add(&sbi->s_dirtyclusters_counter,
++                                 count_clusters);
++              spin_lock(&ei->i_block_reservation_lock);
++              if (flags & EXT4_FREE_BLOCKS_METADATA)
++                      ei->i_reserved_meta_blocks += count_clusters;
++              else
++                      ei->i_reserved_data_blocks += count_clusters;
++              spin_unlock(&ei->i_block_reservation_lock);
++              if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
++                      dquot_reclaim_block(inode,
++                                      EXT4_C2B(sbi, count_clusters));
++      } else if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
+               dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
++      percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
++
++      ext4_mb_unload_buddy(&e4b);
+       /* We dirtied the bitmap block */
+       BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
diff --git a/queue-3.10/quota-provide-interface-for-readding-allocated-space-into-reserved-space.patch b/queue-3.10/quota-provide-interface-for-readding-allocated-space-into-reserved-space.patch
new file mode 100644 (file)
index 0000000..039aa10
--- /dev/null
@@ -0,0 +1,177 @@
+From 1c8924eb106c1ac755d5d35ce9b3ff42e89e2511 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Sat, 17 Aug 2013 09:32:32 -0400
+Subject: quota: provide interface for readding allocated space into reserved space
+
+From: Jan Kara <jack@suse.cz>
+
+commit 1c8924eb106c1ac755d5d35ce9b3ff42e89e2511 upstream.
+
+ext4 needs to convert allocated (metadata) blocks back into blocks
+reserved for delayed allocation. Add functions into quota code for
+supporting such operation.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Cc: Josh Hunt <johunt@akamai.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/quota/dquot.c         |   46 ++++++++++++++++++++++++++++++++++++++++++++++
+ fs/stat.c                |   11 +++++++++--
+ include/linux/fs.h       |    1 +
+ include/linux/quotaops.h |   15 +++++++++++++++
+ 4 files changed, 71 insertions(+), 2 deletions(-)
+
+--- a/fs/quota/dquot.c
++++ b/fs/quota/dquot.c
+@@ -1102,6 +1102,14 @@ static void dquot_claim_reserved_space(s
+       dquot->dq_dqb.dqb_rsvspace -= number;
+ }
++static void dquot_reclaim_reserved_space(struct dquot *dquot, qsize_t number)
++{
++      if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number))
++              number = dquot->dq_dqb.dqb_curspace;
++      dquot->dq_dqb.dqb_rsvspace += number;
++      dquot->dq_dqb.dqb_curspace -= number;
++}
++
+ static inline
+ void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
+ {
+@@ -1536,6 +1544,15 @@ void inode_claim_rsv_space(struct inode
+ }
+ EXPORT_SYMBOL(inode_claim_rsv_space);
++void inode_reclaim_rsv_space(struct inode *inode, qsize_t number)
++{
++      spin_lock(&inode->i_lock);
++      *inode_reserved_space(inode) += number;
++      __inode_sub_bytes(inode, number);
++      spin_unlock(&inode->i_lock);
++}
++EXPORT_SYMBOL(inode_reclaim_rsv_space);
++
+ void inode_sub_rsv_space(struct inode *inode, qsize_t number)
+ {
+       spin_lock(&inode->i_lock);
+@@ -1710,6 +1727,35 @@ int dquot_claim_space_nodirty(struct ino
+ EXPORT_SYMBOL(dquot_claim_space_nodirty);
+ /*
++ * Convert allocated space back to in-memory reserved quotas
++ */
++void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
++{
++      int cnt;
++
++      if (!dquot_active(inode)) {
++              inode_reclaim_rsv_space(inode, number);
++              return;
++      }
++
++      down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
++      spin_lock(&dq_data_lock);
++      /* Claim reserved quotas to allocated quotas */
++      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
++              if (inode->i_dquot[cnt])
++                      dquot_reclaim_reserved_space(inode->i_dquot[cnt],
++                                                   number);
++      }
++      /* Update inode bytes */
++      inode_reclaim_rsv_space(inode, number);
++      spin_unlock(&dq_data_lock);
++      mark_all_dquot_dirty(inode->i_dquot);
++      up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
++      return;
++}
++EXPORT_SYMBOL(dquot_reclaim_space_nodirty);
++
++/*
+  * This operation can block, but only after everything is updated
+  */
+ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -447,9 +447,8 @@ void inode_add_bytes(struct inode *inode
+ EXPORT_SYMBOL(inode_add_bytes);
+-void inode_sub_bytes(struct inode *inode, loff_t bytes)
++void __inode_sub_bytes(struct inode *inode, loff_t bytes)
+ {
+-      spin_lock(&inode->i_lock);
+       inode->i_blocks -= bytes >> 9;
+       bytes &= 511;
+       if (inode->i_bytes < bytes) {
+@@ -457,6 +456,14 @@ void inode_sub_bytes(struct inode *inode
+               inode->i_bytes += 512;
+       }
+       inode->i_bytes -= bytes;
++}
++
++EXPORT_SYMBOL(__inode_sub_bytes);
++
++void inode_sub_bytes(struct inode *inode, loff_t bytes)
++{
++      spin_lock(&inode->i_lock);
++      __inode_sub_bytes(inode, bytes);
+       spin_unlock(&inode->i_lock);
+ }
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2489,6 +2489,7 @@ extern void generic_fillattr(struct inod
+ extern int vfs_getattr(struct path *, struct kstat *);
+ void __inode_add_bytes(struct inode *inode, loff_t bytes);
+ void inode_add_bytes(struct inode *inode, loff_t bytes);
++void __inode_sub_bytes(struct inode *inode, loff_t bytes);
+ void inode_sub_bytes(struct inode *inode, loff_t bytes);
+ loff_t inode_get_bytes(struct inode *inode);
+ void inode_set_bytes(struct inode *inode, loff_t bytes);
+--- a/include/linux/quotaops.h
++++ b/include/linux/quotaops.h
+@@ -41,6 +41,7 @@ void __quota_error(struct super_block *s
+ void inode_add_rsv_space(struct inode *inode, qsize_t number);
+ void inode_claim_rsv_space(struct inode *inode, qsize_t number);
+ void inode_sub_rsv_space(struct inode *inode, qsize_t number);
++void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
+ void dquot_initialize(struct inode *inode);
+ void dquot_drop(struct inode *inode);
+@@ -59,6 +60,7 @@ int dquot_alloc_inode(const struct inode
+ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number);
+ void dquot_free_inode(const struct inode *inode);
++void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number);
+ int dquot_disable(struct super_block *sb, int type, unsigned int flags);
+ /* Suspend quotas on remount RO */
+@@ -238,6 +240,13 @@ static inline int dquot_claim_space_nodi
+       return 0;
+ }
++static inline int dquot_reclaim_space_nodirty(struct inode *inode,
++                                            qsize_t number)
++{
++      inode_sub_bytes(inode, number);
++      return 0;
++}
++
+ static inline int dquot_disable(struct super_block *sb, int type,
+               unsigned int flags)
+ {
+@@ -336,6 +345,12 @@ static inline int dquot_claim_block(stru
+       return ret;
+ }
++static inline void dquot_reclaim_block(struct inode *inode, qsize_t nr)
++{
++      dquot_reclaim_space_nodirty(inode, nr << inode->i_blkbits);
++      mark_inode_dirty_sync(inode);
++}
++
+ static inline void dquot_free_space_nodirty(struct inode *inode, qsize_t nr)
+ {
+       __dquot_free_space(inode, nr, 0);
index a91149a6266a3d227f3b3ff552dad95553b6dd7e..f93d92e0dd031c07edf95417696974270d4021e6 100644 (file)
@@ -27,3 +27,5 @@ drbd-merge_bvec_fn-properly-remap-bvm-bi_bdev.patch
 crypto-prefix-module-autoloading-with-crypto.patch
 crypto-include-crypto-module-prefix-in-template.patch
 crypto-add-missing-crypto-module-aliases.patch
+quota-provide-interface-for-readding-allocated-space-into-reserved-space.patch
+ext4-fix-warning-in-ext4_da_update_reserve_space.patch