aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/balloc.c6
-rw-r--r--fs/ext4/inode.c8
-rw-r--r--fs/ext4/super.c18
-rw-r--r--include/linux/ext4_fs.h9
-rw-r--r--include/linux/ext4_fs_sb.h1
5 files changed, 31 insertions, 11 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index df77ea891f29..3dacb124b8c8 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -74,10 +74,12 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
74 return NULL; 74 return NULL;
75 } 75 }
76 76
77 desc = (struct ext4_group_desc *) sbi->s_group_desc[group_desc]->b_data; 77 desc = (struct ext4_group_desc *)(
78 (__u8 *)sbi->s_group_desc[group_desc]->b_data +
79 offset * EXT4_DESC_SIZE(sb));
78 if (bh) 80 if (bh)
79 *bh = sbi->s_group_desc[group_desc]; 81 *bh = sbi->s_group_desc[group_desc];
80 return desc + offset; 82 return desc;
81} 83}
82 84
83/** 85/**
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c05dc57148bb..d03e7d85a638 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2432,14 +2432,16 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
2432 return 0; 2432 return 0;
2433 } 2433 }
2434 2434
2435 gdp = (struct ext4_group_desc *)bh->b_data; 2435 gdp = (struct ext4_group_desc *)((__u8 *)bh->b_data +
2436 desc * EXT4_DESC_SIZE(sb));
2436 /* 2437 /*
2437 * Figure out the offset within the block group inode table 2438 * Figure out the offset within the block group inode table
2438 */ 2439 */
2439 offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) * 2440 offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) *
2440 EXT4_INODE_SIZE(sb); 2441 EXT4_INODE_SIZE(sb);
2441 block = ext4_inode_table(gdp + desc) + 2442 block = ext4_inode_table(gdp) + (offset >> EXT4_BLOCK_SIZE_BITS(sb));
2442 (offset >> EXT4_BLOCK_SIZE_BITS(sb)); 2443
2444
2443 2445
2444 iloc->block_group = block_group; 2446 iloc->block_group = block_group;
2445 iloc->offset = offset & (EXT4_BLOCK_SIZE(sb) - 1); 2447 iloc->offset = offset & (EXT4_BLOCK_SIZE(sb) - 1);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index d844175e60e8..bc8848bff2f1 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1268,7 +1268,8 @@ static int ext4_check_descriptors (struct super_block * sb)
1268 return 0; 1268 return 0;
1269 } 1269 }
1270 first_block += EXT4_BLOCKS_PER_GROUP(sb); 1270 first_block += EXT4_BLOCKS_PER_GROUP(sb);
1271 gdp++; 1271 gdp = (struct ext4_group_desc *)
1272 ((__u8 *)gdp + EXT4_DESC_SIZE(sb));
1272 } 1273 }
1273 1274
1274 ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb)); 1275 ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
@@ -1619,7 +1620,18 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
1619 sbi->s_frag_size, blocksize); 1620 sbi->s_frag_size, blocksize);
1620 goto failed_mount; 1621 goto failed_mount;
1621 } 1622 }
1622 sbi->s_frags_per_block = 1; 1623 sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
1624 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
1625 if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE ||
1626 sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
1627 sbi->s_desc_size & (sbi->s_desc_size - 1)) {
1628 printk(KERN_ERR
1629 "EXT4-fs: unsupported descriptor size %ld\n",
1630 sbi->s_desc_size);
1631 goto failed_mount;
1632 }
1633 } else
1634 sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
1623 sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group); 1635 sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
1624 sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group); 1636 sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
1625 sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group); 1637 sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
@@ -1630,7 +1642,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
1630 goto cantfind_ext4; 1642 goto cantfind_ext4;
1631 sbi->s_itb_per_group = sbi->s_inodes_per_group / 1643 sbi->s_itb_per_group = sbi->s_inodes_per_group /
1632 sbi->s_inodes_per_block; 1644 sbi->s_inodes_per_block;
1633 sbi->s_desc_per_block = blocksize / sizeof(struct ext4_group_desc); 1645 sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
1634 sbi->s_sbh = bh; 1646 sbi->s_sbh = bh;
1635 sbi->s_mount_state = le16_to_cpu(es->s_state); 1647 sbi->s_mount_state = le16_to_cpu(es->s_state);
1636 sbi->s_addr_per_block_bits = log2(EXT4_ADDR_PER_BLOCK(sb)); 1648 sbi->s_addr_per_block_bits = log2(EXT4_ADDR_PER_BLOCK(sb));
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index 8e5009ee4ad8..a3df2afc004b 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -142,6 +142,9 @@ struct ext4_group_desc
142/* 142/*
143 * Macro-instructions used to manage group descriptors 143 * Macro-instructions used to manage group descriptors
144 */ 144 */
145#define EXT4_MIN_DESC_SIZE 32
146#define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE
147#define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size)
145#ifdef __KERNEL__ 148#ifdef __KERNEL__
146# define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) 149# define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group)
147# define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) 150# define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block)
@@ -149,7 +152,7 @@ struct ext4_group_desc
149# define EXT4_DESC_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_desc_per_block_bits) 152# define EXT4_DESC_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_desc_per_block_bits)
150#else 153#else
151# define EXT4_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group) 154# define EXT4_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
152# define EXT4_DESC_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / sizeof (struct ext4_group_desc)) 155# define EXT4_DESC_PER_BLOCK(s) (EXT4_BLOCK_SIZE(s) / EXT4_DESC_SIZE(s))
153# define EXT4_INODES_PER_GROUP(s) ((s)->s_inodes_per_group) 156# define EXT4_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
154#endif 157#endif
155 158
@@ -474,7 +477,7 @@ struct ext4_super_block {
474 * things it doesn't understand... 477 * things it doesn't understand...
475 */ 478 */
476 __le32 s_first_ino; /* First non-reserved inode */ 479 __le32 s_first_ino; /* First non-reserved inode */
477 __le16 s_inode_size; /* size of inode structure */ 480 __le16 s_inode_size; /* size of inode structure */
478 __le16 s_block_group_nr; /* block group # of this superblock */ 481 __le16 s_block_group_nr; /* block group # of this superblock */
479 __le32 s_feature_compat; /* compatible feature set */ 482 __le32 s_feature_compat; /* compatible feature set */
480/*60*/ __le32 s_feature_incompat; /* incompatible feature set */ 483/*60*/ __le32 s_feature_incompat; /* incompatible feature set */
@@ -500,7 +503,7 @@ struct ext4_super_block {
500 __le32 s_hash_seed[4]; /* HTREE hash seed */ 503 __le32 s_hash_seed[4]; /* HTREE hash seed */
501 __u8 s_def_hash_version; /* Default hash version to use */ 504 __u8 s_def_hash_version; /* Default hash version to use */
502 __u8 s_reserved_char_pad; 505 __u8 s_reserved_char_pad;
503 __u16 s_reserved_word_pad; 506 __le16 s_desc_size; /* size of group descriptor */
504/*100*/ __le32 s_default_mount_opts; 507/*100*/ __le32 s_default_mount_opts;
505 __le32 s_first_meta_bg; /* First metablock block group */ 508 __le32 s_first_meta_bg; /* First metablock block group */
506 __le32 s_mkfs_time; /* When the filesystem was created */ 509 __le32 s_mkfs_time; /* When the filesystem was created */
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
index ce7a844d6703..691a713139ce 100644
--- a/include/linux/ext4_fs_sb.h
+++ b/include/linux/ext4_fs_sb.h
@@ -29,6 +29,7 @@
29 */ 29 */
30struct ext4_sb_info { 30struct ext4_sb_info {
31 unsigned long s_frag_size; /* Size of a fragment in bytes */ 31 unsigned long s_frag_size; /* Size of a fragment in bytes */
32 unsigned long s_desc_size; /* Size of a group descriptor in bytes */
32 unsigned long s_frags_per_block;/* Number of fragments per block */ 33 unsigned long s_frags_per_block;/* Number of fragments per block */
33 unsigned long s_inodes_per_block;/* Number of inodes per block */ 34 unsigned long s_inodes_per_block;/* Number of inodes per block */
34 unsigned long s_frags_per_group;/* Number of fragments in a group */ 35 unsigned long s_frags_per_group;/* Number of fragments in a group */