Whamcloud - gitweb
LU-13416 ldiskfs: don't corrupt data on journal replay 05/38705/4
authorAlexey Lyashkov <c17817@cray.com>
Mon, 20 Apr 2020 09:45:52 +0000 (12:45 +0300)
committerOleg Drokin <green@whamcloud.com>
Wed, 27 May 2020 21:34:33 +0000 (21:34 +0000)
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 <tahsin@google.com>
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 <c17817@cray.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/38705
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
12 files changed:
ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/rhel7.2/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/rhel7.6/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/sles12sp2/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/sles12sp3/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-large-eas.patch
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_io.c
lustre/osd-ldiskfs/osd_scrub.c

index 968ab15..d3ee3dc 100644 (file)
@@ -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) {
index 35ca4d5..0440dd9 100644 (file)
@@ -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
index e86a32b..711eb10 100644 (file)
@@ -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
index 3dbbb18..6c51afe 100644 (file)
@@ -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
index 5ef75ea..a40c28d 100644 (file)
@@ -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
index 6dfcb5c..2c5865a 100644 (file)
@@ -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
index 0bf0c7d..0a75fa5 100644 (file)
@@ -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
index 29833b6..f0fc79c 100644 (file)
@@ -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
index 9383900..ef304d5 100644 (file)
@@ -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
index 575ebe7..83afd3a 100644 (file)
@@ -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);
index a677a33..d9fba93 100644 (file)
@@ -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;
index 6232235..62b1245 100644 (file)
@@ -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.*/