static void test02(struct sb *sb, block_t blocks) { /* Allocate specific range */ block_t start = 121; unsigned count = 10; for (int i = 0; i < count + 2; i++) { struct block_segment seg; int err = balloc_from_range(sb, start, count, 1, 0, &seg, 1); if (i < count) test_assert(!err && seg.block == start + i); else test_assert(err == -ENOSPC); } /* Check bitmap */ test_assert(bitmap_all_set(sb, start, count)); test_assert(bitmap_all_clear(sb, 0, start)); loff_t cnt = ((blocks << sb->blockbits) << 3) - (start + count); test_assert(bitmap_all_clear(sb, start + count, cnt)); for (int i = 0; i < count; i++) { int err = bfree(sb, start + i, 1); if (i < count) test_assert(!err); else test_assert(err); } test_assert(bitmap_all_clear(sb, 0, (blocks << sb->blockbits) << 3)); clean_main(sb); }
static int reserve_superblock(struct sb *sb) { /* Always 8K regardless of blocksize */ int count = 1 << (sb->blockbits > 13 ? 0 : 13 - sb->blockbits); struct block_segment seg; int err; trace("reserve superblock"); /* Reserve blocks from 0 to 8KB */ err = balloc_from_range(sb, 0, count, count, 0, &seg, 1); if (err < 0) return err; log_balloc(sb, seg.block, seg.count); trace("reserve %Lx", seg.block); return 0; }
/* Fill whole bitmap and free */ static void test06(struct sb *sb, block_t blocks) { #define ALLOC_UNIT 8 block_t total = blocks << (sb->blockbits + 3); struct block_segment *seg; int err, nr = total / ALLOC_UNIT; seg = malloc(nr * sizeof(*seg)); assert(seg); for (int i = 0; i < nr; i++) { err = balloc_from_range(sb, 0, total, ALLOC_UNIT, 0, &seg[i], 1); test_assert(!err); test_assert(seg[i].count == ALLOC_UNIT); } for (int i = 0; i < nr; i++) test_assert(bfree(sb, seg[i].block, seg[i].count) == 0); free(seg); clean_main(sb); }
int make_tux3(struct sb *sb) { struct inode *dir = &(struct inode){ .i_sb = sb, .i_mode = S_IFDIR | 0755, }; struct tux_iattr *iattr = &(struct tux_iattr){}; int err; err = clear_other_magic(sb); if (err) return err; trace("create inode table"); init_btree(itable_btree(sb), sb, no_root, &itable_ops); trace("create bitmap"); sb->bitmap = __tux_create_inode(dir, TUX_BITMAP_INO, iattr, 0); if (IS_ERR(sb->bitmap)) { err = PTR_ERR(sb->bitmap); goto eek; } assert(sb->bitmap->inum == TUX_BITMAP_INO); sb->bitmap->i_size = (sb->volblocks + 7) >> 3; /* should this?, tuxtruncate(sb->bitmap, (sb->volblocks + 7) >> 3); */ trace("reserve superblock"); /* Always 8K regardless of blocksize */ int reserve = 1 << (sb->blockbits > 13 ? 0 : 13 - sb->blockbits); for (int i = 0; i < reserve; i++) { block_t block = balloc_from_range(sb, i, 1, 1); if (block == -1) goto eek; trace("reserve %Lx", (L)block); // error ??? } trace("create version table"); sb->vtable = __tux_create_inode(dir, TUX_VTABLE_INO, iattr, 0); if (IS_ERR(sb->vtable)) { err = PTR_ERR(sb->vtable); goto eek; } assert(sb->vtable->inum == TUX_VTABLE_INO); trace("create atom dictionary"); sb->atable = __tux_create_inode(dir, TUX_ATABLE_INO, iattr, 0); if (IS_ERR(sb->atable)) { err = PTR_ERR(sb->atable); goto eek; } assert(sb->atable->inum == TUX_ATABLE_INO); sb->atomref_base = 1 << (40 - sb->blockbits); // see xattr.c sb->unatom_base = sb->atomref_base + (1 << (34 - sb->blockbits)); sb->atomgen = 1; // atom 0 not allowed, means end of atom freelist trace("create root directory"); struct tux_iattr root_iattr = { .mode = S_IFDIR | 0755, }; sb->rootdir = __tux_create_inode(dir, TUX_ROOTDIR_INO, &root_iattr, 0); if (IS_ERR(sb->rootdir)) { err = PTR_ERR(sb->rootdir); goto eek; } assert(sb->rootdir->inum == TUX_ROOTDIR_INO); if ((err = sync_super(sb))) goto eek; show_buffers(mapping(sb->bitmap)); show_buffers(mapping(sb->rootdir)); show_buffers(sb->volmap->map); return 0; eek: if (err) warn("eek, %s", strerror(-err)); iput(sb->bitmap); sb->bitmap = NULL; return err ? err : -ENOSPC; // just guess }
int main(int argc, char *argv[]) { if (1) { warn("---- test bitops ----"); unsigned char bits[16]; memset(bits, 0, sizeof(bits)); set_bits(bits, 6, 20); set_bits(bits, 49, 16); set_bits(bits, 0x51, 2); hexdump(bits, sizeof(bits)); /* should return true */ printf("ones = %i\n", all_set(bits, 6, 20)); printf("ones = %i\n", all_set(bits, 49, 16)); printf("ones = %i\n", all_set(bits, 0x51, 2)); /* should return false */ printf("ones = %i\n", all_set(bits, 5, 20)); printf("ones = %i\n", all_set(bits, 49, 17)); printf("ones = %i\n", all_set(bits, 0x51, 3)); clear_bits(bits, 6, 20); clear_bits(bits, 49, 16); clear_bits(bits, 0x51, 2); hexdump(bits, sizeof(bits)); // all zero now /* corner case */ unsigned char *bitmap = malloc(7); set_bits(bitmap, 0, 7 * 8); int ret = all_set(bitmap, 0, 7 * 8); assert(ret); clear_bits(bitmap, 0, 7 * 8); free(bitmap); } struct dev *dev = &(struct dev){ .bits = 3 }; struct sb *sb = rapid_sb(dev, .volblocks = 150); struct inode *bitmap = rapid_open_inode(sb, NULL, 0); sb->freeblocks = sb->volblocks; sb->nextalloc = sb->volblocks; // this should wrap around to zero sb->bitmap = bitmap; init_buffers(dev, 1 << 20, 0); unsigned blocksize = 1 << dev->bits; unsigned dumpsize = blocksize > 16 ? 16 : blocksize; for (int block = 0; block < 10; block++) { struct buffer_head *buffer = blockget(bitmap->map, block); memset(bufdata(buffer), 0, blocksize); set_buffer_clean(buffer); } for (int i = 0; i < 12; i++) { block_t block = balloc_from_range(sb, 121, 10, 1); printf("%Li\n", (L)block); } hexdump(bufdata(blockget(bitmap->map, 0)), dumpsize); hexdump(bufdata(blockget(bitmap->map, 1)), dumpsize); hexdump(bufdata(blockget(bitmap->map, 2)), dumpsize); block_t block; sb->nextalloc++; // gap for (int i = 0; i < 1; i++) balloc(sb, 1, &block); sb->nextalloc++; // gap for (int i = 0; i < 10; i++) balloc(sb, 1, &block); hexdump(bufdata(blockget(bitmap->map, 0)), dumpsize); hexdump(bufdata(blockget(bitmap->map, 1)), dumpsize); hexdump(bufdata(blockget(bitmap->map, 2)), dumpsize); bitmap_dump(bitmap, 0, sb->volblocks); printf("%Li used, %Li free\n", (L)count_range(bitmap, 0, sb->volblocks), (L)sb->freeblocks); bfree(sb, 0x7e, 1); bfree(sb, 0x80, 1); bitmap_dump(bitmap, 0, sb->volblocks); exit(0); }