aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2011-09-09 18:34:51 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-09-09 18:34:51 -0400
commit281b59959707dfae03ce038cdf231bf4904e170c (patch)
tree3a6b36d060a41b19351c29c51d079149cae7511c /fs/ext4/super.c
parent7c2e70879fc0949b4220ee61b7c4553f6976a94d (diff)
ext4: read-only support for bigalloc file systems
This adds supports for bigalloc file systems. It teaches the mount code just enough about bigalloc superblock fields that it will mount the file system without freaking out that the number of blocks per group is too big. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 5dcd0dacc591..823e7d9deee2 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1953,7 +1953,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
1953 res = MS_RDONLY; 1953 res = MS_RDONLY;
1954 } 1954 }
1955 if (read_only) 1955 if (read_only)
1956 return res; 1956 goto done;
1957 if (!(sbi->s_mount_state & EXT4_VALID_FS)) 1957 if (!(sbi->s_mount_state & EXT4_VALID_FS))
1958 ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, " 1958 ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "
1959 "running e2fsck is recommended"); 1959 "running e2fsck is recommended");
@@ -1984,6 +1984,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
1984 EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 1984 EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
1985 1985
1986 ext4_commit_super(sb, 1); 1986 ext4_commit_super(sb, 1);
1987done:
1987 if (test_opt(sb, DEBUG)) 1988 if (test_opt(sb, DEBUG))
1988 printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, " 1989 printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
1989 "bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n", 1990 "bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n",
@@ -3105,10 +3106,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3105 char *cp; 3106 char *cp;
3106 const char *descr; 3107 const char *descr;
3107 int ret = -ENOMEM; 3108 int ret = -ENOMEM;
3108 int blocksize; 3109 int blocksize, clustersize;
3109 unsigned int db_count; 3110 unsigned int db_count;
3110 unsigned int i; 3111 unsigned int i;
3111 int needs_recovery, has_huge_files; 3112 int needs_recovery, has_huge_files, has_bigalloc;
3112 __u64 blocks_count; 3113 __u64 blocks_count;
3113 int err; 3114 int err;
3114 unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; 3115 unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
@@ -3412,12 +3413,53 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3412 sb->s_dirt = 1; 3413 sb->s_dirt = 1;
3413 } 3414 }
3414 3415
3415 if (sbi->s_blocks_per_group > blocksize * 8) { 3416 /* Handle clustersize */
3416 ext4_msg(sb, KERN_ERR, 3417 clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size);
3417 "#blocks per group too big: %lu", 3418 has_bigalloc = EXT4_HAS_RO_COMPAT_FEATURE(sb,
3418 sbi->s_blocks_per_group); 3419 EXT4_FEATURE_RO_COMPAT_BIGALLOC);
3419 goto failed_mount; 3420 if (has_bigalloc) {
3421 if (clustersize < blocksize) {
3422 ext4_msg(sb, KERN_ERR,
3423 "cluster size (%d) smaller than "
3424 "block size (%d)", clustersize, blocksize);
3425 goto failed_mount;
3426 }
3427 sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
3428 le32_to_cpu(es->s_log_block_size);
3429 sbi->s_clusters_per_group =
3430 le32_to_cpu(es->s_clusters_per_group);
3431 if (sbi->s_clusters_per_group > blocksize * 8) {
3432 ext4_msg(sb, KERN_ERR,
3433 "#clusters per group too big: %lu",
3434 sbi->s_clusters_per_group);
3435 goto failed_mount;
3436 }
3437 if (sbi->s_blocks_per_group !=
3438 (sbi->s_clusters_per_group * (clustersize / blocksize))) {
3439 ext4_msg(sb, KERN_ERR, "blocks per group (%lu) and "
3440 "clusters per group (%lu) inconsistent",
3441 sbi->s_blocks_per_group,
3442 sbi->s_clusters_per_group);
3443 goto failed_mount;
3444 }
3445 } else {
3446 if (clustersize != blocksize) {
3447 ext4_warning(sb, "fragment/cluster size (%d) != "
3448 "block size (%d)", clustersize,
3449 blocksize);
3450 clustersize = blocksize;
3451 }
3452 if (sbi->s_blocks_per_group > blocksize * 8) {
3453 ext4_msg(sb, KERN_ERR,
3454 "#blocks per group too big: %lu",
3455 sbi->s_blocks_per_group);
3456 goto failed_mount;
3457 }
3458 sbi->s_clusters_per_group = sbi->s_blocks_per_group;
3459 sbi->s_cluster_bits = 0;
3420 } 3460 }
3461 sbi->s_cluster_ratio = clustersize / blocksize;
3462
3421 if (sbi->s_inodes_per_group > blocksize * 8) { 3463 if (sbi->s_inodes_per_group > blocksize * 8) {
3422 ext4_msg(sb, KERN_ERR, 3464 ext4_msg(sb, KERN_ERR,
3423 "#inodes per group too big: %lu", 3465 "#inodes per group too big: %lu",