ext4_write.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2011 - 2012 Samsung Electronics
  4. * EXT4 filesystem implementation in Uboot by
  5. * Uma Shankar <uma.shankar@samsung.com>
  6. * Manjunatha C Achar <a.manjunatha@samsung.com>
  7. *
  8. * ext4ls and ext4load : Based on ext2 ls and load support in Uboot.
  9. * Ext4 read optimization taken from Open-Moko
  10. * Qi bootloader
  11. *
  12. * (C) Copyright 2004
  13. * esd gmbh <www.esd-electronics.com>
  14. * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
  15. *
  16. * based on code from grub2 fs/ext2.c and fs/fshelp.c by
  17. * GRUB -- GRand Unified Bootloader
  18. * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
  19. *
  20. * ext4write : Based on generic ext4 protocol.
  21. */
  22. #include <common.h>
  23. #include <blk.h>
  24. #include <malloc.h>
  25. #include <memalign.h>
  26. #include <part.h>
  27. #include <linux/stat.h>
  28. #include <div64.h>
  29. #include "ext4_common.h"
  30. static inline void ext4fs_sb_free_inodes_inc(struct ext2_sblock *sb)
  31. {
  32. sb->free_inodes = cpu_to_le32(le32_to_cpu(sb->free_inodes) + 1);
  33. }
  34. static inline void ext4fs_sb_free_blocks_inc(struct ext2_sblock *sb)
  35. {
  36. sb->free_blocks = cpu_to_le32(le32_to_cpu(sb->free_blocks) + 1);
  37. }
  38. static inline void ext4fs_bg_free_inodes_inc
  39. (struct ext2_block_group *bg, const struct ext_filesystem *fs)
  40. {
  41. uint32_t free_inodes = le16_to_cpu(bg->free_inodes);
  42. if (fs->gdsize == 64)
  43. free_inodes += le16_to_cpu(bg->free_inodes_high) << 16;
  44. free_inodes++;
  45. bg->free_inodes = cpu_to_le16(free_inodes & 0xffff);
  46. if (fs->gdsize == 64)
  47. bg->free_inodes_high = cpu_to_le16(free_inodes >> 16);
  48. }
  49. static inline void ext4fs_bg_free_blocks_inc
  50. (struct ext2_block_group *bg, const struct ext_filesystem *fs)
  51. {
  52. uint32_t free_blocks = le16_to_cpu(bg->free_blocks);
  53. if (fs->gdsize == 64)
  54. free_blocks += le16_to_cpu(bg->free_blocks_high) << 16;
  55. free_blocks++;
  56. bg->free_blocks = cpu_to_le16(free_blocks & 0xffff);
  57. if (fs->gdsize == 64)
  58. bg->free_blocks_high = cpu_to_le16(free_blocks >> 16);
  59. }
  60. static void ext4fs_update(void)
  61. {
  62. short i;
  63. ext4fs_update_journal();
  64. struct ext_filesystem *fs = get_fs();
  65. struct ext2_block_group *bgd = NULL;
  66. /* update super block */
  67. put_ext4((uint64_t)(SUPERBLOCK_SIZE),
  68. (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE);
  69. /* update block bitmaps */
  70. for (i = 0; i < fs->no_blkgrp; i++) {
  71. bgd = ext4fs_get_group_descriptor(fs, i);
  72. bgd->bg_checksum = cpu_to_le16(ext4fs_checksum_update(i));
  73. uint64_t b_bitmap_blk = ext4fs_bg_get_block_id(bgd, fs);
  74. put_ext4(b_bitmap_blk * fs->blksz,
  75. fs->blk_bmaps[i], fs->blksz);
  76. }
  77. /* update inode bitmaps */
  78. for (i = 0; i < fs->no_blkgrp; i++) {
  79. bgd = ext4fs_get_group_descriptor(fs, i);
  80. uint64_t i_bitmap_blk = ext4fs_bg_get_inode_id(bgd, fs);
  81. put_ext4(i_bitmap_blk * fs->blksz,
  82. fs->inode_bmaps[i], fs->blksz);
  83. }
  84. /* update the block group descriptor table */
  85. put_ext4((uint64_t)((uint64_t)fs->gdtable_blkno * (uint64_t)fs->blksz),
  86. (struct ext2_block_group *)fs->gdtable,
  87. (fs->blksz * fs->no_blk_pergdt));
  88. ext4fs_dump_metadata();
  89. gindex = 0;
  90. gd_index = 0;
  91. }
  92. int ext4fs_get_bgdtable(void)
  93. {
  94. int status;
  95. struct ext_filesystem *fs = get_fs();
  96. int gdsize_total = ROUND(fs->no_blkgrp * fs->gdsize, fs->blksz);
  97. fs->no_blk_pergdt = gdsize_total / fs->blksz;
  98. /* allocate memory for gdtable */
  99. fs->gdtable = zalloc(gdsize_total);
  100. if (!fs->gdtable)
  101. return -ENOMEM;
  102. /* read the group descriptor table */
  103. status = ext4fs_devread((lbaint_t)fs->gdtable_blkno * fs->sect_perblk,
  104. 0, fs->blksz * fs->no_blk_pergdt, fs->gdtable);
  105. if (status == 0)
  106. goto fail;
  107. if (ext4fs_log_gdt(fs->gdtable)) {
  108. printf("Error in ext4fs_log_gdt\n");
  109. return -1;
  110. }
  111. return 0;
  112. fail:
  113. free(fs->gdtable);
  114. fs->gdtable = NULL;
  115. return -1;
  116. }
  117. static void delete_single_indirect_block(struct ext2_inode *inode)
  118. {
  119. struct ext2_block_group *bgd = NULL;
  120. static int prev_bg_bmap_idx = -1;
  121. uint32_t blknr;
  122. int remainder;
  123. int bg_idx;
  124. int status;
  125. uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
  126. struct ext_filesystem *fs = get_fs();
  127. char *journal_buffer = zalloc(fs->blksz);
  128. if (!journal_buffer) {
  129. printf("No memory\n");
  130. return;
  131. }
  132. /* deleting the single indirect block associated with inode */
  133. if (inode->b.blocks.indir_block != 0) {
  134. blknr = le32_to_cpu(inode->b.blocks.indir_block);
  135. debug("SIPB releasing %u\n", blknr);
  136. bg_idx = blknr / blk_per_grp;
  137. if (fs->blksz == 1024) {
  138. remainder = blknr % blk_per_grp;
  139. if (!remainder)
  140. bg_idx--;
  141. }
  142. ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
  143. /* get block group descriptor table */
  144. bgd = ext4fs_get_group_descriptor(fs, bg_idx);
  145. ext4fs_bg_free_blocks_inc(bgd, fs);
  146. ext4fs_sb_free_blocks_inc(fs->sb);
  147. /* journal backup */
  148. if (prev_bg_bmap_idx != bg_idx) {
  149. uint64_t b_bitmap_blk = ext4fs_bg_get_block_id(bgd, fs);
  150. status = ext4fs_devread(
  151. b_bitmap_blk * fs->sect_perblk,
  152. 0, fs->blksz, journal_buffer);
  153. if (status == 0)
  154. goto fail;
  155. if (ext4fs_log_journal(journal_buffer, b_bitmap_blk))
  156. goto fail;
  157. prev_bg_bmap_idx = bg_idx;
  158. }
  159. }
  160. fail:
  161. free(journal_buffer);
  162. }
  163. static void delete_double_indirect_block(struct ext2_inode *inode)
  164. {
  165. int i;
  166. short status;
  167. static int prev_bg_bmap_idx = -1;
  168. uint32_t blknr;
  169. int remainder;
  170. int bg_idx;
  171. uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
  172. __le32 *di_buffer = NULL;
  173. void *dib_start_addr = NULL;
  174. struct ext2_block_group *bgd = NULL;
  175. struct ext_filesystem *fs = get_fs();
  176. char *journal_buffer = zalloc(fs->blksz);
  177. if (!journal_buffer) {
  178. printf("No memory\n");
  179. return;
  180. }
  181. if (inode->b.blocks.double_indir_block != 0) {
  182. di_buffer = zalloc(fs->blksz);
  183. if (!di_buffer) {
  184. printf("No memory\n");
  185. return;
  186. }
  187. dib_start_addr = di_buffer;
  188. blknr = le32_to_cpu(inode->b.blocks.double_indir_block);
  189. status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
  190. fs->blksz, (char *)di_buffer);
  191. for (i = 0; i < fs->blksz / sizeof(int); i++) {
  192. if (*di_buffer == 0)
  193. break;
  194. debug("DICB releasing %u\n", *di_buffer);
  195. bg_idx = le32_to_cpu(*di_buffer) / blk_per_grp;
  196. if (fs->blksz == 1024) {
  197. remainder = le32_to_cpu(*di_buffer) % blk_per_grp;
  198. if (!remainder)
  199. bg_idx--;
  200. }
  201. /* get block group descriptor table */
  202. bgd = ext4fs_get_group_descriptor(fs, bg_idx);
  203. ext4fs_reset_block_bmap(le32_to_cpu(*di_buffer),
  204. fs->blk_bmaps[bg_idx], bg_idx);
  205. di_buffer++;
  206. ext4fs_bg_free_blocks_inc(bgd, fs);
  207. ext4fs_sb_free_blocks_inc(fs->sb);
  208. /* journal backup */
  209. if (prev_bg_bmap_idx != bg_idx) {
  210. uint64_t b_bitmap_blk =
  211. ext4fs_bg_get_block_id(bgd, fs);
  212. status = ext4fs_devread(b_bitmap_blk
  213. * fs->sect_perblk, 0,
  214. fs->blksz,
  215. journal_buffer);
  216. if (status == 0)
  217. goto fail;
  218. if (ext4fs_log_journal(journal_buffer,
  219. b_bitmap_blk))
  220. goto fail;
  221. prev_bg_bmap_idx = bg_idx;
  222. }
  223. }
  224. /* removing the parent double indirect block */
  225. blknr = le32_to_cpu(inode->b.blocks.double_indir_block);
  226. bg_idx = blknr / blk_per_grp;
  227. if (fs->blksz == 1024) {
  228. remainder = blknr % blk_per_grp;
  229. if (!remainder)
  230. bg_idx--;
  231. }
  232. /* get block group descriptor table */
  233. bgd = ext4fs_get_group_descriptor(fs, bg_idx);
  234. ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
  235. ext4fs_bg_free_blocks_inc(bgd, fs);
  236. ext4fs_sb_free_blocks_inc(fs->sb);
  237. /* journal backup */
  238. if (prev_bg_bmap_idx != bg_idx) {
  239. uint64_t b_bitmap_blk = ext4fs_bg_get_block_id(bgd, fs);
  240. status = ext4fs_devread(b_bitmap_blk * fs->sect_perblk,
  241. 0, fs->blksz, journal_buffer);
  242. if (status == 0)
  243. goto fail;
  244. if (ext4fs_log_journal(journal_buffer, b_bitmap_blk))
  245. goto fail;
  246. prev_bg_bmap_idx = bg_idx;
  247. }
  248. debug("DIPB releasing %d\n", blknr);
  249. }
  250. fail:
  251. free(dib_start_addr);
  252. free(journal_buffer);
  253. }
  254. static void delete_triple_indirect_block(struct ext2_inode *inode)
  255. {
  256. int i, j;
  257. short status;
  258. static int prev_bg_bmap_idx = -1;
  259. uint32_t blknr;
  260. int remainder;
  261. int bg_idx;
  262. uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
  263. __le32 *tigp_buffer = NULL;
  264. void *tib_start_addr = NULL;
  265. __le32 *tip_buffer = NULL;
  266. void *tipb_start_addr = NULL;
  267. struct ext2_block_group *bgd = NULL;
  268. struct ext_filesystem *fs = get_fs();
  269. char *journal_buffer = zalloc(fs->blksz);
  270. if (!journal_buffer) {
  271. printf("No memory\n");
  272. return;
  273. }
  274. if (inode->b.blocks.triple_indir_block != 0) {
  275. tigp_buffer = zalloc(fs->blksz);
  276. if (!tigp_buffer) {
  277. printf("No memory\n");
  278. return;
  279. }
  280. tib_start_addr = tigp_buffer;
  281. blknr = le32_to_cpu(inode->b.blocks.triple_indir_block);
  282. status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
  283. fs->blksz, (char *)tigp_buffer);
  284. for (i = 0; i < fs->blksz / sizeof(int); i++) {
  285. if (*tigp_buffer == 0)
  286. break;
  287. debug("tigp buffer releasing %u\n", *tigp_buffer);
  288. tip_buffer = zalloc(fs->blksz);
  289. if (!tip_buffer)
  290. goto fail;
  291. tipb_start_addr = tip_buffer;
  292. status = ext4fs_devread((lbaint_t)le32_to_cpu(*tigp_buffer) *
  293. fs->sect_perblk, 0, fs->blksz,
  294. (char *)tip_buffer);
  295. for (j = 0; j < fs->blksz / sizeof(int); j++) {
  296. if (le32_to_cpu(*tip_buffer) == 0)
  297. break;
  298. bg_idx = le32_to_cpu(*tip_buffer) / blk_per_grp;
  299. if (fs->blksz == 1024) {
  300. remainder = le32_to_cpu(*tip_buffer) % blk_per_grp;
  301. if (!remainder)
  302. bg_idx--;
  303. }
  304. ext4fs_reset_block_bmap(le32_to_cpu(*tip_buffer),
  305. fs->blk_bmaps[bg_idx],
  306. bg_idx);
  307. tip_buffer++;
  308. /* get block group descriptor table */
  309. bgd = ext4fs_get_group_descriptor(fs, bg_idx);
  310. ext4fs_bg_free_blocks_inc(bgd, fs);
  311. ext4fs_sb_free_blocks_inc(fs->sb);
  312. /* journal backup */
  313. if (prev_bg_bmap_idx != bg_idx) {
  314. uint64_t b_bitmap_blk =
  315. ext4fs_bg_get_block_id(bgd, fs);
  316. status =
  317. ext4fs_devread(
  318. b_bitmap_blk *
  319. fs->sect_perblk, 0,
  320. fs->blksz,
  321. journal_buffer);
  322. if (status == 0)
  323. goto fail;
  324. if (ext4fs_log_journal(journal_buffer,
  325. b_bitmap_blk))
  326. goto fail;
  327. prev_bg_bmap_idx = bg_idx;
  328. }
  329. }
  330. free(tipb_start_addr);
  331. tipb_start_addr = NULL;
  332. /*
  333. * removing the grand parent blocks
  334. * which is connected to inode
  335. */
  336. bg_idx = le32_to_cpu(*tigp_buffer) / blk_per_grp;
  337. if (fs->blksz == 1024) {
  338. remainder = le32_to_cpu(*tigp_buffer) % blk_per_grp;
  339. if (!remainder)
  340. bg_idx--;
  341. }
  342. ext4fs_reset_block_bmap(le32_to_cpu(*tigp_buffer),
  343. fs->blk_bmaps[bg_idx], bg_idx);
  344. tigp_buffer++;
  345. /* get block group descriptor table */
  346. bgd = ext4fs_get_group_descriptor(fs, bg_idx);
  347. ext4fs_bg_free_blocks_inc(bgd, fs);
  348. ext4fs_sb_free_blocks_inc(fs->sb);
  349. /* journal backup */
  350. if (prev_bg_bmap_idx != bg_idx) {
  351. uint64_t b_bitmap_blk =
  352. ext4fs_bg_get_block_id(bgd, fs);
  353. memset(journal_buffer, '\0', fs->blksz);
  354. status = ext4fs_devread(b_bitmap_blk *
  355. fs->sect_perblk, 0,
  356. fs->blksz,
  357. journal_buffer);
  358. if (status == 0)
  359. goto fail;
  360. if (ext4fs_log_journal(journal_buffer,
  361. b_bitmap_blk))
  362. goto fail;
  363. prev_bg_bmap_idx = bg_idx;
  364. }
  365. }
  366. /* removing the grand parent triple indirect block */
  367. blknr = le32_to_cpu(inode->b.blocks.triple_indir_block);
  368. bg_idx = blknr / blk_per_grp;
  369. if (fs->blksz == 1024) {
  370. remainder = blknr % blk_per_grp;
  371. if (!remainder)
  372. bg_idx--;
  373. }
  374. ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
  375. /* get block group descriptor table */
  376. bgd = ext4fs_get_group_descriptor(fs, bg_idx);
  377. ext4fs_bg_free_blocks_inc(bgd, fs);
  378. ext4fs_sb_free_blocks_inc(fs->sb);
  379. /* journal backup */
  380. if (prev_bg_bmap_idx != bg_idx) {
  381. uint64_t b_bitmap_blk = ext4fs_bg_get_block_id(bgd, fs);
  382. status = ext4fs_devread(b_bitmap_blk * fs->sect_perblk,
  383. 0, fs->blksz, journal_buffer);
  384. if (status == 0)
  385. goto fail;
  386. if (ext4fs_log_journal(journal_buffer, b_bitmap_blk))
  387. goto fail;
  388. prev_bg_bmap_idx = bg_idx;
  389. }
  390. debug("tigp buffer itself releasing %d\n", blknr);
  391. }
  392. fail:
  393. free(tib_start_addr);
  394. free(tipb_start_addr);
  395. free(journal_buffer);
  396. }
  397. static int ext4fs_delete_file(int inodeno)
  398. {
  399. struct ext2_inode inode;
  400. short status;
  401. int i;
  402. int remainder;
  403. long int blknr;
  404. int bg_idx;
  405. int ibmap_idx;
  406. char *read_buffer = NULL;
  407. char *start_block_address = NULL;
  408. uint32_t no_blocks;
  409. static int prev_bg_bmap_idx = -1;
  410. unsigned int inodes_per_block;
  411. uint32_t blkno;
  412. unsigned int blkoff;
  413. uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
  414. uint32_t inode_per_grp = le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
  415. struct ext2_inode *inode_buffer = NULL;
  416. struct ext2_block_group *bgd = NULL;
  417. struct ext_filesystem *fs = get_fs();
  418. char *journal_buffer = zalloc(fs->blksz);
  419. if (!journal_buffer)
  420. return -ENOMEM;
  421. status = ext4fs_read_inode(ext4fs_root, inodeno, &inode);
  422. if (status == 0)
  423. goto fail;
  424. /* read the block no allocated to a file */
  425. no_blocks = le32_to_cpu(inode.size) / fs->blksz;
  426. if (le32_to_cpu(inode.size) % fs->blksz)
  427. no_blocks++;
  428. /*
  429. * special case for symlinks whose target are small enough that
  430. *it fits in struct ext2_inode.b.symlink: no block had been allocated
  431. */
  432. if ((le16_to_cpu(inode.mode) & S_IFLNK) &&
  433. le32_to_cpu(inode.size) <= sizeof(inode.b.symlink)) {
  434. no_blocks = 0;
  435. }
  436. if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) {
  437. /* FIXME delete extent index blocks, i.e. eh_depth >= 1 */
  438. struct ext4_extent_header *eh =
  439. (struct ext4_extent_header *)
  440. inode.b.blocks.dir_blocks;
  441. debug("del: dep=%d entries=%d\n", eh->eh_depth, eh->eh_entries);
  442. } else {
  443. delete_single_indirect_block(&inode);
  444. delete_double_indirect_block(&inode);
  445. delete_triple_indirect_block(&inode);
  446. }
  447. /* release data blocks */
  448. for (i = 0; i < no_blocks; i++) {
  449. blknr = read_allocated_block(&inode, i, NULL);
  450. if (blknr == 0)
  451. continue;
  452. if (blknr < 0)
  453. goto fail;
  454. bg_idx = blknr / blk_per_grp;
  455. if (fs->blksz == 1024) {
  456. remainder = blknr % blk_per_grp;
  457. if (!remainder)
  458. bg_idx--;
  459. }
  460. ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
  461. bg_idx);
  462. debug("EXT4 Block releasing %ld: %d\n", blknr, bg_idx);
  463. /* get block group descriptor table */
  464. bgd = ext4fs_get_group_descriptor(fs, bg_idx);
  465. ext4fs_bg_free_blocks_inc(bgd, fs);
  466. ext4fs_sb_free_blocks_inc(fs->sb);
  467. /* journal backup */
  468. if (prev_bg_bmap_idx != bg_idx) {
  469. uint64_t b_bitmap_blk = ext4fs_bg_get_block_id(bgd, fs);
  470. status = ext4fs_devread(b_bitmap_blk * fs->sect_perblk,
  471. 0, fs->blksz,
  472. journal_buffer);
  473. if (status == 0)
  474. goto fail;
  475. if (ext4fs_log_journal(journal_buffer, b_bitmap_blk))
  476. goto fail;
  477. prev_bg_bmap_idx = bg_idx;
  478. }
  479. }
  480. /* release inode */
  481. /* from the inode no to blockno */
  482. inodes_per_block = fs->blksz / fs->inodesz;
  483. ibmap_idx = inodeno / inode_per_grp;
  484. /* get the block no */
  485. inodeno--;
  486. /* get block group descriptor table */
  487. bgd = ext4fs_get_group_descriptor(fs, ibmap_idx);
  488. blkno = ext4fs_bg_get_inode_table_id(bgd, fs) +
  489. (inodeno % inode_per_grp) / inodes_per_block;
  490. /* get the offset of the inode */
  491. blkoff = ((inodeno) % inodes_per_block) * fs->inodesz;
  492. /* read the block no containing the inode */
  493. read_buffer = zalloc(fs->blksz);
  494. if (!read_buffer)
  495. goto fail;
  496. start_block_address = read_buffer;
  497. status = ext4fs_devread((lbaint_t)blkno * fs->sect_perblk,
  498. 0, fs->blksz, read_buffer);
  499. if (status == 0)
  500. goto fail;
  501. if (ext4fs_log_journal(read_buffer, blkno))
  502. goto fail;
  503. read_buffer = read_buffer + blkoff;
  504. inode_buffer = (struct ext2_inode *)read_buffer;
  505. memset(inode_buffer, '\0', fs->inodesz);
  506. /* write the inode to original position in inode table */
  507. if (ext4fs_put_metadata(start_block_address, blkno))
  508. goto fail;
  509. /* update the respective inode bitmaps */
  510. inodeno++;
  511. ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx);
  512. ext4fs_bg_free_inodes_inc(bgd, fs);
  513. ext4fs_sb_free_inodes_inc(fs->sb);
  514. /* journal backup */
  515. memset(journal_buffer, '\0', fs->blksz);
  516. status = ext4fs_devread(ext4fs_bg_get_inode_id(bgd, fs) *
  517. fs->sect_perblk, 0, fs->blksz, journal_buffer);
  518. if (status == 0)
  519. goto fail;
  520. if (ext4fs_log_journal(journal_buffer, ext4fs_bg_get_inode_id(bgd, fs)))
  521. goto fail;
  522. ext4fs_update();
  523. ext4fs_deinit();
  524. ext4fs_reinit_global();
  525. if (ext4fs_init() != 0) {
  526. printf("error in File System init\n");
  527. goto fail;
  528. }
  529. free(start_block_address);
  530. free(journal_buffer);
  531. return 0;
  532. fail:
  533. free(start_block_address);
  534. free(journal_buffer);
  535. return -1;
  536. }
  537. int ext4fs_init(void)
  538. {
  539. short status;
  540. int i;
  541. uint32_t real_free_blocks = 0;
  542. struct ext_filesystem *fs = get_fs();
  543. /* populate fs */
  544. fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root);
  545. fs->sect_perblk = fs->blksz >> fs->dev_desc->log2blksz;
  546. /* get the superblock */
  547. fs->sb = zalloc(SUPERBLOCK_SIZE);
  548. if (!fs->sb)
  549. return -ENOMEM;
  550. if (!ext4_read_superblock((char *)fs->sb))
  551. goto fail;
  552. /* init journal */
  553. if (ext4fs_init_journal())
  554. goto fail;
  555. /* get total no of blockgroups */
  556. fs->no_blkgrp = (uint32_t)ext4fs_div_roundup(
  557. le32_to_cpu(ext4fs_root->sblock.total_blocks)
  558. - le32_to_cpu(ext4fs_root->sblock.first_data_block),
  559. le32_to_cpu(ext4fs_root->sblock.blocks_per_group));
  560. /* get the block group descriptor table */
  561. fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1);
  562. if (ext4fs_get_bgdtable() == -1) {
  563. printf("Error in getting the block group descriptor table\n");
  564. goto fail;
  565. }
  566. /* load all the available bitmap block of the partition */
  567. fs->blk_bmaps = zalloc(fs->no_blkgrp * sizeof(char *));
  568. if (!fs->blk_bmaps)
  569. goto fail;
  570. for (i = 0; i < fs->no_blkgrp; i++) {
  571. fs->blk_bmaps[i] = zalloc(fs->blksz);
  572. if (!fs->blk_bmaps[i])
  573. goto fail;
  574. }
  575. for (i = 0; i < fs->no_blkgrp; i++) {
  576. struct ext2_block_group *bgd =
  577. ext4fs_get_group_descriptor(fs, i);
  578. status = ext4fs_devread(ext4fs_bg_get_block_id(bgd, fs) *
  579. fs->sect_perblk, 0,
  580. fs->blksz, (char *)fs->blk_bmaps[i]);
  581. if (status == 0)
  582. goto fail;
  583. }
  584. /* load all the available inode bitmap of the partition */
  585. fs->inode_bmaps = zalloc(fs->no_blkgrp * sizeof(unsigned char *));
  586. if (!fs->inode_bmaps)
  587. goto fail;
  588. for (i = 0; i < fs->no_blkgrp; i++) {
  589. fs->inode_bmaps[i] = zalloc(fs->blksz);
  590. if (!fs->inode_bmaps[i])
  591. goto fail;
  592. }
  593. for (i = 0; i < fs->no_blkgrp; i++) {
  594. struct ext2_block_group *bgd =
  595. ext4fs_get_group_descriptor(fs, i);
  596. status = ext4fs_devread(ext4fs_bg_get_inode_id(bgd, fs) *
  597. fs->sect_perblk,
  598. 0, fs->blksz,
  599. (char *)fs->inode_bmaps[i]);
  600. if (status == 0)
  601. goto fail;
  602. }
  603. /*
  604. * check filesystem consistency with free blocks of file system
  605. * some time we observed that superblock freeblocks does not match
  606. * with the blockgroups freeblocks when improper
  607. * reboot of a linux kernel
  608. */
  609. for (i = 0; i < fs->no_blkgrp; i++) {
  610. struct ext2_block_group *bgd =
  611. ext4fs_get_group_descriptor(fs, i);
  612. real_free_blocks = real_free_blocks +
  613. ext4fs_bg_get_free_blocks(bgd, fs);
  614. }
  615. if (real_free_blocks != ext4fs_sb_get_free_blocks(fs->sb))
  616. ext4fs_sb_set_free_blocks(fs->sb, real_free_blocks);
  617. return 0;
  618. fail:
  619. ext4fs_deinit();
  620. return -1;
  621. }
  622. void ext4fs_deinit(void)
  623. {
  624. int i;
  625. struct ext2_inode inode_journal;
  626. struct journal_superblock_t *jsb;
  627. uint32_t blknr;
  628. struct ext_filesystem *fs = get_fs();
  629. uint32_t new_feature_incompat;
  630. /* free journal */
  631. char *temp_buff = zalloc(fs->blksz);
  632. if (temp_buff) {
  633. ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
  634. &inode_journal);
  635. blknr = read_allocated_block(&inode_journal,
  636. EXT2_JOURNAL_SUPERBLOCK, NULL);
  637. ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
  638. temp_buff);
  639. jsb = (struct journal_superblock_t *)temp_buff;
  640. jsb->s_start = 0;
  641. put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
  642. (struct journal_superblock_t *)temp_buff, fs->blksz);
  643. free(temp_buff);
  644. }
  645. ext4fs_free_journal();
  646. /* get the superblock */
  647. ext4_read_superblock((char *)fs->sb);
  648. new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
  649. new_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
  650. fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
  651. put_ext4((uint64_t)(SUPERBLOCK_SIZE),
  652. (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE);
  653. free(fs->sb);
  654. fs->sb = NULL;
  655. if (fs->blk_bmaps) {
  656. for (i = 0; i < fs->no_blkgrp; i++) {
  657. free(fs->blk_bmaps[i]);
  658. fs->blk_bmaps[i] = NULL;
  659. }
  660. free(fs->blk_bmaps);
  661. fs->blk_bmaps = NULL;
  662. }
  663. if (fs->inode_bmaps) {
  664. for (i = 0; i < fs->no_blkgrp; i++) {
  665. free(fs->inode_bmaps[i]);
  666. fs->inode_bmaps[i] = NULL;
  667. }
  668. free(fs->inode_bmaps);
  669. fs->inode_bmaps = NULL;
  670. }
  671. free(fs->gdtable);
  672. fs->gdtable = NULL;
  673. /*
  674. * reinitiliazed the global inode and
  675. * block bitmap first execution check variables
  676. */
  677. fs->first_pass_ibmap = 0;
  678. fs->first_pass_bbmap = 0;
  679. fs->curr_inode_no = 0;
  680. fs->curr_blkno = 0;
  681. }
  682. /*
  683. * Write data to filesystem blocks. Uses same optimization for
  684. * contigous sectors as ext4fs_read_file
  685. */
  686. static int ext4fs_write_file(struct ext2_inode *file_inode,
  687. int pos, unsigned int len, const char *buf)
  688. {
  689. int i;
  690. int blockcnt;
  691. uint32_t filesize = le32_to_cpu(file_inode->size);
  692. struct ext_filesystem *fs = get_fs();
  693. int log2blksz = fs->dev_desc->log2blksz;
  694. int log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_root) - log2blksz;
  695. int previous_block_number = -1;
  696. int delayed_start = 0;
  697. int delayed_extent = 0;
  698. int delayed_next = 0;
  699. const char *delayed_buf = NULL;
  700. /* Adjust len so it we can't read past the end of the file. */
  701. if (len > filesize)
  702. len = filesize;
  703. blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz;
  704. for (i = pos / fs->blksz; i < blockcnt; i++) {
  705. long int blknr;
  706. int blockend = fs->blksz;
  707. int skipfirst = 0;
  708. blknr = read_allocated_block(file_inode, i, NULL);
  709. if (blknr <= 0)
  710. return -1;
  711. blknr = blknr << log2_fs_blocksize;
  712. if (blknr) {
  713. if (previous_block_number != -1) {
  714. if (delayed_next == blknr) {
  715. delayed_extent += blockend;
  716. delayed_next += blockend >> log2blksz;
  717. } else { /* spill */
  718. put_ext4((uint64_t)
  719. ((uint64_t)delayed_start << log2blksz),
  720. delayed_buf,
  721. (uint32_t) delayed_extent);
  722. previous_block_number = blknr;
  723. delayed_start = blknr;
  724. delayed_extent = blockend;
  725. delayed_buf = buf;
  726. delayed_next = blknr +
  727. (blockend >> log2blksz);
  728. }
  729. } else {
  730. previous_block_number = blknr;
  731. delayed_start = blknr;
  732. delayed_extent = blockend;
  733. delayed_buf = buf;
  734. delayed_next = blknr +
  735. (blockend >> log2blksz);
  736. }
  737. } else {
  738. if (previous_block_number != -1) {
  739. /* spill */
  740. put_ext4((uint64_t) ((uint64_t)delayed_start <<
  741. log2blksz),
  742. delayed_buf,
  743. (uint32_t) delayed_extent);
  744. previous_block_number = -1;
  745. }
  746. }
  747. buf += fs->blksz - skipfirst;
  748. }
  749. if (previous_block_number != -1) {
  750. /* spill */
  751. put_ext4((uint64_t) ((uint64_t)delayed_start << log2blksz),
  752. delayed_buf, (uint32_t) delayed_extent);
  753. previous_block_number = -1;
  754. }
  755. return len;
  756. }
  757. int ext4fs_write(const char *fname, const char *buffer,
  758. unsigned long sizebytes, int type)
  759. {
  760. int ret = 0;
  761. struct ext2_inode *file_inode = NULL;
  762. unsigned char *inode_buffer = NULL;
  763. int parent_inodeno;
  764. int inodeno;
  765. time_t timestamp = 0;
  766. uint64_t bytes_reqd_for_file;
  767. unsigned int blks_reqd_for_file;
  768. unsigned int blocks_remaining;
  769. int existing_file_inodeno;
  770. char *temp_ptr = NULL;
  771. long int itable_blkno;
  772. long int parent_itable_blkno;
  773. long int blkoff;
  774. struct ext2_sblock *sblock = &(ext4fs_root->sblock);
  775. unsigned int inodes_per_block;
  776. unsigned int ibmap_idx;
  777. struct ext2_block_group *bgd = NULL;
  778. struct ext_filesystem *fs = get_fs();
  779. ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
  780. bool store_link_in_inode = false;
  781. memset(filename, 0x00, 256);
  782. if (type != FILETYPE_REG && type != FILETYPE_SYMLINK)
  783. return -1;
  784. g_parent_inode = zalloc(fs->inodesz);
  785. if (!g_parent_inode)
  786. goto fail;
  787. if (ext4fs_init() != 0) {
  788. printf("error in File System init\n");
  789. return -1;
  790. }
  791. if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
  792. printf("Unsupported feature metadata_csum found, not writing.\n");
  793. return -1;
  794. }
  795. inodes_per_block = fs->blksz / fs->inodesz;
  796. parent_inodeno = ext4fs_get_parent_inode_num(fname, filename, F_FILE);
  797. if (parent_inodeno == -1)
  798. goto fail;
  799. if (ext4fs_iget(parent_inodeno, g_parent_inode))
  800. goto fail;
  801. /* do not mess up a directory using hash trees */
  802. if (le32_to_cpu(g_parent_inode->flags) & EXT4_INDEX_FL) {
  803. printf("hash tree directory\n");
  804. goto fail;
  805. }
  806. /* check if the filename is already present in root */
  807. existing_file_inodeno = ext4fs_filename_unlink(filename);
  808. if (existing_file_inodeno != -1) {
  809. ret = ext4fs_delete_file(existing_file_inodeno);
  810. fs->first_pass_bbmap = 0;
  811. fs->curr_blkno = 0;
  812. fs->first_pass_ibmap = 0;
  813. fs->curr_inode_no = 0;
  814. if (ret)
  815. goto fail;
  816. }
  817. /* calculate how many blocks required */
  818. if (type == FILETYPE_SYMLINK &&
  819. sizebytes <= sizeof(file_inode->b.symlink)) {
  820. store_link_in_inode = true;
  821. bytes_reqd_for_file = 0;
  822. } else {
  823. bytes_reqd_for_file = sizebytes;
  824. }
  825. blks_reqd_for_file = lldiv(bytes_reqd_for_file, fs->blksz);
  826. if (do_div(bytes_reqd_for_file, fs->blksz) != 0) {
  827. blks_reqd_for_file++;
  828. debug("total bytes for a file %u\n", blks_reqd_for_file);
  829. }
  830. blocks_remaining = blks_reqd_for_file;
  831. /* test for available space in partition */
  832. if (le32_to_cpu(fs->sb->free_blocks) < blks_reqd_for_file) {
  833. printf("Not enough space on partition !!!\n");
  834. goto fail;
  835. }
  836. inodeno = ext4fs_update_parent_dentry(filename, type);
  837. if (inodeno == -1)
  838. goto fail;
  839. /* prepare file inode */
  840. inode_buffer = zalloc(fs->inodesz);
  841. if (!inode_buffer)
  842. goto fail;
  843. file_inode = (struct ext2_inode *)inode_buffer;
  844. file_inode->size = cpu_to_le32(sizebytes);
  845. if (type == FILETYPE_SYMLINK) {
  846. file_inode->mode = cpu_to_le16(S_IFLNK | S_IRWXU | S_IRWXG |
  847. S_IRWXO);
  848. if (store_link_in_inode) {
  849. strncpy(file_inode->b.symlink, buffer, sizebytes);
  850. sizebytes = 0;
  851. }
  852. } else {
  853. file_inode->mode = cpu_to_le16(S_IFREG | S_IRWXU | S_IRGRP |
  854. S_IROTH | S_IXGRP | S_IXOTH);
  855. }
  856. /* ToDo: Update correct time */
  857. file_inode->mtime = cpu_to_le32(timestamp);
  858. file_inode->atime = cpu_to_le32(timestamp);
  859. file_inode->ctime = cpu_to_le32(timestamp);
  860. file_inode->nlinks = cpu_to_le16(1);
  861. /* Allocate data blocks */
  862. ext4fs_allocate_blocks(file_inode, blocks_remaining,
  863. &blks_reqd_for_file);
  864. file_inode->blockcnt = cpu_to_le32((blks_reqd_for_file * fs->blksz) >>
  865. LOG2_SECTOR_SIZE);
  866. temp_ptr = zalloc(fs->blksz);
  867. if (!temp_ptr)
  868. goto fail;
  869. ibmap_idx = inodeno / le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
  870. inodeno--;
  871. bgd = ext4fs_get_group_descriptor(fs, ibmap_idx);
  872. itable_blkno = ext4fs_bg_get_inode_table_id(bgd, fs) +
  873. (inodeno % le32_to_cpu(sblock->inodes_per_group)) /
  874. inodes_per_block;
  875. blkoff = (inodeno % inodes_per_block) * fs->inodesz;
  876. ext4fs_devread((lbaint_t)itable_blkno * fs->sect_perblk, 0, fs->blksz,
  877. temp_ptr);
  878. if (ext4fs_log_journal(temp_ptr, itable_blkno))
  879. goto fail;
  880. memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz);
  881. if (ext4fs_put_metadata(temp_ptr, itable_blkno))
  882. goto fail;
  883. /* copy the file content into data blocks */
  884. if (ext4fs_write_file(file_inode, 0, sizebytes, buffer) == -1) {
  885. printf("Error in copying content\n");
  886. /* FIXME: Deallocate data blocks */
  887. goto fail;
  888. }
  889. ibmap_idx = parent_inodeno / le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
  890. parent_inodeno--;
  891. bgd = ext4fs_get_group_descriptor(fs, ibmap_idx);
  892. parent_itable_blkno = ext4fs_bg_get_inode_table_id(bgd, fs) +
  893. (parent_inodeno %
  894. le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
  895. blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz;
  896. if (parent_itable_blkno != itable_blkno) {
  897. memset(temp_ptr, '\0', fs->blksz);
  898. ext4fs_devread((lbaint_t)parent_itable_blkno * fs->sect_perblk,
  899. 0, fs->blksz, temp_ptr);
  900. if (ext4fs_log_journal(temp_ptr, parent_itable_blkno))
  901. goto fail;
  902. memcpy(temp_ptr + blkoff, g_parent_inode, fs->inodesz);
  903. if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno))
  904. goto fail;
  905. } else {
  906. /*
  907. * If parent and child fall in same inode table block
  908. * both should be kept in 1 buffer
  909. */
  910. memcpy(temp_ptr + blkoff, g_parent_inode, fs->inodesz);
  911. gd_index--;
  912. if (ext4fs_put_metadata(temp_ptr, itable_blkno))
  913. goto fail;
  914. }
  915. ext4fs_update();
  916. ext4fs_deinit();
  917. fs->first_pass_bbmap = 0;
  918. fs->curr_blkno = 0;
  919. fs->first_pass_ibmap = 0;
  920. fs->curr_inode_no = 0;
  921. free(inode_buffer);
  922. free(g_parent_inode);
  923. free(temp_ptr);
  924. g_parent_inode = NULL;
  925. return 0;
  926. fail:
  927. ext4fs_deinit();
  928. free(inode_buffer);
  929. free(g_parent_inode);
  930. free(temp_ptr);
  931. g_parent_inode = NULL;
  932. return -1;
  933. }
  934. int ext4_write_file(const char *filename, void *buf, loff_t offset,
  935. loff_t len, loff_t *actwrite)
  936. {
  937. int ret;
  938. if (offset != 0) {
  939. printf("** Cannot support non-zero offset **\n");
  940. return -1;
  941. }
  942. ret = ext4fs_write(filename, buf, len, FILETYPE_REG);
  943. if (ret) {
  944. printf("** Error ext4fs_write() **\n");
  945. goto fail;
  946. }
  947. *actwrite = len;
  948. return 0;
  949. fail:
  950. *actwrite = 0;
  951. return -1;
  952. }
  953. int ext4fs_create_link(const char *target, const char *fname)
  954. {
  955. return ext4fs_write(fname, target, strlen(target), FILETYPE_SYMLINK);
  956. }