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]
Date:	Sun, 11 Mar 2012 03:51:05 -0600
From:	Andreas Dilger <adilger@...ger.ca>
To:	Sami Liedes <sami.liedes@....fi>
Cc:	linux-ext4@...r.kernel.org
Subject: Re: [PATCH 4/5] libext2fs: Implement ext2fs_find_first_zero_generic_bmap().

On 2012-03-10, at 2:37 PM, Sami Liedes wrote:
> From a58c07c019e4a7e6181f021ae022ebcdc5cce4e2 Mon Sep 17 00:00:00 2001
> From: Sami Liedes <sami.liedes@....fi>
> Date: Sat, 10 Mar 2012 22:36:12 +0200
> Subject: [PATCH] libext2fs: Implement ext2fs_find_first_zero_generic_bmap().
> 
> This function searches a bitmap for the first zero bit within a range.
> It checks if there is a bitmap backend specific implementation
> available (if the relevant field in bitmap_ops is non-NULL). If not,
> it uses a generic and slow method by repeatedly calling test_bmap() in
> a loop. Also change ext2fs_new_inode() to use this new function.
> 
> This change in itself does not result in a large speedup, rather it
> refactors the code in preparation for the introduction of a faster
> find_first_zero() for bitarray based bitmaps.

Rather than making the bitmap searching loop more efficient, I've always thought
it would be better to have an interface that iterates over the bitmap and returns
the next set bit.  It is similar to what you implemented with ->find_first_zero(),
but it would be better to have (IMHO) ->find_next_zero() and ->find_next_set().

This allows the internal bitmap implementation to do efficient walking of the
bitmap/tree/list and in cases where the bitmap is very sparse it can avoid a
lot of scanning.

> Signed-off-by: Sami Liedes <sami.liedes@....fi>
> 
> diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
> index eb4e0f5..1da9532 100644
> --- a/lib/ext2fs/alloc.c
> +++ b/lib/ext2fs/alloc.c
> @@ -109,7 +109,8 @@ errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
> 	ext2_ino_t	dir_group = 0;
> 	ext2_ino_t	i;
> 	ext2_ino_t	start_inode;
> -	ext2_ino_t	modulo;
> +	ext2_ino_t	modulo, upto, first_zero;
> +	errcode_t	err;
> 
> 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
> 
> @@ -128,16 +129,27 @@ errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
> 		return EXT2_ET_INODE_ALLOC_FAIL;
> 	i = start_inode;
> 	modulo = (i - 1) % EXT2_INODES_PER_GROUP(fs->super);
> -
> 	do {
> 		if (modulo == 0)
> 			check_inode_uninit(fs, map, (i - 1) /
> 					   EXT2_INODES_PER_GROUP(fs->super));
> 
> -		if (!ext2fs_fast_test_inode_bitmap2(map, i))
> +		upto = i + (EXT2_INODES_PER_GROUP(fs->super) - modulo);
> +		if (i < start_inode && upto >= start_inode)
> +			upto = start_inode - 1;
> +		if (upto > fs->super->s_inodes_count)
> +			upto = fs->super->s_inodes_count;
> +
> +		err = ext2fs_find_first_zero_inode_bitmap2(map, i, upto, &first_zero);
> +		if (!err) {
> +			i = first_zero;
> 			break;
> -		if (++modulo == EXT2_INODES_PER_GROUP(fs->super))
> -			modulo = 0;
> +		} else {
> +			if (err != ENOENT)
> +				return EXT2_ET_INODE_ALLOC_FAIL;
> +			i = upto;
> +		}
> +
> 		if (++i > fs->super->s_inodes_count) {
> 			i = EXT2_FIRST_INODE(fs->super);
> 			modulo = (i - 1) % EXT2_INODES_PER_GROUP(fs->super);
> diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h
> index 83a01e4..70caa86 100644
> --- a/lib/ext2fs/bitops.h
> +++ b/lib/ext2fs/bitops.h
> @@ -188,6 +188,9 @@ extern void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
> 					    blk64_t block, unsigned int num);
> extern void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
> 					      blk64_t block, unsigned int num);
> +extern errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
> +						     __u64 start, __u64 end,
> +						     __u64 *out);
> 
> /*
>  * The inline routines themselves...
> @@ -593,6 +596,19 @@ _INLINE_ int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
> 					inode);
> }
> 
> +_INLINE_ errcode_t ext2fs_find_first_zero_inode_bitmap2(ext2fs_inode_bitmap bitmap,
> +							ext2_ino_t start,
> +							ext2_ino_t end,
> +							ext2_ino_t *out)
> +{
> +	__u64 o;
> +	errcode_t rv = ext2fs_find_first_zero_generic_bmap((ext2fs_generic_bitmap) bitmap,
> +							   start, end, &o);
> +	if (!rv)
> +		*out = o;
> +	return rv;
> +}
> +
> _INLINE_ blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap)
> {
> 	return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap);
> diff --git a/lib/ext2fs/bmap64.h b/lib/ext2fs/bmap64.h
> index 288e1b6..f44d379 100644
> --- a/lib/ext2fs/bmap64.h
> +++ b/lib/ext2fs/bmap64.h
> @@ -89,6 +89,11 @@ struct ext2_bitmap_ops {
> 				    __u64 start, size_t num, void *out);
> 	void (*clear_bmap)(ext2fs_generic_bitmap bitmap);
> 	void (*print_stats)(ext2fs_generic_bitmap);
> +
> +	/* Find the first zero bit between start and end, inclusive.
> +	 * May be NULL, in which case a generic function is used. */
> +	errcode_t (*find_first_zero)(ext2fs_generic_bitmap bitmap,
> +				     __u64 start, __u64 end, __u64 *out);
> };
> 
> extern struct ext2_bitmap_ops ext2fs_blkmap64_bitarray;
> diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c
> index fa8d7b7..b57df54 100644
> --- a/lib/ext2fs/gen_bitmap64.c
> +++ b/lib/ext2fs/gen_bitmap64.c
> @@ -762,3 +762,31 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
> 	*bitmap = cmap;
> 	return 0;
> }
> +
> +errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
> +					      __u64 start, __u64 end, __u64 *out)
> +{
> +	int b;
> +
> +	if (bitmap->bitmap_ops->find_first_zero)
> +		return bitmap->bitmap_ops->find_first_zero(bitmap, start, end, out);
> +
> +	if (!bitmap || !EXT2FS_IS_64_BITMAP(bitmap) || bitmap->cluster_bits)
> +		return EINVAL;
> +
> +	if (start < bitmap->start || end > bitmap->end || start > end) {
> +		warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
> +		return EINVAL;
> +	}
> +
> +	while (start <= end) {
> +		b = bitmap->bitmap_ops->test_bmap(bitmap, start);
> +		if (!b) {
> +			*out = start;
> +			return 0;
> +		}
> +		start++;
> +	}
> +
> +	return ENOENT;
> +}


Cheers, Andreas





--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ