diff options
author | Kevin | 2014-11-15 11:48:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 11:48:36 +0800 |
commit | d04075478d378d9e15f3e1abfd14b0bd124077d4 (patch) | |
tree | 733dd964582f388b9e3e367c249946cd32a2851f /fs/ext4/format/gen_bitmap.c | |
download | FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.gz FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.bz2 FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.zip |
init commit via android 4.4 uboot
Diffstat (limited to 'fs/ext4/format/gen_bitmap.c')
-rwxr-xr-x | fs/ext4/format/gen_bitmap.c | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/fs/ext4/format/gen_bitmap.c b/fs/ext4/format/gen_bitmap.c new file mode 100755 index 0000000..a3e387b --- /dev/null +++ b/fs/ext4/format/gen_bitmap.c @@ -0,0 +1,456 @@ +/* + * gen_bitmap.c --- Generic (32-bit) bitmap routines + * + * Copyright (C) 2001 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + + +#include <common.h> +//#include <ext_common.h> +//#include <ext4fs.h> +#include <malloc.h> +#include <stddef.h> +#include <linux/stat.h> +#include <linux/time.h> + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct ext2fs_struct_generic_bitmap { + errcode_t magic; + ext2_filsys fs; + __u32 start, end; + __u32 real_end; + char * description; + char * bitmap; + errcode_t base_error_code; + __u32 reserved[7]; +}; + +/* + * Used by previously inlined function, so we have to export this and + * not change the function signature + */ +void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, + int code, unsigned long arg) +{ + printf("ext2fs error code 0x%x, arg %lu\n", code, arg); +} + +static errcode_t check_magic(ext2fs_generic_bitmap bitmap) +{ + if (!bitmap || !((bitmap->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || + (bitmap->magic == EXT2_ET_MAGIC_INODE_BITMAP) || + (bitmap->magic == EXT2_ET_MAGIC_BLOCK_BITMAP))) + return EXT2_ET_MAGIC_GENERIC_BITMAP; + return 0; +} + +errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs, + __u32 start, __u32 end, __u32 real_end, + const char *descr, char *init_map, + ext2fs_generic_bitmap *ret) +{ + ext2fs_generic_bitmap bitmap; + errcode_t retval; + size_t size; + + retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap), + &bitmap); + if (retval) + return retval; + + bitmap->magic = magic; + bitmap->fs = fs; + bitmap->start = start; + bitmap->end = end; + bitmap->real_end = real_end; + switch (magic) { + case EXT2_ET_MAGIC_INODE_BITMAP: + bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK; + break; + case EXT2_ET_MAGIC_BLOCK_BITMAP: + bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK; + break; + default: + bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK; + } + if (descr) { + retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description); + if (retval) { + ext2fs_free_mem(&bitmap); + return retval; + } + strcpy(bitmap->description, descr); + } else + bitmap->description = 0; + + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); + /* Round up to allow for the BT x86 instruction */ + size = (size + 7) & ~3; + retval = ext2fs_get_mem(size, &bitmap->bitmap); + if (retval) { + ext2fs_free_mem(&bitmap->description); + ext2fs_free_mem(&bitmap); + return retval; + } + + if (init_map) + memcpy(bitmap->bitmap, init_map, size); + else + memset(bitmap->bitmap, 0, size); + *ret = bitmap; + return 0; +} + +errcode_t ext2fs_allocate_generic_bitmap(__u32 start, + __u32 end, + __u32 real_end, + const char *descr, + ext2fs_generic_bitmap *ret) +{ + return ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_GENERIC_BITMAP, 0, + start, end, real_end, descr, 0, ret); +} + +errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest) +{ + return (ext2fs_make_generic_bitmap(src->magic, src->fs, + src->start, src->end, + src->real_end, + src->description, src->bitmap, + dest)); +} + +void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap) +{ + if (check_magic(bitmap)) + return; + + bitmap->magic = 0; + if (bitmap->description) { + ext2fs_free_mem(&bitmap->description); + bitmap->description = 0; + } + if (bitmap->bitmap) { + ext2fs_free_mem(&bitmap->bitmap); + bitmap->bitmap = 0; + } + ext2fs_free_mem(&bitmap); +} + +int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno) +{ + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno); + return 0; + } + return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap); +} + +int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 bitno) +{ + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno); + return 0; + } + return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap); +} + +int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno) +{ + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno); + return 0; + } + return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap); +} + +__u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap) +{ + return bitmap->start; +} + +__u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap) +{ + return bitmap->end; +} + +void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap) +{ + if (check_magic(bitmap)) + return; + + memset(bitmap->bitmap, 0, + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); +} + +errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap, + errcode_t magic, errcode_t neq, + ext2_ino_t end, ext2_ino_t *oend) +{ + EXT2_CHECK_MAGIC(bitmap, magic); + + if (end > bitmap->real_end) + return neq; + if (oend) + *oend = bitmap->end; + bitmap->end = end; + return 0; +} + +errcode_t ext2fs_resize_generic_bitmap(errcode_t magic, + __u32 new_end, __u32 new_real_end, + ext2fs_generic_bitmap bmap) +{ + errcode_t retval; + size_t size, new_size; + __u32 bitno; + + if (!bmap || (bmap->magic != magic)) + return magic; + + /* + * If we're expanding the bitmap, make sure all of the new + * parts of the bitmap are zero. + */ + if (new_end > bmap->end) { + bitno = bmap->real_end; + if (bitno > new_end) + bitno = new_end; + for (; bitno > bmap->end; bitno--) + ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap); + } + if (new_real_end == bmap->real_end) { + bmap->end = new_end; + return 0; + } + + size = ((bmap->real_end - bmap->start) / 8) + 1; + new_size = ((new_real_end - bmap->start) / 8) + 1; + + if (size != new_size) { + retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap); + if (retval) + return retval; + } + if (new_size > size) + memset(bmap->bitmap + size, 0, new_size - size); + + bmap->end = new_end; + bmap->real_end = new_real_end; + return 0; +} + +errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq, + ext2fs_generic_bitmap bm1, + ext2fs_generic_bitmap bm2) +{ + blk_t i; + + if (!bm1 || bm1->magic != magic) + return magic; + if (!bm2 || bm2->magic != magic) + return magic; + + if ((bm1->start != bm2->start) || + (bm1->end != bm2->end) || + (memcmp(bm1->bitmap, bm2->bitmap, + (size_t) (bm1->end - bm1->start)/8))) + return neq; + + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) + if (ext2fs_fast_test_block_bitmap(bm1, i) != + ext2fs_fast_test_block_bitmap(bm2, i)) + return neq; + + return 0; +} + +void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map) +{ + __u32 i, j; + + /* Protect loop from wrap-around if map->real_end is maxed */ + for (i=map->end+1, j = i - map->start; + i <= map->real_end && i > map->end; + i++, j++) + ext2fs_set_bit(j, map->bitmap); +} + +errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap, + errcode_t magic, + __u32 start, __u32 num, + void *out) +{ + if (!bmap || (bmap->magic != magic)) + return magic; + + if ((start < bmap->start) || (start+num-1 > bmap->real_end)) + return EXT2_ET_INVALID_ARGUMENT; + + memcpy(out, bmap->bitmap + (start >> 3), (num+7) >> 3); + return 0; +} + +errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap, + errcode_t magic, + __u32 start, __u32 num, + void *in) +{ + if (!bmap || (bmap->magic != magic)) + return magic; + + if ((start < bmap->start) || (start+num-1 > bmap->real_end)) + return EXT2_ET_INVALID_ARGUMENT; + + memcpy(bmap->bitmap + (start >> 3), in, (num+7) >> 3); + return 0; +} + +/* + * Compare @mem to zero buffer by 256 bytes. + * Return 1 if @mem is zeroed memory, otherwise return 0. + */ +static int mem_is_zero(const char *mem, size_t len) +{ + static const char zero_buf[256]; + + while (len >= sizeof(zero_buf)) { + if (memcmp(mem, zero_buf, sizeof(zero_buf))) + return 0; + len -= sizeof(zero_buf); + mem += sizeof(zero_buf); + } + /* Deal with leftover bytes. */ + if (len) + return !memcmp(mem, zero_buf, len); + return 1; +} + +/* + * Return true if all of the bits in a specified range are clear + */ +static int ext2fs_test_clear_generic_bitmap_range(ext2fs_generic_bitmap bitmap, + unsigned int start, + unsigned int len) +{ + size_t start_byte, len_byte = len >> 3; + unsigned int start_bit, len_bit = len % 8; + int first_bit = 0; + int last_bit = 0; + int mark_count = 0; + int mark_bit = 0; + int i; + const char *ADDR = bitmap->bitmap; + + start -= bitmap->start; + start_byte = start >> 3; + start_bit = start % 8; + + if (start_bit != 0) { + /* + * The compared start block number or start inode number + * is not the first bit in a byte. + */ + mark_count = 8 - start_bit; + if (len < 8 - start_bit) { + mark_count = (int)len; + mark_bit = len + start_bit - 1; + } else + mark_bit = 7; + + for (i = mark_count; i > 0; i--, mark_bit--) + first_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the first byte. + * If there is any marked bit, this function returns 0. + */ + if (first_bit & ADDR[start_byte]) + return 0; + else if (len <= 8 - start_bit) + return 1; + + start_byte++; + len_bit = (len - mark_count) % 8; + len_byte = (len - mark_count) >> 3; + } + + /* + * The compared start block number or start inode number is + * the first bit in a byte. + */ + if (len_bit != 0) { + /* + * The compared end block number or end inode number is + * not the last bit in a byte. + */ + for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--) + last_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the last byte. + * If there is any marked bit, this function returns 0. + */ + if (last_bit & ADDR[start_byte + len_byte]) + return 0; + else if (len_byte == 0) + return 1; + } + + /* Check whether all bytes are 0 */ + return mem_is_zero(ADDR + start_byte, len_byte); +} + +int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP); + if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, + block, bitmap->description); + return 0; + } + return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap) + bitmap, block, num); +} + + +void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, + bitmap->description); + return; + } + for (i=0; i < num; i++) + ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap); +} + +void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, + bitmap->description); + return; + } + for (i=0; i < num; i++) + ext2fs_fast_clear_bit(block + i - bitmap->start, + bitmap->bitmap); +} |