[Devel] [PATCH RHEL7 COMMIT] ext4: add missing brelse() for bh2 in ext4_dx_add_entry()

Konstantin Khorenko khorenko at virtuozzo.com
Tue Apr 21 17:32:26 MSK 2026


The commit is pushed to "branch-rh7-3.10.0-1160.129.1.vz7.226.x-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh7-3.10.0-1160.129.1.vz7.226.2
------>
commit 5838c5d07c0dd76cbadbc52296e43401475bbac6
Author: Kemeng Shi <shikemeng at huaweicloud.com>
Date:   Sat Mar 21 12:30:04 2026 +0100

    ext4: add missing brelse() for bh2 in ext4_dx_add_entry()
    
    Add missing brelse() for bh2 in ext4_dx_add_entry().
    
    Fixes: ac27a0ec112a ("[PATCH] ext4: initial copy of files from ext3")
    Signed-off-by: Kemeng Shi <shikemeng at huaweicloud.com>
    Reviewed-by: Ojaswin Mujoo <ojaswin at linux.ibm.com>
    Reviewed-by: Zhang Yi <yi.zhang at huawei.com>
    Link: https://patch.msgid.link/20250123162050.2114499-2-shikemeng@huaweicloud.com
    Signed-off-by: Theodore Ts'o <tytso at mit.edu>
    
    [khorenko: backport to 3.10 - adapted to older ext4_dx_add_entry()
     code structure.  Applied 3 of 4 upstream hunks:
    
     1. ext4_journal_get_write_access(handle, frame->bh) error path:
        bh2 was just allocated via ext4_append() and not yet stored in
        any dx_frame, so dx_release() would not free it.  Need explicit
        brelse(bh2).
    
     2. ext4_journal_get_write_access(handle, frames[0].bh) error path
        inside "if (levels)" block:
        swap(frame->bh, bh2) has not executed yet, so bh2 is still not
        referenced by any frame - same situation as (1).
    
     3. ext4_handle_dirty_dx_node(handle, dir, bh2) inside "if (levels)"
        block:
        Regardless of whether swap(frame->bh, bh2) happened, bh2 holds
        a buffer that dx_release() does not cover.  Moved brelse(bh2)
        before the error check since it is needed on both success and
        error paths.
    
     Skipped the 4th upstream hunk (else branch - creating second level
     index): in our code frame->bh = bh2 is assigned and indirect_levels
     is set to 1 before the error path, so dx_release() calls
     brelse(frames[1].bh) which is bh2.  Adding explicit brelse(bh2)
     there would cause a double-free.]
    
    https://virtuozzo.atlassian.net/browse/PSBM-161670
    (cherry picked from commit eb640af64db6d4702a85ab001b9cc7f4c5dd6abb)
    Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
    Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 fs/ext4/namei.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 5279a83f4040f..bacdd0630b2c0 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2055,8 +2055,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 							   sb->s_blocksize);
 		BUFFER_TRACE(frame->bh, "get_write_access");
 		err = ext4_journal_get_write_access(handle, frame->bh);
-		if (err)
+		if (err) {
+			brelse(bh2);
 			goto journal_error;
+		}
 		if (levels) {
 			unsigned icount1 = icount/2, icount2 = icount - icount1;
 			unsigned hash2 = dx_get_hash(entries + icount1);
@@ -2066,8 +2068,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
 			err = ext4_journal_get_write_access(handle,
 							     frames[0].bh);
-			if (err)
+			if (err) {
+				brelse(bh2);
 				goto journal_error;
+			}
 
 			memcpy((char *) entries2, (char *) (entries + icount1),
 			       icount2 * sizeof(struct dx_entry));
@@ -2086,9 +2090,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			dxtrace(dx_show_index("node",
 			       ((struct dx_node *) bh2->b_data)->entries));
 			err = ext4_handle_dirty_dx_node(handle, dir, bh2);
+			brelse(bh2);
 			if (err)
 				goto journal_error;
-			brelse (bh2);
 		} else {
 			dxtrace(printk(KERN_DEBUG
 				       "Creating second level index...\n"));


More information about the Devel mailing list