c689618
From af7e95c32cea40c1e443ae301e64b27f068b4915 Mon Sep 17 00:00:00 2001
c689618
From: Paulo Alcantara <pcacjr@zytor.com>
c689618
Date: Wed, 11 Oct 2017 07:00:31 -0400
c689618
Subject: [PATCH] ext4: Fix 64bit feature
c689618
c689618
As per ext4 specification:
c689618
c689618
> In ext2, ext3, and ext4 (when the 64bit feature is not enabled), the
c689618
> block group descriptor was only 32 bytes long and therefore ends at
c689618
> bg_checksum. On an ext4 filesystem with the 64bit feature enabled, the
c689618
> block group descriptor expands to at least the 64 bytes described below;
c689618
> the size is stored in the superblock.
c689618
c689618
Since block group descriptor has been expanded to 64 bytes long (when 64
c689618
bit feature is enabled), we cannot index ext2_group_desc and return it
c689618
*directly* -- as we did it in ext2_get_group_desc -- it's still 32 bytes
c689618
long.
c689618
c689618
Instead, use s_desc_size field from superblock to correctly index and
c689618
return block group descriptors.
c689618
c689618
Cc: H. Peter Anvin <hpa@zytor.com>
c689618
Cc: Gene Cumm <gene.cumm@gmail.com>
c689618
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
c689618
---
c689618
 core/fs/ext2/ext2.c    | 23 ++++++++++++++---------
c689618
 core/fs/ext2/ext2_fs.h |  1 +
c689618
 2 files changed, 15 insertions(+), 9 deletions(-)
c689618
c689618
diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c
c689618
index 76bd1d5..4bc0a53 100644
c689618
--- a/core/fs/ext2/ext2.c
c689618
+++ b/core/fs/ext2/ext2.c
c689618
@@ -25,22 +25,17 @@ static enum dirent_type ext2_cvt_type(unsigned int d_file_type)
c689618
 	return inode_type[d_file_type];
c689618
 }
c689618
 
c689618
-/*
c689618
- * get the group's descriptor of group_num
c689618
- */
c689618
-static const struct ext2_group_desc *
c689618
-ext2_get_group_desc(struct fs_info *fs, uint32_t group_num)
c689618
+static const void *__ext2_get_group_desc(struct fs_info *fs, uint32_t group_num)
c689618
 {
c689618
     struct ext2_sb_info *sbi = EXT2_SB(fs);
c689618
     uint32_t desc_block, desc_index;
c689618
-    const struct ext2_group_desc *desc_data_block;
c689618
+    uint8_t *p;
c689618
 
c689618
     if (group_num >= sbi->s_groups_count) {
c689618
 	printf ("ext2_get_group_desc"
c689618
 		"block_group >= groups_count - "
c689618
 		"block_group = %d, groups_count = %d",
c689618
 		group_num, sbi->s_groups_count);
c689618
-
c689618
 	return NULL;
c689618
     }
c689618
 
c689618
@@ -49,8 +44,17 @@ ext2_get_group_desc(struct fs_info *fs, uint32_t group_num)
c689618
 
c689618
     desc_block += sbi->s_first_data_block + 1;
c689618
 
c689618
-    desc_data_block = get_cache(fs->fs_dev, desc_block);
c689618
-    return &desc_data_block[desc_index];
c689618
+    p = get_cache(fs->fs_dev, desc_block);
c689618
+    return p + sbi->s_desc_size * desc_index;
c689618
+}
c689618
+
c689618
+/*
c689618
+ * get the group's descriptor of group_num
c689618
+ */
c689618
+static inline const struct ext2_group_desc *
c689618
+ext2_get_group_desc(struct fs_info *fs, uint32_t group_num)
c689618
+{
c689618
+    return __ext2_get_group_desc(fs, group_num);
c689618
 }
c689618
 
c689618
 /*
c689618
@@ -306,6 +310,7 @@ static int ext2_fs_init(struct fs_info *fs)
c689618
     if (sb.s_desc_size < sizeof(struct ext2_group_desc))
c689618
 	sb.s_desc_size = sizeof(struct ext2_group_desc);
c689618
     sbi->s_desc_per_block   = BLOCK_SIZE(fs) / sb.s_desc_size;
c689618
+    sbi->s_desc_size = sb.s_desc_size;
c689618
     sbi->s_groups_count     = (sb.s_blocks_count - sb.s_first_data_block
c689618
 			       + EXT2_BLOCKS_PER_GROUP(fs) - 1)
c689618
 	                      / EXT2_BLOCKS_PER_GROUP(fs);
c689618
diff --git a/core/fs/ext2/ext2_fs.h b/core/fs/ext2/ext2_fs.h
c689618
index 803a995..d8d07eb 100644
c689618
--- a/core/fs/ext2/ext2_fs.h
c689618
+++ b/core/fs/ext2/ext2_fs.h
c689618
@@ -278,6 +278,7 @@ struct ext2_sb_info {
c689618
     uint32_t s_first_data_block;	/* First Data Block */
c689618
     int      s_inode_size;
c689618
     uint8_t  s_uuid[16];	/* 128-bit uuid for volume */
c689618
+    int      s_desc_size;	/* size of group descriptor */
c689618
 };
c689618
 
c689618
 static inline struct ext2_sb_info *EXT2_SB(struct fs_info *fs)
c689618
-- 
c689618
2.7.4.GIT
c689618