mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-07 04:26:29 +00:00
Get rid of bricks
Get rid of the explicit distinction between brick and block numbers. The format is now defined it terms of fixed 4k blocks. Logs become a logical structure that's made up of a fixed number of blocks. The allocator still manages large log sized regions.
This commit is contained in:
@@ -32,8 +32,8 @@ u64 crc32c_64(u32 crc, const void *data, unsigned int len)
|
||||
crc32c(~crc, data + len - half, half);
|
||||
}
|
||||
|
||||
u32 crc_header(struct scoutfs_header *hdr, size_t size)
|
||||
u32 crc_block(struct scoutfs_block_header *hdr)
|
||||
{
|
||||
return crc32c(~0, (char *)hdr + sizeof(hdr->crc),
|
||||
size - sizeof(hdr->crc));
|
||||
SCOUTFS_BLOCK_SIZE - sizeof(hdr->crc));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
|
||||
u32 crc32c(u32 crc, const void *data, unsigned int len);
|
||||
u64 crc32c_64(u32 crc, const void *data, unsigned int len);
|
||||
u32 crc_header(struct scoutfs_header *hdr, size_t size);
|
||||
u32 crc_block(struct scoutfs_block_header *hdr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,53 +7,66 @@
|
||||
#define SCOUTFS_SUPER_ID 0x2e736674756f6373ULL /* "scoutfs." */
|
||||
|
||||
/*
|
||||
* Some fs structures are stored in smaller fixed size 4k bricks.
|
||||
* Structures are stored and referenced in fixed 4k chunks to
|
||||
* simplify block buffer access at run time.
|
||||
*/
|
||||
#define SCOUTFS_BRICK_SHIFT 12
|
||||
#define SCOUTFS_BRICK_SIZE (1 << SCOUTFS_BRICK_SHIFT)
|
||||
|
||||
/*
|
||||
* A large block size reduces the amount of per-block overhead throughout
|
||||
* the system: block IO, manifest communications and storage, etc.
|
||||
*/
|
||||
#define SCOUTFS_BLOCK_SHIFT 22
|
||||
#define SCOUTFS_BLOCK_SHIFT 12
|
||||
#define SCOUTFS_BLOCK_SIZE (1 << SCOUTFS_BLOCK_SHIFT)
|
||||
|
||||
/* for shifting between brick and block numbers */
|
||||
#define SCOUTFS_BLOCK_BRICK (SCOUTFS_BLOCK_SHIFT - SCOUTFS_BRICK_SHIFT)
|
||||
/*
|
||||
* Logs are a logical structure that is made up of a fixed number of
|
||||
* contiguously allocated blocks.
|
||||
*
|
||||
* The allocator manages log-sized regions. Smaller metadata blocks
|
||||
* like the ring and super blocks are stored inside large log
|
||||
* allocations.
|
||||
*/
|
||||
#define SCOUTFS_LOG_SHIFT 22
|
||||
#define SCOUTFS_LOG_SIZE (1 << SCOUTFS_LOG_SHIFT)
|
||||
#define SCOUTFS_LOG_BLOCK_SHIFT (SCOUTFS_LOG_SHIFT - SCOUTFS_BLOCK_SHIFT)
|
||||
#define SCOUTFS_BLOCKS_PER_LOG (1 << SCOUTFS_LOG_BLOCK_SHIFT)
|
||||
|
||||
/*
|
||||
* The super bricks leave a bunch of room at the start of the first
|
||||
* block for platform structures like boot loaders.
|
||||
* The super blocks leave some room at the start of the first block for
|
||||
* platform structures like boot loaders.
|
||||
*/
|
||||
#define SCOUTFS_SUPER_BRICK 16
|
||||
#define SCOUTFS_SUPER_BLKNO ((64 * 1024) >> SCOUTFS_BLOCK_SHIFT)
|
||||
#define SCOUTFS_SUPER_NR 2
|
||||
|
||||
/*
|
||||
* This header is found at the start of every brick and block
|
||||
* so that we can verify that it's what we were looking for.
|
||||
* This header is found at the start of every block so that we can
|
||||
* verify that it's what we were looking for. The crc and padding
|
||||
* starts the block so that its calculation operations on a nice 64bit
|
||||
* aligned region.
|
||||
*/
|
||||
struct scoutfs_header {
|
||||
struct scoutfs_block_header {
|
||||
__le32 crc;
|
||||
__le32 _pad;
|
||||
__le64 fsid;
|
||||
__le64 seq;
|
||||
__le64 nr;
|
||||
__le64 blkno;
|
||||
} __packed;
|
||||
|
||||
#define SCOUTFS_UUID_BYTES 16
|
||||
|
||||
/*
|
||||
* The super is stored in a pair of bricks in the first block.
|
||||
* The super is stored in a pair of blocks in log 0 on the device.
|
||||
*
|
||||
* The ring layout blocks describe the location of the ring blocks. The
|
||||
* ring start and length refers to the logical ring blocks within that
|
||||
* storage which contain live data.
|
||||
*/
|
||||
struct scoutfs_super {
|
||||
struct scoutfs_header hdr;
|
||||
struct scoutfs_super_block {
|
||||
struct scoutfs_block_header hdr;
|
||||
__le64 id;
|
||||
__u8 uuid[SCOUTFS_UUID_BYTES];
|
||||
__le64 total_blocks;
|
||||
__le64 ring_layout_block;
|
||||
__le64 total_logs;
|
||||
__le64 ring_layout_blkno;
|
||||
__le64 ring_layout_nr_blocks;
|
||||
__le64 ring_layout_seq;
|
||||
__le64 last_ring_brick;
|
||||
__le64 last_ring_seq;
|
||||
__le64 last_block_seq;
|
||||
__le64 ring_block;
|
||||
__le64 ring_nr_blocks;
|
||||
__le64 ring_seq;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
@@ -71,10 +84,10 @@ struct scoutfs_key {
|
||||
#define SCOUTFS_INODE_KEY 128
|
||||
#define SCOUTFS_DIRENT_KEY 192
|
||||
|
||||
struct scoutfs_ring_layout {
|
||||
struct scoutfs_header hdr;
|
||||
struct scoutfs_layout_block {
|
||||
struct scoutfs_block_header hdr;
|
||||
__le32 nr_blocks;
|
||||
__le64 blocks[0];
|
||||
__le64 blknos[0];
|
||||
} __packed;
|
||||
|
||||
struct scoutfs_ring_entry {
|
||||
@@ -83,16 +96,16 @@ struct scoutfs_ring_entry {
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Ring blocks are 4k blocks stored inside the large ring blocks
|
||||
* referenced by the ring descriptor block.
|
||||
* Ring blocks are 4k blocks stored inside the regions described by the
|
||||
* ring layout block referenced by the super.
|
||||
*
|
||||
* The manifest entries describe the position of a given block in the
|
||||
* manifest. They're keyed by the block number so that we can log
|
||||
* movement of a block in the manifest with one log entry and we can log
|
||||
* deletion with just the block number.
|
||||
*/
|
||||
struct scoutfs_ring_brick {
|
||||
struct scoutfs_header hdr;
|
||||
struct scoutfs_ring_block {
|
||||
struct scoutfs_block_header hdr;
|
||||
__le16 nr_entries;
|
||||
} __packed;
|
||||
|
||||
@@ -108,7 +121,7 @@ enum {
|
||||
* without the key.
|
||||
*/
|
||||
struct scoutfs_ring_remove_manifest {
|
||||
__le64 block;
|
||||
__le64 blkno;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
@@ -119,7 +132,7 @@ struct scoutfs_ring_remove_manifest {
|
||||
* blocks when we didn't need to.
|
||||
*/
|
||||
struct scoutfs_ring_add_manifest {
|
||||
__le64 block;
|
||||
__le64 blkno;
|
||||
__le64 seq;
|
||||
__u8 level;
|
||||
struct scoutfs_key first;
|
||||
@@ -132,23 +145,15 @@ struct scoutfs_ring_bitmap {
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This bloom size is chosen to have a roughly 1% false positive rate
|
||||
* for ~90k items which is roughly the worst case for a block full of
|
||||
* dirents with reasonably small names. Pathologically smaller items
|
||||
* could be even more dense.
|
||||
* To start the logs are a trivial single item block. We'll flesh this out
|
||||
* into larger blocks once the rest of the architecture is in
|
||||
* place.
|
||||
*/
|
||||
#define SCOUTFS_BLOOM_FILTER_BYTES (128 * 1024)
|
||||
#define SCOUTFS_BLOOM_FILTER_BITS (SCOUTFS_BLOOM_FILTER_BYTES * 8)
|
||||
#define SCOUTFS_BLOOM_INDEX_BITS (ilog2(SCOUTFS_BLOOM_FILTER_BITS))
|
||||
#define SCOUTFS_BLOOM_INDEX_MASK ((1 << SCOUTFS_BLOOM_INDEX_BITS) - 1)
|
||||
#define SCOUTFS_BLOOM_INDEX_NR 7
|
||||
|
||||
struct scoutfs_lsm_block {
|
||||
struct scoutfs_header hdr;
|
||||
struct scoutfs_item_block {
|
||||
struct scoutfs_block_header hdr;
|
||||
struct scoutfs_key first;
|
||||
struct scoutfs_key last;
|
||||
__le32 nr_items;
|
||||
/* u8 bloom[SCOUTFS_BLOOM_BYTES]; */
|
||||
/* struct scoutfs_item_header items[0] .. */
|
||||
} __packed;
|
||||
|
||||
|
||||
201
utils/src/mkfs.c
201
utils/src/mkfs.c
@@ -17,77 +17,56 @@
|
||||
#include "crc.h"
|
||||
#include "rand.h"
|
||||
|
||||
|
||||
/*
|
||||
* Update the buffer's header and write it out.
|
||||
* Update the block's header and write it out.
|
||||
*/
|
||||
static int write_header(int fd, u64 nr, struct scoutfs_header *hdr, size_t size)
|
||||
static int write_block(int fd, u64 blkno, struct scoutfs_block_header *hdr)
|
||||
{
|
||||
off_t off = nr * size;
|
||||
ssize_t ret;
|
||||
|
||||
hdr->nr = cpu_to_le64(nr);
|
||||
hdr->crc = cpu_to_le32(crc_header(hdr, size));
|
||||
hdr->blkno = cpu_to_le64(blkno);
|
||||
hdr->crc = cpu_to_le32(crc_block(hdr));
|
||||
|
||||
ret = pwrite(fd, hdr, size, off);
|
||||
if (ret != size) {
|
||||
fprintf(stderr, "write at nr %llu (offset %llu, size %zu) returned %zd: %s (%d)\n",
|
||||
nr, (long long)off, size, ret, strerror(errno), errno);
|
||||
ret = pwrite(fd, hdr, SCOUTFS_BLOCK_SIZE, blkno << SCOUTFS_BLOCK_SHIFT);
|
||||
if (ret != SCOUTFS_BLOCK_SIZE) {
|
||||
fprintf(stderr, "write to blkno %llu returned %zd: %s (%d)\n",
|
||||
blkno, ret, strerror(errno), errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_brick(int fd, u64 nr, struct scoutfs_header *hdr)
|
||||
{
|
||||
return write_header(fd, nr, hdr, SCOUTFS_BRICK_SIZE);
|
||||
}
|
||||
|
||||
static int write_block(int fd, u64 nr, struct scoutfs_header *hdr)
|
||||
{
|
||||
return write_header(fd, nr, hdr, SCOUTFS_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* - config blocks that describe ring
|
||||
* - ring entries for lots of free blocks
|
||||
* - manifest that references single block
|
||||
* - block with inode
|
||||
*/
|
||||
/*
|
||||
* So what does mkfs really need to do?
|
||||
*
|
||||
* - super blocks that describe ring log
|
||||
* - ring log with free bitmap entries
|
||||
* - ring log with manifest entries
|
||||
* - single item block with root dir
|
||||
*/
|
||||
static int write_new_fs(char *path, int fd)
|
||||
{
|
||||
struct scoutfs_super *super;
|
||||
struct scoutfs_super_block *super;
|
||||
struct scoutfs_block_header hdr;
|
||||
struct scoutfs_inode *inode;
|
||||
struct scoutfs_ring_layout *rlo;
|
||||
struct scoutfs_ring_brick *ring;
|
||||
struct scoutfs_layout_block *lout;
|
||||
struct scoutfs_ring_block *ring;
|
||||
struct scoutfs_ring_entry *ent;
|
||||
struct scoutfs_ring_add_manifest *mani;
|
||||
struct scoutfs_ring_bitmap *bm;
|
||||
struct scoutfs_lsm_block *lblk;
|
||||
struct scoutfs_item_block *iblk;
|
||||
struct scoutfs_item_header *ihdr;
|
||||
struct scoutfs_key root_key;
|
||||
struct timeval tv;
|
||||
char uuid_str[37];
|
||||
struct stat st;
|
||||
unsigned int i;
|
||||
u64 total_blocks;
|
||||
u64 total_logs;
|
||||
u64 blkno;
|
||||
void *buf;
|
||||
int ret;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
/* crc and blkno written for each write */
|
||||
hdr._pad = 0;
|
||||
pseudo_random_bytes(&hdr.fsid, sizeof(hdr.fsid));
|
||||
hdr.seq = cpu_to_le64(1);
|
||||
|
||||
super = malloc(SCOUTFS_BRICK_SIZE);
|
||||
buf = malloc(SCOUTFS_BLOCK_SIZE);
|
||||
if (!super || !buf) {
|
||||
if (!buf) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "failed to allocate a block: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
@@ -101,75 +80,23 @@ static int write_new_fs(char *path, int fd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
total_blocks = st.st_size >> SCOUTFS_BLOCK_SHIFT;
|
||||
total_logs = st.st_size >> SCOUTFS_LOG_SHIFT;
|
||||
|
||||
root_key.inode = cpu_to_le64(SCOUTFS_ROOT_INO);
|
||||
root_key.type = SCOUTFS_INODE_KEY;
|
||||
root_key.offset = 0;
|
||||
|
||||
/* initialize the super */
|
||||
memset(super, 0, sizeof(struct scoutfs_super));
|
||||
pseudo_random_bytes(&super->hdr.fsid, sizeof(super->hdr.fsid));
|
||||
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->ring_layout_block = cpu_to_le64(1);
|
||||
super->ring_layout_seq = cpu_to_le64(1);
|
||||
super->last_ring_brick = cpu_to_le64(1);
|
||||
super->last_ring_seq = cpu_to_le64(1);
|
||||
super->last_block_seq = cpu_to_le64(1);
|
||||
/* super in log 0, first fs log block in log 1 */
|
||||
blkno = 1 << SCOUTFS_LOG_BLOCK_SHIFT;
|
||||
|
||||
/* the ring has a single block for now */
|
||||
/* write a single log block with the root inode item */
|
||||
memset(buf, 0, SCOUTFS_BLOCK_SIZE);
|
||||
rlo = buf;
|
||||
rlo->hdr.fsid = super->hdr.fsid;
|
||||
rlo->hdr.seq = super->ring_layout_seq;
|
||||
rlo->nr_blocks = cpu_to_le32(1);
|
||||
rlo->blocks[0] = cpu_to_le64(2);
|
||||
|
||||
ret = write_block(fd, 1, &rlo->hdr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* log the root inode block manifest and free bitmap */
|
||||
memset(buf, 0, SCOUTFS_BLOCK_SIZE);
|
||||
ring = buf;
|
||||
ring->hdr.fsid = super->hdr.fsid;
|
||||
ring->hdr.seq = super->last_ring_seq;
|
||||
ring->nr_entries = cpu_to_le16(2);
|
||||
ent = (void *)(ring + 1);
|
||||
ent->type = SCOUTFS_RING_ADD_MANIFEST;
|
||||
ent->len = cpu_to_le16(sizeof(*mani));
|
||||
mani = (void *)(ent + 1);
|
||||
mani->block = cpu_to_le64(3);
|
||||
mani->seq = super->last_block_seq;
|
||||
mani->level = 0;
|
||||
mani->first = root_key;
|
||||
mani->last = root_key;
|
||||
ent = (void *)(mani + 1);
|
||||
ent->type = SCOUTFS_RING_BITMAP;
|
||||
ent->len = cpu_to_le16(sizeof(*bm));
|
||||
bm = (void *)(ent + 1);
|
||||
memset(bm->bits, 0xff, sizeof(bm->bits));
|
||||
/* the first three blocks are allocated */
|
||||
bm->bits[0] = cpu_to_le64(~7ULL);
|
||||
bm->bits[1] = cpu_to_le64(~0ULL);
|
||||
|
||||
ret = write_brick(fd, 2 << SCOUTFS_BLOCK_BRICK, &ring->hdr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* write a single lsm block with the root inode item */
|
||||
memset(buf, 0, SCOUTFS_BLOCK_SIZE);
|
||||
lblk = buf;
|
||||
lblk->hdr.fsid = super->hdr.fsid;
|
||||
lblk->hdr.seq = super->last_block_seq;
|
||||
lblk->first = root_key;
|
||||
lblk->last = root_key;
|
||||
lblk->nr_items = cpu_to_le32(1);
|
||||
/* XXX set bloom */
|
||||
ihdr = (void *)((char *)(lblk + 1) + SCOUTFS_BLOOM_FILTER_BYTES);
|
||||
iblk = buf;
|
||||
iblk->hdr = hdr;
|
||||
iblk->first = root_key;
|
||||
iblk->last = root_key;
|
||||
iblk->nr_items = cpu_to_le32(1);
|
||||
ihdr = (void *)(iblk + 1);
|
||||
ihdr->key = root_key;
|
||||
ihdr->len = cpu_to_le16(sizeof(struct scoutfs_inode));
|
||||
inode = (void *)(ihdr + 1);
|
||||
@@ -182,14 +109,67 @@ static int write_new_fs(char *path, int fd)
|
||||
inode->mtime.sec = inode->atime.sec;
|
||||
inode->mtime.nsec = inode->atime.nsec;
|
||||
|
||||
ret = write_block(fd, 3, &ring->hdr);
|
||||
ret = write_block(fd, blkno, &iblk->hdr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* write the two super bricks */
|
||||
for (i = 0; i < 2; i++) {
|
||||
super->hdr.seq = cpu_to_le64(i);
|
||||
ret = write_brick(fd, SCOUTFS_SUPER_BRICK + i, &super->hdr);
|
||||
/* write the ring block whose manifest entry references the log block */
|
||||
memset(buf, 0, SCOUTFS_BLOCK_SIZE);
|
||||
ring = buf;
|
||||
ring->hdr = hdr;
|
||||
ring->nr_entries = cpu_to_le16(2);
|
||||
ent = (void *)(ring + 1);
|
||||
ent->type = SCOUTFS_RING_ADD_MANIFEST;
|
||||
ent->len = cpu_to_le16(sizeof(*mani));
|
||||
mani = (void *)(ent + 1);
|
||||
mani->blkno = cpu_to_le64(blkno);
|
||||
mani->seq = hdr.seq;
|
||||
mani->level = 0;
|
||||
mani->first = root_key;
|
||||
mani->last = root_key;
|
||||
ent = (void *)(mani + 1);
|
||||
ent->type = SCOUTFS_RING_BITMAP;
|
||||
ent->len = cpu_to_le16(sizeof(*bm));
|
||||
bm = (void *)(ent + 1);
|
||||
memset(bm->bits, 0xff, sizeof(bm->bits));
|
||||
/* the first three blocks are allocated */
|
||||
bm->bits[0] = cpu_to_le64(~7ULL);
|
||||
bm->bits[1] = cpu_to_le64(~0ULL);
|
||||
|
||||
blkno += SCOUTFS_BLOCKS_PER_LOG;
|
||||
ret = write_block(fd, blkno, &ring->hdr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* the ring has a single block for now */
|
||||
memset(buf, 0, SCOUTFS_BLOCK_SIZE);
|
||||
lout = buf;
|
||||
lout->hdr = hdr;
|
||||
lout->nr_blocks = cpu_to_le32(1);
|
||||
lout->blknos[0] = cpu_to_le64(blkno);
|
||||
|
||||
blkno += SCOUTFS_BLOCKS_PER_LOG;
|
||||
ret = write_block(fd, blkno, &lout->hdr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* write the two super blocks */
|
||||
memset(buf, 0, SCOUTFS_BLOCK_SIZE);
|
||||
super = buf;
|
||||
super->hdr = hdr;
|
||||
super->id = cpu_to_le64(SCOUTFS_SUPER_ID);
|
||||
uuid_generate(super->uuid);
|
||||
super->total_logs = cpu_to_le64(total_logs);
|
||||
super->ring_layout_blkno = cpu_to_le64(blkno);
|
||||
super->ring_layout_nr_blocks = cpu_to_le64(1);
|
||||
super->ring_layout_seq = hdr.seq;
|
||||
super->ring_block = cpu_to_le64(0);
|
||||
super->ring_nr_blocks = cpu_to_le64(1);
|
||||
super->ring_seq = hdr.seq;
|
||||
|
||||
for (i = 0; i < SCOUTFS_SUPER_NR; i++) {
|
||||
super->hdr.seq = cpu_to_le64(i + 1);
|
||||
ret = write_block(fd, SCOUTFS_SUPER_BLKNO + i, &super->hdr);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
@@ -204,14 +184,13 @@ static int write_new_fs(char *path, int fd)
|
||||
uuid_unparse(super->uuid, uuid_str);
|
||||
|
||||
printf("Created scoutfs filesystem:\n"
|
||||
" total blocks: %llu\n"
|
||||
" total logs: %llu\n"
|
||||
" fsid: %llx\n"
|
||||
" uuid: %s\n",
|
||||
total_blocks, le64_to_cpu(super->hdr.fsid), uuid_str);
|
||||
total_logs, le64_to_cpu(super->hdr.fsid), uuid_str);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
free(super);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -22,20 +22,19 @@
|
||||
#define SKA(k) le64_to_cpu((k)->inode), (k)->type, \
|
||||
le64_to_cpu((k)->offset)
|
||||
|
||||
static void *read_buf(int fd, u64 nr, size_t size)
|
||||
static void *read_block(int fd, u64 blkno)
|
||||
{
|
||||
off_t off = nr * size;
|
||||
ssize_t ret;
|
||||
void *buf;
|
||||
|
||||
buf = malloc(size);
|
||||
buf = malloc(SCOUTFS_BLOCK_SIZE);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
ret = pread(fd, buf, size, off);
|
||||
if (ret != size) {
|
||||
fprintf(stderr, "read at blkno %llu (offset %llu) returned %zd: %s (%d)\n",
|
||||
nr, (long long)off, ret, strerror(errno), errno);
|
||||
ret = pread(fd, buf, SCOUTFS_BLOCK_SIZE, blkno << SCOUTFS_BLOCK_SHIFT);
|
||||
if (ret != SCOUTFS_BLOCK_SIZE) {
|
||||
fprintf(stderr, "read blkno %llu returned %zd: %s (%d)\n",
|
||||
blkno, ret, strerror(errno), errno);
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
@@ -43,19 +42,9 @@ static void *read_buf(int fd, u64 nr, size_t size)
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void *read_brick(int fd, u64 nr)
|
||||
static void print_block_header(struct scoutfs_block_header *hdr)
|
||||
{
|
||||
return read_buf(fd, nr, SCOUTFS_BRICK_SIZE);
|
||||
}
|
||||
|
||||
static void *read_block(int fd, u64 nr)
|
||||
{
|
||||
return read_buf(fd, nr, SCOUTFS_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static void print_header(struct scoutfs_header *hdr, size_t size)
|
||||
{
|
||||
u32 crc = crc_header(hdr, size);
|
||||
u32 crc = crc_block(hdr);
|
||||
char valid_str[40];
|
||||
|
||||
if (crc != le32_to_cpu(hdr->crc))
|
||||
@@ -67,19 +56,9 @@ static void print_header(struct scoutfs_header *hdr, size_t size)
|
||||
" crc: %08x %s\n"
|
||||
" fsid: %llx\n"
|
||||
" seq: %llu\n"
|
||||
" nr: %llu\n",
|
||||
" blkno: %llu\n",
|
||||
le32_to_cpu(hdr->crc), valid_str, le64_to_cpu(hdr->fsid),
|
||||
le64_to_cpu(hdr->seq), le64_to_cpu(hdr->nr));
|
||||
}
|
||||
|
||||
static void print_brick_header(struct scoutfs_header *hdr)
|
||||
{
|
||||
return print_header(hdr, SCOUTFS_BRICK_SIZE);
|
||||
}
|
||||
|
||||
static void print_block_header(struct scoutfs_header *hdr)
|
||||
{
|
||||
return print_header(hdr, SCOUTFS_BLOCK_SIZE);
|
||||
le64_to_cpu(hdr->seq), le64_to_cpu(hdr->blkno));
|
||||
}
|
||||
|
||||
static void print_inode(struct scoutfs_inode *inode)
|
||||
@@ -108,12 +87,12 @@ static void print_inode(struct scoutfs_inode *inode)
|
||||
le32_to_cpu(inode->mtime.nsec));
|
||||
}
|
||||
|
||||
static void print_item(struct scoutfs_item_header *ihdr, size_t off)
|
||||
static void print_item(struct scoutfs_item_header *ihdr)
|
||||
{
|
||||
printf(" item: &%zu\n"
|
||||
printf(" item:\n"
|
||||
" key: "SKF"\n"
|
||||
" len: %u\n",
|
||||
off, SKA(&ihdr->key), le16_to_cpu(ihdr->len));
|
||||
SKA(&ihdr->key), le16_to_cpu(ihdr->len));
|
||||
|
||||
switch(ihdr->key.type) {
|
||||
case SCOUTFS_INODE_KEY:
|
||||
@@ -122,49 +101,49 @@ static void print_item(struct scoutfs_item_header *ihdr, size_t off)
|
||||
}
|
||||
}
|
||||
|
||||
static int print_block(int fd, u64 nr)
|
||||
static int print_item_block(int fd, u64 nr)
|
||||
{
|
||||
struct scoutfs_item_header *ihdr;
|
||||
struct scoutfs_lsm_block *lblk;
|
||||
struct scoutfs_item_block *iblk;
|
||||
size_t off;
|
||||
int i;
|
||||
|
||||
lblk = read_block(fd, nr);
|
||||
if (!lblk)
|
||||
iblk = read_block(fd, nr);
|
||||
if (!iblk)
|
||||
return -ENOMEM;
|
||||
|
||||
printf("block: &%llu\n", le64_to_cpu(lblk->hdr.nr));
|
||||
print_block_header(&lblk->hdr);
|
||||
printf("item block:\n");
|
||||
print_block_header(&iblk->hdr);
|
||||
printf(" first: "SKF"\n"
|
||||
" last: "SKF"\n"
|
||||
" nr_items: %u\n",
|
||||
SKA(&lblk->first), SKA(&lblk->last),
|
||||
le32_to_cpu(lblk->nr_items));
|
||||
off = (char *)(lblk + 1) - (char *)lblk + SCOUTFS_BLOOM_FILTER_BYTES;
|
||||
SKA(&iblk->first), SKA(&iblk->last),
|
||||
le32_to_cpu(iblk->nr_items));
|
||||
|
||||
for (i = 0; i < le32_to_cpu(lblk->nr_items); i++) {
|
||||
ihdr = (void *)((char *)lblk + off);
|
||||
print_item(ihdr, off);
|
||||
off = sizeof(struct scoutfs_item_block);
|
||||
for (i = 0; i < le32_to_cpu(iblk->nr_items); i++) {
|
||||
ihdr = (void *)((char *)iblk + off);
|
||||
print_item(ihdr);
|
||||
|
||||
off += sizeof(struct scoutfs_item_header) +
|
||||
le16_to_cpu(ihdr->len);
|
||||
}
|
||||
|
||||
free(lblk);
|
||||
free(iblk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_blocks(int fd, __le64 *live_blocks, u64 total_blocks)
|
||||
static int print_log_blocks(int fd, __le64 *live_logs, u64 total_logs)
|
||||
{
|
||||
int ret = 0;
|
||||
int err;
|
||||
s64 nr;
|
||||
|
||||
while ((nr = find_first_le_bit(live_blocks, total_blocks)) >= 0) {
|
||||
clear_le_bit(live_blocks, nr);
|
||||
while ((nr = find_first_le_bit(live_logs, total_logs)) >= 0) {
|
||||
clear_le_bit(live_logs, nr);
|
||||
|
||||
err = print_block(fd, nr);
|
||||
err = print_item_block(fd, nr << SCOUTFS_LOG_BLOCK_SHIFT);
|
||||
if (!ret && err)
|
||||
ret = err;
|
||||
}
|
||||
@@ -186,32 +165,31 @@ static char *ent_type_str(u8 type)
|
||||
}
|
||||
}
|
||||
|
||||
static void print_ring_entry(int fd, struct scoutfs_ring_entry *ent,
|
||||
size_t off)
|
||||
static void print_ring_entry(int fd, struct scoutfs_ring_entry *ent)
|
||||
{
|
||||
struct scoutfs_ring_remove_manifest *rem;
|
||||
struct scoutfs_ring_add_manifest *add;
|
||||
struct scoutfs_ring_bitmap *bm;
|
||||
|
||||
printf(" entry: &%zu\n"
|
||||
printf(" entry:\n"
|
||||
" type: %u # %s\n"
|
||||
" len: %u\n",
|
||||
off, ent->type, ent_type_str(ent->type), le16_to_cpu(ent->len));
|
||||
ent->type, ent_type_str(ent->type), le16_to_cpu(ent->len));
|
||||
|
||||
switch(ent->type) {
|
||||
case SCOUTFS_RING_REMOVE_MANIFEST:
|
||||
rem = (void *)(ent + 1);
|
||||
printf(" block: %llu\n",
|
||||
le64_to_cpu(rem->block));
|
||||
printf(" blkno: %llu\n",
|
||||
le64_to_cpu(rem->blkno));
|
||||
break;
|
||||
case SCOUTFS_RING_ADD_MANIFEST:
|
||||
add = (void *)(ent + 1);
|
||||
printf(" block: %llu\n"
|
||||
printf(" blkno: %llu\n"
|
||||
" seq: %llu\n"
|
||||
" level: %u\n"
|
||||
" first: "SKF"\n"
|
||||
" last: "SKF"\n",
|
||||
le64_to_cpu(add->block), le64_to_cpu(add->seq),
|
||||
le64_to_cpu(add->blkno), le64_to_cpu(add->seq),
|
||||
add->level, SKA(&add->first), SKA(&add->last));
|
||||
break;
|
||||
case SCOUTFS_RING_BITMAP:
|
||||
@@ -224,51 +202,51 @@ static void print_ring_entry(int fd, struct scoutfs_ring_entry *ent,
|
||||
}
|
||||
}
|
||||
|
||||
static void update_live_blocks(struct scoutfs_ring_entry *ent,
|
||||
__le64 *live_blocks)
|
||||
static void update_live_logs(struct scoutfs_ring_entry *ent,
|
||||
__le64 *live_logs)
|
||||
{
|
||||
struct scoutfs_ring_remove_manifest *rem;
|
||||
struct scoutfs_ring_add_manifest *add;
|
||||
u64 bit;
|
||||
|
||||
switch(ent->type) {
|
||||
case SCOUTFS_RING_REMOVE_MANIFEST:
|
||||
rem = (void *)(ent + 1);
|
||||
clear_le_bit(live_blocks, le64_to_cpu(rem->block));
|
||||
bit = le64_to_cpu(rem->blkno) >> SCOUTFS_LOG_BLOCK_SHIFT;
|
||||
clear_le_bit(live_logs, bit);
|
||||
break;
|
||||
case SCOUTFS_RING_ADD_MANIFEST:
|
||||
add = (void *)(ent + 1);
|
||||
set_le_bit(live_blocks, le64_to_cpu(add->block));
|
||||
bit = le64_to_cpu(add->blkno) >> SCOUTFS_LOG_BLOCK_SHIFT;
|
||||
set_le_bit(live_logs, bit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int print_ring_block(int fd, u64 block_nr, __le64 *live_blocks)
|
||||
static int print_ring_block(int fd, u64 blkno, __le64 *live_logs)
|
||||
{
|
||||
struct scoutfs_ring_brick *ring;
|
||||
struct scoutfs_ring_block *ring;
|
||||
struct scoutfs_ring_entry *ent;
|
||||
size_t off;
|
||||
int ret = 0;
|
||||
u64 nr;
|
||||
int i;
|
||||
|
||||
/* XXX just printing the first brick for now */
|
||||
/* XXX just printing the first block for now */
|
||||
|
||||
nr = block_nr << SCOUTFS_BLOCK_BRICK;
|
||||
ring = read_brick(fd, nr);
|
||||
ring = read_block(fd, blkno);
|
||||
if (!ring)
|
||||
return -ENOMEM;
|
||||
|
||||
printf("ring brick: &%llu\n", nr);
|
||||
print_brick_header(&ring->hdr);
|
||||
printf("ring block:\n");
|
||||
print_block_header(&ring->hdr);
|
||||
printf(" nr_entries: %u\n", le16_to_cpu(ring->nr_entries));
|
||||
|
||||
off = sizeof(struct scoutfs_ring_brick);
|
||||
off = sizeof(struct scoutfs_ring_block);
|
||||
for (i = 0; i < le16_to_cpu(ring->nr_entries); i++) {
|
||||
ent = (void *)((char *)ring + off);
|
||||
|
||||
update_live_blocks(ent, live_blocks);
|
||||
|
||||
print_ring_entry(fd, ent, off);
|
||||
update_live_logs(ent, live_logs);
|
||||
print_ring_entry(fd, ent);
|
||||
|
||||
off += sizeof(struct scoutfs_ring_entry) +
|
||||
le16_to_cpu(ent->len);
|
||||
@@ -278,95 +256,97 @@ static int print_ring_block(int fd, u64 block_nr, __le64 *live_blocks)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int print_ring_layout(int fd, u64 blkno, __le64 *live_blocks)
|
||||
static int print_layout_block(int fd, u64 blkno, __le64 *live_logs)
|
||||
{
|
||||
struct scoutfs_ring_layout *rlo;
|
||||
struct scoutfs_layout_block *lout;
|
||||
int ret = 0;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
rlo = read_block(fd, blkno);
|
||||
if (!rlo)
|
||||
lout = read_block(fd, blkno);
|
||||
if (!lout)
|
||||
return -ENOMEM;
|
||||
|
||||
printf("ring layout: &%llu\n", blkno);
|
||||
print_block_header(&rlo->hdr);
|
||||
printf(" nr_blocks: %u\n", le32_to_cpu(rlo->nr_blocks));
|
||||
printf("layout block:\n");
|
||||
print_block_header(&lout->hdr);
|
||||
printf(" nr_blocks: %u\n", le32_to_cpu(lout->nr_blocks));
|
||||
|
||||
printf(" blocks: ");
|
||||
for (i = 0; i < le32_to_cpu(rlo->nr_blocks); i++)
|
||||
printf(" %llu\n", le64_to_cpu(rlo->blocks[i]));
|
||||
printf(" blknos: ");
|
||||
for (i = 0; i < le32_to_cpu(lout->nr_blocks); i++)
|
||||
printf(" %llu\n", le64_to_cpu(lout->blknos[i]));
|
||||
|
||||
for (i = 0; i < le32_to_cpu(rlo->nr_blocks); i++) {
|
||||
err = print_ring_block(fd, le64_to_cpu(rlo->blocks[i]),
|
||||
live_blocks);
|
||||
for (i = 0; i < le32_to_cpu(lout->nr_blocks); i++) {
|
||||
err = print_ring_block(fd, le64_to_cpu(lout->blknos[i]),
|
||||
live_logs);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
}
|
||||
|
||||
free(rlo);
|
||||
free(lout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_super_brick(int fd)
|
||||
{
|
||||
struct scoutfs_super *super;
|
||||
struct scoutfs_super_block *super;
|
||||
char uuid_str[37];
|
||||
__le64 *live_blocks;
|
||||
u64 total_blocks;
|
||||
__le64 *live_logs;
|
||||
u64 total_logs;
|
||||
size_t bytes;
|
||||
int ret = 0;
|
||||
int err;
|
||||
|
||||
/* XXX print both */
|
||||
super = read_brick(fd, SCOUTFS_SUPER_BRICK);
|
||||
super = read_block(fd, SCOUTFS_SUPER_BLKNO);
|
||||
if (!super)
|
||||
return -ENOMEM;
|
||||
|
||||
uuid_unparse(super->uuid, uuid_str);
|
||||
|
||||
total_blocks = le64_to_cpu(super->total_blocks);
|
||||
total_logs = le64_to_cpu(super->total_logs);
|
||||
|
||||
printf("super: &%llu\n", le64_to_cpu(super->hdr.nr));
|
||||
print_brick_header(&super->hdr);
|
||||
printf("super:\n");
|
||||
print_block_header(&super->hdr);
|
||||
printf(" id: %llx\n"
|
||||
" uuid: %s\n"
|
||||
" total_blocks: %llu\n"
|
||||
" ring_layout_block: %llu\n"
|
||||
" total_logs: %llu\n"
|
||||
" ring_layout_blkno: %llu\n"
|
||||
" ring_layout_nr_blocks: %llu\n"
|
||||
" ring_layout_seq: %llu\n"
|
||||
" last_ring_brick: %llu\n"
|
||||
" last_ring_seq: %llu\n"
|
||||
" last_block_seq: %llu\n",
|
||||
" ring_block: %llu\n"
|
||||
" ring_seq: %llu\n"
|
||||
" ring_nr_blocks: %llu\n",
|
||||
le64_to_cpu(super->id),
|
||||
uuid_str,
|
||||
total_blocks,
|
||||
le64_to_cpu(super->ring_layout_block),
|
||||
total_logs,
|
||||
le64_to_cpu(super->ring_layout_blkno),
|
||||
le64_to_cpu(super->ring_layout_nr_blocks),
|
||||
le64_to_cpu(super->ring_layout_seq),
|
||||
le64_to_cpu(super->last_ring_brick),
|
||||
le64_to_cpu(super->last_ring_seq),
|
||||
le64_to_cpu(super->last_block_seq));
|
||||
le64_to_cpu(super->ring_block),
|
||||
le64_to_cpu(super->ring_nr_blocks),
|
||||
le64_to_cpu(super->ring_seq));
|
||||
|
||||
/* XXX by hand? */
|
||||
bytes = (total_blocks + 63) / 8;
|
||||
live_blocks = malloc(bytes);
|
||||
if (!live_blocks) {
|
||||
bytes = (total_logs + 63) / 8;
|
||||
live_logs = malloc(bytes);
|
||||
if (!live_logs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset(live_blocks, 0, bytes);
|
||||
memset(live_logs, 0, bytes);
|
||||
|
||||
err = print_ring_layout(fd, le64_to_cpu(super->ring_layout_block),
|
||||
live_blocks);
|
||||
err = print_layout_block(fd, le64_to_cpu(super->ring_layout_blkno),
|
||||
live_logs);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
|
||||
err = print_blocks(fd, live_blocks, total_blocks);
|
||||
err = print_log_blocks(fd, live_logs, total_logs);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
|
||||
out:
|
||||
free(super);
|
||||
free(live_blocks);
|
||||
free(live_logs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user