diff options
-rw-r--r-- | fs/ext4/ext4.h | 17 | ||||
-rw-r--r-- | fs/ext4/super.c | 58 |
2 files changed, 64 insertions, 11 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 48ae98819d35..f7257aa6bf81 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -239,8 +239,11 @@ struct ext4_io_submit { | |||
239 | # define EXT4_BLOCK_SIZE(s) (EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size) | 239 | # define EXT4_BLOCK_SIZE(s) (EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size) |
240 | #endif | 240 | #endif |
241 | #define EXT4_ADDR_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / sizeof(__u32)) | 241 | #define EXT4_ADDR_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / sizeof(__u32)) |
242 | #define EXT4_CLUSTER_SIZE(s) (EXT4_BLOCK_SIZE(s) << \ | ||
243 | EXT4_SB(s)->s_cluster_bits) | ||
242 | #ifdef __KERNEL__ | 244 | #ifdef __KERNEL__ |
243 | # define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) | 245 | # define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) |
246 | # define EXT4_CLUSTER_BITS(s) (EXT4_SB(s)->s_cluster_bits) | ||
244 | #else | 247 | #else |
245 | # define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) | 248 | # define EXT4_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) |
246 | #endif | 249 | #endif |
@@ -306,6 +309,7 @@ struct flex_groups { | |||
306 | #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) | 309 | #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) |
307 | #ifdef __KERNEL__ | 310 | #ifdef __KERNEL__ |
308 | # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) | 311 | # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) |
312 | # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) | ||
309 | # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) | 313 | # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) |
310 | # define EXT4_INODES_PER_GROUP(s) (EXT4_SB(s)->s_inodes_per_group) | 314 | # define EXT4_INODES_PER_GROUP(s) (EXT4_SB(s)->s_inodes_per_group) |
311 | # define EXT4_DESC_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_desc_per_block_bits) | 315 | # define EXT4_DESC_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_desc_per_block_bits) |
@@ -975,9 +979,9 @@ struct ext4_super_block { | |||
975 | /*10*/ __le32 s_free_inodes_count; /* Free inodes count */ | 979 | /*10*/ __le32 s_free_inodes_count; /* Free inodes count */ |
976 | __le32 s_first_data_block; /* First Data Block */ | 980 | __le32 s_first_data_block; /* First Data Block */ |
977 | __le32 s_log_block_size; /* Block size */ | 981 | __le32 s_log_block_size; /* Block size */ |
978 | __le32 s_obso_log_frag_size; /* Obsoleted fragment size */ | 982 | __le32 s_log_cluster_size; /* Allocation cluster size */ |
979 | /*20*/ __le32 s_blocks_per_group; /* # Blocks per group */ | 983 | /*20*/ __le32 s_blocks_per_group; /* # Blocks per group */ |
980 | __le32 s_obso_frags_per_group; /* Obsoleted fragments per group */ | 984 | __le32 s_clusters_per_group; /* # Clusters per group */ |
981 | __le32 s_inodes_per_group; /* # Inodes per group */ | 985 | __le32 s_inodes_per_group; /* # Inodes per group */ |
982 | __le32 s_mtime; /* Mount time */ | 986 | __le32 s_mtime; /* Mount time */ |
983 | /*30*/ __le32 s_wtime; /* Write time */ | 987 | /*30*/ __le32 s_wtime; /* Write time */ |
@@ -1073,7 +1077,10 @@ struct ext4_super_block { | |||
1073 | __u8 s_last_error_func[32]; /* function where the error happened */ | 1077 | __u8 s_last_error_func[32]; /* function where the error happened */ |
1074 | #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts) | 1078 | #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts) |
1075 | __u8 s_mount_opts[64]; | 1079 | __u8 s_mount_opts[64]; |
1076 | __le32 s_reserved[112]; /* Padding to the end of the block */ | 1080 | __le32 s_usr_quota_inum; /* inode for tracking user quota */ |
1081 | __le32 s_grp_quota_inum; /* inode for tracking group quota */ | ||
1082 | __le32 s_overhead_clusters; /* overhead blocks/clusters in fs */ | ||
1083 | __le32 s_reserved[109]; /* Padding to the end of the block */ | ||
1077 | }; | 1084 | }; |
1078 | 1085 | ||
1079 | #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) | 1086 | #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) |
@@ -1093,6 +1100,7 @@ struct ext4_sb_info { | |||
1093 | unsigned long s_desc_size; /* Size of a group descriptor in bytes */ | 1100 | unsigned long s_desc_size; /* Size of a group descriptor in bytes */ |
1094 | unsigned long s_inodes_per_block;/* Number of inodes per block */ | 1101 | unsigned long s_inodes_per_block;/* Number of inodes per block */ |
1095 | unsigned long s_blocks_per_group;/* Number of blocks in a group */ | 1102 | unsigned long s_blocks_per_group;/* Number of blocks in a group */ |
1103 | unsigned long s_clusters_per_group; /* Number of clusters in a group */ | ||
1096 | unsigned long s_inodes_per_group;/* Number of inodes in a group */ | 1104 | unsigned long s_inodes_per_group;/* Number of inodes in a group */ |
1097 | unsigned long s_itb_per_group; /* Number of inode table blocks per group */ | 1105 | unsigned long s_itb_per_group; /* Number of inode table blocks per group */ |
1098 | unsigned long s_gdb_count; /* Number of group descriptor blocks */ | 1106 | unsigned long s_gdb_count; /* Number of group descriptor blocks */ |
@@ -1101,6 +1109,8 @@ struct ext4_sb_info { | |||
1101 | ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */ | 1109 | ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */ |
1102 | unsigned long s_overhead_last; /* Last calculated overhead */ | 1110 | unsigned long s_overhead_last; /* Last calculated overhead */ |
1103 | unsigned long s_blocks_last; /* Last seen block count */ | 1111 | unsigned long s_blocks_last; /* Last seen block count */ |
1112 | unsigned int s_cluster_ratio; /* Number of blocks per cluster */ | ||
1113 | unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */ | ||
1104 | loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ | 1114 | loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ |
1105 | struct buffer_head * s_sbh; /* Buffer containing the super block */ | 1115 | struct buffer_head * s_sbh; /* Buffer containing the super block */ |
1106 | struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */ | 1116 | struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */ |
@@ -1367,6 +1377,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) | |||
1367 | #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 | 1377 | #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 |
1368 | #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 | 1378 | #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 |
1369 | #define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 | 1379 | #define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 |
1380 | #define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200 | ||
1370 | 1381 | ||
1371 | #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 | 1382 | #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 |
1372 | #define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002 | 1383 | #define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002 |
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); |
1987 | done: | ||
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", |