Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 176556 Details for
Bug 250829
support ext4 extents with sys-boot/grub 0.97
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Alternative ext4 patch
ext4-support (text/plain), 14.93 KB, created by
Diego Elio Pettenò (RETIRED)
on 2008-12-28 02:23:17 UTC
(
hide
)
Description:
Alternative ext4 patch
Filename:
MIME Type:
Creator:
Diego Elio Pettenò (RETIRED)
Created:
2008-12-28 02:23:17 UTC
Size:
14.93 KB
patch
obsolete
>Index: grub-0.97/stage2/fsys_ext2fs.c >=================================================================== >--- grub-0.97.orig/stage2/fsys_ext2fs.c >+++ grub-0.97/stage2/fsys_ext2fs.c >@@ -41,6 +41,7 @@ typedef __signed__ short __s16; > typedef unsigned short __u16; > typedef __signed__ int __s32; > typedef unsigned int __u32; >+typedef unsigned long long __u64; > > /* > * Constants relative to the data blocks, from ext2_fs.h >@@ -61,9 +62,9 @@ struct ext2_super_block > __u32 s_free_inodes_count; /* Free inodes count */ > __u32 s_first_data_block; /* First Data Block */ > __u32 s_log_block_size; /* Block size */ >- __s32 s_log_frag_size; /* Fragment size */ >+ __s32 s_obso_log_frag_size; /* Obsoleted Fragment size */ > __u32 s_blocks_per_group; /* # Blocks per group */ >- __u32 s_frags_per_group; /* # Fragments per group */ >+ __u32 s_obso_frags_per_group; /* Obsoleted Fragments per group */ > __u32 s_inodes_per_group; /* # Inodes per group */ > __u32 s_mtime; /* Mount time */ > __u32 s_wtime; /* Write time */ >@@ -72,7 +73,7 @@ struct ext2_super_block > __u16 s_magic; /* Magic signature */ > __u16 s_state; /* File system state */ > __u16 s_errors; /* Behaviour when detecting errors */ >- __u16 s_pad; >+ __u16 s_minor_rev_level; /* minor revision level */ > __u32 s_lastcheck; /* time of last check */ > __u32 s_checkinterval; /* max. time between checks */ > __u32 s_creator_os; /* OS */ >@@ -119,7 +120,7 @@ struct ext2_super_block > __u32 s_hash_seed[4]; /* HTREE hash seed */ > __u8 s_def_hash_version; /* Default hash version to use */ > __u8 s_jnl_backup_type; /* Default type of journal backup */ >- __u16 s_reserved_word_pad; >+ __u16 s_desc_size; /* size of group descriptor */ > __u32 s_default_mount_opts; > __u32 s_first_meta_bg; /* First metablock group */ > __u32 s_mkfs_time; /* When the filesystem was created */ >@@ -127,7 +128,7 @@ struct ext2_super_block > __u32 s_reserved[172]; /* Padding to the end of the block */ > }; > >-struct ext2_group_desc >+struct ext4_group_desc > { > __u32 bg_block_bitmap; /* Blocks bitmap block */ > __u32 bg_inode_bitmap; /* Inodes bitmap block */ >@@ -135,8 +136,18 @@ struct ext2_group_desc > __u16 bg_free_blocks_count; /* Free blocks count */ > __u16 bg_free_inodes_count; /* Free inodes count */ > __u16 bg_used_dirs_count; /* Directories count */ >- __u16 bg_pad; >- __u32 bg_reserved[3]; >+ __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */ >+ __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */ >+ __u16 bg_itable_unused; /* Unused inodes count */ >+ __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */ >+ __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ >+ __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */ >+ __u32 bg_inode_table_hi; /* Inodes table block MSB */ >+ __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */ >+ __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */ >+ __u16 bg_used_dirs_count_hi; /* Directories count MSB */ >+ __u16 bg_itable_unused_hi; /* Unused inodes count MSB */ >+ __u32 bg_reserved2[3]; > }; > > struct ext2_inode >@@ -174,22 +185,22 @@ struct ext2_inode > __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ > __u32 i_version; /* File version (for NFS) */ > __u32 i_file_acl; /* File ACL */ >- __u32 i_dir_acl; /* Directory ACL */ >- __u32 i_faddr; /* Fragment address */ >+ __u32 i_size_high; >+ __u32 i_obso_faddr; /* Obsoleted fragment address */ > union > { > struct > { >- __u8 l_i_frag; /* Fragment number */ >- __u8 l_i_fsize; /* Fragment size */ >- __u16 i_pad1; >- __u32 l_i_reserved2[2]; >+ __u16 l_i_blocks_high; /* were l_i_reserved1 */ >+ __u16 l_i_file_acl_high; >+ __u16 l_i_uid_high; /* these 2 fields */ >+ __u16 l_i_gid_high; /* were reserved2[0] */ >+ __u32 l_i_reserved2; > } > linux2; > struct > { >- __u8 h_i_frag; /* Fragment number */ >- __u8 h_i_fsize; /* Fragment size */ >+ __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ > __u16 h_i_mode_high; > __u16 h_i_uid_high; > __u16 h_i_gid_high; >@@ -198,16 +209,36 @@ struct ext2_inode > hurd2; > struct > { >- __u8 m_i_frag; /* Fragment number */ >- __u8 m_i_fsize; /* Fragment size */ >- __u16 m_pad1; >+ __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ >+ __u16 m_i_file_acl_high; > __u32 m_i_reserved2[2]; > } > masix2; > } > osd2; /* OS dependent 2 */ >+ __u16 i_extra_isize; >+ __u16 i_pad1; >+ __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */ >+ __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */ >+ __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ >+ __u32 i_crtime; /* File Creation time */ >+ __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */ >+ __u32 i_version_hi; /* high 32 bits for 64-bit version */ > }; > >+#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ >+#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/ >+#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 >+#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 >+ >+#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \ >+ ( sb->s_feature_incompat & mask ) >+ >+#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ >+#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */ >+ >+#define EXT4_MIN_DESC_SIZE 32 >+ > /* linux/limits.h */ > #define NAME_MAX 255 /* # chars in a file name */ > >@@ -225,6 +256,57 @@ struct ext2_dir_entry > char name[EXT2_NAME_LEN]; /* File name */ > }; > >+/* linux/ext4_fs_extents.h */ >+/* This is the extent on-disk structure. >+ * It's used at the bottom of the tree. >+ */ >+struct ext4_extent >+ { >+ __u32 ee_block; /* first logical block extent covers */ >+ __u16 ee_len; /* number of blocks covered by extent */ >+ __u16 ee_start_hi; /* high 16 bits of physical block */ >+ __u32 ee_start_lo; /* low 32 bits of physical block */ >+ }; >+ >+/* >+ * This is index on-disk structure. >+ * It's used at all the levels except the bottom. >+ */ >+struct ext4_extent_idx >+ { >+ __u32 ei_block; /* index covers logical blocks from 'block' */ >+ __u32 ei_leaf_lo; /* pointer to the physical block of the next * >+ * level. leaf or next index could be there */ >+ __u16 ei_leaf_hi; /* high 16 bits of physical block */ >+ __u16 ei_unused; >+ }; >+ >+/* >+ * Each block (leaves and indexes), even inode-stored has header. >+ */ >+struct ext4_extent_header >+ { >+ __u16 eh_magic; /* probably will support different formats */ >+ __u16 eh_entries; /* number of valid entries */ >+ __u16 eh_max; /* capacity of store in entries */ >+ __u16 eh_depth; /* has tree real underlying blocks? */ >+ __u32 eh_generation; /* generation of the tree */ >+ }; >+ >+#define EXT4_EXT_MAGIC (0xf30a) >+#define EXT_FIRST_EXTENT(__hdr__) \ >+ ((struct ext4_extent *) (((char *) (__hdr__)) + \ >+ sizeof(struct ext4_extent_header))) >+#define EXT_FIRST_INDEX(__hdr__) \ >+ ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \ >+ sizeof(struct ext4_extent_header))) >+#define EXT_LAST_EXTENT(__hdr__) \ >+ (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1) >+#define EXT_LAST_INDEX(__hdr__) \ >+ (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1) >+ >+ >+ > /* linux/ext2fs.h */ > /* > * EXT2_DIR_PAD defines the directory entries boundaries >@@ -276,8 +358,17 @@ struct ext2_dir_entry > /* kind of from ext2/super.c */ > #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s)) > /* linux/ext2fs.h */ >+/* sizeof(struct ext2_group_desc) is changed in ext4 >+ * in kernel code, ext2/3 uses sizeof(struct ext2_group_desc) to calculate >+ * number of desc per block, while ext4 uses superblock->s_desc_size in stead >+ * superblock->s_desc_size is not available in ext2/3 >+ * */ >+#define EXT2_DESC_SIZE(s) \ >+ (EXT4_HAS_INCOMPAT_FEATURE(s,EXT4_FEATURE_INCOMPAT_64BIT)? \ >+ s->s_desc_size : EXT4_MIN_DESC_SIZE) > #define EXT2_DESC_PER_BLOCK(s) \ >- (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) >+ (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s)) >+ > /* linux/stat.h */ > #define S_IFMT 00170000 > #define S_IFLNK 0120000 >@@ -439,6 +530,122 @@ ext2fs_block_map (int logical_block) > [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; > } > >+/* extent binary search index >+ * find closest index in the current level extent tree >+ * kind of from ext4_ext_binsearch_idx in ext4/extents.c >+ */ >+static struct ext4_extent_idx* >+ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block) >+{ >+ struct ext4_extent_idx *r, *l, *m; >+ l = EXT_FIRST_INDEX(eh) + 1; >+ r = EXT_LAST_INDEX(eh); >+ while (l <= r) >+ { >+ m = l + (r - l) / 2; >+ if (logical_block < m->ei_block) >+ r = m - 1; >+ else >+ l = m + 1; >+ } >+ return (struct ext4_extent_idx*)(l - 1); >+} >+ >+/* extent binary search >+ * find closest extent in the leaf level >+ * kind of from ext4_ext_binsearch in ext4/extents.c >+ */ >+static struct ext4_extent* >+ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block) >+{ >+ struct ext4_extent *r, *l, *m; >+ l = EXT_FIRST_EXTENT(eh) + 1; >+ r = EXT_LAST_EXTENT(eh); >+ while (l <= r) >+ { >+ m = l + (r - l) / 2; >+ if (logical_block < m->ee_block) >+ r = m - 1; >+ else >+ l = m + 1; >+ } >+ return (struct ext4_extent*)(l - 1); >+} >+ >+/* Maps extents enabled logical block into physical block via an inode. >+ * EXT4_HUGE_FILE_FL should be checked before calling this. >+ */ >+static int >+ext4fs_block_map (int logical_block) >+{ >+ struct ext4_extent_header *eh; >+ struct ext4_extent *ex, *extent; >+ struct ext4_extent_idx *ei, *index; >+ int depth; >+ int i; >+ >+#ifdef E2DEBUG >+ unsigned char *i; >+ for (i = (unsigned char *) INODE; >+ i < ((unsigned char *) INODE + sizeof (struct ext2_inode)); >+ i++) >+ { >+ printf ("%c", "0123456789abcdef"[*i >> 4]); >+ printf ("%c", "0123456789abcdef"[*i % 16]); >+ if (!((i + 1 - (unsigned char *) INODE) % 16)) >+ { >+ printf ("\n"); >+ } >+ else >+ { >+ printf (" "); >+ } >+ } >+ printf ("logical block %d\n", logical_block); >+#endif /* E2DEBUG */ >+ eh = (struct ext4_extent_header*)INODE->i_block; >+ if (eh->eh_magic != EXT4_EXT_MAGIC) >+ { >+ errnum = ERR_FSYS_CORRUPT; >+ return -1; >+ } >+ while((depth = eh->eh_depth) != 0) >+ { /* extent index */ >+ if (eh->eh_magic != EXT4_EXT_MAGIC) >+ { >+ errnum = ERR_FSYS_CORRUPT; >+ return -1; >+ } >+ ei = ext4_ext_binsearch_idx(eh, logical_block); >+ if (ei->ei_leaf_hi) >+ {/* 64bit physical block number not supported */ >+ errnum = ERR_FILELENGTH; >+ return -1; >+ } >+ if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1)) >+ { >+ errnum = ERR_FSYS_CORRUPT; >+ return -1; >+ } >+ eh = (struct ext4_extent_header*)DATABLOCK1; >+ } >+ >+ /* depth==0, we come to the leaf */ >+ ex = ext4_ext_binsearch(eh, logical_block); >+ if (ex->ee_start_hi) >+ {/* 64bit physical block number not supported */ >+ errnum = ERR_FILELENGTH; >+ return -1; >+ } >+ if ((ex->ee_block + ex->ee_len) < logical_block) >+ { >+ errnum = ERR_FSYS_CORRUPT; >+ return -1; >+ } >+ return ex->ee_start_lo + logical_block - ex->ee_block; >+ >+} >+ > /* preconditions: all preconds of ext2fs_block_map */ > int > ext2fs_read (char *buf, int len) >@@ -473,6 +680,11 @@ ext2fs_read (char *buf, int len) > /* find the (logical) block component of our location */ > logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); > offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); >+ /* map extents enabled logical block number to physical fs on-dick block number */ >+ if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS) >+ && INODE->i_flags & EXT4_EXTENTS_FL) >+ map = ext4fs_block_map (logical_block); >+ else > map = ext2fs_block_map (logical_block); > #ifdef E2DEBUG > printf ("map=%d\n", map); >@@ -557,7 +769,7 @@ ext2fs_dir (char *dirname) > int desc; /* index within that group */ > int ino_blk; /* fs pointer of the inode's information */ > int str_chk = 0; /* used to hold the results of a string compare */ >- struct ext2_group_desc *gdp; >+ struct ext4_group_desc *ext4_gdp; > struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */ > > char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ >@@ -603,8 +815,15 @@ ext2fs_dir (char *dirname) > { > return 0; > } >- gdp = GROUP_DESC; >- ino_blk = gdp[desc].bg_inode_table + >+ ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC + >+ desc * EXT2_DESC_SIZE(SUPERBLOCK)); >+ if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT) >+ && (! ext4_gdp->bg_inode_table_hi)) >+ {/* 64bit itable not supported */ >+ errnum = ERR_FILELENGTH; >+ return -1; >+ } >+ ino_blk = ext4_gdp->bg_inode_table + > (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group)) > >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK))); > #ifdef E2DEBUG >@@ -681,7 +900,10 @@ ext2fs_dir (char *dirname) > } > linkbuf[filemax + len] = '\0'; > >- /* Read the symlink data. */ >+ /* Read the symlink data. >+ * Slow symlink is extents enabled >+ * But since grub_read invokes ext2fs_read, nothing to change here >+ * */ > if (! ext2_is_fast_symlink ()) > { > /* Read the necessary blocks, and reset the file pointer. */ >@@ -692,7 +914,9 @@ ext2fs_dir (char *dirname) > } > else > { >- /* Copy the data directly from the inode. */ >+ /* Copy the data directly from the inode. >+ * Fast symlink is not extents enabled >+ * */ > len = filemax; > memmove (linkbuf, (char *) INODE->i_block, len); > } >@@ -726,6 +950,13 @@ ext2fs_dir (char *dirname) > errnum = ERR_BAD_FILETYPE; > return 0; > } >+ /* if file is too large, just stop and report an error*/ >+ if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high)) >+ { >+ /* file too large, stop reading */ >+ errnum = ERR_FILELENGTH; >+ return 0; >+ } > > filemax = (INODE->i_size); > return 1; >@@ -780,17 +1011,28 @@ ext2fs_dir (char *dirname) > } > > /* else, find the (logical) block component of our location */ >+ /* ext4 logical block number the same as ext2/3 */ > blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); > > /* we know which logical block of the directory entry we are looking > for, now we have to translate that to the physical (fs) block on > the disk */ >+ /* map extents enabled logical block number to physical fs on-dick block number */ >+ if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS) >+ && INODE->i_flags & EXT4_EXTENTS_FL) >+ map = ext4fs_block_map (blk); >+ else > map = ext2fs_block_map (blk); > #ifdef E2DEBUG > printf ("fs block=%d\n", map); > #endif /* E2DEBUG */ > mapblock2 = -1; >- if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2)) >+ if (map < 0) >+ { >+ *rest = ch; >+ return 0; >+ } >+ if (!ext2_rdfsb (map, DATABLOCK2)) > { > errnum = ERR_FSYS_CORRUPT; > *rest = ch;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 250829
:
176095
|
176097
| 176556