lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250326014928.61507-5-catherine.hoang@oracle.com>
Date: Tue, 25 Mar 2025 18:49:28 -0700
From: Catherine Hoang <catherine.hoang@...cle.com>
To: linux-ext4@...r.kernel.org
Cc: djwong@...nel.org
Subject: [RFC PATCH v2 4/4] ext2: remove buffer heads from block bitmaps

The block allocation code uses buffer_heads to store block bitmaps.
Replace these buffer heads with the new ext2_buffer and update the
buffer functions accordingly.

Signed-off-by: Catherine Hoang <catherine.hoang@...cle.com>
---
 fs/ext2/balloc.c | 108 +++++++++++++++++++++--------------------------
 1 file changed, 48 insertions(+), 60 deletions(-)

diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 21dafa9ae2ea..2195c6ddbc83 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -71,7 +71,7 @@ struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
 static int ext2_valid_block_bitmap(struct super_block *sb,
 					struct ext2_group_desc *desc,
 					unsigned int block_group,
-					struct buffer_head *bh)
+					struct ext2_buffer *buf)
 {
 	ext2_grpblk_t offset;
 	ext2_grpblk_t next_zero_bit;
@@ -86,7 +86,7 @@ static int ext2_valid_block_bitmap(struct super_block *sb,
 	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
 	offset = bitmap_blk - group_first_block;
 	if (offset < 0 || offset > max_bit ||
-	    !ext2_test_bit(offset, bh->b_data))
+	    !ext2_test_bit(offset, buf->b_data))
 		/* bad block bitmap */
 		goto err_out;
 
@@ -94,7 +94,7 @@ static int ext2_valid_block_bitmap(struct super_block *sb,
 	bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
 	offset = bitmap_blk - group_first_block;
 	if (offset < 0 || offset > max_bit ||
-	    !ext2_test_bit(offset, bh->b_data))
+	    !ext2_test_bit(offset, buf->b_data))
 		/* bad block bitmap */
 		goto err_out;
 
@@ -104,7 +104,7 @@ static int ext2_valid_block_bitmap(struct super_block *sb,
 	if (offset < 0 || offset > max_bit ||
 	    offset + EXT2_SB(sb)->s_itb_per_group - 1 > max_bit)
 		goto err_out;
-	next_zero_bit = ext2_find_next_zero_bit(bh->b_data,
+	next_zero_bit = ext2_find_next_zero_bit(buf->b_data,
 				offset + EXT2_SB(sb)->s_itb_per_group,
 				offset);
 	if (next_zero_bit >= offset + EXT2_SB(sb)->s_itb_per_group)
@@ -125,31 +125,19 @@ static int ext2_valid_block_bitmap(struct super_block *sb,
  *
  * Return buffer_head on success or NULL in case of failure.
  */
-static struct buffer_head *
+static struct ext2_buffer *
 read_block_bitmap(struct super_block *sb, unsigned int block_group)
 {
 	struct ext2_group_desc * desc;
-	struct buffer_head * bh = NULL;
+	struct ext2_buffer * buf = NULL;
 	ext2_fsblk_t bitmap_blk;
-	int ret;
 
 	desc = ext2_get_group_desc(sb, block_group, NULL);
 	if (!desc)
 		return NULL;
 	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
-	bh = sb_getblk(sb, bitmap_blk);
-	if (unlikely(!bh)) {
-		ext2_error(sb, __func__,
-			    "Cannot read block bitmap - "
-			    "block_group = %d, block_bitmap = %u",
-			    block_group, le32_to_cpu(desc->bg_block_bitmap));
-		return NULL;
-	}
-	ret = bh_read(bh, 0);
-	if (ret > 0)
-		return bh;
-	if (ret < 0) {
-		brelse(bh);
+	buf = ext2_read_buffer(sb, bitmap_blk);
+	if (unlikely(IS_ERR(buf))) {
 		ext2_error(sb, __func__,
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %u",
@@ -157,12 +145,12 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
 		return NULL;
 	}
 
-	ext2_valid_block_bitmap(sb, desc, block_group, bh);
+	ext2_valid_block_bitmap(sb, desc, block_group, buf);
 	/*
 	 * file system mounted not to panic on error, continue with corrupt
 	 * bitmap
 	 */
-	return bh;
+	return buf;
 }
 
 static void group_adjust_blocks(struct super_block *sb, int group_no,
@@ -482,7 +470,7 @@ void ext2_discard_reservation(struct inode *inode)
 void ext2_free_blocks(struct inode * inode, ext2_fsblk_t block,
 		      unsigned long count)
 {
-	struct buffer_head *bitmap_bh = NULL;
+	struct ext2_buffer *bitmap_buf = NULL;
 	struct ext2_buffer * buf2;
 	unsigned long block_group;
 	unsigned long bit;
@@ -517,9 +505,9 @@ void ext2_free_blocks(struct inode * inode, ext2_fsblk_t block,
 		overflow = bit + count - EXT2_BLOCKS_PER_GROUP(sb);
 		count -= overflow;
 	}
-	brelse(bitmap_bh);
-	bitmap_bh = read_block_bitmap(sb, block_group);
-	if (!bitmap_bh)
+	ext2_put_buffer(sb, bitmap_buf);
+	bitmap_buf = read_block_bitmap(sb, block_group);
+	if (IS_ERR(bitmap_buf))
 		goto error_return;
 
 	desc = ext2_get_group_desc (sb, block_group, &buf2);
@@ -541,7 +529,7 @@ void ext2_free_blocks(struct inode * inode, ext2_fsblk_t block,
 
 	for (i = 0, group_freed = 0; i < count; i++) {
 		if (!ext2_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
-						bit + i, bitmap_bh->b_data)) {
+						bit + i, bitmap_buf->b_data)) {
 			ext2_error(sb, __func__,
 				"bit already cleared for block %lu", block + i);
 		} else {
@@ -549,9 +537,9 @@ void ext2_free_blocks(struct inode * inode, ext2_fsblk_t block,
 		}
 	}
 
-	mark_buffer_dirty(bitmap_bh);
+	ext2_buffer_set_dirty(bitmap_buf);
 	if (sb->s_flags & SB_SYNCHRONOUS)
-		sync_dirty_buffer(bitmap_bh);
+		ext2_sync_buffer_wait(sb, bitmap_buf);
 
 	group_adjust_blocks(sb, block_group, desc, buf2, group_freed);
 	freed += group_freed;
@@ -562,7 +550,7 @@ void ext2_free_blocks(struct inode * inode, ext2_fsblk_t block,
 		goto do_more;
 	}
 error_return:
-	brelse(bitmap_bh);
+	ext2_put_buffer(sb, bitmap_buf);
 	if (freed) {
 		percpu_counter_add(&sbi->s_freeblocks_counter, freed);
 		dquot_free_block_nodirty(inode, freed);
@@ -580,12 +568,12 @@ void ext2_free_blocks(struct inode * inode, ext2_fsblk_t block,
  * we find a bit free.
  */
 static ext2_grpblk_t
-bitmap_search_next_usable_block(ext2_grpblk_t start, struct buffer_head *bh,
+bitmap_search_next_usable_block(ext2_grpblk_t start, struct ext2_buffer *buf,
 					ext2_grpblk_t maxblocks)
 {
 	ext2_grpblk_t next;
 
-	next = ext2_find_next_zero_bit(bh->b_data, maxblocks, start);
+	next = ext2_find_next_zero_bit(buf->b_data, maxblocks, start);
 	if (next >= maxblocks)
 		return -1;
 	return next;
@@ -604,7 +592,7 @@ bitmap_search_next_usable_block(ext2_grpblk_t start, struct buffer_head *bh,
  * then for any free bit in the bitmap.
  */
 static ext2_grpblk_t
-find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
+find_next_usable_block(int start, struct ext2_buffer *buf, int maxblocks)
 {
 	ext2_grpblk_t here, next;
 	char *p, *r;
@@ -621,7 +609,7 @@ find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
 		ext2_grpblk_t end_goal = (start + 63) & ~63;
 		if (end_goal > maxblocks)
 			end_goal = maxblocks;
-		here = ext2_find_next_zero_bit(bh->b_data, end_goal, start);
+		here = ext2_find_next_zero_bit(buf->b_data, end_goal, start);
 		if (here < end_goal)
 			return here;
 		ext2_debug("Bit not found near goal\n");
@@ -631,14 +619,14 @@ find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
 	if (here < 0)
 		here = 0;
 
-	p = ((char *)bh->b_data) + (here >> 3);
+	p = ((char *)buf->b_data) + (here >> 3);
 	r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
-	next = (r - ((char *)bh->b_data)) << 3;
+	next = (r - ((char *)buf->b_data)) << 3;
 
 	if (next < maxblocks && next >= here)
 		return next;
 
-	here = bitmap_search_next_usable_block(here, bh, maxblocks);
+	here = bitmap_search_next_usable_block(here, buf, maxblocks);
 	return here;
 }
 
@@ -666,7 +654,7 @@ find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
  */
 static int
 ext2_try_to_allocate(struct super_block *sb, int group,
-			struct buffer_head *bitmap_bh, ext2_grpblk_t grp_goal,
+			struct ext2_buffer *bitmap_buf, ext2_grpblk_t grp_goal,
 			unsigned long *count,
 			struct ext2_reserve_window *my_rsv)
 {
@@ -689,7 +677,7 @@ ext2_try_to_allocate(struct super_block *sb, int group,
 	BUG_ON(start > EXT2_BLOCKS_PER_GROUP(sb));
 
 	if (grp_goal < 0) {
-		grp_goal = find_next_usable_block(start, bitmap_bh, end);
+		grp_goal = find_next_usable_block(start, bitmap_buf, end);
 		if (grp_goal < 0)
 			goto fail_access;
 		if (!my_rsv) {
@@ -697,7 +685,7 @@ ext2_try_to_allocate(struct super_block *sb, int group,
 
 			for (i = 0; i < 7 && grp_goal > start &&
 					!ext2_test_bit(grp_goal - 1,
-					     		bitmap_bh->b_data);
+					     		bitmap_buf->b_data);
 			     		i++, grp_goal--)
 				;
 		}
@@ -705,7 +693,7 @@ ext2_try_to_allocate(struct super_block *sb, int group,
 
 	for (; num < *count && grp_goal < end; grp_goal++) {
 		if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group),
-					grp_goal, bitmap_bh->b_data)) {
+					grp_goal, bitmap_buf->b_data)) {
 			if (num == 0)
 				continue;
 			break;
@@ -869,7 +857,7 @@ static int find_next_reservable_window(
  */
 static int alloc_new_reservation(struct ext2_reserve_window_node *my_rsv,
 		ext2_grpblk_t grp_goal, struct super_block *sb,
-		unsigned int group, struct buffer_head *bitmap_bh)
+		unsigned int group, struct ext2_buffer *bitmap_buf)
 {
 	struct ext2_reserve_window_node *search_head;
 	ext2_fsblk_t group_first_block, group_end_block, start_block;
@@ -960,7 +948,7 @@ static int alloc_new_reservation(struct ext2_reserve_window_node *my_rsv,
 	spin_unlock(rsv_lock);
 	first_free_block = bitmap_search_next_usable_block(
 			my_rsv->rsv_start - group_first_block,
-			bitmap_bh, group_end_block - group_first_block + 1);
+			bitmap_buf, group_end_block - group_first_block + 1);
 
 	if (first_free_block < 0) {
 		/*
@@ -1062,7 +1050,7 @@ static void try_to_extend_reservation(struct ext2_reserve_window_node *my_rsv,
  */
 static ext2_grpblk_t
 ext2_try_to_allocate_with_rsv(struct super_block *sb, unsigned int group,
-			struct buffer_head *bitmap_bh, ext2_grpblk_t grp_goal,
+			struct ext2_buffer *bitmap_buf, ext2_grpblk_t grp_goal,
 			struct ext2_reserve_window_node * my_rsv,
 			unsigned long *count)
 {
@@ -1077,7 +1065,7 @@ ext2_try_to_allocate_with_rsv(struct super_block *sb, unsigned int group,
 	 * or last attempt to allocate a block with reservation turned on failed
 	 */
 	if (my_rsv == NULL) {
-		return ext2_try_to_allocate(sb, group, bitmap_bh,
+		return ext2_try_to_allocate(sb, group, bitmap_buf,
 						grp_goal, count, NULL);
 	}
 	/*
@@ -1111,7 +1099,7 @@ ext2_try_to_allocate_with_rsv(struct super_block *sb, unsigned int group,
 			if (my_rsv->rsv_goal_size < *count)
 				my_rsv->rsv_goal_size = *count;
 			ret = alloc_new_reservation(my_rsv, grp_goal, sb,
-							group, bitmap_bh);
+							group, bitmap_buf);
 			if (ret < 0)
 				break;			/* failed */
 
@@ -1137,7 +1125,7 @@ ext2_try_to_allocate_with_rsv(struct super_block *sb, unsigned int group,
 			rsv_window_dump(&EXT2_SB(sb)->s_rsv_window_root, 1);
 			return -1;
 		}
-		ret = ext2_try_to_allocate(sb, group, bitmap_bh, grp_goal,
+		ret = ext2_try_to_allocate(sb, group, bitmap_buf, grp_goal,
 					   &num, &my_rsv->rsv_window);
 		if (ret >= 0) {
 			my_rsv->rsv_alloc_hit += num;
@@ -1208,7 +1196,7 @@ int ext2_data_block_valid(struct ext2_sb_info *sbi, ext2_fsblk_t start_blk,
 ext2_fsblk_t ext2_new_blocks(struct inode *inode, ext2_fsblk_t goal,
 		    unsigned long *count, int *errp, unsigned int flags)
 {
-	struct buffer_head *bitmap_bh = NULL;
+	struct ext2_buffer *bitmap_buf = NULL;
 	struct ext2_buffer *gdp_buf;
 	int group_no;
 	int goal_group;
@@ -1297,12 +1285,12 @@ ext2_fsblk_t ext2_new_blocks(struct inode *inode, ext2_fsblk_t goal,
 		 * pointer and we have to release it before calling
 		 * read_block_bitmap().
 		 */
-		brelse(bitmap_bh);
-		bitmap_bh = read_block_bitmap(sb, group_no);
-		if (!bitmap_bh)
+		ext2_put_buffer(sb, bitmap_buf);
+		bitmap_buf = read_block_bitmap(sb, group_no);
+		if (IS_ERR(bitmap_buf))
 			goto io_error;
 		grp_alloc_blk = ext2_try_to_allocate_with_rsv(sb, group_no,
-					bitmap_bh, grp_target_blk,
+					bitmap_buf, grp_target_blk,
 					my_rsv, &num);
 		if (grp_alloc_blk >= 0)
 			goto allocated;
@@ -1338,15 +1326,15 @@ ext2_fsblk_t ext2_new_blocks(struct inode *inode, ext2_fsblk_t goal,
 		if (my_rsv && (free_blocks <= (windowsz/2)))
 			continue;
 
-		brelse(bitmap_bh);
-		bitmap_bh = read_block_bitmap(sb, group_no);
-		if (!bitmap_bh)
+		ext2_put_buffer(sb, bitmap_buf);
+		bitmap_buf = read_block_bitmap(sb, group_no);
+		if (IS_ERR(bitmap_buf))
 			goto io_error;
 		/*
 		 * try to allocate block(s) from this group, without a goal(-1).
 		 */
 		grp_alloc_blk = ext2_try_to_allocate_with_rsv(sb, group_no,
-					bitmap_bh, -1, my_rsv, &num);
+					bitmap_buf, -1, my_rsv, &num);
 		if (grp_alloc_blk >= 0)
 			goto allocated;
 	}
@@ -1406,12 +1394,12 @@ ext2_fsblk_t ext2_new_blocks(struct inode *inode, ext2_fsblk_t goal,
 	group_adjust_blocks(sb, group_no, gdp, gdp_buf, -num);
 	percpu_counter_sub(&sbi->s_freeblocks_counter, num);
 
-	mark_buffer_dirty(bitmap_bh);
+	ext2_buffer_set_dirty(bitmap_buf);
 	if (sb->s_flags & SB_SYNCHRONOUS)
-		sync_dirty_buffer(bitmap_bh);
+		ext2_sync_buffer_wait(sb, bitmap_buf);
 
 	*errp = 0;
-	brelse(bitmap_bh);
+	ext2_put_buffer(sb, bitmap_buf);
 	if (num < *count) {
 		dquot_free_block_nodirty(inode, *count-num);
 		mark_inode_dirty(inode);
@@ -1429,7 +1417,7 @@ ext2_fsblk_t ext2_new_blocks(struct inode *inode, ext2_fsblk_t goal,
 		dquot_free_block_nodirty(inode, *count);
 		mark_inode_dirty(inode);
 	}
-	brelse(bitmap_bh);
+	ext2_put_buffer(sb, bitmap_buf);
 	return 0;
 }
 
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ