1e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 2e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * blkmap64_ba.c --- Simple bitarray implementation for bitmaps 3e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 4e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Copyright (C) 2008 Theodore Ts'o. 5e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 6e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * %Begin-Header% 7e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * This file may be redistributed under the terms of the GNU Public 8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * License. 9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * %End-Header% 10e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdio.h> 13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <string.h> 14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if HAVE_UNISTD_H 15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <unistd.h> 16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <fcntl.h> 18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <time.h> 19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if HAVE_SYS_STAT_H 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/stat.h> 21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if HAVE_SYS_TYPES_H 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/types.h> 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "ext2_fs.h" 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "ext2fsP.h" 28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "bmap64.h" 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Private data for bit array implementation of bitmap ops. 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Currently, this is just a pointer to our big flat hunk of memory, 33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * exactly equivalent to the old-skool char * bitmap member. 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct ext2fs_ba_private_struct { 37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *bitarray; 38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgralltypedef struct ext2fs_ba_private_struct *ext2fs_ba_private; 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t ba_alloc_private_data (ext2fs_generic_bitmap bitmap) 43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp; 45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval; 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_t size; 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Since we only have the one pointer, we could just shove our 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * private data in the void *private field itself, but then 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * we'd have to do a fair bit of rewriting if we ever added a 52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * field. I'm agnostic. 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_get_mem(sizeof (ext2fs_ba_private), &bp); 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_get_mem(size, &bp->bitarray); 61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) { 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_mem(&bp); 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bp = 0; 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitmap->private = (void *) bp; 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t ba_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)), 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_generic_bitmap bitmap) 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp; 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval; 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_t size; 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ba_alloc_private_data (bitmap); 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bp = (ext2fs_ba_private) bitmap->private; 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(bp->bitarray, 0, size); 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void ba_free_bmap(ext2fs_generic_bitmap bitmap) 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!bp) 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (bp->bitarray) { 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_mem (&bp->bitarray); 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bp->bitarray = 0; 98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_mem (&bp); 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bp = 0; 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t ba_copy_bmap(ext2fs_generic_bitmap src, 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_generic_bitmap dest) 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private src_bp = (ext2fs_ba_private) src->private; 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private dest_bp; 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval; 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_t size; 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ba_alloc_private_data (dest); 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dest_bp = (ext2fs_ba_private) dest->private; 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size = (size_t) (((src->real_end - src->start) / 8) + 1); 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memcpy (dest_bp->bitarray, src_bp->bitarray, size); 119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t ba_resize_bmap(ext2fs_generic_bitmap bmap, 124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 new_end, __u64 new_real_end) 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bmap->private; 127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval; 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_t size, new_size; 129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 bitno; 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If we're expanding the bitmap, make sure all of the new 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * parts of the bitmap are zero. 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (new_end > bmap->end) { 136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitno = bmap->real_end; 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (bitno > new_end) 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitno = new_end; 139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (; bitno > bmap->end; bitno--) 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_clear_bit64(bitno - bmap->start, bp->bitarray); 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (new_real_end == bmap->real_end) { 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bmap->end = new_end; 144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size = ((bmap->real_end - bmap->start) / 8) + 1; 148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_size = ((new_real_end - bmap->start) / 8) + 1; 149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (size != new_size) { 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_resize_mem(size, new_size, &bp->bitarray); 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (new_size > size) 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(bp->bitarray + size, 0, new_size - size); 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bmap->end = new_end; 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bmap->real_end = new_real_end; 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int ba_mark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg) 165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t bitno = (blk64_t) arg; 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_set_bit64(bitno - bitmap->start, bp->bitarray); 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int ba_unmark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg) 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t bitno = (blk64_t) arg; 176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_clear_bit64(bitno - bitmap->start, bp->bitarray); 178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int ba_test_bmap(ext2fs_generic_bitmap bitmap, __u64 arg) 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t bitno = (blk64_t) arg; 184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_test_bit64(bitno - bitmap->start, bp->bitarray); 186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void ba_mark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg, 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int num) 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t bitno = (blk64_t) arg; 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int i; 194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < num; i++) 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_fast_set_bit64(bitno + i - bitmap->start, bp->bitarray); 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void ba_unmark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg, 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int num) 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t bitno = (blk64_t) arg; 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int i; 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < num; i++) 207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_fast_clear_bit64(bitno + i - bitmap->start, bp->bitarray); 208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int ba_test_clear_bmap_extent(ext2fs_generic_bitmap bitmap, 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 start, unsigned int len) 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 start_byte, len_byte = len >> 3; 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int start_bit, len_bit = len % 8; 216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int first_bit = 0; 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int last_bit = 0; 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int mark_count = 0; 219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int mark_bit = 0; 220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i; 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *ADDR; 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ADDR = bp->bitarray; 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall start -= bitmap->start; 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall start_byte = start >> 3; 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall start_bit = start % 8; 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (start_bit != 0) { 229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * The compared start block number or start inode number 231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * is not the first bit in a byte. 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mark_count = 8 - start_bit; 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (len < 8 - start_bit) { 235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mark_count = (int)len; 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mark_bit = len + start_bit - 1; 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mark_bit = 7; 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = mark_count; i > 0; i--, mark_bit--) 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall first_bit |= 1 << mark_bit; 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Compare blocks or inodes in the first byte. 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If there is any marked bit, this function returns 0. 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (first_bit & ADDR[start_byte]) 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (len <= 8 - start_bit) 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 1; 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall start_byte++; 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall len_bit = (len - mark_count) % 8; 254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall len_byte = (len - mark_count) >> 3; 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * The compared start block number or start inode number is 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * the first bit in a byte. 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (len_bit != 0) { 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * The compared end block number or end inode number is 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * not the last bit in a byte. 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--) 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall last_bit |= 1 << mark_bit; 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Compare blocks or inodes in the last byte. 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If there is any marked bit, this function returns 0. 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (last_bit & ADDR[start_byte + len_byte]) 274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (len_byte == 0) 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 1; 277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Check whether all bytes are 0 */ 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_mem_is_zero(ADDR + start_byte, len_byte); 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t ba_set_bmap_range(ext2fs_generic_bitmap bitmap, 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 start, size_t num, void *in) 286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memcpy (bp->bitarray + (start >> 3), in, (num + 7) >> 3); 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t ba_get_bmap_range(ext2fs_generic_bitmap bitmap, 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 start, size_t num, void *out) 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memcpy (out, bp->bitarray + (start >> 3), (num + 7) >> 3); 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void ba_clear_bmap(ext2fs_generic_bitmap bitmap) 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(bp->bitarray, 0, 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void ba_print_stats(ext2fs_generic_bitmap bitmap) 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "%16llu Bytes used by bitarray\n", 315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((bitmap->real_end - bitmap->start) >> 3) + 1 + 316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct ext2fs_ba_private_struct)); 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Find the first zero bit between start and end, inclusive. */ 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t ba_find_first_zero(ext2fs_generic_bitmap bitmap, 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 start, __u64 end, __u64 *out) 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private; 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long bitpos = start - bitmap->start; 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long count = end - start + 1; 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int byte_found = 0; /* whether a != 0xff byte has been found */ 327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const unsigned char *pos; 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long max_loop_count, i; 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (start < bitmap->start || end > bitmap->end || start > end) 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return EINVAL; 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (bitmap->cluster_bits) 334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return EINVAL; 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* scan bits until we hit a byte boundary */ 337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((bitpos & 0x7) != 0 && count > 0) { 338e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ext2fs_test_bit64(bitpos, bp->bitarray)) { 339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *out = bitpos + bitmap->start; 340e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 341e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 342e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitpos++; 343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall count--; 344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!count) 347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ENOENT; 348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3); 350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* scan bytes until 8-byte (64-bit) aligned */ 351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (count >= 8 && (((unsigned long)pos) & 0x07)) { 352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*pos != 0xff) { 353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall byte_found = 1; 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pos++; 357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall count -= 8; 358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitpos += 8; 359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!byte_found) { 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall max_loop_count = count >> 6; /* 8-byte blocks */ 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i = max_loop_count; 364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (i) { 365e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*((const __u64 *)pos) != ((__u64)-1)) 366e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 367e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pos += 8; 368e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i--; 369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall count -= 64 * (max_loop_count - i); 371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitpos += 64 * (max_loop_count - i); 372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall max_loop_count = count >> 3; 374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i = max_loop_count; 375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (i) { 376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*pos != 0xff) { 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall byte_found = 1; 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pos++; 381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i--; 382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall count -= 8 * (max_loop_count - i); 384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitpos += 8 * (max_loop_count - i); 385e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Here either count < 8 or byte_found == 1. */ 388e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (count-- > 0) { 389e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ext2fs_test_bit64(bitpos, bp->bitarray)) { 390e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *out = bitpos + bitmap->start; 391e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 392e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bitpos++; 394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ENOENT; 397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 398e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct ext2_bitmap_ops ext2fs_blkmap64_bitarray = { 400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .type = EXT2FS_BMAP64_BITARRAY, 401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .new_bmap = ba_new_bmap, 402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .free_bmap = ba_free_bmap, 403e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .copy_bmap = ba_copy_bmap, 404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .resize_bmap = ba_resize_bmap, 405e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .mark_bmap = ba_mark_bmap, 406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .unmark_bmap = ba_unmark_bmap, 407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .test_bmap = ba_test_bmap, 408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .test_clear_bmap_extent = ba_test_clear_bmap_extent, 409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .mark_bmap_extent = ba_mark_bmap_extent, 410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .unmark_bmap_extent = ba_unmark_bmap_extent, 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .set_bmap_range = ba_set_bmap_range, 412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .get_bmap_range = ba_get_bmap_range, 413e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .clear_bmap = ba_clear_bmap, 414e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .print_stats = ba_print_stats, 415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall .find_first_zero = ba_find_first_zero 416e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 417