Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 diff -Naur grub-0.97/stage2/fsys_ext2fs.c grub-0.97-magellan/stage2/fsys_ext2fs.c
2 --- 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 __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 - __u32 s_reserved[235]; /* Padding to the end of the block */
47 - };
48 + /*
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 + /* 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;