Magellan Linux

Annotation of /trunk/grub/patches/grub-0.97-ext4-3.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 900 - (hide annotations) (download)
Fri Oct 16 15:47:23 2009 UTC (14 years, 7 months ago) by niro
File size: 18122 byte(s)
-fixed

1 niro 899 diff -Naur grub-0.97/stage2/fsys_ext2fs.c grub-0.97-magellan/stage2/fsys_ext2fs.c
2 niro 900 --- grub-0.97/stage2/fsys_ext2fs.c 2004-08-08 20:19:18.000000000 +0200
3     +++ grub-0.97-magellan/stage2/fsys_ext2fs.c 2009-10-16 17:55:35.000000000 +0200
4     @@ -41,6 +41,7 @@
5     typedef unsigned short __u16;
6     typedef __signed__ int __s32;
7     typedef unsigned int __u32;
8     +typedef unsigned long long __u64;
9    
10     /*
11     * Constants relative to the data blocks, from ext2_fs.h
12     @@ -51,7 +52,7 @@
13     #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
14     #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
15    
16     -/* include/linux/ext2_fs.h */
17     +/* lib/ext2fs/ext2_fs.h from e2fsprogs */
18     struct ext2_super_block
19     {
20     __u32 s_inodes_count; /* Inodes count */
21     @@ -61,9 +62,9 @@
22     __u32 s_free_inodes_count; /* Free inodes count */
23     __u32 s_first_data_block; /* First Data Block */
24     __u32 s_log_block_size; /* Block size */
25     - __s32 s_log_frag_size; /* Fragment size */
26     + __s32 s_obso_log_frag_size; /* Obsoleted Fragment size */
27     __u32 s_blocks_per_group; /* # Blocks per group */
28     - __u32 s_frags_per_group; /* # Fragments per group */
29     + __u32 s_obso_frags_per_group; /* Obsoleted Fragments per group */
30     __u32 s_inodes_per_group; /* # Inodes per group */
31     __u32 s_mtime; /* Mount time */
32     __u32 s_wtime; /* Write time */
33     @@ -72,17 +73,77 @@
34     __u16 s_magic; /* Magic signature */
35     __u16 s_state; /* File system state */
36     __u16 s_errors; /* Behaviour when detecting errors */
37     - __u16 s_pad;
38     + __u16 s_minor_rev_level; /* minor revision level */
39     + __u16 s_desc_size; /* size of group descriptor */
40     __u32 s_lastcheck; /* time of last check */
41     __u32 s_checkinterval; /* max. time between checks */
42     __u32 s_creator_os; /* OS */
43 niro 899 __u32 s_rev_level; /* Revision level */
44     __u16 s_def_resuid; /* Default uid for reserved blocks */
45     __u16 s_def_resgid; /* Default gid for reserved blocks */
46 niro 900 - __u32 s_reserved[235]; /* Padding to the end of the block */
47     - };
48 niro 899 + /*
49     + * These fields are for EXT2_DYNAMIC_REV superblocks only.
50     + *
51     + * Note: the difference between the compatible feature set and
52     + * the incompatible feature set is that if there is a bit set
53     + * in the incompatible feature set that the kernel doesn't
54     + * know about, it should refuse to mount the filesystem.
55     + *
56     + * e2fsck's requirements are more strict; if it doesn't know
57     + * about a feature in either the compatible or incompatible
58     + * feature set, it must abort and not try to meddle with
59     + * things it doesn't understand...
60     + */
61     + __u32 s_first_ino; /* First non-reserved inode */
62     + __u16 s_inode_size; /* size of inode structure */
63     + __u16 s_block_group_nr; /* block group # of this superblock */
64     + __u32 s_feature_compat; /* compatible feature set */
65     + __u32 s_feature_incompat; /* incompatible feature set */
66     + __u32 s_feature_ro_compat; /* readonly-compatible feature set */
67     + __u8 s_uuid[16]; /* 128-bit uuid for volume */
68     + char s_volume_name[16]; /* volume name */
69     + char s_last_mounted[64]; /* directory where last mounted */
70     + __u32 s_algorithm_usage_bitmap; /* For compression */
71     + /*
72     + * Performance hints. Directory preallocation should only
73     + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
74     + */
75     + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
76     + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
77     + __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
78     + /*
79     + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
80     + */
81     + __u8 s_journal_uuid[16]; /* uuid of journal superblock */
82     + __u32 s_journal_inum; /* inode number of journal file */
83     + __u32 s_journal_dev; /* device number of journal file */
84     + __u32 s_last_orphan; /* start of list of inodes to delete */
85     + __u32 s_hash_seed[4]; /* HTREE hash seed */
86     + __u8 s_def_hash_version; /* Default hash version to use */
87     + __u8 s_jnl_backup_type; /* Default type of journal backup */
88     + __u16 s_reserved_word_pad;
89     + __u32 s_default_mount_opts;
90     + __u32 s_first_meta_bg; /* First metablock group */
91     + __u32 s_mkfs_time; /* When the filesystem was created */
92     + __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
93 niro 900 + /* 64bit desc support valid if EXT4_FEATURE_INCOMPAT_64BIT */
94     + __u32 s_blocks_count_hi; /* Blocks count */
95     + __u32 s_r_blocks_count_hi; /* Reserved blocks count */
96     + __u32 s_free_blocks_count_hi; /* Free blocks count */
97     + __u16 s_min_extra_isize; /* All inodes have at least # bytes */
98     + __u16 s_max_extra_isize; /* New inodes should reverve # bytes */
99     + __u32 s_flags; /* Miscellaneous flags */
100     + __u16 s_raid_stride; /* Raid stride */
101     + __u16 s_mmp_interval; /* # seconds to wait MMP checking */
102     + __u64 s_mmp_block; /* Block for multi-mount protection */
103     + __u32 s_raid_stripe_width; /* Blocks on all data disks (N*stride)*/
104     + __u8 s_log_groups_per_flex;/* FLEX_BG group size*/
105     + __u8 s_reserved_char_pad;
106     + __u16 s_reserved_pad;
107     + __u32 s_reserved[162]; /* Padding to the end of the block */
108     +};
109    
110     -struct ext2_group_desc
111     +struct ext4_group_desc
112     {
113     __u32 bg_block_bitmap; /* Blocks bitmap block */
114     __u32 bg_inode_bitmap; /* Inodes bitmap block */
115     @@ -90,8 +151,18 @@
116     __u16 bg_free_blocks_count; /* Free blocks count */
117     __u16 bg_free_inodes_count; /* Free inodes count */
118     __u16 bg_used_dirs_count; /* Directories count */
119     - __u16 bg_pad;
120     - __u32 bg_reserved[3];
121     + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
122     + __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
123     + __u16 bg_itable_unused; /* Unused inodes count */
124     + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
125     + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
126     + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
127     + __u32 bg_inode_table_hi; /* Inodes table block MSB */
128     + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
129     + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
130     + __u16 bg_used_dirs_count_hi; /* Directories count MSB */
131     + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
132     + __u32 bg_reserved2[3];
133     };
134    
135     struct ext2_inode
136     @@ -129,22 +200,22 @@
137     __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
138     __u32 i_version; /* File version (for NFS) */
139     __u32 i_file_acl; /* File ACL */
140     - __u32 i_dir_acl; /* Directory ACL */
141     - __u32 i_faddr; /* Fragment address */
142     + __u32 i_size_high;
143     + __u32 i_obso_faddr; /* Obsoleted fragment address */
144     union
145     {
146     struct
147     {
148     - __u8 l_i_frag; /* Fragment number */
149     - __u8 l_i_fsize; /* Fragment size */
150     - __u16 i_pad1;
151     - __u32 l_i_reserved2[2];
152     + __u16 l_i_blocks_high; /* were l_i_reserved1 */
153     + __u16 l_i_file_acl_high;
154     + __u16 l_i_uid_high; /* these 2 fields */
155     + __u16 l_i_gid_high; /* were reserved2[0] */
156     + __u32 l_i_reserved2;
157     }
158     linux2;
159     struct
160     {
161     - __u8 h_i_frag; /* Fragment number */
162     - __u8 h_i_fsize; /* Fragment size */
163     + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
164     __u16 h_i_mode_high;
165     __u16 h_i_uid_high;
166     __u16 h_i_gid_high;
167     @@ -153,16 +224,36 @@
168     hurd2;
169     struct
170     {
171     - __u8 m_i_frag; /* Fragment number */
172     - __u8 m_i_fsize; /* Fragment size */
173     - __u16 m_pad1;
174     + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
175     + __u16 m_i_file_acl_high;
176     __u32 m_i_reserved2[2];
177     }
178     masix2;
179     }
180     osd2; /* OS dependent 2 */
181     + __u16 i_extra_isize;
182     + __u16 i_pad1;
183     + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
184     + __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
185     + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
186     + __u32 i_crtime; /* File Creation time */
187     + __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
188     + __u32 i_version_hi; /* high 32 bits for 64-bit version */
189     };
190    
191     +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
192     +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/
193     +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
194     +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
195     +
196     +#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
197     + ( sb->s_feature_incompat & mask )
198     +
199     +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
200     +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
201     +
202     +#define EXT4_MIN_DESC_SIZE 32
203     +
204     /* linux/limits.h */
205     #define NAME_MAX 255 /* # chars in a file name */
206    
207     @@ -180,6 +271,56 @@
208     char name[EXT2_NAME_LEN]; /* File name */
209     };
210    
211     +/* linux/ext4_fs_extents.h */
212     +/* This is the extent on-disk structure.
213     + * It's used at the bottom of the tree.
214     + */
215     +struct ext4_extent
216     + {
217     + __u32 ee_block; /* first logical block extent covers */
218     + __u16 ee_len; /* number of blocks covered by extent */
219     + __u16 ee_start_hi; /* high 16 bits of physical block */
220     + __u32 ee_start_lo; /* low 32 bits of physical block */
221     + };
222     +
223     +/*
224     + * This is index on-disk structure.
225     + * It's used at all the levels except the bottom.
226     + */
227     +struct ext4_extent_idx
228     + {
229     + __u32 ei_block; /* index covers logical blocks from 'block' */
230     + __u32 ei_leaf_lo; /* pointer to the physical block of the next *
231     + * level. leaf or next index could be there */
232     + __u16 ei_leaf_hi; /* high 16 bits of physical block */
233     + __u16 ei_unused;
234     + };
235     +
236     +/*
237     + * Each block (leaves and indexes), even inode-stored has header.
238     + */
239     +struct ext4_extent_header
240     + {
241     + __u16 eh_magic; /* probably will support different formats */
242     + __u16 eh_entries; /* number of valid entries */
243     + __u16 eh_max; /* capacity of store in entries */
244     + __u16 eh_depth; /* has tree real underlying blocks? */
245     + __u32 eh_generation; /* generation of the tree */
246     + };
247     +
248     +#define EXT4_EXT_MAGIC (0xf30a)
249     +#define EXT_FIRST_EXTENT(__hdr__) \
250     + ((struct ext4_extent *) (((char *) (__hdr__)) + \
251     + sizeof(struct ext4_extent_header)))
252     +#define EXT_FIRST_INDEX(__hdr__) \
253     + ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
254     + sizeof(struct ext4_extent_header)))
255     +#define EXT_LAST_EXTENT(__hdr__) \
256     + (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
257     +#define EXT_LAST_INDEX(__hdr__) \
258     + (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
259     +
260     +
261     /* linux/ext2fs.h */
262     /*
263     * EXT2_DIR_PAD defines the directory entries boundaries
264     @@ -223,8 +364,17 @@
265     /* kind of from ext2/super.c */
266     #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
267     /* linux/ext2fs.h */
268     +/* sizeof(struct ext2_group_desc) is changed in ext4
269     + * in kernel code, ext2/3 uses sizeof(struct ext2_group_desc) to calculate
270     + * number of desc per block, while ext4 uses superblock->s_desc_size in stead
271     + * superblock->s_desc_size is not available in ext2/3
272     + * */
273     +#define EXT2_DESC_SIZE(s) \
274     + (EXT4_HAS_INCOMPAT_FEATURE(s,EXT4_FEATURE_INCOMPAT_64BIT)? \
275     + s->s_desc_size : EXT4_MIN_DESC_SIZE)
276     #define EXT2_DESC_PER_BLOCK(s) \
277     - (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
278     + (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
279     +
280     /* linux/stat.h */
281     #define S_IFMT 00170000
282     #define S_IFLNK 0120000
283     @@ -386,6 +536,122 @@
284     [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
285     }
286    
287     +/* extent binary search index
288     + * find closest index in the current level extent tree
289     + * kind of from ext4_ext_binsearch_idx in ext4/extents.c
290     + */
291     +static struct ext4_extent_idx*
292     +ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
293     +{
294     + struct ext4_extent_idx *r, *l, *m;
295     + l = EXT_FIRST_INDEX(eh) + 1;
296     + r = EXT_LAST_INDEX(eh);
297     + while (l <= r)
298     + {
299     + m = l + (r - l) / 2;
300     + if (logical_block < m->ei_block)
301     + r = m - 1;
302     + else
303     + l = m + 1;
304     + }
305     + return (struct ext4_extent_idx*)(l - 1);
306     +}
307     +
308     +/* extent binary search
309     + * find closest extent in the leaf level
310     + * kind of from ext4_ext_binsearch in ext4/extents.c
311     + */
312     +static struct ext4_extent*
313     +ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
314     +{
315     + struct ext4_extent *r, *l, *m;
316     + l = EXT_FIRST_EXTENT(eh) + 1;
317     + r = EXT_LAST_EXTENT(eh);
318     + while (l <= r)
319     + {
320     + m = l + (r - l) / 2;
321     + if (logical_block < m->ee_block)
322     + r = m - 1;
323     + else
324     + l = m + 1;
325     + }
326     + return (struct ext4_extent*)(l - 1);
327     +}
328     +
329     +/* Maps extents enabled logical block into physical block via an inode.
330     + * EXT4_HUGE_FILE_FL should be checked before calling this.
331     + */
332     +static int
333     +ext4fs_block_map (int logical_block)
334     +{
335     + struct ext4_extent_header *eh;
336     + struct ext4_extent *ex, *extent;
337     + struct ext4_extent_idx *ei, *index;
338     + int depth;
339     + int i;
340     +
341     +#ifdef E2DEBUG
342     + unsigned char *i;
343     + for (i = (unsigned char *) INODE;
344     + i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
345     + i++)
346     + {
347     + printf ("%c", "0123456789abcdef"[*i >> 4]);
348     + printf ("%c", "0123456789abcdef"[*i % 16]);
349     + if (!((i + 1 - (unsigned char *) INODE) % 16))
350     + {
351     + printf ("\n");
352     + }
353     + else
354     + {
355     + printf (" ");
356     + }
357     + }
358     + printf ("logical block %d\n", logical_block);
359     +#endif /* E2DEBUG */
360     + eh = (struct ext4_extent_header*)INODE->i_block;
361     + if (eh->eh_magic != EXT4_EXT_MAGIC)
362     + {
363     + errnum = ERR_FSYS_CORRUPT;
364     + return -1;
365     + }
366     + while((depth = eh->eh_depth) != 0)
367     + { /* extent index */
368     + if (eh->eh_magic != EXT4_EXT_MAGIC)
369     + {
370     + errnum = ERR_FSYS_CORRUPT;
371     + return -1;
372     + }
373     + ei = ext4_ext_binsearch_idx(eh, logical_block);
374     + if (ei->ei_leaf_hi)
375     + {/* 64bit physical block number not supported */
376     + errnum = ERR_FILELENGTH;
377     + return -1;
378     + }
379     + if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
380     + {
381     + errnum = ERR_FSYS_CORRUPT;
382     + return -1;
383     + }
384     + eh = (struct ext4_extent_header*)DATABLOCK1;
385     + }
386     +
387     + /* depth==0, we come to the leaf */
388     + ex = ext4_ext_binsearch(eh, logical_block);
389     + if (ex->ee_start_hi)
390     + {/* 64bit physical block number not supported */
391     + errnum = ERR_FILELENGTH;
392     + return -1;
393     + }
394     + if ((ex->ee_block + ex->ee_len) < logical_block)
395     + {
396     + errnum = ERR_FSYS_CORRUPT;
397     + return -1;
398     + }
399     + return ex->ee_start_lo + logical_block - ex->ee_block;
400     +
401     +}
402     +
403     /* preconditions: all preconds of ext2fs_block_map */
404     int
405     ext2fs_read (char *buf, int len)
406     @@ -420,6 +686,11 @@
407     /* find the (logical) block component of our location */
408     logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
409     offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
410     + /* map extents enabled logical block number to physical fs on-disk block number */
411     + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
412     + && INODE->i_flags & EXT4_EXTENTS_FL)
413     + map = ext4fs_block_map (logical_block);
414     + else
415     map = ext2fs_block_map (logical_block);
416     #ifdef E2DEBUG
417     printf ("map=%d\n", map);
418     @@ -504,7 +775,7 @@
419     int desc; /* index within that group */
420     int ino_blk; /* fs pointer of the inode's information */
421     int str_chk = 0; /* used to hold the results of a string compare */
422     - struct ext2_group_desc *gdp;
423     + struct ext4_group_desc *ext4_gdp;
424     struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
425    
426     char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
427     @@ -550,8 +821,15 @@
428     {
429     return 0;
430     }
431     - gdp = GROUP_DESC;
432     - ino_blk = gdp[desc].bg_inode_table +
433     + ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC +
434     + desc * EXT2_DESC_SIZE(SUPERBLOCK));
435     + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT)
436     + && (! ext4_gdp->bg_inode_table_hi))
437     + {/* 64bit itable not supported */
438     + errnum = ERR_FILELENGTH;
439     + return -1;
440     + }
441     + ino_blk = ext4_gdp->bg_inode_table +
442     (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
443     >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
444     #ifdef E2DEBUG
445     @@ -629,7 +907,10 @@
446     }
447     linkbuf[filemax + len] = '\0';
448    
449     - /* Read the symlink data. */
450     + /* Read the symlink data.
451     + * Slow symlink is extents enabled
452     + * But since grub_read invokes ext2fs_read, nothing to change here
453     + */
454     if (! ext2_is_fast_symlink ())
455     {
456     /* Read the necessary blocks, and reset the file pointer. */
457     @@ -640,7 +921,9 @@
458     }
459     else
460     {
461     - /* Copy the data directly from the inode. */
462     + /* Copy the data directly from the inode.
463     + * Fast symlink is not extents enabled
464     + */
465     len = filemax;
466     memmove (linkbuf, (char *) INODE->i_block, len);
467     }
468     @@ -674,7 +957,13 @@
469     errnum = ERR_BAD_FILETYPE;
470     return 0;
471     }
472     -
473     + /* if file is too large, just stop and report an error*/
474     + if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high))
475     + {
476     + /* file too large, stop reading */
477     + errnum = ERR_FILELENGTH;
478     + return 0;
479     + }
480     filemax = (INODE->i_size);
481     return 1;
482     }
483     @@ -728,17 +1017,28 @@
484     }
485    
486     /* else, find the (logical) block component of our location */
487     + /* ext4 logical block number the same as ext2/3 */
488     blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
489    
490     /* we know which logical block of the directory entry we are looking
491     for, now we have to translate that to the physical (fs) block on
492     the disk */
493     + /* map extents enabled logical block number to physical fs on-disk block number */
494     + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
495     + && INODE->i_flags & EXT4_EXTENTS_FL)
496     + map = ext4fs_block_map (blk);
497     + else
498     map = ext2fs_block_map (blk);
499     #ifdef E2DEBUG
500     printf ("fs block=%d\n", map);
501     #endif /* E2DEBUG */
502     mapblock2 = -1;
503     - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
504     + if (map < 0)
505     + {
506     + *rest = ch;
507     + return 0;
508     + }
509     + if (!ext2_rdfsb (map, DATABLOCK2))
510     {
511     errnum = ERR_FSYS_CORRUPT;
512     *rest = ch;