|
@@ -55,6 +55,12 @@
|
|
#include <asm/cpufeature.h>
|
|
#include <asm/cpufeature.h>
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#define BTRFS_SUPER_FLAG_SUPP (BTRFS_HEADER_FLAG_WRITTEN |\
|
|
|
|
+ BTRFS_HEADER_FLAG_RELOC |\
|
|
|
|
+ BTRFS_SUPER_FLAG_ERROR |\
|
|
|
|
+ BTRFS_SUPER_FLAG_SEEDING |\
|
|
|
|
+ BTRFS_SUPER_FLAG_METADUMP)
|
|
|
|
+
|
|
static const struct extent_io_ops btree_extent_io_ops;
|
|
static const struct extent_io_ops btree_extent_io_ops;
|
|
static void end_workqueue_fn(struct btrfs_work *work);
|
|
static void end_workqueue_fn(struct btrfs_work *work);
|
|
static void free_fs_root(struct btrfs_root *root);
|
|
static void free_fs_root(struct btrfs_root *root);
|
|
@@ -2760,26 +2766,6 @@ int open_ctree(struct super_block *sb,
|
|
goto fail_alloc;
|
|
goto fail_alloc;
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * Leafsize and nodesize were always equal, this is only a sanity check.
|
|
|
|
- */
|
|
|
|
- if (le32_to_cpu(disk_super->__unused_leafsize) !=
|
|
|
|
- btrfs_super_nodesize(disk_super)) {
|
|
|
|
- printk(KERN_ERR "BTRFS: couldn't mount because metadata "
|
|
|
|
- "blocksizes don't match. node %d leaf %d\n",
|
|
|
|
- btrfs_super_nodesize(disk_super),
|
|
|
|
- le32_to_cpu(disk_super->__unused_leafsize));
|
|
|
|
- err = -EINVAL;
|
|
|
|
- goto fail_alloc;
|
|
|
|
- }
|
|
|
|
- if (btrfs_super_nodesize(disk_super) > BTRFS_MAX_METADATA_BLOCKSIZE) {
|
|
|
|
- printk(KERN_ERR "BTRFS: couldn't mount because metadata "
|
|
|
|
- "blocksize (%d) was too large\n",
|
|
|
|
- btrfs_super_nodesize(disk_super));
|
|
|
|
- err = -EINVAL;
|
|
|
|
- goto fail_alloc;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
features = btrfs_super_incompat_flags(disk_super);
|
|
features = btrfs_super_incompat_flags(disk_super);
|
|
features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF;
|
|
features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF;
|
|
if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO)
|
|
if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO)
|
|
@@ -2851,17 +2837,6 @@ int open_ctree(struct super_block *sb,
|
|
sb->s_blocksize = sectorsize;
|
|
sb->s_blocksize = sectorsize;
|
|
sb->s_blocksize_bits = blksize_bits(sectorsize);
|
|
sb->s_blocksize_bits = blksize_bits(sectorsize);
|
|
|
|
|
|
- if (btrfs_super_magic(disk_super) != BTRFS_MAGIC) {
|
|
|
|
- printk(KERN_ERR "BTRFS: valid FS not found on %s\n", sb->s_id);
|
|
|
|
- goto fail_sb_buffer;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (sectorsize != PAGE_SIZE) {
|
|
|
|
- printk(KERN_ERR "BTRFS: incompatible sector size (%lu) "
|
|
|
|
- "found on %s\n", (unsigned long)sectorsize, sb->s_id);
|
|
|
|
- goto fail_sb_buffer;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
mutex_lock(&fs_info->chunk_mutex);
|
|
mutex_lock(&fs_info->chunk_mutex);
|
|
ret = btrfs_read_sys_array(tree_root);
|
|
ret = btrfs_read_sys_array(tree_root);
|
|
mutex_unlock(&fs_info->chunk_mutex);
|
|
mutex_unlock(&fs_info->chunk_mutex);
|
|
@@ -4048,8 +4023,17 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
|
|
int read_only)
|
|
int read_only)
|
|
{
|
|
{
|
|
struct btrfs_super_block *sb = fs_info->super_copy;
|
|
struct btrfs_super_block *sb = fs_info->super_copy;
|
|
|
|
+ u64 nodesize = btrfs_super_nodesize(sb);
|
|
|
|
+ u64 sectorsize = btrfs_super_sectorsize(sb);
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
|
|
+ if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
|
|
|
|
+ printk(KERN_ERR "BTRFS: no valid FS found\n");
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ if (btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP)
|
|
|
|
+ printk(KERN_WARNING "BTRFS: unrecognized super flag: %llu\n",
|
|
|
|
+ btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
|
|
if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
|
if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
|
|
printk(KERN_ERR "BTRFS: tree_root level too big: %d >= %d\n",
|
|
printk(KERN_ERR "BTRFS: tree_root level too big: %d >= %d\n",
|
|
btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
|
|
btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
|
|
@@ -4067,31 +4051,46 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * The common minimum, we don't know if we can trust the nodesize/sectorsize
|
|
|
|
- * items yet, they'll be verified later. Issue just a warning.
|
|
|
|
|
|
+ * Check sectorsize and nodesize first, other check will need it.
|
|
|
|
+ * Check all possible sectorsize(4K, 8K, 16K, 32K, 64K) here.
|
|
*/
|
|
*/
|
|
- if (!IS_ALIGNED(btrfs_super_root(sb), 4096))
|
|
|
|
|
|
+ if (!is_power_of_2(sectorsize) || sectorsize < 4096 ||
|
|
|
|
+ sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
|
|
|
|
+ printk(KERN_ERR "BTRFS: invalid sectorsize %llu\n", sectorsize);
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ /* Only PAGE SIZE is supported yet */
|
|
|
|
+ if (sectorsize != PAGE_CACHE_SIZE) {
|
|
|
|
+ printk(KERN_ERR "BTRFS: sectorsize %llu not supported yet, only support %lu\n",
|
|
|
|
+ sectorsize, PAGE_CACHE_SIZE);
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ if (!is_power_of_2(nodesize) || nodesize < sectorsize ||
|
|
|
|
+ nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
|
|
|
|
+ printk(KERN_ERR "BTRFS: invalid nodesize %llu\n", nodesize);
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ if (nodesize != le32_to_cpu(sb->__unused_leafsize)) {
|
|
|
|
+ printk(KERN_ERR "BTRFS: invalid leafsize %u, should be %llu\n",
|
|
|
|
+ le32_to_cpu(sb->__unused_leafsize),
|
|
|
|
+ nodesize);
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Root alignment check */
|
|
|
|
+ if (!IS_ALIGNED(btrfs_super_root(sb), sectorsize)) {
|
|
printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
|
|
printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
|
|
btrfs_super_root(sb));
|
|
btrfs_super_root(sb));
|
|
- if (!IS_ALIGNED(btrfs_super_chunk_root(sb), 4096))
|
|
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ if (!IS_ALIGNED(btrfs_super_chunk_root(sb), sectorsize)) {
|
|
printk(KERN_WARNING "BTRFS: chunk_root block unaligned: %llu\n",
|
|
printk(KERN_WARNING "BTRFS: chunk_root block unaligned: %llu\n",
|
|
btrfs_super_chunk_root(sb));
|
|
btrfs_super_chunk_root(sb));
|
|
- if (!IS_ALIGNED(btrfs_super_log_root(sb), 4096))
|
|
|
|
- printk(KERN_WARNING "BTRFS: log_root block unaligned: %llu\n",
|
|
|
|
- btrfs_super_log_root(sb));
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Check the lower bound, the alignment and other constraints are
|
|
|
|
- * checked later.
|
|
|
|
- */
|
|
|
|
- if (btrfs_super_nodesize(sb) < 4096) {
|
|
|
|
- printk(KERN_ERR "BTRFS: nodesize too small: %u < 4096\n",
|
|
|
|
- btrfs_super_nodesize(sb));
|
|
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
}
|
|
}
|
|
- if (btrfs_super_sectorsize(sb) < 4096) {
|
|
|
|
- printk(KERN_ERR "BTRFS: sectorsize too small: %u < 4096\n",
|
|
|
|
- btrfs_super_sectorsize(sb));
|
|
|
|
|
|
+ if (!IS_ALIGNED(btrfs_super_log_root(sb), sectorsize)) {
|
|
|
|
+ printk(KERN_WARNING "BTRFS: log_root block unaligned: %llu\n",
|
|
|
|
+ btrfs_super_log_root(sb));
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
}
|
|
}
|
|
|
|
|