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>
7 * ext4ls and ext4load : Based on ext2 ls and load support in Uboot.
8 * Ext4 read optimization taken from Open-Moko
12 * esd gmbh <www.esd-electronics.com>
13 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
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.
19 * ext4write : Based on generic ext4 protocol.
21 * SPDX-License-Identifier: GPL-2.0+
26 #include <linux/stat.h>
28 #include "ext4_common.h"
30 static void ext4fs_update(void)
33 ext4fs_update_journal();
34 struct ext_filesystem *fs = get_fs();
36 /* update super block */
37 put_ext4((uint64_t)(SUPERBLOCK_SIZE),
38 (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE);
40 /* update block groups */
41 for (i = 0; i < fs->no_blkgrp; i++) {
42 fs->bgd[i].bg_checksum = ext4fs_checksum_update(i);
43 put_ext4((uint64_t)((uint64_t)fs->bgd[i].block_id * (uint64_t)fs->blksz),
44 fs->blk_bmaps[i], fs->blksz);
47 /* update inode table groups */
48 for (i = 0; i < fs->no_blkgrp; i++) {
49 put_ext4((uint64_t) ((uint64_t)fs->bgd[i].inode_id * (uint64_t)fs->blksz),
50 fs->inode_bmaps[i], fs->blksz);
53 /* update the block group descriptor table */
54 put_ext4((uint64_t)((uint64_t)fs->gdtable_blkno * (uint64_t)fs->blksz),
55 (struct ext2_block_group *)fs->gdtable,
56 (fs->blksz * fs->no_blk_pergdt));
58 ext4fs_dump_metadata();
64 int ext4fs_get_bgdtable(void)
68 struct ext_filesystem *fs = get_fs();
69 grp_desc_size = sizeof(struct ext2_block_group);
70 fs->no_blk_pergdt = (fs->no_blkgrp * grp_desc_size) / fs->blksz;
71 if ((fs->no_blkgrp * grp_desc_size) % fs->blksz)
74 /* allocate memory for gdtable */
75 fs->gdtable = zalloc(fs->blksz * fs->no_blk_pergdt);
78 /* read the group descriptor table */
79 status = ext4fs_devread((lbaint_t)fs->gdtable_blkno * fs->sect_perblk,
80 0, fs->blksz * fs->no_blk_pergdt, fs->gdtable);
84 if (ext4fs_log_gdt(fs->gdtable)) {
85 printf("Error in ext4fs_log_gdt\n");
97 static void delete_single_indirect_block(struct ext2_inode *inode)
99 struct ext2_block_group *bgd = NULL;
100 static int prev_bg_bmap_idx = -1;
105 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
106 struct ext_filesystem *fs = get_fs();
107 char *journal_buffer = zalloc(fs->blksz);
108 if (!journal_buffer) {
109 printf("No memory\n");
112 /* get block group descriptor table */
113 bgd = (struct ext2_block_group *)fs->gdtable;
115 /* deleting the single indirect block associated with inode */
116 if (inode->b.blocks.indir_block != 0) {
117 debug("SIPB releasing %u\n", inode->b.blocks.indir_block);
118 blknr = inode->b.blocks.indir_block;
119 if (fs->blksz != 1024) {
120 bg_idx = blknr / blk_per_grp;
122 bg_idx = blknr / blk_per_grp;
123 remainder = blknr % blk_per_grp;
127 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
128 bgd[bg_idx].free_blocks++;
129 fs->sb->free_blocks++;
131 if (prev_bg_bmap_idx != bg_idx) {
133 ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
134 fs->sect_perblk, 0, fs->blksz,
138 if (ext4fs_log_journal
139 (journal_buffer, bgd[bg_idx].block_id))
141 prev_bg_bmap_idx = bg_idx;
145 free(journal_buffer);
148 static void delete_double_indirect_block(struct ext2_inode *inode)
152 static int prev_bg_bmap_idx = -1;
156 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
157 unsigned int *di_buffer = NULL;
158 unsigned int *DIB_start_addr = NULL;
159 struct ext2_block_group *bgd = NULL;
160 struct ext_filesystem *fs = get_fs();
161 char *journal_buffer = zalloc(fs->blksz);
162 if (!journal_buffer) {
163 printf("No memory\n");
166 /* get the block group descriptor table */
167 bgd = (struct ext2_block_group *)fs->gdtable;
169 if (inode->b.blocks.double_indir_block != 0) {
170 di_buffer = zalloc(fs->blksz);
172 printf("No memory\n");
175 DIB_start_addr = (unsigned int *)di_buffer;
176 blknr = inode->b.blocks.double_indir_block;
177 status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
178 fs->blksz, (char *)di_buffer);
179 for (i = 0; i < fs->blksz / sizeof(int); i++) {
183 debug("DICB releasing %u\n", *di_buffer);
184 if (fs->blksz != 1024) {
185 bg_idx = (*di_buffer) / blk_per_grp;
187 bg_idx = (*di_buffer) / blk_per_grp;
188 remainder = (*di_buffer) % blk_per_grp;
192 ext4fs_reset_block_bmap(*di_buffer,
193 fs->blk_bmaps[bg_idx], bg_idx);
195 bgd[bg_idx].free_blocks++;
196 fs->sb->free_blocks++;
198 if (prev_bg_bmap_idx != bg_idx) {
199 status = ext4fs_devread((lbaint_t)
201 * fs->sect_perblk, 0,
207 if (ext4fs_log_journal(journal_buffer,
208 bgd[bg_idx].block_id))
210 prev_bg_bmap_idx = bg_idx;
214 /* removing the parent double indirect block */
215 blknr = inode->b.blocks.double_indir_block;
216 if (fs->blksz != 1024) {
217 bg_idx = blknr / blk_per_grp;
219 bg_idx = blknr / blk_per_grp;
220 remainder = blknr % blk_per_grp;
224 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
225 bgd[bg_idx].free_blocks++;
226 fs->sb->free_blocks++;
228 if (prev_bg_bmap_idx != bg_idx) {
229 memset(journal_buffer, '\0', fs->blksz);
230 status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
231 fs->sect_perblk, 0, fs->blksz,
236 if (ext4fs_log_journal(journal_buffer,
237 bgd[bg_idx].block_id))
239 prev_bg_bmap_idx = bg_idx;
241 debug("DIPB releasing %ld\n", blknr);
244 free(DIB_start_addr);
245 free(journal_buffer);
248 static void delete_triple_indirect_block(struct ext2_inode *inode)
252 static int prev_bg_bmap_idx = -1;
256 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
257 unsigned int *tigp_buffer = NULL;
258 unsigned int *tib_start_addr = NULL;
259 unsigned int *tip_buffer = NULL;
260 unsigned int *tipb_start_addr = NULL;
261 struct ext2_block_group *bgd = NULL;
262 struct ext_filesystem *fs = get_fs();
263 char *journal_buffer = zalloc(fs->blksz);
264 if (!journal_buffer) {
265 printf("No memory\n");
268 /* get block group descriptor table */
269 bgd = (struct ext2_block_group *)fs->gdtable;
271 if (inode->b.blocks.triple_indir_block != 0) {
272 tigp_buffer = zalloc(fs->blksz);
274 printf("No memory\n");
277 tib_start_addr = (unsigned int *)tigp_buffer;
278 blknr = 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)
284 debug("tigp buffer releasing %u\n", *tigp_buffer);
286 tip_buffer = zalloc(fs->blksz);
289 tipb_start_addr = (unsigned int *)tip_buffer;
290 status = ext4fs_devread((lbaint_t)(*tigp_buffer) *
291 fs->sect_perblk, 0, fs->blksz,
293 for (j = 0; j < fs->blksz / sizeof(int); j++) {
294 if (*tip_buffer == 0)
296 if (fs->blksz != 1024) {
297 bg_idx = (*tip_buffer) / blk_per_grp;
299 bg_idx = (*tip_buffer) / blk_per_grp;
301 remainder = (*tip_buffer) % blk_per_grp;
306 ext4fs_reset_block_bmap(*tip_buffer,
307 fs->blk_bmaps[bg_idx],
311 bgd[bg_idx].free_blocks++;
312 fs->sb->free_blocks++;
314 if (prev_bg_bmap_idx != bg_idx) {
318 bgd[bg_idx].block_id *
325 if (ext4fs_log_journal(journal_buffer,
329 prev_bg_bmap_idx = bg_idx;
332 free(tipb_start_addr);
333 tipb_start_addr = NULL;
336 * removing the grand parent blocks
337 * which is connected to inode
339 if (fs->blksz != 1024) {
340 bg_idx = (*tigp_buffer) / blk_per_grp;
342 bg_idx = (*tigp_buffer) / blk_per_grp;
344 remainder = (*tigp_buffer) % blk_per_grp;
348 ext4fs_reset_block_bmap(*tigp_buffer,
349 fs->blk_bmaps[bg_idx], bg_idx);
352 bgd[bg_idx].free_blocks++;
353 fs->sb->free_blocks++;
355 if (prev_bg_bmap_idx != bg_idx) {
356 memset(journal_buffer, '\0', fs->blksz);
358 ext4fs_devread((lbaint_t)
359 bgd[bg_idx].block_id *
361 fs->blksz, journal_buffer);
365 if (ext4fs_log_journal(journal_buffer,
366 bgd[bg_idx].block_id))
368 prev_bg_bmap_idx = bg_idx;
372 /* removing the grand parent triple indirect block */
373 blknr = inode->b.blocks.triple_indir_block;
374 if (fs->blksz != 1024) {
375 bg_idx = blknr / blk_per_grp;
377 bg_idx = blknr / blk_per_grp;
378 remainder = blknr % blk_per_grp;
382 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
383 bgd[bg_idx].free_blocks++;
384 fs->sb->free_blocks++;
386 if (prev_bg_bmap_idx != bg_idx) {
387 memset(journal_buffer, '\0', fs->blksz);
388 status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
389 fs->sect_perblk, 0, fs->blksz,
394 if (ext4fs_log_journal(journal_buffer,
395 bgd[bg_idx].block_id))
397 prev_bg_bmap_idx = bg_idx;
399 debug("tigp buffer itself releasing %ld\n", blknr);
402 free(tib_start_addr);
403 free(tipb_start_addr);
404 free(journal_buffer);
407 static int ext4fs_delete_file(int inodeno)
409 struct ext2_inode inode;
416 char *read_buffer = NULL;
417 char *start_block_address = NULL;
418 unsigned int no_blocks;
420 static int prev_bg_bmap_idx = -1;
421 unsigned int inodes_per_block;
424 unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
425 unsigned int inode_per_grp = ext4fs_root->sblock.inodes_per_group;
426 struct ext2_inode *inode_buffer = NULL;
427 struct ext2_block_group *bgd = NULL;
428 struct ext_filesystem *fs = get_fs();
429 char *journal_buffer = zalloc(fs->blksz);
432 /* get the block group descriptor table */
433 bgd = (struct ext2_block_group *)fs->gdtable;
434 status = ext4fs_read_inode(ext4fs_root, inodeno, &inode);
438 /* read the block no allocated to a file */
439 no_blocks = inode.size / fs->blksz;
440 if (inode.size % fs->blksz)
443 if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) {
444 struct ext2fs_node *node_inode =
445 zalloc(sizeof(struct ext2fs_node));
448 node_inode->data = ext4fs_root;
449 node_inode->ino = inodeno;
450 node_inode->inode_read = 0;
451 memcpy(&(node_inode->inode), &inode, sizeof(struct ext2_inode));
453 for (i = 0; i < no_blocks; i++) {
454 blknr = read_allocated_block(&(node_inode->inode), i);
455 if (fs->blksz != 1024) {
456 bg_idx = blknr / blk_per_grp;
458 bg_idx = blknr / blk_per_grp;
459 remainder = blknr % blk_per_grp;
463 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
465 debug("EXT4_EXTENTS Block releasing %ld: %d\n",
468 bgd[bg_idx].free_blocks++;
469 fs->sb->free_blocks++;
472 if (prev_bg_bmap_idx != bg_idx) {
474 ext4fs_devread((lbaint_t)
475 bgd[bg_idx].block_id *
477 fs->blksz, journal_buffer);
480 if (ext4fs_log_journal(journal_buffer,
481 bgd[bg_idx].block_id))
483 prev_bg_bmap_idx = bg_idx;
492 delete_single_indirect_block(&inode);
493 delete_double_indirect_block(&inode);
494 delete_triple_indirect_block(&inode);
496 /* read the block no allocated to a file */
497 no_blocks = inode.size / fs->blksz;
498 if (inode.size % fs->blksz)
500 for (i = 0; i < no_blocks; i++) {
501 blknr = read_allocated_block(&inode, i);
502 if (fs->blksz != 1024) {
503 bg_idx = blknr / blk_per_grp;
505 bg_idx = blknr / blk_per_grp;
506 remainder = blknr % blk_per_grp;
510 ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
512 debug("ActualB releasing %ld: %d\n", blknr, bg_idx);
514 bgd[bg_idx].free_blocks++;
515 fs->sb->free_blocks++;
517 if (prev_bg_bmap_idx != bg_idx) {
518 memset(journal_buffer, '\0', fs->blksz);
519 status = ext4fs_devread((lbaint_t)
526 if (ext4fs_log_journal(journal_buffer,
527 bgd[bg_idx].block_id))
529 prev_bg_bmap_idx = bg_idx;
534 /* from the inode no to blockno */
535 inodes_per_block = fs->blksz / fs->inodesz;
536 ibmap_idx = inodeno / inode_per_grp;
538 /* get the block no */
540 blkno = __le32_to_cpu(bgd[ibmap_idx].inode_table_id) +
541 (inodeno % __le32_to_cpu(inode_per_grp)) / inodes_per_block;
543 /* get the offset of the inode */
544 blkoff = ((inodeno) % inodes_per_block) * fs->inodesz;
546 /* read the block no containing the inode */
547 read_buffer = zalloc(fs->blksz);
550 start_block_address = read_buffer;
551 status = ext4fs_devread((lbaint_t)blkno * fs->sect_perblk,
552 0, fs->blksz, read_buffer);
556 if (ext4fs_log_journal(read_buffer, blkno))
559 read_buffer = read_buffer + blkoff;
560 inode_buffer = (struct ext2_inode *)read_buffer;
561 memset(inode_buffer, '\0', sizeof(struct ext2_inode));
563 /* write the inode to original position in inode table */
564 if (ext4fs_put_metadata(start_block_address, blkno))
567 /* update the respective inode bitmaps */
569 ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx);
570 bgd[ibmap_idx].free_inodes++;
571 fs->sb->free_inodes++;
573 memset(journal_buffer, '\0', fs->blksz);
574 status = ext4fs_devread((lbaint_t)bgd[ibmap_idx].inode_id *
575 fs->sect_perblk, 0, fs->blksz, journal_buffer);
578 if (ext4fs_log_journal(journal_buffer, bgd[ibmap_idx].inode_id))
584 if (ext4fs_init() != 0) {
585 printf("error in File System init\n");
589 free(start_block_address);
590 free(journal_buffer);
594 free(start_block_address);
595 free(journal_buffer);
600 int ext4fs_init(void)
604 unsigned int real_free_blocks = 0;
605 struct ext_filesystem *fs = get_fs();
608 fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root);
609 fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root);
610 fs->sect_perblk = fs->blksz >> fs->dev_desc->log2blksz;
612 /* get the superblock */
613 fs->sb = zalloc(SUPERBLOCK_SIZE);
616 if (!ext4_read_superblock((char *)fs->sb))
620 if (ext4fs_init_journal())
623 /* get total no of blockgroups */
624 fs->no_blkgrp = (uint32_t)ext4fs_div_roundup(
625 (ext4fs_root->sblock.total_blocks -
626 ext4fs_root->sblock.first_data_block),
627 ext4fs_root->sblock.blocks_per_group);
629 /* get the block group descriptor table */
630 fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1);
631 if (ext4fs_get_bgdtable() == -1) {
632 printf("Error in getting the block group descriptor table\n");
635 fs->bgd = (struct ext2_block_group *)fs->gdtable;
637 /* load all the available bitmap block of the partition */
638 fs->blk_bmaps = zalloc(fs->no_blkgrp * sizeof(char *));
641 for (i = 0; i < fs->no_blkgrp; i++) {
642 fs->blk_bmaps[i] = zalloc(fs->blksz);
643 if (!fs->blk_bmaps[i])
647 for (i = 0; i < fs->no_blkgrp; i++) {
649 ext4fs_devread((lbaint_t)fs->bgd[i].block_id *
651 fs->blksz, (char *)fs->blk_bmaps[i]);
656 /* load all the available inode bitmap of the partition */
657 fs->inode_bmaps = zalloc(fs->no_blkgrp * sizeof(unsigned char *));
658 if (!fs->inode_bmaps)
660 for (i = 0; i < fs->no_blkgrp; i++) {
661 fs->inode_bmaps[i] = zalloc(fs->blksz);
662 if (!fs->inode_bmaps[i])
666 for (i = 0; i < fs->no_blkgrp; i++) {
667 status = ext4fs_devread((lbaint_t)fs->bgd[i].inode_id *
670 (char *)fs->inode_bmaps[i]);
676 * check filesystem consistency with free blocks of file system
677 * some time we observed that superblock freeblocks does not match
678 * with the blockgroups freeblocks when improper
679 * reboot of a linux kernel
681 for (i = 0; i < fs->no_blkgrp; i++)
682 real_free_blocks = real_free_blocks + fs->bgd[i].free_blocks;
683 if (real_free_blocks != fs->sb->free_blocks)
684 fs->sb->free_blocks = real_free_blocks;
693 void ext4fs_deinit(void)
696 struct ext2_inode inode_journal;
697 struct journal_superblock_t *jsb;
699 struct ext_filesystem *fs = get_fs();
702 char *temp_buff = zalloc(fs->blksz);
704 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
706 blknr = read_allocated_block(&inode_journal,
707 EXT2_JOURNAL_SUPERBLOCK);
708 ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
710 jsb = (struct journal_superblock_t *)temp_buff;
711 jsb->s_start = cpu_to_be32(0);
712 put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
713 (struct journal_superblock_t *)temp_buff, fs->blksz);
716 ext4fs_free_journal();
718 /* get the superblock */
719 ext4_read_superblock((char *)fs->sb);
720 fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
721 put_ext4((uint64_t)(SUPERBLOCK_SIZE),
722 (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE);
727 for (i = 0; i < fs->no_blkgrp; i++) {
728 free(fs->blk_bmaps[i]);
729 fs->blk_bmaps[i] = NULL;
732 fs->blk_bmaps = NULL;
735 if (fs->inode_bmaps) {
736 for (i = 0; i < fs->no_blkgrp; i++) {
737 free(fs->inode_bmaps[i]);
738 fs->inode_bmaps[i] = NULL;
740 free(fs->inode_bmaps);
741 fs->inode_bmaps = NULL;
749 * reinitiliazed the global inode and
750 * block bitmap first execution check variables
752 fs->first_pass_ibmap = 0;
753 fs->first_pass_bbmap = 0;
754 fs->curr_inode_no = 0;
758 static int ext4fs_write_file(struct ext2_inode *file_inode,
759 int pos, unsigned int len, char *buf)
763 unsigned int filesize = __le32_to_cpu(file_inode->size);
764 struct ext_filesystem *fs = get_fs();
765 int log2blksz = fs->dev_desc->log2blksz;
766 int log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_root) - log2blksz;
767 int previous_block_number = -1;
768 int delayed_start = 0;
769 int delayed_extent = 0;
770 int delayed_next = 0;
771 char *delayed_buf = NULL;
773 /* Adjust len so it we can't read past the end of the file. */
777 blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz;
779 for (i = pos / fs->blksz; i < blockcnt; i++) {
781 int blockend = fs->blksz;
783 blknr = read_allocated_block(file_inode, i);
787 blknr = blknr << log2_fs_blocksize;
790 if (previous_block_number != -1) {
791 if (delayed_next == blknr) {
792 delayed_extent += blockend;
793 delayed_next += blockend >> log2blksz;
796 ((uint64_t)delayed_start << log2blksz),
798 (uint32_t) delayed_extent);
799 previous_block_number = blknr;
800 delayed_start = blknr;
801 delayed_extent = blockend;
803 delayed_next = blknr +
804 (blockend >> log2blksz);
807 previous_block_number = blknr;
808 delayed_start = blknr;
809 delayed_extent = blockend;
811 delayed_next = blknr +
812 (blockend >> log2blksz);
815 if (previous_block_number != -1) {
817 put_ext4((uint64_t) ((uint64_t)delayed_start <<
820 (uint32_t) delayed_extent);
821 previous_block_number = -1;
823 memset(buf, 0, fs->blksz - skipfirst);
825 buf += fs->blksz - skipfirst;
827 if (previous_block_number != -1) {
829 put_ext4((uint64_t) ((uint64_t)delayed_start << log2blksz),
830 delayed_buf, (uint32_t) delayed_extent);
831 previous_block_number = -1;
837 int ext4fs_write(const char *fname, unsigned char *buffer,
838 unsigned long sizebytes)
841 struct ext2_inode *file_inode = NULL;
842 unsigned char *inode_buffer = NULL;
845 time_t timestamp = 0;
847 uint64_t bytes_reqd_for_file;
848 unsigned int blks_reqd_for_file;
849 unsigned int blocks_remaining;
850 int existing_file_inodeno;
851 char *temp_ptr = NULL;
852 long int itable_blkno;
853 long int parent_itable_blkno;
855 struct ext2_sblock *sblock = &(ext4fs_root->sblock);
856 unsigned int inodes_per_block;
857 unsigned int ibmap_idx;
858 struct ext_filesystem *fs = get_fs();
859 ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
860 memset(filename, 0x00, sizeof(filename));
862 g_parent_inode = zalloc(sizeof(struct ext2_inode));
866 if (ext4fs_init() != 0) {
867 printf("error in File System init\n");
870 inodes_per_block = fs->blksz / fs->inodesz;
871 parent_inodeno = ext4fs_get_parent_inode_num(fname, filename, F_FILE);
872 if (parent_inodeno == -1)
874 if (ext4fs_iget(parent_inodeno, g_parent_inode))
876 /* check if the filename is already present in root */
877 existing_file_inodeno = ext4fs_filename_check(filename);
878 if (existing_file_inodeno != -1) {
879 ret = ext4fs_delete_file(existing_file_inodeno);
880 fs->first_pass_bbmap = 0;
883 fs->first_pass_ibmap = 0;
884 fs->curr_inode_no = 0;
888 /* calucalate how many blocks required */
889 bytes_reqd_for_file = sizebytes;
890 blks_reqd_for_file = lldiv(bytes_reqd_for_file, fs->blksz);
891 if (do_div(bytes_reqd_for_file, fs->blksz) != 0) {
892 blks_reqd_for_file++;
893 debug("total bytes for a file %u\n", blks_reqd_for_file);
895 blocks_remaining = blks_reqd_for_file;
896 /* test for available space in partition */
897 if (fs->sb->free_blocks < blks_reqd_for_file) {
898 printf("Not enough space on partition !!!\n");
902 ext4fs_update_parent_dentry(filename, &inodeno, FILETYPE_REG);
903 /* prepare file inode */
904 inode_buffer = zalloc(fs->inodesz);
907 file_inode = (struct ext2_inode *)inode_buffer;
908 file_inode->mode = S_IFREG | S_IRWXU |
909 S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH;
910 /* ToDo: Update correct time */
911 file_inode->mtime = timestamp;
912 file_inode->atime = timestamp;
913 file_inode->ctime = timestamp;
914 file_inode->nlinks = 1;
915 file_inode->size = sizebytes;
917 /* Allocate data blocks */
918 ext4fs_allocate_blocks(file_inode, blocks_remaining,
919 &blks_reqd_for_file);
920 file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) >>
921 fs->dev_desc->log2blksz;
923 temp_ptr = zalloc(fs->blksz);
926 ibmap_idx = inodeno / ext4fs_root->sblock.inodes_per_group;
928 itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
929 (inodeno % __le32_to_cpu(sblock->inodes_per_group)) /
931 blkoff = (inodeno % inodes_per_block) * fs->inodesz;
932 ext4fs_devread((lbaint_t)itable_blkno * fs->sect_perblk, 0, fs->blksz,
934 if (ext4fs_log_journal(temp_ptr, itable_blkno))
937 memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz);
938 if (ext4fs_put_metadata(temp_ptr, itable_blkno))
940 /* copy the file content into data blocks */
941 if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) {
942 printf("Error in copying content\n");
945 ibmap_idx = parent_inodeno / ext4fs_root->sblock.inodes_per_group;
947 parent_itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
949 __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
950 blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz;
951 if (parent_itable_blkno != itable_blkno) {
952 memset(temp_ptr, '\0', fs->blksz);
953 ext4fs_devread((lbaint_t)parent_itable_blkno * fs->sect_perblk,
954 0, fs->blksz, temp_ptr);
955 if (ext4fs_log_journal(temp_ptr, parent_itable_blkno))
958 memcpy(temp_ptr + blkoff, g_parent_inode,
959 sizeof(struct ext2_inode));
960 if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno))
965 * If parent and child fall in same inode table block
966 * both should be kept in 1 buffer
968 memcpy(temp_ptr + blkoff, g_parent_inode,
969 sizeof(struct ext2_inode));
971 if (ext4fs_put_metadata(temp_ptr, itable_blkno))
978 fs->first_pass_bbmap = 0;
980 fs->first_pass_ibmap = 0;
981 fs->curr_inode_no = 0;
983 free(g_parent_inode);
984 g_parent_inode = NULL;
990 free(g_parent_inode);
991 g_parent_inode = NULL;