ext4_write.c 28 KB

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