mirror of
https://github.com/versity/scoutfs.git
synced 2026-05-31 16:56:18 +00:00
Generic block header checks: crc, magic.
Generally as we call block_get() we should validate that if the block has a hdr, at a minimum the crc is correct and the magic value is the expected value passed, and the fsid matches the superblock. This function implements just that. Returns -EINVAL, up to the caller to report a problem() and handle the outcome. For now the code just hard fails, which incedentally makes it fail the clobber-repair.sh tests I wrote. Signed-off-by: Auke Kok <auke.kok@versity.com>
This commit is contained in:
@@ -50,6 +50,10 @@ int alloc_list_meta_iter(struct scoutfs_alloc_list_head *lhead, extent_cb_t cb,
|
||||
|
||||
lblk = block_buf(blk);
|
||||
/* XXX verify block */
|
||||
ret = block_hdr_valid(blk, blkno, 0, SCOUTFS_BLOCK_MAGIC_ALLOC_LIST);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* XXX sort? maybe */
|
||||
|
||||
ref = lblk->next;
|
||||
@@ -89,6 +93,9 @@ int alloc_list_extent_iter(struct scoutfs_alloc_list_head *lhead, extent_cb_t cb
|
||||
|
||||
lblk = block_buf(blk);
|
||||
/* XXX verify block */
|
||||
ret = block_hdr_valid(blk, blkno, 0, SCOUTFS_BLOCK_MAGIC_ALLOC_LIST);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/* XXX sort? maybe */
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
|
||||
#include "block.h"
|
||||
#include "debug.h"
|
||||
#include "super.h"
|
||||
#include "eno.h"
|
||||
#include "crc.h"
|
||||
#include "sns.h"
|
||||
|
||||
static struct block_data {
|
||||
struct list_head *hash_lists;
|
||||
@@ -297,6 +300,45 @@ static struct list_head *hash_bucket(struct block_data *bdat, u64 blkno)
|
||||
return &bdat->hash_lists[hash % bdat->hash_nr];
|
||||
}
|
||||
|
||||
int block_hdr_valid(struct block *blk, u64 blkno, int bf, u32 magic)
|
||||
{
|
||||
struct scoutfs_block_header *hdr;
|
||||
size_t size = (bf & BF_SM) ? SCOUTFS_BLOCK_SM_SIZE : SCOUTFS_BLOCK_LG_SIZE;
|
||||
int ret;
|
||||
u32 crc;
|
||||
|
||||
ret = block_get(&blk, blkno, bf);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "error reading block %llu\n", blkno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = block_buf(blk);
|
||||
|
||||
crc = crc_block(hdr, size);
|
||||
|
||||
if ((le32_to_cpu(hdr->crc) != crc) ||
|
||||
(le32_to_cpu(hdr->magic) != magic))
|
||||
ret = -EINVAL;
|
||||
|
||||
/*
|
||||
* Our first caller fills in global_super. Until this completes,
|
||||
* we can't do this check.
|
||||
*/
|
||||
if ((blkno != SCOUTFS_SUPER_BLKNO) &&
|
||||
(hdr->fsid != global_super->hdr.fsid))
|
||||
ret = -EINVAL;
|
||||
|
||||
block_put(&blk);
|
||||
|
||||
debug("%s blk_hdr_valid blkno %llu size %lu crc 0x%08x magic 0x%08x ret %d",
|
||||
sns_str(), blkno, size, le32_to_cpu(hdr->crc), le32_to_cpu(hdr->magic),
|
||||
ret);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct block *get_or_alloc(struct block_data *bdat, u64 blkno, int bf)
|
||||
{
|
||||
struct list_head *bucket = hash_bucket(bdat, blkno);
|
||||
|
||||
@@ -29,4 +29,6 @@ int block_try_commit(bool force);
|
||||
int block_setup(int meta_fd, size_t max_cached_bytes, size_t max_dirty_bytes);
|
||||
void block_shutdown(void);
|
||||
|
||||
int block_hdr_valid(struct block *blk, u64 blkno, int bf, u32 magic);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -88,6 +88,10 @@ static int btree_ref_meta_iter(struct scoutfs_block_ref *ref, unsigned level, ex
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = block_hdr_valid(blk, blkno, 0, SCOUTFS_BLOCK_MAGIC_BTREE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
sns_push("btree_parent", blkno, 0);
|
||||
|
||||
bt = block_buf(blk);
|
||||
@@ -157,6 +161,10 @@ static int btree_ref_item_iter(struct scoutfs_block_ref *ref, unsigned level,
|
||||
else
|
||||
sns_push("btree_leaf", blkno, 0);
|
||||
|
||||
ret = block_hdr_valid(blk, blkno, 0, SCOUTFS_BLOCK_MAGIC_BTREE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bt = block_buf(blk);
|
||||
|
||||
/* XXX integrate verification with block cache */
|
||||
|
||||
@@ -28,6 +28,8 @@ int check_supers(void)
|
||||
struct block *blk = NULL;
|
||||
int ret;
|
||||
|
||||
sns_push("supers", 0, 0);
|
||||
|
||||
global_super = malloc(sizeof(struct scoutfs_super_block));
|
||||
if (!global_super) {
|
||||
fprintf(stderr, "error allocating super block buffer\n");
|
||||
@@ -41,6 +43,10 @@ int check_supers(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = block_hdr_valid(blk, SCOUTFS_SUPER_BLKNO, BF_SM, SCOUTFS_BLOCK_MAGIC_SUPER);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
super = block_buf(blk);
|
||||
|
||||
memcpy(global_super, super, sizeof(struct scoutfs_super_block));
|
||||
@@ -48,6 +54,8 @@ int check_supers(void)
|
||||
out:
|
||||
block_put(&blk);
|
||||
|
||||
sns_pop();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user