summaryrefslogtreecommitdiff
path: root/lib/ext2fs/gen_bitmap64.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext2fs/gen_bitmap64.c')
-rw-r--r--lib/ext2fs/gen_bitmap64.c138
1 files changed, 126 insertions, 12 deletions
diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c
index b57df546..af550972 100644
--- a/lib/ext2fs/gen_bitmap64.c
+++ b/lib/ext2fs/gen_bitmap64.c
@@ -128,6 +128,7 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
if (gettimeofday(&bitmap->stats.created,
(struct timezone *) NULL) == -1) {
perror("gettimeofday");
+ ext2fs_free_mem(&bitmap);
return 1;
}
bitmap->stats.type = type;
@@ -174,11 +175,13 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
}
#ifdef BMAP_STATS
-void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap)
+static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap)
{
struct ext2_bmap_statistics *stats = &bitmap->stats;
+#ifdef BMAP_STATS_OPS
float mark_seq_perc = 0.0, test_seq_perc = 0.0;
float mark_back_perc = 0.0, test_back_perc = 0.0;
+#endif
double inuse;
struct timeval now;
@@ -298,6 +301,7 @@ errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
if (gettimeofday(&new_bmap->stats.created,
(struct timezone *) NULL) == -1) {
perror("gettimeofday");
+ ext2fs_free_mem(&new_bmap);
return 1;
}
new_bmap->stats.type = src->stats.type;
@@ -622,6 +626,8 @@ void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t block, unsigned int num)
{
+ __u64 end = block + num;
+
if (!bmap)
return EINVAL;
@@ -644,12 +650,26 @@ int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
INC_STAT(bmap, test_ext_count);
+ /* convert to clusters if necessary */
+ block >>= bmap->cluster_bits;
+ end += (1 << bmap->cluster_bits) - 1;
+ end >>= bmap->cluster_bits;
+ num = end - block;
+
+ if ((block < bmap->start) || (block+num-1 > bmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block,
+ bmap->description);
+ return EINVAL;
+ }
+
return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
}
void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t block, unsigned int num)
{
+ __u64 end = block + num;
+
if (!bmap)
return;
@@ -668,6 +688,12 @@ void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
INC_STAT(bmap, mark_ext_count);
+ /* convert to clusters if necessary */
+ block >>= bmap->cluster_bits;
+ end += (1 << bmap->cluster_bits) - 1;
+ end >>= bmap->cluster_bits;
+ num = end - block;
+
if ((block < bmap->start) || (block+num-1 > bmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
bmap->description);
@@ -680,6 +706,8 @@ void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t block, unsigned int num)
{
+ __u64 end = block + num;
+
if (!bmap)
return;
@@ -698,6 +726,12 @@ void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
INC_STAT(bmap, unmark_ext_count);
+ /* convert to clusters if necessary */
+ block >>= bmap->cluster_bits;
+ end += (1 << bmap->cluster_bits) - 1;
+ end >>= bmap->cluster_bits;
+ num = end - block;
+
if ((block < bmap->start) || (block+num-1 > bmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
bmap->description);
@@ -766,27 +800,107 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out)
{
- int b;
+ __u64 cstart, cend, cout;
+ errcode_t retval;
- if (bitmap->bitmap_ops->find_first_zero)
- return bitmap->bitmap_ops->find_first_zero(bitmap, start, end, out);
+ if (!bitmap)
+ return EINVAL;
+
+ if (EXT2FS_IS_32_BITMAP(bitmap)) {
+ blk_t blk = 0;
- if (!bitmap || !EXT2FS_IS_64_BITMAP(bitmap) || bitmap->cluster_bits)
+ if (((start) & ~0xffffffffULL) ||
+ ((end) & ~0xffffffffULL)) {
+ ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
+ return EINVAL;
+ }
+
+ retval = ext2fs_find_first_zero_generic_bitmap(bitmap, start,
+ end, &blk);
+ if (retval == 0)
+ *out = blk;
+ return retval;
+ }
+
+ if (!EXT2FS_IS_64_BITMAP(bitmap))
return EINVAL;
- if (start < bitmap->start || end > bitmap->end || start > end) {
+ cstart = start >> bitmap->cluster_bits;
+ cend = end >> bitmap->cluster_bits;
+
+ if (cstart < bitmap->start || cend > 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;
+ if (bitmap->bitmap_ops->find_first_zero) {
+ retval = bitmap->bitmap_ops->find_first_zero(bitmap, cstart,
+ cend, &cout);
+ if (retval)
+ return retval;
+ found:
+ cout <<= bitmap->cluster_bits;
+ *out = (cout >= start) ? cout : start;
+ return 0;
+ }
+
+ for (cout = cstart; cout <= cend; cout++)
+ if (!bitmap->bitmap_ops->test_bmap(bitmap, cout))
+ goto found;
+
+ return ENOENT;
+}
+
+errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
+ __u64 start, __u64 end, __u64 *out)
+{
+ __u64 cstart, cend, cout;
+ errcode_t retval;
+
+ if (!bitmap)
+ return EINVAL;
+
+ if (EXT2FS_IS_32_BITMAP(bitmap)) {
+ blk_t blk = 0;
+
+ if (((start) & ~0xffffffffULL) ||
+ ((end) & ~0xffffffffULL)) {
+ ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
+ return EINVAL;
}
- start++;
+
+ retval = ext2fs_find_first_set_generic_bitmap(bitmap, start,
+ end, &blk);
+ if (retval == 0)
+ *out = blk;
+ return retval;
}
+ if (!EXT2FS_IS_64_BITMAP(bitmap))
+ return EINVAL;
+
+ cstart = start >> bitmap->cluster_bits;
+ cend = end >> bitmap->cluster_bits;
+
+ if (cstart < bitmap->start || cend > bitmap->end || start > end) {
+ warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
+ return EINVAL;
+ }
+
+ if (bitmap->bitmap_ops->find_first_set) {
+ retval = bitmap->bitmap_ops->find_first_set(bitmap, cstart,
+ cend, &cout);
+ if (retval)
+ return retval;
+ found:
+ cout <<= bitmap->cluster_bits;
+ *out = (cout >= start) ? cout : start;
+ return 0;
+ }
+
+ for (cout = cstart; cout <= cend; cout++)
+ if (bitmap->bitmap_ops->test_bmap(bitmap, cout))
+ goto found;
+
return ENOENT;
}