From e065d04c3cdcf40ae4d4fd4aee0b2548aca4d045 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Fri, 26 Jun 2015 05:46:59 +0800 Subject: [PATCH 1/1] LU-6722 ldiskfs: declare credits for quota when destroy inode When destroy the inode, if it has large EA that occupies another separated block, then it calls ldiskfs_xattr_delete_inode(). But such function does not consider the quota modification as to that before making the group descriptor dirty, the persevered credits becomes zero, so jbd2_journal_dirty_metadata() failed as "-ENOSPC", then the subsequent journal abort makes the system as RDONLY. Signed-off-by: Fan Yong Change-Id: I0567d6b6d54cd57b25524c3d58190926e3505867 Reviewed-on: http://review.whamcloud.com/15334 Tested-by: Jenkins Reviewed-by: Bobi Jam Tested-by: Maloo Reviewed-by: Yang Sheng Reviewed-by: Niu Yawei Reviewed-by: Oleg Drokin --- .../patches/rhel6.3/ext4-back-dquot-to.patch | 38 ------------------ .../patches/rhel6.3/ext4-large-eas.patch | 45 +++++++++++++++------- .../patches/rhel6.4/ext4-back-dquot-to.patch | 43 --------------------- .../patches/rhel7/ext4-large-eas.patch | 31 +++++++++++---- .../patches/sles11sp2/ext4-large-eas.patch | 45 +++++++++++++--------- 5 files changed, 81 insertions(+), 121 deletions(-) diff --git a/ldiskfs/kernel_patches/patches/rhel6.3/ext4-back-dquot-to.patch b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-back-dquot-to.patch index e0bf364..f69a7c8 100644 --- a/ldiskfs/kernel_patches/patches/rhel6.3/ext4-back-dquot-to.patch +++ b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-back-dquot-to.patch @@ -58,41 +58,3 @@ Index: linux-stage/fs/ext4/super.c .alloc_space = dquot_alloc_space, .reserve_space = dquot_reserve_space, .claim_space = dquot_claim_space, -Index: linux-stage/fs/ext4/inode.c -=================================================================== ---- linux-stage.orig/fs/ext4/inode.c -+++ linux-stage/fs/ext4/inode.c -@@ -222,6 +222,7 @@ void ext4_delete_inode(struct inode *ino - { - handle_t *handle; - int err; -+ int extra_credits = 3; - - if (ext4_should_order_data(inode)) - ext4_begin_ordered_truncate(inode, 0); -@@ -230,7 +231,10 @@ void ext4_delete_inode(struct inode *ino - if (is_bad_inode(inode)) - goto no_delete; - -- handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3); -+ if (!IS_NOQUOTA(inode)) -+ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); -+ handle = ext4_journal_start(inode, -+ blocks_for_truncate(inode) + extra_credits); - if (IS_ERR(handle)) { - ext4_std_error(inode->i_sb, PTR_ERR(handle)); - /* -@@ -266,10 +270,10 @@ void ext4_delete_inode(struct inode *ino - * enough credits left in the handle to remove the inode from - * the orphan list and set the dtime field. - */ -- if (!ext4_handle_has_enough_credits(handle, 3)) { -- err = ext4_journal_extend(handle, 3); -+ if (!ext4_handle_has_enough_credits(handle, extra_credits)) { -+ err = ext4_journal_extend(handle, extra_credits); - if (err > 0) -- err = ext4_journal_restart(handle, 3); -+ err = ext4_journal_restart(handle, extra_credits); - if (err != 0) { - ext4_warning(inode->i_sb, - "couldn't extend journal (err %d)", err); diff --git a/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch index 53e0e03..9f41d82 100644 --- a/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch @@ -705,7 +705,7 @@ Index: linux-stage/fs/ext4/xattr.c + struct ext4_inode *raw_inode; + struct ext4_iloc iloc; + struct ext4_xattr_entry *entry; -+ int error = 0; ++ int credits = 3, error = 0; + + if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) + goto delete_external_ea; @@ -732,7 +732,7 @@ Index: linux-stage/fs/ext4/xattr.c if (!EXT4_I(inode)->i_file_acl) goto cleanup; bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); -@@ -1384,11 +1764,74 @@ ext4_xattr_delete_inode(handle_t *handle +@@ -1384,11 +1764,88 @@ ext4_xattr_delete_inode(handle_t *handle inode->i_ino, EXT4_I(inode)->i_file_acl); goto cleanup; } @@ -753,10 +753,10 @@ Index: linux-stage/fs/ext4/xattr.c + int idx = 0; + + for (; idx < (*lea_ino_array)->xia_count; ++idx) { -+ if (!ext4_handle_has_enough_credits(handle, 3)) { -+ error = ext4_journal_extend(handle, 3); ++ if (!ext4_handle_has_enough_credits(handle, credits)) { ++ error = ext4_journal_extend(handle, credits); + if (error > 0) -+ error = ext4_journal_restart(handle, 3); ++ error = ext4_journal_restart(handle, credits); + if (error != 0) { + ext4_warning(inode->i_sb, + "couldn't extend journal " @@ -773,6 +773,20 @@ Index: linux-stage/fs/ext4/xattr.c + } + } + ++ if (!IS_NOQUOTA(inode)) ++ credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ ++ if (!ext4_handle_has_enough_credits(handle, credits)) { ++ error = ext4_journal_extend(handle, credits); ++ if (error > 0) ++ error = ext4_journal_restart(handle, credits); ++ if (error != 0) { ++ ext4_warning(inode->i_sb, ++ "couldn't extend journal (err %d)", error); ++ goto cleanup; ++ } ++ } ++ ext4_xattr_release_block(handle, inode, bh); EXT4_I(inode)->i_file_acl = 0; @@ -807,7 +821,7 @@ Index: linux-stage/fs/ext4/xattr.c } /* -@@ -1458,10 +1901,9 @@ ext4_xattr_cmp(struct ext4_xattr_header +@@ -1458,10 +1915,9 @@ ext4_xattr_cmp(struct ext4_xattr_header entry1->e_name_index != entry2->e_name_index || entry1->e_name_len != entry2->e_name_len || entry1->e_value_size != entry2->e_value_size || @@ -819,7 +833,7 @@ Index: linux-stage/fs/ext4/xattr.c if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), (char *)header2 + le16_to_cpu(entry2->e_value_offs), le32_to_cpu(entry1->e_value_size))) -@@ -1546,7 +1988,7 @@ static inline void ext4_xattr_hash_entry +@@ -1546,7 +2002,7 @@ static inline void ext4_xattr_hash_entry *name++; } @@ -890,26 +904,26 @@ Index: linux-stage/fs/ext4/inode.c =================================================================== --- linux-stage.orig/fs/ext4/inode.c +++ linux-stage/fs/ext4/inode.c -@@ -223,6 +223,7 @@ void ext4_delete_inode(struct inode *ino +@@ -222,6 +222,8 @@ void ext4_delete_inode(struct inode *ino + { handle_t *handle; int err; - int extra_credits = 3; ++ int extra_credits = 3; + struct ext4_xattr_ino_array *lea_ino_array = NULL; if (ext4_should_order_data(inode)) ext4_begin_ordered_truncate(inode, 0); -@@ -238,8 +239,8 @@ void ext4_delete_inode(struct inode *ino +@@ -238,7 +239,8 @@ void ext4_delete_inode(struct inode *ino * protection against it */ sb_start_intwrite(inode->i_sb); -- handle = ext4_journal_start(inode, -- blocks_for_truncate(inode) + extra_credits); +- handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3); + + handle = ext4_journal_start(inode, extra_credits); if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); /* -@@ -251,9 +252,33 @@ void ext4_delete_inode(struct inode *ino +@@ -251,9 +252,36 @@ void ext4_delete_inode(struct inode *ino sb_end_intwrite(inode->i_sb); goto no_delete; } @@ -927,6 +941,9 @@ Index: linux-stage/fs/ext4/inode.c + goto stop_handle; + } + ++ if (!IS_NOQUOTA(inode)) ++ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ + if (!ext4_handle_has_enough_credits(handle, + blocks_for_truncate(inode) + extra_credits)) { + err = ext4_journal_extend(handle, @@ -944,7 +961,7 @@ Index: linux-stage/fs/ext4/inode.c inode->i_size = 0; err = ext4_mark_inode_dirty(handle, inode); if (err) { -@@ -307,8 +332,12 @@ void ext4_delete_inode(struct inode *ino +@@ -307,8 +335,12 @@ void ext4_delete_inode(struct inode *ino clear_inode(inode); else ext4_free_inode(handle, inode); diff --git a/ldiskfs/kernel_patches/patches/rhel6.4/ext4-back-dquot-to.patch b/ldiskfs/kernel_patches/patches/rhel6.4/ext4-back-dquot-to.patch index d95021e..f69a7c8 100644 --- a/ldiskfs/kernel_patches/patches/rhel6.4/ext4-back-dquot-to.patch +++ b/ldiskfs/kernel_patches/patches/rhel6.4/ext4-back-dquot-to.patch @@ -58,46 +58,3 @@ Index: linux-stage/fs/ext4/super.c .alloc_space = dquot_alloc_space, .reserve_space = dquot_reserve_space, .claim_space = dquot_claim_space, -Index: linux-stage/fs/ext4/inode.c -=================================================================== ---- linux-stage.orig/fs/ext4/inode.c -+++ linux-stage/fs/ext4/inode.c -@@ -222,6 +222,7 @@ void ext4_delete_inode(struct inode *ino - { - handle_t *handle; - int err; -+ int extra_credits = 3; - - if (ext4_should_order_data(inode)) - ext4_begin_ordered_truncate(inode, 0); -@@ -230,12 +231,15 @@ void ext4_delete_inode(struct inode *ino - if (is_bad_inode(inode)) - goto no_delete; - -+ if (!IS_NOQUOTA(inode)) -+ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); - /* - * Protect us against freezing - iput() caller didn't have to have any - * protection against it - */ - sb_start_intwrite(inode->i_sb); -- handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3); -+ handle = ext4_journal_start(inode, -+ blocks_for_truncate(inode) + extra_credits); - if (IS_ERR(handle)) { - ext4_std_error(inode->i_sb, PTR_ERR(handle)); - /* -@@ -266,10 +270,10 @@ void ext4_delete_inode(struct inode *ino - * enough credits left in the handle to remove the inode from - * the orphan list and set the dtime field. - */ -- if (!ext4_handle_has_enough_credits(handle, 3)) { -- err = ext4_journal_extend(handle, 3); -+ if (!ext4_handle_has_enough_credits(handle, extra_credits)) { -+ err = ext4_journal_extend(handle, extra_credits); - if (err > 0) -- err = ext4_journal_restart(handle, 3); -+ err = ext4_journal_restart(handle, extra_credits); - if (err != 0) { - ext4_warning(inode->i_sb, - "couldn't extend journal (err %d)", err); diff --git a/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch index f5e02d5..0a18c55 100644 --- a/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch @@ -81,7 +81,7 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/inode.c if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); /* -@@ -248,9 +250,33 @@ void ext4_evict_inode(struct inode *inod +@@ -248,9 +250,36 @@ void ext4_evict_inode(struct inode *inod sb_end_intwrite(inode->i_sb); goto no_delete; } @@ -99,6 +99,9 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/inode.c + goto stop_handle; + } + ++ if (!IS_NOQUOTA(inode)) ++ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ + if (!ext4_handle_has_enough_credits(handle, + ext4_blocks_for_truncate(inode) + extra_credits)) { + err = ext4_journal_extend(handle, @@ -116,7 +119,7 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/inode.c inode->i_size = 0; err = ext4_mark_inode_dirty(handle, inode); if (err) { -@@ -305,8 +331,12 @@ void ext4_evict_inode(struct inode *inod +@@ -305,8 +334,12 @@ void ext4_evict_inode(struct inode *inod ext4_clear_inode(inode); else ext4_free_inode(handle, inode); @@ -129,7 +132,7 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/inode.c return; no_delete: ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ -@@ -4841,7 +4871,7 @@ static int ext4_index_trans_blocks(struc +@@ -4841,7 +4874,7 @@ static int ext4_index_trans_blocks(struc * * Also account for superblock, inode, quota and xattr blocks */ @@ -803,7 +806,7 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/xattr.c + struct ext4_inode *raw_inode; + struct ext4_iloc iloc; + struct ext4_xattr_entry *entry; -+ int error = 0; ++ int credits = 3, error = 0; + + if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) + goto delete_external_ea; @@ -830,7 +833,7 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/xattr.c if (!EXT4_I(inode)->i_file_acl) goto cleanup; bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); -@@ -1468,11 +1848,74 @@ ext4_xattr_delete_inode(handle_t *handle +@@ -1468,11 +1848,88 @@ ext4_xattr_delete_inode(handle_t *handle EXT4_I(inode)->i_file_acl); goto cleanup; } @@ -871,6 +874,20 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/xattr.c + } + } + ++ if (!IS_NOQUOTA(inode)) ++ credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ ++ if (!ext4_handle_has_enough_credits(handle, credits)) { ++ error = ext4_journal_extend(handle, credits); ++ if (error > 0) ++ error = ext4_journal_restart(handle, credits); ++ if (error != 0) { ++ ext4_warning(inode->i_sb, ++ "couldn't extend journal (err %d)", error); ++ goto cleanup; ++ } ++ } ++ ext4_xattr_release_block(handle, inode, bh); EXT4_I(inode)->i_file_acl = 0; @@ -905,7 +922,7 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/xattr.c } /* -@@ -1542,10 +1985,9 @@ ext4_xattr_cmp(struct ext4_xattr_header +@@ -1542,10 +1999,9 @@ ext4_xattr_cmp(struct ext4_xattr_header entry1->e_name_index != entry2->e_name_index || entry1->e_name_len != entry2->e_name_len || entry1->e_value_size != entry2->e_value_size || @@ -917,7 +934,7 @@ Index: linux-3.10.0-123.13.2.el7.x86_64/fs/ext4/xattr.c if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), (char *)header2 + le16_to_cpu(entry2->e_value_offs), le32_to_cpu(entry1->e_value_size))) -@@ -1629,7 +2071,7 @@ static inline void ext4_xattr_hash_entry +@@ -1629,7 +2085,7 @@ static inline void ext4_xattr_hash_entry *name++; } diff --git a/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch index 90a3afd..133006f 100644 --- a/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch @@ -55,17 +55,7 @@ Index: linux-stage/fs/ext4/inode.c trace_ext4_evict_inode(inode); -@@ -197,6 +199,9 @@ void ext4_evict_inode(struct inode *inod - goto no_delete; - } - -+ if (!IS_NOQUOTA(inode)) -+ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); -+ - if (!is_bad_inode(inode)) - dquot_initialize(inode); - -@@ -207,7 +212,10 @@ void ext4_evict_inode(struct inode *inod +@@ -207,7 +209,10 @@ void ext4_evict_inode(struct inode *inod if (is_bad_inode(inode)) goto no_delete; @@ -77,7 +67,7 @@ Index: linux-stage/fs/ext4/inode.c if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); /* -@@ -218,9 +226,30 @@ void ext4_evict_inode(struct inode *inod +@@ -218,9 +223,33 @@ void ext4_evict_inode(struct inode *inod ext4_orphan_del(NULL, inode); goto no_delete; } @@ -92,6 +82,9 @@ Index: linux-stage/fs/ext4/inode.c + goto stop_handle; + } + ++ if (!IS_NOQUOTA(inode)) ++ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ + if (!ext4_handle_has_enough_credits(handle, + blocks_for_truncate(inode) + extra_credits)) { + err = ext4_journal_extend(handle, @@ -810,7 +803,7 @@ Index: linux-stage/fs/ext4/xattr.c + struct ext4_inode *raw_inode; + struct ext4_iloc iloc; + struct ext4_xattr_entry *entry; -+ int error = 0; ++ int credits = 3, error = 0; + + if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) + goto delete_external_ea; @@ -837,7 +830,7 @@ Index: linux-stage/fs/ext4/xattr.c if (!EXT4_I(inode)->i_file_acl) goto cleanup; bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); -@@ -1387,11 +1770,74 @@ ext4_xattr_delete_inode(handle_t *handle +@@ -1387,11 +1770,88 @@ ext4_xattr_delete_inode(handle_t *handle EXT4_I(inode)->i_file_acl); goto cleanup; } @@ -858,10 +851,10 @@ Index: linux-stage/fs/ext4/xattr.c + int idx = (*lea_ino_array)->xia_count; + + for (idx = 0; idx < (*lea_ino_array)->xia_count; ++idx) { -+ if (!ext4_handle_has_enough_credits(handle, 3)) { -+ error = ext4_journal_extend(handle, 3); ++ if (!ext4_handle_has_enough_credits(handle, credits)) { ++ error = ext4_journal_extend(handle, credits); + if (error > 0) -+ error = ext4_journal_restart(handle, 3); ++ error = ext4_journal_restart(handle, credits); + if (error != 0) { + ext4_warning(inode->i_sb, + "couldn't extend journal " @@ -878,6 +871,20 @@ Index: linux-stage/fs/ext4/xattr.c + } + } + ++ if (!IS_NOQUOTA(inode)) ++ credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ ++ if (!ext4_handle_has_enough_credits(handle, credits)) { ++ error = ext4_journal_extend(handle, credits); ++ if (error > 0) ++ error = ext4_journal_restart(handle, credits); ++ if (error != 0) { ++ ext4_warning(inode->i_sb, ++ "couldn't extend journal (err %d)", error); ++ goto cleanup; ++ } ++ } ++ ext4_xattr_release_block(handle, inode, bh); EXT4_I(inode)->i_file_acl = 0; @@ -912,7 +919,7 @@ Index: linux-stage/fs/ext4/xattr.c } /* -@@ -1461,10 +1907,9 @@ ext4_xattr_cmp(struct ext4_xattr_header +@@ -1461,10 +1921,9 @@ ext4_xattr_cmp(struct ext4_xattr_header entry1->e_name_index != entry2->e_name_index || entry1->e_name_len != entry2->e_name_len || entry1->e_value_size != entry2->e_value_size || @@ -924,7 +931,7 @@ Index: linux-stage/fs/ext4/xattr.c if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), (char *)header2 + le16_to_cpu(entry2->e_value_offs), le32_to_cpu(entry1->e_value_size))) -@@ -1548,7 +1993,7 @@ static inline void ext4_xattr_hash_entry +@@ -1548,7 +2007,7 @@ static inline void ext4_xattr_hash_entry *name++; } -- 1.8.3.1