From: Andrew Perepechko Date: Fri, 5 Mar 2021 14:10:38 +0000 (+0300) Subject: LU-14491 ldiskfs: do not corrupt journal with bh modification X-Git-Tag: 2.14.51~37 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=d563f5140ffa183d0854cf7cd493ad884e314e3d LU-14491 ldiskfs: do not corrupt journal with bh modification 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 HPE-bug-id: LUS-9483 Reviewed-on: https://review.whamcloud.com/41896 Tested-by: jenkins Reviewed-by: Alexander Zarochentsev Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- 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 b9ae354..b8148e0 100644 --- a/ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel7.7/ext4-large-eas.patch @@ -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) -@@ -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 ext4_iloc iloc; ++ struct ext4_iloc iloc = { .bh = NULL }; + 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) -+ goto cleanup; + goto cleanup; + 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, -+ 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; -+ } + 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); - 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", -@@ -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; } @@ -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; ++ ++ error = ext4_journal_get_write_access(handle, bh); ++ if (error) ++ goto cleanup; + 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 */ @@ -964,6 +977,7 @@ Index: linux-stage/fs/ext4/xattr.c cleanup: brelse(bh); ++ brelse(iloc.bh); + + return error; +} diff --git a/ldiskfs/kernel_patches/patches/sles15sp1/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles15sp1/ext4-large-eas.patch index 7d64fb3..5436ee4 100644 --- a/ldiskfs/kernel_patches/patches/sles15sp1/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles15sp1/ext4-large-eas.patch @@ -802,7 +802,7 @@ Signed-off-by: Dan Carpenter if (error) goto out; -@@ -1578,21 +1887,135 @@ cleanup: +@@ -1578,21 +1887,140 @@ cleanup: } @@ -907,7 +907,7 @@ Signed-off-by: Dan Carpenter 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; @@ -917,7 +917,7 @@ Signed-off-by: Dan Carpenter + + 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); @@ -925,25 +925,30 @@ Signed-off-by: Dan Carpenter + 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; -+ } + 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); - 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", -@@ -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; } @@ -955,7 +960,15 @@ Signed-off-by: Dan Carpenter + 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_size = 0; ++ error = ext4_handle_dirty_metadata(handle, inode, bh); ++ if (error) ++ goto cleanup; + } + + /* add xattr inode to orphan list */ @@ -983,6 +996,7 @@ Signed-off-by: Dan Carpenter cleanup: brelse(bh); ++ brelse(iloc.bh); + + return error; +}