mirror of
https://github.com/versity/scoutfs.git
synced 2026-07-31 20:36:42 +00:00
Add mkfs and print support for buddy alloc
Initialize the block count fields in the super block on mkfs and print out the buddy allocator fields and blocks. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
#define SCOUTFS_SUPER_BLKNO ((64 * 1024) >> SCOUTFS_BLOCK_SHIFT)
|
||||
#define SCOUTFS_SUPER_NR 2
|
||||
#define SCOUTFS_BUDDY_BLKNO (SCOUTFS_SUPER_BLKNO + SCOUTFS_SUPER_NR)
|
||||
|
||||
/*
|
||||
* This header is found at the start of every block so that we can
|
||||
@@ -102,6 +103,38 @@ struct scoutfs_btree_item {
|
||||
|
||||
#define SCOUTFS_UUID_BYTES 16
|
||||
|
||||
/*
|
||||
* Arbitrarily choose a reasonably fine grained 64byte chunk. This is a
|
||||
* balance between write amplification of writing chunks with a single
|
||||
* modified bit, storage overhead of partial blocks losing a chunk to
|
||||
* make room for the block header and having a pos field per chunk, and
|
||||
* runtime memory overhead of a bit per chunk.
|
||||
*/
|
||||
#define SCOUTFS_BUDDY_CHUNK_LE64S 8
|
||||
#define SCOUTFS_BUDDY_CHUNK_BYTES (SCOUTFS_BUDDY_CHUNK_LE64S * 8)
|
||||
#define SCOUTFS_BUDDY_CHUNK_BITS (SCOUTFS_BUDDY_CHUNK_BYTES * 8)
|
||||
|
||||
/*
|
||||
* After the pair of super blocks are a preallocated ring of blocks
|
||||
* which record modified regions of the buddy bitmap allocator.
|
||||
*
|
||||
* The seq's header needs to match the unwrapped ring index of the
|
||||
* block.
|
||||
*/
|
||||
struct scoutfs_buddy_block {
|
||||
struct scoutfs_block_header hdr;
|
||||
u8 nr_chunks;
|
||||
struct scoutfs_buddy_chunk {
|
||||
__le32 pos;
|
||||
__le64 bits[SCOUTFS_BUDDY_CHUNK_LE64S];
|
||||
} __packed chunks[0];
|
||||
} __packed;
|
||||
|
||||
#define SCOUTFS_BUDDY_CHUNKS_PER_BLOCK \
|
||||
((SCOUTFS_BLOCK_SIZE - offsetof(struct scoutfs_buddy_block, chunks)) /\
|
||||
SCOUTFS_BUDDY_CHUNK_BYTES)
|
||||
|
||||
|
||||
/*
|
||||
* The super is stored in a pair of blocks in the first chunk on the
|
||||
* device.
|
||||
@@ -116,6 +149,11 @@ struct scoutfs_super_block {
|
||||
struct scoutfs_block_header hdr;
|
||||
__le64 id;
|
||||
__u8 uuid[SCOUTFS_UUID_BYTES];
|
||||
__le64 total_blocks;
|
||||
__le32 buddy_blocks;
|
||||
__le32 buddy_sweep_bit;
|
||||
__le64 buddy_head;
|
||||
__le64 buddy_tail;
|
||||
struct scoutfs_btree_root btree_root;
|
||||
} __packed;
|
||||
|
||||
|
||||
+35
-2
@@ -39,6 +39,24 @@ static int write_block(int fd, u64 blkno, struct scoutfs_block_header *hdr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the number of buddy blocks that are needed to track the
|
||||
* allocation of a device with the given byte size. We need an even
|
||||
* number of buddy blocks that contain 8 bits for every device block. This
|
||||
* is a bit overly conservative in that it doesn't subtract the buddy
|
||||
* blocks and super block from the calculation.
|
||||
*/
|
||||
static u32 calc_buddy_blocks(u64 total_blocks)
|
||||
{
|
||||
u64 buddy_bits = total_blocks * 8;
|
||||
u64 chunks = DIV_ROUND_UP(buddy_bits, SCOUTFS_BUDDY_CHUNK_BITS);
|
||||
u64 blocks = DIV_ROUND_UP(chunks, SCOUTFS_BUDDY_CHUNKS_PER_BLOCK);
|
||||
|
||||
/* XXX check u32 overflow? */
|
||||
|
||||
return round_up(blocks, 2);
|
||||
}
|
||||
|
||||
static int write_new_fs(char *path, int fd)
|
||||
{
|
||||
struct scoutfs_super_block *super;
|
||||
@@ -51,6 +69,8 @@ static int write_new_fs(char *path, int fd)
|
||||
unsigned int i;
|
||||
u64 size;
|
||||
u64 blkno;
|
||||
u64 total_blocks;
|
||||
u64 buddy_blocks;
|
||||
void *buf;
|
||||
int ret;
|
||||
|
||||
@@ -72,6 +92,15 @@ static int write_new_fs(char *path, int fd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* the block limit is totally arbitrary */
|
||||
total_blocks = size / SCOUTFS_BLOCK_SIZE;
|
||||
if (total_blocks < 32) {
|
||||
fprintf(stderr, "%llu byte device only has room for %llu %u byte blocks, needs at least 32 blocks\n",
|
||||
size, total_blocks, SCOUTFS_BLOCK_SIZE);
|
||||
goto out;
|
||||
}
|
||||
buddy_blocks = calc_buddy_blocks(total_blocks);
|
||||
|
||||
root_key.inode = cpu_to_le64(SCOUTFS_ROOT_INO);
|
||||
root_key.type = SCOUTFS_INODE_KEY;
|
||||
root_key.offset = 0;
|
||||
@@ -85,6 +114,8 @@ static int write_new_fs(char *path, int fd)
|
||||
super->hdr.seq = cpu_to_le64(1);
|
||||
super->id = cpu_to_le64(SCOUTFS_SUPER_ID);
|
||||
uuid_generate(super->uuid);
|
||||
super->total_blocks = cpu_to_le64(total_blocks);
|
||||
super->buddy_blocks = cpu_to_le32(buddy_blocks);
|
||||
|
||||
/* write a btree leaf root inode item */
|
||||
memset(buf, 0, SCOUTFS_BLOCK_SIZE);
|
||||
@@ -142,10 +173,12 @@ static int write_new_fs(char *path, int fd)
|
||||
uuid_unparse(super->uuid, uuid_str);
|
||||
|
||||
printf("Created scoutfs filesystem:\n"
|
||||
" block size: %u\n"
|
||||
" total blocks: %llu\n"
|
||||
" buddy blocks: %llu\n"
|
||||
" fsid: %llx\n"
|
||||
" uuid: %s\n",
|
||||
SCOUTFS_BLOCK_SIZE, le64_to_cpu(super->hdr.fsid), uuid_str);
|
||||
total_blocks, buddy_blocks,
|
||||
le64_to_cpu(super->hdr.fsid), uuid_str);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
|
||||
+57
-3
@@ -178,6 +178,49 @@ static int print_btree_block(int fd, __le64 blkno, u8 level)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int print_buddy_blocks(int fd, struct scoutfs_super_block *super)
|
||||
{
|
||||
struct scoutfs_buddy_chunk *chunk;
|
||||
struct scoutfs_buddy_block *bb;
|
||||
u64 blkno;
|
||||
u64 blocks;
|
||||
u64 head;
|
||||
u64 tail;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
blocks = le32_to_cpu(super->buddy_blocks);
|
||||
head = le64_to_cpu(super->buddy_head);
|
||||
tail = le64_to_cpu(super->buddy_tail);
|
||||
|
||||
/* XXX make sure values are sane */
|
||||
|
||||
for (; head < tail; head++) {
|
||||
|
||||
blkno = SCOUTFS_BUDDY_BLKNO + (head % blocks);
|
||||
bb = read_block(fd, blkno);
|
||||
if (!bb)
|
||||
return -ENOMEM;
|
||||
|
||||
printf("buddy blkno %llu\n", blkno);
|
||||
print_block_header(&bb->hdr);
|
||||
printf(" nr_chunks %u\n", bb->nr_chunks);
|
||||
for (i = 0; i < bb->nr_chunks; i++) {
|
||||
chunk = &bb->chunks[i];
|
||||
|
||||
printf(" [%u]: pos %u bits ",
|
||||
i, le32_to_cpu(chunk->pos));
|
||||
for (j = 0; j < SCOUTFS_BUDDY_CHUNK_LE64S; j++)
|
||||
printf("%016llx", le64_to_cpu(chunk->bits[j]));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
free(bb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_super_blocks(int fd)
|
||||
{
|
||||
struct scoutfs_super_block *super;
|
||||
@@ -198,6 +241,13 @@ static int print_super_blocks(int fd)
|
||||
print_block_header(&super->hdr);
|
||||
printf(" id %llx uuid %s\n",
|
||||
le64_to_cpu(super->id), uuid_str);
|
||||
printf(" total_blocks %llu buddy_blocks %u buddy_sweep_bit %u\n"
|
||||
" buddy_head %llu buddy_tail %llu\n",
|
||||
le64_to_cpu(super->total_blocks),
|
||||
le32_to_cpu(super->buddy_blocks),
|
||||
le32_to_cpu(super->buddy_sweep_bit),
|
||||
le64_to_cpu(super->buddy_head),
|
||||
le64_to_cpu(super->buddy_tail));
|
||||
printf(" btree_root: height %u seq %llu blkno %llu\n",
|
||||
super->btree_root.height,
|
||||
le64_to_cpu(super->btree_root.ref.seq),
|
||||
@@ -211,11 +261,15 @@ static int print_super_blocks(int fd)
|
||||
|
||||
super = &recent;
|
||||
|
||||
if (super->btree_root.height)
|
||||
ret = print_buddy_blocks(fd, super);
|
||||
|
||||
if (super->btree_root.height) {
|
||||
err = print_btree_block(fd, super->btree_root.ref.blkno,
|
||||
super->btree_root.height - 1);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user