diff --git a/kmod/src/Makefile b/kmod/src/Makefile index 14e8d5a4..5f23e87d 100644 --- a/kmod/src/Makefile +++ b/kmod/src/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_SCOUTFS_FS) := scoutfs.o -scoutfs-y += dir.o inode.o item.o msg.o super.o +scoutfs-y += block.o dir.o inode.o item.o msg.o super.o diff --git a/kmod/src/block.c b/kmod/src/block.c new file mode 100644 index 00000000..cb403465 --- /dev/null +++ b/kmod/src/block.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Versity Software, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include + +#include "super.h" +#include "format.h" +#include "block.h" +#include "crc.h" + +#define BH_Private_Verified BH_PrivateStart + +BUFFER_FNS(Private_Verified, private_verified) + + +/* + * A quick metadata read wrapper which knows how to validate the + * block header. + */ +struct buffer_head *scoutfs_read_block(struct super_block *sb, u64 blkno) +{ + struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); + struct scoutfs_super_block *super = &sbi->super; + struct scoutfs_block_header *hdr; + struct buffer_head *bh; + u32 crc; + + bh = sb_bread(sb, blkno); + if (!bh || buffer_private_verified(bh)) + return bh; + + hdr = (void *)bh->b_data; + crc = scoutfs_crc_block(hdr); + + if (le32_to_cpu(hdr->crc) != crc) { + printk("blkno %llu hdr crc %x != calculated %x\n", blkno, + le32_to_cpu(hdr->crc), crc); + } else if (super->hdr.fsid && hdr->fsid != super->hdr.fsid) { + printk("blkno %llu fsid %llx != super fsid %llx\n", blkno, + le64_to_cpu(hdr->fsid), le64_to_cpu(super->hdr.fsid)); + } else if (le64_to_cpu(hdr->blkno) != blkno) { + printk("blkno %llu invalid hdr blkno %llx\n", blkno, + le64_to_cpu(hdr->blkno)); + } else { + set_buffer_private_verified(bh); + return bh; + } + + brelse(bh); + return NULL; +} diff --git a/kmod/src/block.h b/kmod/src/block.h new file mode 100644 index 00000000..c87fb6b8 --- /dev/null +++ b/kmod/src/block.h @@ -0,0 +1,6 @@ +#ifndef _SCOUTFS_BLOCK_H_ +#define _SCOUTFS_BLOCK_H_ + +struct buffer_head *scoutfs_read_block(struct super_block *sb, u64 blkno); + +#endif diff --git a/kmod/src/crc.c b/kmod/src/crc.c new file mode 100644 index 00000000..9869cbd1 --- /dev/null +++ b/kmod/src/crc.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2015 Versity Software, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include + +#include "format.h" +#include "crc.h" + +u32 scoutfs_crc_block(struct scoutfs_block_header *hdr) +{ + return crc32c(~0, (char *)hdr + sizeof(hdr->crc), + SCOUTFS_BLOCK_SIZE - sizeof(hdr->crc)); +} diff --git a/kmod/src/crc.h b/kmod/src/crc.h new file mode 100644 index 00000000..7f1fbf56 --- /dev/null +++ b/kmod/src/crc.h @@ -0,0 +1,6 @@ +#ifndef _SCOUTFS_CRC_H_ +#define _SCOUTFS_CRC_H_ + +u32 scoutfs_crc_block(struct scoutfs_block_header *hdr); + +#endif diff --git a/kmod/src/super.c b/kmod/src/super.c index b14f495d..27e12c52 100644 --- a/kmod/src/super.c +++ b/kmod/src/super.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include "super.h" @@ -24,6 +23,7 @@ #include "inode.h" #include "dir.h" #include "msg.h" +#include "block.h" static const struct super_operations scoutfs_super_ops = { .alloc_inode = scoutfs_alloc_inode, @@ -36,13 +36,12 @@ static int read_supers(struct super_block *sb) struct scoutfs_super_block *super; struct buffer_head *bh = NULL; int found = -1; - u32 crc; int i; for (i = 0; i < SCOUTFS_SUPER_NR; i++) { if (bh) brelse(bh); - bh = sb_bread(sb, SCOUTFS_SUPER_BLKNO + i); + bh = scoutfs_read_block(sb, SCOUTFS_SUPER_BLKNO + i); if (!bh) { scoutfs_warn(sb, "couldn't read super block %u", i); continue; @@ -56,14 +55,6 @@ static int read_supers(struct super_block *sb) continue; } - crc = crc32c(~0, (char *)&super->hdr.crc + sizeof(crc), - SCOUTFS_BLOCK_SIZE - sizeof(crc)); - if (crc != le32_to_cpu(super->hdr.crc)) { - scoutfs_warn(sb, "super block %u has bad crc %x (expected %x)", - i, crc, le32_to_cpu(super->hdr.crc)); - continue; - } - if (found < 0 || (le64_to_cpu(super->hdr.seq) > le64_to_cpu(sbi->super.hdr.seq))) { memcpy(&sbi->super, super,