📄 bitmap.c
字号:
/* * Copyright 2000-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README *//* * 2000/10/26 - Initial version. */#include "includes.h"#include <assert.h>/* create clean bitmap */reiserfs_bitmap_t * reiserfs_create_bitmap (unsigned int bit_count){ reiserfs_bitmap_t * bm; bm = getmem (sizeof (*bm)); if (!bm) return 0; bm->bm_bit_size = bit_count; bm->bm_byte_size = ((unsigned long long)bit_count + 7) / 8; bm->bm_set_bits = 0; bm->bm_map = getmem (bm->bm_byte_size); if (!bm->bm_map) { freemem (bm); return 0; } return bm;}/* Expand existing bitmap. Return non-zero if can't. FIXME: it is assumed that bit_count is new number of blocks to be addressed */int reiserfs_expand_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count){ unsigned int byte_count = ((bit_count + 7) / 8); char * new_map; new_map = expandmem (bm->bm_map, bm->bm_byte_size, byte_count - bm->bm_byte_size); if (!new_map) { return 1; } bm->bm_map = new_map; bm->bm_byte_size = byte_count; bm->bm_bit_size = bit_count; bm->bm_dirty = 1; return 0;}void reiserfs_shrink_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count){ unsigned long i; assert (bm->bm_bit_size >= bit_count); bm->bm_byte_size = (bit_count + 7) / 8; bm->bm_bit_size = bit_count; bm->bm_set_bits = 0; bm->bm_dirty = 1; for (i = 0; i < bm->bm_bit_size; i++) { if (reiserfs_bitmap_test_bit(bm, i)) bm->bm_set_bits++; }}/* bitmap destructor */void reiserfs_delete_bitmap (reiserfs_bitmap_t * bm){ freemem(bm->bm_map); bm->bm_map = NULL; /* to not reuse bitmap handle */ bm->bm_bit_size = 0; bm->bm_byte_size = 0; freemem(bm);}void reiserfs_bitmap_copy (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from){ assert (to->bm_byte_size == from->bm_byte_size); memcpy (to->bm_map, from->bm_map, from->bm_byte_size); to->bm_bit_size = from->bm_bit_size; to->bm_set_bits = from->bm_set_bits; to->bm_dirty = 1;}int reiserfs_bitmap_compare (reiserfs_bitmap_t * bm1, reiserfs_bitmap_t * bm2){ unsigned long i, diff; unsigned long int bytes, bits; assert (bm1->bm_byte_size == bm2->bm_byte_size && bm1->bm_bit_size == bm2->bm_bit_size); diff = 0; /* compare full bytes */ bytes = bm1->bm_bit_size / 8; bits = bytes * 8; if (memcmp (bm1->bm_map, bm2->bm_map, bytes)) { for (i = 0; i < bits; i ++) if (reiserfs_bitmap_test_bit(bm1, i) != reiserfs_bitmap_test_bit(bm2, i)) diff ++; } /* compare last byte of bitmap which can be used partially */ bits = bm1->bm_bit_size % 8; for (i = bm1->bm_bit_size / 8 * 8; i < bm1->bm_bit_size / 8 * 8 + bits; i ++) if (reiserfs_bitmap_test_bit(bm1, i) != reiserfs_bitmap_test_bit(bm2, i)) diff ++;/* int mask; mask = 255 >> (8 - bits); if ((bm1->bm_map [bytes] & mask) != (bm2->bm_map [bytes] & mask)) { diff ++; } }*/ return diff;}/* Does X | Y for every bit of the bitmap `to`, where X - bit of the `to` bitmap, Y - `from` bitmap. Save result in the `to` bitmap.*/void reiserfs_bitmap_disjunction (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from) { unsigned int i; assert (to->bm_byte_size == from->bm_byte_size && to->bm_bit_size == from->bm_bit_size); for (i = 0; i < to->bm_bit_size; i++) { if (misc_test_bit(i, from->bm_map) && !misc_test_bit(i, to->bm_map)) { misc_set_bit(i, to->bm_map); to->bm_set_bits ++; to->bm_dirty = 1; } }}/* Does X & !Y for every bit of the bitmap `base`, where X - bit of the `base` bitmap, Y - `exclude` bitmap. Save result in the `base` bitmap.*/void reiserfs_bitmap_delta (reiserfs_bitmap_t * base, reiserfs_bitmap_t * exclude) { unsigned int i; assert (base->bm_byte_size == exclude->bm_byte_size && base->bm_bit_size == exclude->bm_bit_size); for (i = 0; i < base->bm_bit_size; i++) { if (misc_test_bit(i, exclude->bm_map) && misc_test_bit(i, base->bm_map)) { misc_clear_bit(i, base->bm_map); base->bm_set_bits --; base->bm_dirty = 1; } }}void reiserfs_bitmap_set_bit (reiserfs_bitmap_t * bm, unsigned int bit_number){ assert(bit_number < bm->bm_bit_size); if (misc_test_bit (bit_number, bm->bm_map)) return; misc_set_bit(bit_number, bm->bm_map); bm->bm_set_bits ++; bm->bm_dirty = 1;}void reiserfs_bitmap_clear_bit (reiserfs_bitmap_t * bm, unsigned int bit_number){ assert(bit_number < bm->bm_bit_size); if (!misc_test_bit (bit_number, bm->bm_map)) return; misc_clear_bit (bit_number, bm->bm_map); bm->bm_set_bits --; bm->bm_dirty = 1;}int reiserfs_bitmap_test_bit (reiserfs_bitmap_t * bm, unsigned int bit_number){ if (bit_number >= bm->bm_bit_size) printf ("bit %u, bitsize %lu\n", bit_number, bm->bm_bit_size); assert(bit_number < bm->bm_bit_size); return misc_test_bit(bit_number, bm->bm_map);}unsigned int reiserfs_bitmap_zeros (reiserfs_bitmap_t * bm) { return bm->bm_bit_size - bm->bm_set_bits;}unsigned int reiserfs_bitmap_ones (reiserfs_bitmap_t * bm) { return bm->bm_set_bits;}int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t * bm, unsigned long * first){ unsigned long bit_nr = *first; assert(*first < bm->bm_bit_size); bit_nr = misc_find_next_zero_bit(bm->bm_map, bm->bm_bit_size, *first); if (bit_nr >= bm->bm_bit_size) { /* search failed */ return 1; } *first = bit_nr; return 0;}/* read every bitmap block and copy their content into bitmap 'bm' */static int reiserfs_fetch_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs){ unsigned int last_byte_unused_bits; unsigned long block, to_copy; struct buffer_head * bh; unsigned int i; int copied; int ret = 0; char * p; to_copy = (get_sb_block_count (fs->fs_ondisk_sb) + 7) / 8; /*reiserfs_warning (stderr, "Fetching on-disk bitmap..");*/ assert (bm->bm_byte_size == to_copy); copied = fs->fs_blocksize; p = bm->bm_map; block = fs->fs_super_bh->b_blocknr + 1; while (to_copy) { bh = bread (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_fetch_ondisk_bitmap: " "bread failed reading bitmap (%lu)\n", block); bh = getblk (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { reiserfs_exit (1, "reiserfs_fetch_ondisk_bitmap: " "getblk failed"); } memset (bh->b_data, 0xff, bh->b_size); mark_buffer_uptodate (bh, 1); } if (to_copy < fs->fs_blocksize) { for (i = to_copy; i < fs->fs_blocksize; i++) { if (bh->b_data[i] != (char)0xff) { ret = 1; break; } } copied = to_copy; } memcpy (p, bh->b_data, copied); brelse (bh); p += copied; to_copy -= copied; /* next bitmap block */ if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; } /* on disk bitmap has bits out of SB_BLOCK_COUNT set to 1, where as reiserfs_bitmap_t has those bits set to 0 */ last_byte_unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size; for (i = 0; i < last_byte_unused_bits; i ++) { if (misc_test_bit (bm->bm_bit_size + i, bm->bm_map) == 0) ret = 1; else misc_clear_bit (bm->bm_bit_size + i, bm->bm_map); } bm->bm_set_bits = 0; /* FIXME: optimize that */ for (i = 0; i < bm->bm_bit_size; i ++) if (reiserfs_bitmap_test_bit (bm, i)) bm->bm_set_bits ++; bm->bm_dirty = 0; return ret;}/* copy bitmap 'bm' to buffers which hold on-disk bitmap if bitmap was ever changed and return 1. Otherwise - return 0 */int reiserfs_flush_to_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs){ unsigned int last_byte_unused_bits, i; unsigned long to_copy, copied, block; struct buffer_head * bh; char * p; /* make sure that the device is big enough */ bh = bread (fs->fs_dev, bm->bm_bit_size - 1, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_flush_to_ondisk_bitmap: bread failed for block %lu\n", bm->bm_bit_size - 1);/* bh = getblk (fs->fs_dev, bm->bm_bit_size - 1, fs->fs_blocksize); if (!bh) reiserfs_panic ("reiserfs_flush_to_ondisk_bitmap: getblk failed"); mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); bwrite (bh);*/ } brelse (bh); if (!bm->bm_dirty) return 0; to_copy = bm->bm_byte_size; copied = fs->fs_blocksize; p = bm->bm_map; block = fs->fs_super_bh->b_blocknr + 1; while (to_copy) { /* we bread to make sure that filesystem contains enough blocks */ bh = getblk (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { reiserfs_exit (1, "Getblk failed for (%lu)\n", block); } memset (bh->b_data, 0xff, bh->b_size); mark_buffer_uptodate (bh, 1); if (to_copy < fs->fs_blocksize) copied = to_copy; memcpy (bh->b_data, p, copied); if (copied == to_copy) { /* set unused bits of last byte of a bitmap to 1 */ last_byte_unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size; for (i = 0; i < last_byte_unused_bits; i ++) misc_set_bit ((bm->bm_bit_size % (fs->fs_blocksize * 8)) + i, bh->b_data); } mark_buffer_dirty (bh); brelse (bh);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -