ext4_write.c 28 KB

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