020-ext4_support.patch 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. --- a/stage2/fsys_ext2fs.c
  2. +++ b/stage2/fsys_ext2fs.c
  3. @@ -51,6 +51,9 @@ typedef unsigned int __u32;
  4. #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
  5. #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
  6. +/* Inode flags */
  7. +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
  8. +
  9. /* include/linux/ext2_fs.h */
  10. struct ext2_super_block
  11. {
  12. @@ -191,6 +194,42 @@ struct ext2_dir_entry
  13. #define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
  14. ~EXT2_DIR_ROUND)
  15. +/* linux/ext4_fs_extents.h */
  16. +/*
  17. + * This is the extent on-disk structure.
  18. + * It's used at the bottom of the tree.
  19. + */
  20. +struct ext4_extent {
  21. + __u32 ee_block; /* first logical block extent covers */
  22. + __u16 ee_len; /* number of blocks covered by extent */
  23. + __u16 ee_start_hi; /* high 16 bits of physical block */
  24. + __u32 ee_start; /* low 32 bits of physical block */
  25. +};
  26. +
  27. +/*
  28. + * This is index on-disk structure.
  29. + * It's used at all the levels except the bottom.
  30. + */
  31. +struct ext4_extent_idx {
  32. + __u32 ei_block; /* index covers logical blocks from 'block' */
  33. + __u32 ei_leaf; /* pointer to the physical block of the next *
  34. + * level. leaf or next index could be there */
  35. + __u16 ei_leaf_hi; /* high 16 bits of physical block */
  36. + __u16 ei_unused;
  37. +};
  38. +
  39. +/*
  40. + * Each block (leaves and indexes), even inode-stored has header.
  41. + */
  42. +struct ext4_extent_header {
  43. + __u16 eh_magic; /* probably will support different formats */
  44. + __u16 eh_entries; /* number of valid entries */
  45. + __u16 eh_max; /* capacity of store in entries */
  46. + __u16 eh_depth; /* has tree real underlying blocks? */
  47. + __u32 eh_generation; /* generation of the tree */
  48. +};
  49. +
  50. +#define EXT4_EXT_MAGIC 0xf30a
  51. /* ext2/super.c */
  52. #define log2(n) ffz(~(n))
  53. @@ -279,6 +318,27 @@ ext2_rdfsb (int fsblock, int buffer)
  54. EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
  55. }
  56. +/* Walk through extents index tree to find the good leaf */
  57. +static struct ext4_extent_header *
  58. +ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block)
  59. +{
  60. + int i;
  61. + struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1);
  62. + if (extent_block->eh_magic != EXT4_EXT_MAGIC)
  63. + return NULL;
  64. + if (extent_block->eh_depth == 0)
  65. + return extent_block;
  66. + for (i = 0; i < extent_block->eh_entries; i++)
  67. + {
  68. + if (logical_block < index[i].ei_block)
  69. + break;
  70. + }
  71. + if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1))
  72. + return NULL;
  73. + return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block));
  74. +}
  75. +
  76. +
  77. /* from
  78. ext2/inode.c:ext2_bmap()
  79. */
  80. @@ -287,7 +347,6 @@ ext2_rdfsb (int fsblock, int buffer)
  81. static int
  82. ext2fs_block_map (int logical_block)
  83. {
  84. -
  85. #ifdef E2DEBUG
  86. unsigned char *i;
  87. for (i = (unsigned char *) INODE;
  88. @@ -308,82 +367,106 @@ ext2fs_block_map (int logical_block)
  89. printf ("logical block %d\n", logical_block);
  90. #endif /* E2DEBUG */
  91. - /* if it is directly pointed to by the inode, return that physical addr */
  92. - if (logical_block < EXT2_NDIR_BLOCKS)
  93. + if (!(INODE->i_flags & EXT4_EXTENTS_FL))
  94. {
  95. -#ifdef E2DEBUG
  96. - printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
  97. - printf ("returning %d\n", INODE->i_block[logical_block]);
  98. -#endif /* E2DEBUG */
  99. - return INODE->i_block[logical_block];
  100. - }
  101. - /* else */
  102. - logical_block -= EXT2_NDIR_BLOCKS;
  103. - /* try the indirect block */
  104. - if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
  105. - {
  106. - if (mapblock1 != 1
  107. - && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
  108. - {
  109. - errnum = ERR_FSYS_CORRUPT;
  110. - return -1;
  111. - }
  112. - mapblock1 = 1;
  113. - return ((__u32 *) DATABLOCK1)[logical_block];
  114. - }
  115. - /* else */
  116. - logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
  117. - /* now try the double indirect block */
  118. - if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
  119. - {
  120. - int bnum;
  121. - if (mapblock1 != 2
  122. - && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
  123. - {
  124. - errnum = ERR_FSYS_CORRUPT;
  125. - return -1;
  126. - }
  127. - mapblock1 = 2;
  128. - if ((bnum = (((__u32 *) DATABLOCK1)
  129. - [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
  130. - != mapblock2
  131. - && !ext2_rdfsb (bnum, DATABLOCK2))
  132. - {
  133. - errnum = ERR_FSYS_CORRUPT;
  134. - return -1;
  135. - }
  136. - mapblock2 = bnum;
  137. + /* if it is directly pointed to by the inode, return that physical addr */
  138. + if (logical_block < EXT2_NDIR_BLOCKS)
  139. + {
  140. +#ifdef E2DEBUG
  141. + printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
  142. + printf ("returning %d\n", INODE->i_block[logical_block]);
  143. +#endif /* E2DEBUG */
  144. + return INODE->i_block[logical_block];
  145. + }
  146. + /* else */
  147. + logical_block -= EXT2_NDIR_BLOCKS;
  148. + /* try the indirect block */
  149. + if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
  150. + {
  151. + if (mapblock1 != 1 && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
  152. + {
  153. + errnum = ERR_FSYS_CORRUPT;
  154. + return -1;
  155. + }
  156. + mapblock1 = 1;
  157. + return ((__u32 *) DATABLOCK1)[logical_block];
  158. + }
  159. + /* else */
  160. + logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
  161. + /* now try the double indirect block */
  162. + if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
  163. + {
  164. + int bnum;
  165. + if (mapblock1 != 2 && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
  166. + {
  167. + errnum = ERR_FSYS_CORRUPT;
  168. + return -1;
  169. + }
  170. + mapblock1 = 2;
  171. + if ((bnum = (((__u32 *) DATABLOCK1)
  172. + [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
  173. + != mapblock2
  174. + && !ext2_rdfsb (bnum, DATABLOCK2))
  175. + {
  176. + errnum = ERR_FSYS_CORRUPT;
  177. + return -1;
  178. + }
  179. + mapblock2 = bnum;
  180. + return ((__u32 *) DATABLOCK2)
  181. + [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  182. + }
  183. + /* else */
  184. + mapblock2 = -1;
  185. + logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
  186. + if (mapblock1 != 3
  187. + && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
  188. + {
  189. + errnum = ERR_FSYS_CORRUPT;
  190. + return -1;
  191. + }
  192. + mapblock1 = 3;
  193. + if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
  194. + [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
  195. + * 2)],
  196. + DATABLOCK2))
  197. + {
  198. + errnum = ERR_FSYS_CORRUPT;
  199. + return -1;
  200. + }
  201. + if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
  202. + [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
  203. + & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
  204. + DATABLOCK2))
  205. + {
  206. + errnum = ERR_FSYS_CORRUPT;
  207. + return -1;
  208. + }
  209. +
  210. return ((__u32 *) DATABLOCK2)
  211. - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  212. + [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  213. }
  214. - /* else */
  215. - mapblock2 = -1;
  216. - logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
  217. - if (mapblock1 != 3
  218. - && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
  219. - {
  220. - errnum = ERR_FSYS_CORRUPT;
  221. - return -1;
  222. - }
  223. - mapblock1 = 3;
  224. - if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
  225. - [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
  226. - * 2)],
  227. - DATABLOCK2))
  228. - {
  229. - errnum = ERR_FSYS_CORRUPT;
  230. - return -1;
  231. - }
  232. - if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
  233. - [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
  234. - & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
  235. - DATABLOCK2))
  236. + /* inode is in extents format */
  237. + else
  238. {
  239. + int i;
  240. + struct ext4_extent_header *extent_hdr =
  241. + ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block);
  242. + struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1);
  243. + if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC)
  244. + {
  245. + errnum = ERR_FSYS_CORRUPT;
  246. + return -1;
  247. + }
  248. + for (i = 0; i<extent_hdr->eh_entries; i++)
  249. + {
  250. + if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15))
  251. + return (logical_block - extent[i].ee_block + extent[i].ee_start);
  252. + }
  253. + /* We should not arrive here */
  254. +
  255. errnum = ERR_FSYS_CORRUPT;
  256. return -1;
  257. }
  258. - return ((__u32 *) DATABLOCK2)
  259. - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  260. }
  261. /* preconditions: all preconds of ext2fs_block_map */