aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
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
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')
-rw-r--r--fs/ext4/ext4.h17
-rw-r--r--fs/ext4/super.c58
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);
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",