Whamcloud - gitweb
LU-14491 ldiskfs: do not corrupt journal with bh modification 96/41896/2
authorAndrew Perepechko <andrew.perepechko@hpe.com>
Fri, 5 Mar 2021 14:10:38 +0000 (17:10 +0300)
committerOleg Drokin <green@whamcloud.com>
Sat, 13 Mar 2021 18:33:36 +0000 (18:33 +0000)
Currently, ldiskfs_xattr_delete_inode() zeroes xattr inode
references in cached buffers that haven't been prepared by
get_write_access().

When using journal checksums, it is possible that these buffers
are modified after the checksum is calculated but before the
buffer has been written to journal. Journal replay will fail
with a journal checksum error message if this transaction needs
to be replayed.

Change-Id: Ia3d44f24715ad97b505e08706933e4eb608c115f
Signed-off-by: Andrew Perepechko <andrew.perepechko@hpe.com>
HPE-bug-id: LUS-9483
Reviewed-on: https://review.whamcloud.com/41896
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Alexander Zarochentsev <alexander.zarochentsev@hpe.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch
ldiskfs/kernel_patches/patches/sles15sp1/ext4-large-eas.patch

index b9ae354..b8148e0 100644 (file)
@@ -783,7 +783,7 @@ Index: linux-stage/fs/ext4/xattr.c
                        new_offs = le16_to_cpu(last->e_value_offs) +
                                                        value_offs_shift;
                        BUG_ON(new_offs + le32_to_cpu(last->e_value_size)
                        new_offs = le16_to_cpu(last->e_value_offs) +
                                                        value_offs_shift;
                        BUG_ON(new_offs + le32_to_cpu(last->e_value_size)
-@@ -1494,21 +1838,135 @@ cleanup:
+@@ -1494,21 +1835,140 @@ cleanup:
  }
  
  
  }
  
  
@@ -888,7 +888,7 @@ Index: linux-stage/fs/ext4/xattr.c
        struct buffer_head *bh = NULL;
 +      struct ext4_xattr_ibody_header *header;
 +      struct ext4_inode *raw_inode;
        struct buffer_head *bh = NULL;
 +      struct ext4_xattr_ibody_header *header;
 +      struct ext4_inode *raw_inode;
-+      struct ext4_iloc iloc;
++      struct ext4_iloc iloc = { .bh = NULL };
 +      struct ext4_xattr_entry *entry;
 +      int credits = 3, error = 0;
  
 +      struct ext4_xattr_entry *entry;
 +      int credits = 3, error = 0;
  
@@ -898,7 +898,7 @@ Index: linux-stage/fs/ext4/xattr.c
 +
 +      error = ext4_get_inode_loc(inode, &iloc);
 +      if (error)
 +
 +      error = ext4_get_inode_loc(inode, &iloc);
 +      if (error)
-+              goto cleanup;
+               goto cleanup;
 +      raw_inode = ext4_raw_inode(&iloc);
 +      header = IHDR(inode, raw_inode);
 +      for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
 +      raw_inode = ext4_raw_inode(&iloc);
 +      header = IHDR(inode, raw_inode);
 +      for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
@@ -906,25 +906,30 @@ Index: linux-stage/fs/ext4/xattr.c
 +              if (!entry->e_value_inum)
 +                      continue;
 +              if (ext4_expand_ino_array(lea_ino_array,
 +              if (!entry->e_value_inum)
 +                      continue;
 +              if (ext4_expand_ino_array(lea_ino_array,
-+                                        entry->e_value_inum) != 0) {
-+                      brelse(iloc.bh);
++                                        entry->e_value_inum) != 0)
++                      goto cleanup;
++
++              error = ext4_journal_get_write_access(handle, iloc.bh);
++              if (error)
 +                      goto cleanup;
 +                      goto cleanup;
-+              }
 +              entry->e_value_inum = 0;
 +              entry->e_value_inum = 0;
++              entry->e_value_size = 0;
++              error = ext4_handle_dirty_metadata(handle, inode, iloc.bh);
++              if (error)
++                      goto cleanup;
 +      }
 +      }
-+      brelse(iloc.bh);
 +
 +delete_external_ea:
 +      if (!EXT4_I(inode)->i_file_acl) {
 +              /* add xattr inode to orphan list */
 +              ext4_xattr_inode_orphan_add(handle, inode, credits,
 +                                              *lea_ino_array);
 +
 +delete_external_ea:
 +      if (!EXT4_I(inode)->i_file_acl) {
 +              /* add xattr inode to orphan list */
 +              ext4_xattr_inode_orphan_add(handle, inode, credits,
 +                                              *lea_ino_array);
-               goto cleanup;
++              goto cleanup;
 +      }
        bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
        if (!bh) {
                EXT4_ERROR_INODE(inode, "block %llu read error",
 +      }
        bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
        if (!bh) {
                EXT4_ERROR_INODE(inode, "block %llu read error",
-@@ -1521,11 +1979,69 @@ ext4_xattr_delete_inode(handle_t *handle
+@@ -1521,11 +1983,78 @@ ext4_xattr_delete_inode(handle_t *han
                                 EXT4_I(inode)->i_file_acl);
                goto cleanup;
        }
                                 EXT4_I(inode)->i_file_acl);
                goto cleanup;
        }
@@ -936,7 +941,15 @@ Index: linux-stage/fs/ext4/xattr.c
 +              if (ext4_expand_ino_array(lea_ino_array,
 +                                        entry->e_value_inum) != 0)
 +                      goto cleanup;
 +              if (ext4_expand_ino_array(lea_ino_array,
 +                                        entry->e_value_inum) != 0)
 +                      goto cleanup;
++
++              error = ext4_journal_get_write_access(handle, bh);
++              if (error)
++                      goto cleanup;
 +              entry->e_value_inum = 0;
 +              entry->e_value_inum = 0;
++              entry->e_value_size = 0;
++              error = ext4_handle_dirty_metadata(handle, inode, bh);
++              if (error)
++                      goto cleanup;
 +      }
 +
 +      /* add xattr inode to orphan list */
 +      }
 +
 +      /* add xattr inode to orphan list */
@@ -964,6 +977,7 @@ Index: linux-stage/fs/ext4/xattr.c
  
  cleanup:
        brelse(bh);
  
  cleanup:
        brelse(bh);
++      brelse(iloc.bh);
 +
 +      return error;
 +}
 +
 +      return error;
 +}
index 7d64fb3..5436ee4 100644 (file)
@@ -802,7 +802,7 @@ Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
        if (error)
                goto out;
  
        if (error)
                goto out;
  
-@@ -1578,21 +1887,135 @@ cleanup:
+@@ -1578,21 +1887,140 @@ cleanup:
  }
  
  
  }
  
  
@@ -907,7 +907,7 @@ Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
        struct buffer_head *bh = NULL;
 +      struct ext4_xattr_ibody_header *header;
 +      struct ext4_inode *raw_inode;
        struct buffer_head *bh = NULL;
 +      struct ext4_xattr_ibody_header *header;
 +      struct ext4_inode *raw_inode;
-+      struct ext4_iloc iloc;
++      struct ext4_iloc iloc = { .bh = NULL };
 +      struct ext4_xattr_entry *entry;
 +      int credits = 3, error = 0;
  
 +      struct ext4_xattr_entry *entry;
 +      int credits = 3, error = 0;
  
@@ -917,7 +917,7 @@ Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
 +
 +      error = ext4_get_inode_loc(inode, &iloc);
 +      if (error)
 +
 +      error = ext4_get_inode_loc(inode, &iloc);
 +      if (error)
-+              goto cleanup;
+               goto cleanup;
 +      raw_inode = ext4_raw_inode(&iloc);
 +      header = IHDR(inode, raw_inode);
 +      for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
 +      raw_inode = ext4_raw_inode(&iloc);
 +      header = IHDR(inode, raw_inode);
 +      for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
@@ -925,25 +925,30 @@ Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
 +              if (!entry->e_value_inum)
 +                      continue;
 +              if (ext4_expand_ino_array(lea_ino_array,
 +              if (!entry->e_value_inum)
 +                      continue;
 +              if (ext4_expand_ino_array(lea_ino_array,
-+                                        entry->e_value_inum) != 0) {
-+                      brelse(iloc.bh);
++                                        entry->e_value_inum) != 0)
++                      goto cleanup;
++
++              error = ext4_journal_get_write_access(handle, iloc.bh);
++              if (error)
 +                      goto cleanup;
 +                      goto cleanup;
-+              }
 +              entry->e_value_inum = 0;
 +              entry->e_value_inum = 0;
++              entry->e_value_size = 0;
++              error = ext4_handle_dirty_metadata(handle, inode, iloc.bh);
++              if (error)
++                      goto cleanup;
 +      }
 +      }
-+      brelse(iloc.bh);
 +
 +delete_external_ea:
 +      if (!EXT4_I(inode)->i_file_acl) {
 +              /* add xattr inode to orphan list */
 +              ext4_xattr_inode_orphan_add(handle, inode, credits,
 +                                              *lea_ino_array);
 +
 +delete_external_ea:
 +      if (!EXT4_I(inode)->i_file_acl) {
 +              /* add xattr inode to orphan list */
 +              ext4_xattr_inode_orphan_add(handle, inode, credits,
 +                                              *lea_ino_array);
-               goto cleanup;
++              goto cleanup;
 +      }
        bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
        if (!bh) {
                EXT4_ERROR_INODE(inode, "block %llu read error",
 +      }
        bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
        if (!bh) {
                EXT4_ERROR_INODE(inode, "block %llu read error",
-@@ -1605,11 +2028,69 @@ ext4_xattr_delete_inode(handle_t *handle
+@@ -1605,11 +2028,78 @@ ext4_xattr_delete_inode(handle_t *handle
                                 EXT4_I(inode)->i_file_acl);
                goto cleanup;
        }
                                 EXT4_I(inode)->i_file_acl);
                goto cleanup;
        }
@@ -955,7 +960,15 @@ Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
 +              if (ext4_expand_ino_array(lea_ino_array,
 +                                        entry->e_value_inum) != 0)
 +                      goto cleanup;
 +              if (ext4_expand_ino_array(lea_ino_array,
 +                                        entry->e_value_inum) != 0)
 +                      goto cleanup;
++
++              error = ext4_journal_get_write_access(handle, bh);
++              if (error)
++                      goto cleanup;
 +              entry->e_value_inum = 0;
 +              entry->e_value_inum = 0;
++              entry->e_value_size = 0;
++              error = ext4_handle_dirty_metadata(handle, inode, bh);
++              if (error)
++                      goto cleanup;
 +      }
 +
 +      /* add xattr inode to orphan list */
 +      }
 +
 +      /* add xattr inode to orphan list */
@@ -983,6 +996,7 @@ Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
  
  cleanup:
        brelse(bh);
  
  cleanup:
        brelse(bh);
++      brelse(iloc.bh);
 +
 +      return error;
 +}
 +
 +      return error;
 +}