From 76b1050a56385cf8ddea47c9fea12eec21478601 Mon Sep 17 00:00:00 2001 From: Alexey Lyashkov Date: Mon, 20 Apr 2020 12:45:52 +0300 Subject: [PATCH] LU-13416 ldiskfs: don't corrupt data on journal replay Journalled write want a special attention on blocks release, revoke records must added to avoid replace new write blocks with stale data. Mark inode as "journal write" to generate valid revoke records. Large EA inode updates affected with this bug also. large ea fix is Linux-commit: ddfa17e4adc4bd19c32216aaa6250dc38b0579df Author: Tahsin Erdogan Date: Wed Jun 21 21:36:51 2017 -0400 ext4: call journal revoke when freeing ea_inode blocks Lustre-change: https://review.whamcloud.com/38281 Lustre-commit: a23aac2219047cb04ed1fa555f31fa39e5c499dc Change-Id: I605128c4ba70331a48715dc95546430909efb893 Signed-off-by: Alexey Lyashkov Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Reviewed-on: https://review.whamcloud.com/38705 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- .../patches/rhel6.3/ext4-large-eas.patch | 28 +++++++++++ .../patches/rhel7.2/ext4-large-eas.patch | 28 +++++++++++ .../patches/rhel7.6/ext4-large-eas.patch | 54 ++++++++++++++++------ .../patches/rhel7.7/ext4-large-eas.patch | 54 ++++++++++++++++------ .../patches/rhel7/ext4-large-eas.patch | 28 +++++++++++ .../patches/sles12/ext4-large-eas.patch | 28 +++++++++++ .../patches/sles12sp2/ext4-large-eas.patch | 28 +++++++++++ .../patches/sles12sp3/ext4-large-eas.patch | 28 +++++++++++ .../patches/ubuntu14+16/ext4-large-eas.patch | 28 +++++++++++ lustre/osd-ldiskfs/osd_handler.c | 3 ++ lustre/osd-ldiskfs/osd_io.c | 12 +++-- lustre/osd-ldiskfs/osd_scrub.c | 1 + 12 files changed, 289 insertions(+), 31 deletions(-) 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 968ab15..d3ee3dc 100644 --- a/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch @@ -1012,6 +1012,20 @@ Index: linux-stage/fs/ext4/inode.c return; no_delete: clear_inode(inode); /* We must guarantee clearing of inode... */ +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2163,7 +2163,8 @@ int ext4_remove_blocks(handle_t *handle + unsigned short ee_len = ext4_ext_get_actual_len(ex); + int i, metadata = 0; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + metadata = 1; + #ifdef EXTENTS_STATS + { Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c @@ -1024,3 +1038,17 @@ Index: linux-stage/fs/ext4/ialloc.c vfs_dq_free_inode(inode); vfs_dq_drop(inode); +Index: linux-stage/fs/ext4/inode.c +=================================================================== +--- linux-stage.orig/fs/ext4/inode.c ++++ linux-stage/fs/ext4/inode.c +@@ -4385,7 +4385,8 @@ static void ext4_clear_blocks(handle_t *h + __le32 *last) + { + __le32 *p; +- int is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode); ++ int is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL); + + if (try_to_extend_transaction(handle, inode)) { + if (bh) { diff --git a/ldiskfs/kernel_patches/patches/rhel7.2/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel7.2/ext4-large-eas.patch index 35ca4d5..0440dd9 100644 --- a/ldiskfs/kernel_patches/patches/rhel7.2/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel7.2/ext4-large-eas.patch @@ -1066,6 +1066,20 @@ Index: linux-stage/fs/ext4/xattr.h extern void ext4_xattr_put_super(struct super_block *); extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2461,7 +2461,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c @@ -1078,6 +1092,20 @@ Index: linux-stage/fs/ext4/ialloc.c dquot_free_inode(inode); dquot_drop(inode); +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -959,7 +959,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/inline.c =================================================================== --- linux-stage.orig/fs/ext4/inline.c diff --git a/ldiskfs/kernel_patches/patches/rhel7.6/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel7.6/ext4-large-eas.patch index e86a32bd..711eb10 100644 --- a/ldiskfs/kernel_patches/patches/rhel7.6/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel7.6/ext4-large-eas.patch @@ -8,7 +8,7 @@ Index: linux-stage/fs/ext4/ext4.h =================================================================== --- linux-stage.orig/fs/ext4/ext4.h +++ linux-stage/fs/ext4/ext4.h -@@ -1579,6 +1579,7 @@ static inline void ext4_clear_state_flag +@@ -1617,6 +1617,7 @@ static inline void ext4_clear_state_flag EXT4_FEATURE_INCOMPAT_EXTENTS| \ EXT4_FEATURE_INCOMPAT_64BIT| \ EXT4_FEATURE_INCOMPAT_FLEX_BG| \ @@ -16,7 +16,7 @@ Index: linux-stage/fs/ext4/ext4.h EXT4_FEATURE_INCOMPAT_MMP | \ EXT4_FEATURE_INCOMPAT_DIRDATA| \ EXT4_FEATURE_INCOMPAT_INLINE_DATA) -@@ -1990,6 +1997,10 @@ struct mmpd_data { +@@ -2028,6 +2029,10 @@ struct mmpd_data { # define ATTRIB_NORET __attribute__((noreturn)) # define NORET_AND noreturn, @@ -27,7 +27,7 @@ Index: linux-stage/fs/ext4/ext4.h /* bitmap.c */ extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, -@@ -2194,6 +2205,7 @@ extern void ext4_set_inode_flags(struct +@@ -2233,6 +2238,7 @@ extern void ext4_set_inode_flags(struct extern void ext4_get_inode_flags(struct ext4_inode_info *); extern int ext4_alloc_da_blocks(struct inode *inode); extern void ext4_set_aops(struct inode *inode); @@ -39,7 +39,7 @@ Index: linux-stage/fs/ext4/inode.c =================================================================== --- linux-stage.orig/fs/ext4/inode.c +++ linux-stage/fs/ext4/inode.c -@@ -134,8 +134,6 @@ static void ext4_invalidatepage(struct p +@@ -136,8 +136,6 @@ static void ext4_invalidatepage(struct p unsigned int length); static int __ext4_journalled_writepage(struct page *page, unsigned int len); static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh); @@ -48,7 +48,7 @@ Index: linux-stage/fs/ext4/inode.c /* * Test whether an inode is a fast symlink. -@@ -184,6 +182,8 @@ void ext4_evict_inode(struct inode *inod +@@ -186,6 +184,8 @@ void ext4_evict_inode(struct inode *inod { handle_t *handle; int err; @@ -57,7 +57,7 @@ Index: linux-stage/fs/ext4/inode.c trace_ext4_evict_inode(inode); -@@ -236,8 +236,8 @@ void ext4_evict_inode(struct inode *inod +@@ -235,8 +235,8 @@ void ext4_evict_inode(struct inode *inod * protection against it */ sb_start_intwrite(inode->i_sb); @@ -68,7 +68,7 @@ Index: linux-stage/fs/ext4/inode.c if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); /* -@@ -252,6 +252,32 @@ void ext4_evict_inode(struct inode *inod +@@ -251,6 +251,32 @@ void ext4_evict_inode(struct inode *inod if (IS_SYNC(inode)) ext4_handle_sync(handle); @@ -101,7 +101,7 @@ Index: linux-stage/fs/ext4/inode.c inode->i_size = 0; err = ext4_mark_inode_dirty(handle, inode); if (err) { -@@ -269,10 +296,10 @@ void ext4_evict_inode(struct inode *inod +@@ -267,10 +293,10 @@ void ext4_evict_inode(struct inode *inod * enough credits left in the handle to remove the inode from * the orphan list and set the dtime field. */ @@ -115,7 +115,7 @@ Index: linux-stage/fs/ext4/inode.c if (err != 0) { ext4_warning(inode->i_sb, "couldn't extend journal (err %d)", err); -@@ -308,6 +335,9 @@ void ext4_evict_inode(struct inode *inod +@@ -307,6 +333,9 @@ void ext4_evict_inode(struct inode *inod ext4_free_inode(handle, inode); ext4_journal_stop(handle); sb_end_intwrite(inode->i_sb); @@ -125,7 +125,7 @@ Index: linux-stage/fs/ext4/inode.c return; no_delete: ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ -@@ -4681,7 +4711,7 @@ static int ext4_index_trans_blocks(struc +@@ -5132,7 +5161,7 @@ static int ext4_index_trans_blocks(struc * * Also account for superblock, inode, quota and xattr blocks */ @@ -1032,7 +1032,7 @@ Index: linux-stage/fs/ext4/xattr.h #define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data)) #define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr)) #define BFIRST(bh) ENTRY(BHDR(bh)+1) -@@ -75,10 +84,11 @@ struct ext4_xattr_entry { +@@ -75,10 +95,11 @@ struct ext4_xattr_entry { #define EXT4_ZERO_XATTR_VALUE ((void *)-1) struct ext4_xattr_info { @@ -1045,7 +1045,7 @@ Index: linux-stage/fs/ext4/xattr.h }; struct ext4_xattr_search { -@@ -106,7 +116,13 @@ extern int ext4_xattr_get(struct inode * +@@ -106,7 +127,13 @@ extern int ext4_xattr_get(struct inode * extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int); @@ -1060,11 +1060,25 @@ Index: linux-stage/fs/ext4/xattr.h extern void ext4_xattr_put_super(struct super_block *); extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2461,7 +2461,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c +++ linux-stage/fs/ext4/ialloc.c -@@ -269,7 +269,6 @@ void ext4_free_inode(handle_t *handle, s +@@ -247,7 +247,6 @@ void ext4_free_inode(handle_t *handle, s * as writing the quota to disk may need the lock as well. */ dquot_initialize(inode); @@ -1072,6 +1086,20 @@ Index: linux-stage/fs/ext4/ialloc.c dquot_free_inode(inode); dquot_drop(inode); +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -959,7 +959,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/inline.c =================================================================== --- linux-stage.orig/fs/ext4/inline.c diff --git a/ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch index 3dbbb18..6c51afe 100644 --- a/ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch @@ -8,7 +8,7 @@ Index: linux-stage/fs/ext4/ext4.h =================================================================== --- linux-stage.orig/fs/ext4/ext4.h +++ linux-stage/fs/ext4/ext4.h -@@ -1579,6 +1579,7 @@ static inline void ext4_clear_state_flag +@@ -1620,6 +1620,7 @@ static inline void ext4_clear_state_flag EXT4_FEATURE_INCOMPAT_EXTENTS| \ EXT4_FEATURE_INCOMPAT_64BIT| \ EXT4_FEATURE_INCOMPAT_FLEX_BG| \ @@ -16,7 +16,7 @@ Index: linux-stage/fs/ext4/ext4.h EXT4_FEATURE_INCOMPAT_MMP | \ EXT4_FEATURE_INCOMPAT_DIRDATA| \ EXT4_FEATURE_INCOMPAT_INLINE_DATA) -@@ -1990,6 +1997,10 @@ struct mmpd_data { +@@ -2033,6 +2034,10 @@ struct mmpd_data { # define ATTRIB_NORET __attribute__((noreturn)) # define NORET_AND noreturn, @@ -27,7 +27,7 @@ Index: linux-stage/fs/ext4/ext4.h /* bitmap.c */ extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, -@@ -2194,6 +2205,7 @@ extern void ext4_set_inode_flags(struct +@@ -2238,6 +2243,7 @@ extern void ext4_set_inode_flags(struct extern void ext4_get_inode_flags(struct ext4_inode_info *); extern int ext4_alloc_da_blocks(struct inode *inode); extern void ext4_set_aops(struct inode *inode); @@ -39,7 +39,7 @@ Index: linux-stage/fs/ext4/inode.c =================================================================== --- linux-stage.orig/fs/ext4/inode.c +++ linux-stage/fs/ext4/inode.c -@@ -134,8 +134,6 @@ static void ext4_invalidatepage(struct p +@@ -136,8 +136,6 @@ static void ext4_invalidatepage(struct p unsigned int length); static int __ext4_journalled_writepage(struct page *page, unsigned int len); static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh); @@ -48,7 +48,7 @@ Index: linux-stage/fs/ext4/inode.c /* * Test whether an inode is a fast symlink. -@@ -184,6 +182,8 @@ void ext4_evict_inode(struct inode *inod +@@ -186,6 +184,8 @@ void ext4_evict_inode(struct inode *inod { handle_t *handle; int err; @@ -57,7 +57,7 @@ Index: linux-stage/fs/ext4/inode.c trace_ext4_evict_inode(inode); -@@ -236,8 +236,8 @@ void ext4_evict_inode(struct inode *inod +@@ -235,8 +235,8 @@ void ext4_evict_inode(struct inode *inod * protection against it */ sb_start_intwrite(inode->i_sb); @@ -68,7 +68,7 @@ Index: linux-stage/fs/ext4/inode.c if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); /* -@@ -252,6 +252,32 @@ void ext4_evict_inode(struct inode *inod +@@ -251,6 +251,32 @@ void ext4_evict_inode(struct inode *inod if (IS_SYNC(inode)) ext4_handle_sync(handle); @@ -101,7 +101,7 @@ Index: linux-stage/fs/ext4/inode.c inode->i_size = 0; err = ext4_mark_inode_dirty(handle, inode); if (err) { -@@ -269,10 +296,10 @@ void ext4_evict_inode(struct inode *inod +@@ -267,10 +293,10 @@ void ext4_evict_inode(struct inode *inod * enough credits left in the handle to remove the inode from * the orphan list and set the dtime field. */ @@ -115,7 +115,7 @@ Index: linux-stage/fs/ext4/inode.c if (err != 0) { ext4_warning(inode->i_sb, "couldn't extend journal (err %d)", err); -@@ -308,6 +335,9 @@ void ext4_evict_inode(struct inode *inod +@@ -307,6 +333,9 @@ void ext4_evict_inode(struct inode *inod ext4_free_inode(handle, inode); ext4_journal_stop(handle); sb_end_intwrite(inode->i_sb); @@ -125,7 +125,7 @@ Index: linux-stage/fs/ext4/inode.c return; no_delete: ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ -@@ -4681,7 +4711,7 @@ static int ext4_index_trans_blocks(struc +@@ -5140,7 +5169,7 @@ static int ext4_index_trans_blocks(struc * * Also account for superblock, inode, quota and xattr blocks */ @@ -1055,7 +1055,7 @@ Index: linux-stage/fs/ext4/xattr.h #define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data)) #define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr)) #define BFIRST(bh) ENTRY(BHDR(bh)+1) -@@ -75,10 +84,11 @@ struct ext4_xattr_entry { +@@ -75,10 +95,11 @@ struct ext4_xattr_entry { #define EXT4_ZERO_XATTR_VALUE ((void *)-1) struct ext4_xattr_info { @@ -1068,7 +1068,7 @@ Index: linux-stage/fs/ext4/xattr.h }; struct ext4_xattr_search { -@@ -106,7 +116,13 @@ extern int ext4_xattr_get(struct inode * +@@ -106,7 +127,13 @@ extern int ext4_xattr_get(struct inode * extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int); @@ -1083,11 +1083,25 @@ Index: linux-stage/fs/ext4/xattr.h extern void ext4_xattr_put_super(struct super_block *); extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2474,7 +2474,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c +++ linux-stage/fs/ext4/ialloc.c -@@ -269,7 +269,6 @@ void ext4_free_inode(handle_t *handle, s +@@ -247,7 +247,6 @@ void ext4_free_inode(handle_t *handle, s * as writing the quota to disk may need the lock as well. */ dquot_initialize(inode); @@ -1095,6 +1109,20 @@ Index: linux-stage/fs/ext4/ialloc.c dquot_free_inode(inode); dquot_drop(inode); +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -967,7 +967,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/inline.c =================================================================== --- linux-stage.orig/fs/ext4/inline.c diff --git a/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch index 5ef75ea..a40c28d 100644 --- a/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch @@ -1070,6 +1070,20 @@ Index: linux-stage/fs/ext4/xattr.h extern void ext4_xattr_put_super(struct super_block *); extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2474,7 +2474,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c @@ -1083,6 +1097,20 @@ Index: linux-stage/fs/ext4/ialloc.c dquot_drop(inode); Index: linux-stage/fs/ext4/inline.c +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -967,7 +967,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; =================================================================== --- linux-stage.orig/fs/ext4/inline.c +++ linux-stage/fs/ext4/inline.c diff --git a/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch index 6dfcb5c..2c5865a 100644 --- a/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch @@ -1065,6 +1065,20 @@ Index: linux-stage/fs/ext4/xattr.h extern void ext4_xattr_put_super(struct super_block *); extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2461,7 +2461,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c @@ -1077,6 +1091,20 @@ Index: linux-stage/fs/ext4/ialloc.c dquot_free_inode(inode); dquot_drop(inode); +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -959,7 +959,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/inline.c =================================================================== --- linux-stage.orig/fs/ext4/inline.c diff --git a/ldiskfs/kernel_patches/patches/sles12sp2/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles12sp2/ext4-large-eas.patch index 0bf0c7d..0a75fa5 100644 --- a/ldiskfs/kernel_patches/patches/sles12sp2/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles12sp2/ext4-large-eas.patch @@ -1070,6 +1070,20 @@ Index: linux-stage/fs/ext4/xattr.h extern void ext4_xattr_put_super(struct super_block *); extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2461,7 +2461,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c @@ -1082,6 +1096,20 @@ Index: linux-stage/fs/ext4/ialloc.c dquot_free_inode(inode); dquot_drop(inode); +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -959,7 +959,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/inline.c =================================================================== --- linux-stage.orig/fs/ext4/inline.c diff --git a/ldiskfs/kernel_patches/patches/sles12sp3/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles12sp3/ext4-large-eas.patch index 29833b6..f0fc79c 100644 --- a/ldiskfs/kernel_patches/patches/sles12sp3/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles12sp3/ext4-large-eas.patch @@ -1064,6 +1064,20 @@ Index: linux-stage/fs/ext4/xattr.h extern void ext4_xattr_put_super(struct super_block *); extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2461,7 +2461,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c @@ -1076,6 +1090,20 @@ Index: linux-stage/fs/ext4/ialloc.c dquot_free_inode(inode); dquot_drop(inode); +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -959,7 +959,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; Index: linux-stage/fs/ext4/inline.c =================================================================== --- linux-stage.orig/fs/ext4/inline.c diff --git a/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-large-eas.patch index 9383900..ef304d5 100644 --- a/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-large-eas.patch @@ -29,6 +29,20 @@ index 10a2a86..217fdcc 100644 extern int ext4_writepage_trans_blocks(struct inode *); extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode, +Index: linux-stage/fs/ext4/extents.c +=================================================================== +--- linux-stage.orig/fs/ext4/extents.c ++++ linux-stage/fs/ext4/extents.c +@@ -2461,7 +2461,8 @@ int ext4_ext_index_trans_blocks(struct i + + static inline int get_default_free_blocks_flags(struct inode *inode) + { +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + return EXT4_FREE_BLOCKS_FORGET; diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 0cccda3..43ca376 100644 --- a/fs/ext4/ialloc.c @@ -41,6 +55,20 @@ index 0cccda3..43ca376 100644 dquot_free_inode(inode); dquot_drop(inode); +Index: linux-stage/fs/ext4/indirect.c +=================================================================== +--- linux-stage.orig/fs/ext4/indirect.c ++++ linux-stage/fs/ext4/indirect.c +@@ -959,7 +959,8 @@ static int ext4_clear_blocks(handle_t *h + int flags = EXT4_FREE_BLOCKS_VALIDATED; + int err; + +- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) ++ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || ++ (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) + flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 53e8a88..5112c5a 100644 --- a/fs/ext4/inline.c diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 575ebe7..83afd3a 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -2118,6 +2118,9 @@ static void osd_object_delete(const struct lu_env *env, struct lu_object *l) if (!inode) return; + if (osd_has_index(obj) && obj->oo_dt.do_index_ops == &osd_index_iam_ops) + ldiskfs_set_inode_flag(inode, LDISKFS_INODE_JOURNAL_DATA); + uid = i_uid_read(inode); gid = i_gid_read(inode); projid = i_projid_read(inode); diff --git a/lustre/osd-ldiskfs/osd_io.c b/lustre/osd-ldiskfs/osd_io.c index a677a33..d9fba93 100644 --- a/lustre/osd-ldiskfs/osd_io.c +++ b/lustre/osd-ldiskfs/osd_io.c @@ -2052,11 +2052,11 @@ static int osd_ldiskfs_write_record(struct dt_object *dt, void *buf, loff_t new_size = i_size_read(inode); unsigned long block; int blocksize = 1 << inode->i_blkbits; + struct ldiskfs_inode_info *ei = LDISKFS_I(inode); int err = 0; int size; int boffs; int dirty_inode = 0; - struct ldiskfs_inode_info *ei = LDISKFS_I(inode); bool create, sparse, sync = false; if (write_NUL) { @@ -2069,6 +2069,8 @@ static int osd_ldiskfs_write_record(struct dt_object *dt, void *buf, ++bufsize; } + dirty_inode = test_and_set_bit(LDISKFS_INODE_JOURNAL_DATA, &ei->i_flags); + /* sparse checking is racy, but sparse is very rare case, leave as is */ sparse = (new_size > 0 && (inode->i_blocks >> (inode->i_blkbits - 9)) < ((new_size - 1) >> inode->i_blkbits) + 1); @@ -2172,14 +2174,14 @@ static int osd_ldiskfs_write_record(struct dt_object *dt, void *buf, spin_lock(&inode->i_lock); if (new_size > i_size_read(inode)) i_size_write(inode, new_size); - if (i_size_read(inode) > LDISKFS_I(inode)->i_disksize) { - LDISKFS_I(inode)->i_disksize = i_size_read(inode); + if (i_size_read(inode) > ei->i_disksize) { + ei->i_disksize = i_size_read(inode); dirty_inode = 1; } spin_unlock(&inode->i_lock); - if (dirty_inode) - ll_dirty_inode(inode, I_DIRTY_DATASYNC); } + if (dirty_inode) + ll_dirty_inode(inode, I_DIRTY_DATASYNC); if (err == 0) *offs = offset; diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c index 6232235..62b1245 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c @@ -2615,6 +2615,7 @@ int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev) } inode = file_inode(filp); + ldiskfs_set_inode_flag(inode, LDISKFS_INODE_JOURNAL_DATA); if (!dev->od_dt_dev.dd_rdonly) { /* 'What the @fid is' is not imporatant, because the object * has no OI mapping, and only is visible inside the OSD.*/ -- 1.8.3.1