linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sami Liedes <sami.liedes@iki.fi>
To: linux-ext4@vger.kernel.org
Subject: [PATCH 5/5] libext2fs: Implement fast find_first_zero() for bitarray bitmaps.
Date: Sat, 10 Mar 2012 23:38:40 +0200	[thread overview]
Message-ID: <20120310213840.GP6961@sli.dy.fi> (raw)
In-Reply-To: <20120310213321.GK6961@sli.dy.fi>

[-- Attachment #1: Type: text/plain, Size: 3001 bytes --]

From 020d7721d9de525e511b4778795d375675160844 Mon Sep 17 00:00:00 2001
From: Sami Liedes <sami.liedes@iki.fi>
Date: Sat, 10 Mar 2012 22:50:51 +0200
Subject: [PATCH] libext2fs: Implement fast find_first_zero() for bitarray
 bitmaps.

With this change the CPU time needed to shrink a 100G filesystem drops
to 0.8% of the original (17 CPU seconds instead of 2057).

Signed-off-by: Sami Liedes <sami.liedes@iki.fi>

diff --git a/lib/ext2fs/blkmap64_ba.c b/lib/ext2fs/blkmap64_ba.c
index 3f0c643..8eddde9 100644
--- a/lib/ext2fs/blkmap64_ba.c
+++ b/lib/ext2fs/blkmap64_ba.c
@@ -317,6 +317,86 @@ static void ba_print_stats(ext2fs_generic_bitmap bitmap)
 		sizeof(struct ext2fs_ba_private_struct));
 }
 
+/* Find the first zero bit between start and end, inclusive. */
+static errcode_t ba_find_first_zero(ext2fs_generic_bitmap bitmap,
+				    __u64 start, __u64 end, __u64 *out)
+{
+	ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
+	unsigned long bitpos = start - bitmap->start;
+	unsigned long count = end - start + 1;
+	int byte_found = 0; /* whether a != 0xff byte has been found */
+	const unsigned char *pos;
+	unsigned long max_loop_count, i;
+
+	if (start < bitmap->start || end > bitmap->end || start > end)
+		return EINVAL;
+
+	if (bitmap->cluster_bits)
+		return EINVAL;
+
+	/* scan bits until we hit a byte boundary */
+	while ((bitpos & 0x7) != 0 && count > 0) {
+		if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
+			*out = bitpos + bitmap->start;
+			return 0;
+		}
+		bitpos++;
+		count--;
+	}
+
+	if (!count)
+		return ENOENT;
+
+	pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
+	/* scan bytes until 8-byte (64-bit) aligned */
+	while (count >= 8 && (((unsigned long)pos) & 0x07)) {
+		if (*pos != 0xff) {
+			byte_found = 1;
+			break;
+		}
+		pos++;
+		count -= 8;
+		bitpos += 8;
+	}
+
+	if (!byte_found) {
+		max_loop_count = count >> 6; /* 8-byte blocks */
+		i = max_loop_count;
+		while (i) {
+			if (*((const __u64 *)pos) != ((__u64)-1))
+				break;
+			pos += 8;
+			i--;
+		}
+		count -= 64 * (max_loop_count - i);
+		bitpos += 64 * (max_loop_count - i);
+
+		max_loop_count = count >> 3;
+		i = max_loop_count;
+		while (i) {
+			if (*pos != 0xff) {
+				byte_found = 1;
+				break;
+			}
+			pos++;
+			i--;
+		}
+		count -= 8 * (max_loop_count - i);
+		bitpos += 8 * (max_loop_count - i);
+	}
+
+	/* Here either count < 8 or byte_found == 1. */
+	while (count-- > 0) {
+		if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
+			*out = bitpos + bitmap->start;
+			return 0;
+		}
+		bitpos++;
+	}
+
+	return ENOENT;
+}
+
 struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
 	.type = EXT2FS_BMAP64_BITARRAY,
 	.new_bmap = ba_new_bmap,
@@ -333,4 +413,5 @@ struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
 	.get_bmap_range = ba_get_bmap_range,
 	.clear_bmap = ba_clear_bmap,
 	.print_stats = ba_print_stats,
+	.find_first_zero = ba_find_first_zero
 };

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

  parent reply	other threads:[~2012-03-10 21:38 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-10 21:33 [PATCH 0/5] Make filesystem shrinking faster and less CPU-intensive Sami Liedes
2012-03-10 21:34 ` [PATCH 1/5] libext2fs: Move a modulo operation out of a hot loop Sami Liedes
2012-03-11  9:50   ` Andreas Dilger
2012-03-10 21:35 ` [PATCH 2/5] resize2fs: Use EXT2_FLAG_64BITS Sami Liedes
2012-03-10 21:36 ` [PATCH 3/5] libext2fs: Document EXT2_FLAG_64BITS in ext2fs_open2() Sami Liedes
2012-03-10 21:37 ` [PATCH 4/5] libext2fs: Implement ext2fs_find_first_zero_generic_bmap() Sami Liedes
2012-03-11  9:51   ` Andreas Dilger
2012-03-12 19:15     ` Sami Liedes
2012-03-12 23:09       ` Andreas Dilger
2012-03-23 22:33       ` Ted Ts'o
2012-03-26 13:53         ` Sami Liedes
2012-03-26 15:34           ` Ted Ts'o
2012-03-26  2:39   ` Ted Ts'o
2012-03-10 21:38 ` Sami Liedes [this message]
2012-03-26  2:34   ` [PATCH 5/5] libext2fs: Implement fast find_first_zero() for bitarray bitmaps Ted Ts'o
2012-03-26 13:22     ` Sami Liedes
2012-03-26 15:26       ` Ted Ts'o

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120310213840.GP6961@sli.dy.fi \
    --to=sami.liedes@iki.fi \
    --cc=linux-ext4@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).