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 load support in Uboot.
10 * esd gmbh <www.esd-electronics.com>
11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
14 * GRUB -- GRand Unified Bootloader
15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
17 * ext4write : Based on generic ext4 protocol.
19 * SPDX-License-Identifier: GPL-2.0+
23 #include <ext_common.h>
29 #include <linux/stat.h>
30 #include <linux/time.h>
31 #include <asm/byteorder.h>
32 #include "ext4_common.h"
34 struct ext2_data
*ext4fs_root
;
35 struct ext2fs_node
*ext4fs_file
;
36 __le32
*ext4fs_indir1_block
;
37 int ext4fs_indir1_size
;
38 int ext4fs_indir1_blkno
= -1;
39 __le32
*ext4fs_indir2_block
;
40 int ext4fs_indir2_size
;
41 int ext4fs_indir2_blkno
= -1;
43 __le32
*ext4fs_indir3_block
;
44 int ext4fs_indir3_size
;
45 int ext4fs_indir3_blkno
= -1;
46 struct ext2_inode
*g_parent_inode
;
47 static int symlinknest
;
49 #if defined(CONFIG_EXT4_WRITE)
50 static inline void ext4fs_sb_free_inodes_dec(struct ext2_sblock
*sb
)
52 sb
->free_inodes
= cpu_to_le32(le32_to_cpu(sb
->free_inodes
) - 1);
55 static inline void ext4fs_sb_free_blocks_dec(struct ext2_sblock
*sb
)
57 sb
->free_blocks
= cpu_to_le32(le32_to_cpu(sb
->free_blocks
) - 1);
60 static inline void ext4fs_bg_free_inodes_dec(struct ext2_block_group
*bg
)
62 bg
->free_inodes
= cpu_to_le16(le16_to_cpu(bg
->free_inodes
) - 1);
65 static inline void ext4fs_bg_free_blocks_dec(struct ext2_block_group
*bg
)
67 bg
->free_blocks
= cpu_to_le16(le16_to_cpu(bg
->free_blocks
) - 1);
70 static inline void ext4fs_bg_itable_unused_dec(struct ext2_block_group
*bg
)
72 bg
->bg_itable_unused
= cpu_to_le16(le16_to_cpu(bg
->bg_itable_unused
) - 1);
75 uint32_t ext4fs_div_roundup(uint32_t size
, uint32_t n
)
77 uint32_t res
= size
/ n
;
84 void put_ext4(uint64_t off
, void *buf
, uint32_t size
)
88 unsigned char *temp_ptr
= NULL
;
89 struct ext_filesystem
*fs
= get_fs();
90 int log2blksz
= fs
->dev_desc
->log2blksz
;
91 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf
, fs
->dev_desc
->blksz
);
93 startblock
= off
>> log2blksz
;
94 startblock
+= part_offset
;
95 remainder
= off
& (uint64_t)(fs
->dev_desc
->blksz
- 1);
97 if (fs
->dev_desc
== NULL
)
100 if ((startblock
+ (size
>> log2blksz
)) >
101 (part_offset
+ fs
->total_sect
)) {
102 printf("part_offset is " LBAFU
"\n", part_offset
);
103 printf("total_sector is %" PRIu64
"\n", fs
->total_sect
);
104 printf("error: overflow occurs\n");
109 blk_dread(fs
->dev_desc
, startblock
, 1, sec_buf
);
111 memcpy((temp_ptr
+ remainder
), (unsigned char *)buf
, size
);
112 blk_dwrite(fs
->dev_desc
, startblock
, 1, sec_buf
);
114 if (size
>> log2blksz
!= 0) {
115 blk_dwrite(fs
->dev_desc
, startblock
, size
>> log2blksz
,
116 (unsigned long *)buf
);
118 blk_dread(fs
->dev_desc
, startblock
, 1, sec_buf
);
120 memcpy(temp_ptr
, buf
, size
);
121 blk_dwrite(fs
->dev_desc
, startblock
, 1,
122 (unsigned long *)sec_buf
);
127 static int _get_new_inode_no(unsigned char *buffer
)
129 struct ext_filesystem
*fs
= get_fs();
135 /* get the blocksize of the filesystem */
136 unsigned char *ptr
= buffer
;
137 while (*ptr
== 255) {
140 if (count
> le32_to_cpu(ext4fs_root
->sblock
.inodes_per_group
))
144 for (j
= 0; j
< fs
->blksz
; j
++) {
149 status
= input
& operand
;
164 static int _get_new_blk_no(unsigned char *buffer
)
170 unsigned char *ptr
= buffer
;
171 struct ext_filesystem
*fs
= get_fs();
173 if (fs
->blksz
!= 1024)
178 while (*ptr
== 255) {
181 if (count
== (fs
->blksz
* 8))
185 for (j
= 0; j
< fs
->blksz
; j
++) {
190 status
= input
& operand
;
205 int ext4fs_set_block_bmap(long int blockno
, unsigned char *buffer
, int index
)
207 int i
, remainder
, status
;
208 unsigned char *ptr
= buffer
;
209 unsigned char operand
;
211 remainder
= blockno
% 8;
212 int blocksize
= EXT2_BLOCK_SIZE(ext4fs_root
);
214 i
= i
- (index
* blocksize
);
215 if (blocksize
!= 1024) {
217 operand
= 1 << remainder
;
218 status
= *ptr
& operand
;
222 *ptr
= *ptr
| operand
;
225 if (remainder
== 0) {
230 operand
= (1 << (remainder
- 1));
232 status
= *ptr
& operand
;
236 *ptr
= *ptr
| operand
;
241 void ext4fs_reset_block_bmap(long int blockno
, unsigned char *buffer
, int index
)
243 int i
, remainder
, status
;
244 unsigned char *ptr
= buffer
;
245 unsigned char operand
;
247 remainder
= blockno
% 8;
248 int blocksize
= EXT2_BLOCK_SIZE(ext4fs_root
);
250 i
= i
- (index
* blocksize
);
251 if (blocksize
!= 1024) {
253 operand
= (1 << remainder
);
254 status
= *ptr
& operand
;
256 *ptr
= *ptr
& ~(operand
);
258 if (remainder
== 0) {
263 operand
= (1 << (remainder
- 1));
265 status
= *ptr
& operand
;
267 *ptr
= *ptr
& ~(operand
);
271 int ext4fs_set_inode_bmap(int inode_no
, unsigned char *buffer
, int index
)
273 int i
, remainder
, status
;
274 unsigned char *ptr
= buffer
;
275 unsigned char operand
;
277 inode_no
-= (index
* le32_to_cpu(ext4fs_root
->sblock
.inodes_per_group
));
279 remainder
= inode_no
% 8;
280 if (remainder
== 0) {
285 operand
= (1 << (remainder
- 1));
287 status
= *ptr
& operand
;
291 *ptr
= *ptr
| operand
;
296 void ext4fs_reset_inode_bmap(int inode_no
, unsigned char *buffer
, int index
)
298 int i
, remainder
, status
;
299 unsigned char *ptr
= buffer
;
300 unsigned char operand
;
302 inode_no
-= (index
* le32_to_cpu(ext4fs_root
->sblock
.inodes_per_group
));
304 remainder
= inode_no
% 8;
305 if (remainder
== 0) {
310 operand
= (1 << (remainder
- 1));
312 status
= *ptr
& operand
;
314 *ptr
= *ptr
& ~(operand
);
317 uint16_t ext4fs_checksum_update(uint32_t i
)
319 struct ext2_block_group
*desc
;
320 struct ext_filesystem
*fs
= get_fs();
322 __le32 le32_i
= cpu_to_le32(i
);
324 desc
= (struct ext2_block_group
*)&fs
->bgd
[i
];
325 if (le32_to_cpu(fs
->sb
->feature_ro_compat
) & EXT4_FEATURE_RO_COMPAT_GDT_CSUM
) {
326 int offset
= offsetof(struct ext2_block_group
, bg_checksum
);
328 crc
= ext2fs_crc16(~0, fs
->sb
->unique_id
,
329 sizeof(fs
->sb
->unique_id
));
330 crc
= ext2fs_crc16(crc
, &le32_i
, sizeof(le32_i
));
331 crc
= ext2fs_crc16(crc
, desc
, offset
);
332 offset
+= sizeof(desc
->bg_checksum
); /* skip checksum */
333 assert(offset
== sizeof(*desc
));
339 static int check_void_in_dentry(struct ext2_dirent
*dir
, char *filename
)
342 int sizeof_void_space
;
343 int new_entry_byte_reqd
;
344 short padding_factor
= 0;
346 if (dir
->namelen
% 4 != 0)
347 padding_factor
= 4 - (dir
->namelen
% 4);
349 dentry_length
= sizeof(struct ext2_dirent
) +
350 dir
->namelen
+ padding_factor
;
351 sizeof_void_space
= le16_to_cpu(dir
->direntlen
) - dentry_length
;
352 if (sizeof_void_space
== 0)
356 if (strlen(filename
) % 4 != 0)
357 padding_factor
= 4 - (strlen(filename
) % 4);
359 new_entry_byte_reqd
= strlen(filename
) +
360 sizeof(struct ext2_dirent
) + padding_factor
;
361 if (sizeof_void_space
>= new_entry_byte_reqd
) {
362 dir
->direntlen
= cpu_to_le16(dentry_length
);
363 return sizeof_void_space
;
369 int ext4fs_update_parent_dentry(char *filename
, int file_type
)
371 unsigned int *zero_buffer
= NULL
;
372 char *root_first_block_buffer
= NULL
;
374 long int first_block_no_of_root
= 0;
376 unsigned int new_entry_byte_reqd
;
377 int sizeof_void_space
= 0;
381 struct ext_filesystem
*fs
= get_fs();
382 /* directory entry */
383 struct ext2_dirent
*dir
;
384 char *temp_dir
= NULL
;
387 uint32_t new_blockcnt
;
388 uint32_t directory_blocks
;
390 zero_buffer
= zalloc(fs
->blksz
);
392 printf("No Memory\n");
395 root_first_block_buffer
= zalloc(fs
->blksz
);
396 if (!root_first_block_buffer
) {
398 printf("No Memory\n");
401 new_entry_byte_reqd
= ROUND(strlen(filename
) +
402 sizeof(struct ext2_dirent
), 4);
404 directory_blocks
= le32_to_cpu(g_parent_inode
->size
) >>
405 LOG2_BLOCK_SIZE(ext4fs_root
);
406 blk_idx
= directory_blocks
- 1;
409 /* read the block no allocated to a file */
410 first_block_no_of_root
= read_allocated_block(g_parent_inode
, blk_idx
);
411 if (first_block_no_of_root
<= 0)
414 status
= ext4fs_devread((lbaint_t
)first_block_no_of_root
416 0, fs
->blksz
, root_first_block_buffer
);
420 if (ext4fs_log_journal(root_first_block_buffer
, first_block_no_of_root
))
422 dir
= (struct ext2_dirent
*)root_first_block_buffer
;
425 while (le16_to_cpu(dir
->direntlen
) > 0) {
426 unsigned short used_len
= ROUND(dir
->namelen
+
427 sizeof(struct ext2_dirent
), 4);
429 /* last entry of block */
430 if (fs
->blksz
- totalbytes
== le16_to_cpu(dir
->direntlen
)) {
432 /* check if new entry fits */
433 if ((used_len
+ new_entry_byte_reqd
) <=
434 le16_to_cpu(dir
->direntlen
)) {
435 dir
->direntlen
= cpu_to_le16(used_len
);
439 printf("Block full, trying previous\n");
443 printf("All blocks full: Allocate new\n");
445 if (le32_to_cpu(g_parent_inode
->flags
) &
447 printf("Directory uses extents\n");
450 if (directory_blocks
>= INDIRECT_BLOCKS
) {
451 printf("Directory exceeds limit\n");
454 new_blk_no
= ext4fs_get_new_blk_no();
455 if (new_blk_no
== -1) {
456 printf("no block left to assign\n");
459 put_ext4((uint64_t)new_blk_no
* fs
->blksz
, zero_buffer
, fs
->blksz
);
460 g_parent_inode
->b
.blocks
.
461 dir_blocks
[directory_blocks
] =
462 cpu_to_le32(new_blk_no
);
464 new_size
= le32_to_cpu(g_parent_inode
->size
);
465 new_size
+= fs
->blksz
;
466 g_parent_inode
->size
= cpu_to_le32(new_size
);
468 new_blockcnt
= le32_to_cpu(g_parent_inode
->blockcnt
);
469 new_blockcnt
+= fs
->sect_perblk
;
470 g_parent_inode
->blockcnt
= cpu_to_le32(new_blockcnt
);
472 if (ext4fs_put_metadata
473 (root_first_block_buffer
,
474 first_block_no_of_root
))
480 templength
= le16_to_cpu(dir
->direntlen
);
481 totalbytes
= totalbytes
+ templength
;
482 sizeof_void_space
= check_void_in_dentry(dir
, filename
);
483 if (sizeof_void_space
)
486 dir
= (struct ext2_dirent
*)((char *)dir
+ templength
);
489 /* make a pointer ready for creating next directory entry */
490 templength
= le16_to_cpu(dir
->direntlen
);
491 totalbytes
= totalbytes
+ templength
;
492 dir
= (struct ext2_dirent
*)((char *)dir
+ templength
);
494 /* get the next available inode number */
495 inodeno
= ext4fs_get_new_inode_no();
497 printf("no inode left to assign\n");
500 dir
->inode
= cpu_to_le32(inodeno
);
501 if (sizeof_void_space
)
502 dir
->direntlen
= cpu_to_le16(sizeof_void_space
);
504 dir
->direntlen
= cpu_to_le16(fs
->blksz
- totalbytes
);
506 dir
->namelen
= strlen(filename
);
507 dir
->filetype
= FILETYPE_REG
; /* regular file */
508 temp_dir
= (char *)dir
;
509 temp_dir
= temp_dir
+ sizeof(struct ext2_dirent
);
510 memcpy(temp_dir
, filename
, strlen(filename
));
512 /* update or write the 1st block of root inode */
513 if (ext4fs_put_metadata(root_first_block_buffer
,
514 first_block_no_of_root
))
519 free(root_first_block_buffer
);
524 static int search_dir(struct ext2_inode
*parent_inode
, char *dirname
)
531 char *block_buffer
= NULL
;
532 struct ext2_dirent
*dir
= NULL
;
533 struct ext_filesystem
*fs
= get_fs();
534 uint32_t directory_blocks
;
537 directory_blocks
= le32_to_cpu(parent_inode
->size
) >>
538 LOG2_BLOCK_SIZE(ext4fs_root
);
540 block_buffer
= zalloc(fs
->blksz
);
544 /* get the block no allocated to a file */
545 for (blk_idx
= 0; blk_idx
< directory_blocks
; blk_idx
++) {
546 blknr
= read_allocated_block(parent_inode
, blk_idx
);
550 /* read the directory block */
551 status
= ext4fs_devread((lbaint_t
)blknr
* fs
->sect_perblk
,
552 0, fs
->blksz
, (char *)block_buffer
);
558 dir
= (struct ext2_dirent
*)(block_buffer
+ offset
);
559 direntname
= (char*)(dir
) + sizeof(struct ext2_dirent
);
561 int direntlen
= le16_to_cpu(dir
->direntlen
);
562 if (direntlen
< sizeof(struct ext2_dirent
))
565 if (dir
->inode
&& (strlen(dirname
) == dir
->namelen
) &&
566 (strncmp(dirname
, direntname
, dir
->namelen
) == 0)) {
567 inodeno
= le32_to_cpu(dir
->inode
);
573 } while (offset
< fs
->blksz
);
587 static int find_dir_depth(char *dirname
)
589 char *token
= strtok(dirname
, "/");
591 while (token
!= NULL
) {
592 token
= strtok(NULL
, "/");
595 return count
+ 1 + 1;
597 * for example for string /home/temp
598 * depth=home(1)+temp(1)+1 extra for NULL;
603 static int parse_path(char **arr
, char *dirname
)
605 char *token
= strtok(dirname
, "/");
609 arr
[i
] = zalloc(strlen("/") + 1);
612 memcpy(arr
[i
++], "/", strlen("/"));
614 /* add each path entry after root */
615 while (token
!= NULL
) {
616 arr
[i
] = zalloc(strlen(token
) + 1);
619 memcpy(arr
[i
++], token
, strlen(token
));
620 token
= strtok(NULL
, "/");
627 int ext4fs_iget(int inode_no
, struct ext2_inode
*inode
)
629 if (ext4fs_read_inode(ext4fs_root
, inode_no
, inode
) == 0)
636 * Function: ext4fs_get_parent_inode_num
637 * Return Value: inode Number of the parent directory of file/Directory to be
639 * dirname : Input parmater, input path name of the file/directory to be created
640 * dname : Output parameter, to be filled with the name of the directory
641 * extracted from dirname
643 int ext4fs_get_parent_inode_num(const char *dirname
, char *dname
, int flags
)
647 int matched_inode_no
;
648 int result_inode_no
= -1;
650 char *depth_dirname
= NULL
;
651 char *parse_dirname
= NULL
;
652 struct ext2_inode
*parent_inode
= NULL
;
653 struct ext2_inode
*first_inode
= NULL
;
654 struct ext2_inode temp_inode
;
656 if (*dirname
!= '/') {
657 printf("Please supply Absolute path\n");
661 /* TODO: input validation make equivalent to linux */
662 depth_dirname
= zalloc(strlen(dirname
) + 1);
666 memcpy(depth_dirname
, dirname
, strlen(dirname
));
667 depth
= find_dir_depth(depth_dirname
);
668 parse_dirname
= zalloc(strlen(dirname
) + 1);
671 memcpy(parse_dirname
, dirname
, strlen(dirname
));
673 /* allocate memory for each directory level */
674 ptr
= zalloc((depth
) * sizeof(char *));
677 if (parse_path(ptr
, parse_dirname
))
679 parent_inode
= zalloc(sizeof(struct ext2_inode
));
682 first_inode
= zalloc(sizeof(struct ext2_inode
));
685 memcpy(parent_inode
, ext4fs_root
->inode
, sizeof(struct ext2_inode
));
686 memcpy(first_inode
, parent_inode
, sizeof(struct ext2_inode
));
688 result_inode_no
= EXT2_ROOT_INO
;
689 for (i
= 1; i
< depth
; i
++) {
690 matched_inode_no
= search_dir(parent_inode
, ptr
[i
]);
691 if (matched_inode_no
== -1) {
692 if (ptr
[i
+ 1] == NULL
&& i
== 1) {
693 result_inode_no
= EXT2_ROOT_INO
;
696 if (ptr
[i
+ 1] == NULL
)
698 printf("Invalid path\n");
699 result_inode_no
= -1;
703 if (ptr
[i
+ 1] != NULL
) {
704 memset(parent_inode
, '\0',
705 sizeof(struct ext2_inode
));
706 if (ext4fs_iget(matched_inode_no
,
708 result_inode_no
= -1;
711 result_inode_no
= matched_inode_no
;
720 matched_inode_no
= search_dir(first_inode
, ptr
[i
]);
722 matched_inode_no
= search_dir(parent_inode
, ptr
[i
]);
724 if (matched_inode_no
!= -1) {
725 ext4fs_iget(matched_inode_no
, &temp_inode
);
726 if (le16_to_cpu(temp_inode
.mode
) & S_IFDIR
) {
727 printf("It is a Directory\n");
728 result_inode_no
= -1;
733 if (strlen(ptr
[i
]) > 256) {
734 result_inode_no
= -1;
737 memcpy(dname
, ptr
[i
], strlen(ptr
[i
]));
742 for (i
= 0; i
< depth
; i
++) {
751 return result_inode_no
;
754 static int unlink_filename(char *filename
, unsigned int blknr
)
760 char *root_first_block_buffer
= NULL
;
761 struct ext2_dirent
*dir
= NULL
;
762 struct ext2_dirent
*previous_dir
= NULL
;
764 struct ext_filesystem
*fs
= get_fs();
767 /* get the first block of root */
768 root_first_block_buffer
= zalloc(fs
->blksz
);
769 if (!root_first_block_buffer
)
771 status
= ext4fs_devread((lbaint_t
)blknr
* fs
->sect_perblk
, 0,
772 fs
->blksz
, root_first_block_buffer
);
776 if (ext4fs_log_journal(root_first_block_buffer
, blknr
))
778 dir
= (struct ext2_dirent
*)root_first_block_buffer
;
781 while (le16_to_cpu(dir
->direntlen
) >= 0) {
783 * blocksize-totalbytes because last
784 * directory length i.e., *dir->direntlen
785 * is free availble space in the block that
786 * means it is a last entry of directory entry
788 if (dir
->inode
&& (strlen(filename
) == dir
->namelen
) &&
789 (strncmp(ptr
+ sizeof(struct ext2_dirent
),
790 filename
, dir
->namelen
) == 0)) {
791 printf("file found, deleting\n");
792 inodeno
= le32_to_cpu(dir
->inode
);
795 new_len
= le16_to_cpu(previous_dir
->direntlen
);
796 new_len
+= le16_to_cpu(dir
->direntlen
);
797 previous_dir
->direntlen
= cpu_to_le16(new_len
);
805 if (fs
->blksz
- totalbytes
== le16_to_cpu(dir
->direntlen
))
808 /* traversing the each directory entry */
809 templength
= le16_to_cpu(dir
->direntlen
);
810 totalbytes
= totalbytes
+ templength
;
812 dir
= (struct ext2_dirent
*)((char *)dir
+ templength
);
818 if (ext4fs_put_metadata(root_first_block_buffer
, blknr
))
823 free(root_first_block_buffer
);
828 int ext4fs_filename_unlink(char *filename
)
833 uint32_t directory_blocks
;
835 directory_blocks
= le32_to_cpu(g_parent_inode
->size
) >>
836 LOG2_BLOCK_SIZE(ext4fs_root
);
838 /* read the block no allocated to a file */
839 for (blk_idx
= 0; blk_idx
< directory_blocks
; blk_idx
++) {
840 blknr
= read_allocated_block(g_parent_inode
, blk_idx
);
843 inodeno
= unlink_filename(filename
, blknr
);
851 uint32_t ext4fs_get_new_blk_no(void)
857 static int prev_bg_bitmap_index
= -1;
858 unsigned int blk_per_grp
= le32_to_cpu(ext4fs_root
->sblock
.blocks_per_group
);
859 struct ext_filesystem
*fs
= get_fs();
860 char *journal_buffer
= zalloc(fs
->blksz
);
861 char *zero_buffer
= zalloc(fs
->blksz
);
862 if (!journal_buffer
|| !zero_buffer
)
864 struct ext2_block_group
*bgd
= (struct ext2_block_group
*)fs
->gdtable
;
866 if (fs
->first_pass_bbmap
== 0) {
867 for (i
= 0; i
< fs
->no_blkgrp
; i
++) {
868 if (le16_to_cpu(bgd
[i
].free_blocks
)) {
869 if (le16_to_cpu(bgd
[i
].bg_flags
) & EXT4_BG_BLOCK_UNINIT
) {
871 put_ext4((uint64_t)le32_to_cpu(bgd
[i
].block_id
) * fs
->blksz
,
872 zero_buffer
, fs
->blksz
);
873 new_flags
= le16_to_cpu(bgd
[i
].bg_flags
) & ~EXT4_BG_BLOCK_UNINIT
;
874 bgd
[i
].bg_flags
= cpu_to_le16(new_flags
);
875 memcpy(fs
->blk_bmaps
[i
], zero_buffer
,
879 _get_new_blk_no(fs
->blk_bmaps
[i
]);
880 if (fs
->curr_blkno
== -1)
881 /* if block bitmap is completely fill */
883 fs
->curr_blkno
= fs
->curr_blkno
+
885 fs
->first_pass_bbmap
++;
886 ext4fs_bg_free_blocks_dec(&bgd
[i
]);
887 ext4fs_sb_free_blocks_dec(fs
->sb
);
888 status
= ext4fs_devread(
889 (lbaint_t
)le32_to_cpu(bgd
[i
].block_id
) *
895 if (ext4fs_log_journal(journal_buffer
,
896 le32_to_cpu(bgd
[i
].block_id
)))
900 debug("no space left on block group %d\n", i
);
908 /* get the blockbitmap index respective to blockno */
909 bg_idx
= fs
->curr_blkno
/ blk_per_grp
;
910 if (fs
->blksz
== 1024) {
911 remainder
= fs
->curr_blkno
% blk_per_grp
;
917 * To skip completely filled block group bitmaps
918 * Optimize the block allocation
920 if (bg_idx
>= fs
->no_blkgrp
)
923 if (bgd
[bg_idx
].free_blocks
== 0) {
924 debug("block group %u is full. Skipping\n", bg_idx
);
925 fs
->curr_blkno
= (bg_idx
+ 1) * blk_per_grp
;
926 if (fs
->blksz
== 1024)
931 if (le16_to_cpu(bgd
[bg_idx
].bg_flags
) & EXT4_BG_BLOCK_UNINIT
) {
933 put_ext4((uint64_t)le32_to_cpu(bgd
[bg_idx
].block_id
) * fs
->blksz
,
934 zero_buffer
, fs
->blksz
);
935 memcpy(fs
->blk_bmaps
[bg_idx
], zero_buffer
, fs
->blksz
);
936 new_flags
= le16_to_cpu(bgd
[bg_idx
].bg_flags
) & ~EXT4_BG_BLOCK_UNINIT
;
937 bgd
[bg_idx
].bg_flags
= cpu_to_le16(new_flags
);
940 if (ext4fs_set_block_bmap(fs
->curr_blkno
, fs
->blk_bmaps
[bg_idx
],
942 debug("going for restart for the block no %ld %u\n",
943 fs
->curr_blkno
, bg_idx
);
949 if (prev_bg_bitmap_index
!= bg_idx
) {
950 status
= ext4fs_devread(
951 (lbaint_t
)le32_to_cpu(bgd
[bg_idx
].block_id
)
953 0, fs
->blksz
, journal_buffer
);
956 if (ext4fs_log_journal(journal_buffer
,
957 le32_to_cpu(bgd
[bg_idx
].block_id
)))
960 prev_bg_bitmap_index
= bg_idx
;
962 ext4fs_bg_free_blocks_dec(&bgd
[bg_idx
]);
963 ext4fs_sb_free_blocks_dec(fs
->sb
);
967 free(journal_buffer
);
970 return fs
->curr_blkno
;
972 free(journal_buffer
);
978 int ext4fs_get_new_inode_no(void)
982 unsigned int ibmap_idx
;
983 static int prev_inode_bitmap_index
= -1;
984 unsigned int inodes_per_grp
= le32_to_cpu(ext4fs_root
->sblock
.inodes_per_group
);
985 struct ext_filesystem
*fs
= get_fs();
986 char *journal_buffer
= zalloc(fs
->blksz
);
987 char *zero_buffer
= zalloc(fs
->blksz
);
988 if (!journal_buffer
|| !zero_buffer
)
990 struct ext2_block_group
*bgd
= (struct ext2_block_group
*)fs
->gdtable
;
991 int has_gdt_chksum
= le32_to_cpu(fs
->sb
->feature_ro_compat
) &
992 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
? 1 : 0;
994 if (fs
->first_pass_ibmap
== 0) {
995 for (i
= 0; i
< fs
->no_blkgrp
; i
++) {
996 if (bgd
[i
].free_inodes
) {
998 bgd
[i
].bg_itable_unused
=
1000 if (le16_to_cpu(bgd
[i
].bg_flags
) & EXT4_BG_INODE_UNINIT
) {
1002 put_ext4((uint64_t)le32_to_cpu(bgd
[i
].inode_id
) * fs
->blksz
,
1003 zero_buffer
, fs
->blksz
);
1004 new_flags
= le16_to_cpu(bgd
[i
].bg_flags
) & ~EXT4_BG_INODE_UNINIT
;
1005 bgd
[i
].bg_flags
= cpu_to_le16(new_flags
);
1006 memcpy(fs
->inode_bmaps
[i
],
1007 zero_buffer
, fs
->blksz
);
1010 _get_new_inode_no(fs
->inode_bmaps
[i
]);
1011 if (fs
->curr_inode_no
== -1)
1012 /* if block bitmap is completely fill */
1014 fs
->curr_inode_no
= fs
->curr_inode_no
+
1015 (i
* inodes_per_grp
);
1016 fs
->first_pass_ibmap
++;
1017 ext4fs_bg_free_inodes_dec(&bgd
[i
]);
1019 ext4fs_bg_itable_unused_dec(&bgd
[i
]);
1020 ext4fs_sb_free_inodes_dec(fs
->sb
);
1021 status
= ext4fs_devread(
1022 (lbaint_t
)le32_to_cpu(bgd
[i
].inode_id
) *
1028 if (ext4fs_log_journal(journal_buffer
,
1029 le32_to_cpu(bgd
[i
].inode_id
)))
1033 debug("no inode left on block group %d\n", i
);
1038 fs
->curr_inode_no
++;
1039 /* get the blockbitmap index respective to blockno */
1040 ibmap_idx
= fs
->curr_inode_no
/ inodes_per_grp
;
1041 if (le16_to_cpu(bgd
[ibmap_idx
].bg_flags
) & EXT4_BG_INODE_UNINIT
) {
1043 put_ext4((uint64_t)le32_to_cpu(bgd
[ibmap_idx
].inode_id
) * fs
->blksz
,
1044 zero_buffer
, fs
->blksz
);
1045 new_flags
= le16_to_cpu(bgd
[ibmap_idx
].bg_flags
) & ~EXT4_BG_INODE_UNINIT
;
1046 bgd
[ibmap_idx
].bg_flags
= cpu_to_le16(new_flags
);
1047 memcpy(fs
->inode_bmaps
[ibmap_idx
], zero_buffer
,
1051 if (ext4fs_set_inode_bmap(fs
->curr_inode_no
,
1052 fs
->inode_bmaps
[ibmap_idx
],
1054 debug("going for restart for the block no %d %u\n",
1055 fs
->curr_inode_no
, ibmap_idx
);
1059 /* journal backup */
1060 if (prev_inode_bitmap_index
!= ibmap_idx
) {
1061 memset(journal_buffer
, '\0', fs
->blksz
);
1062 status
= ext4fs_devread(
1063 (lbaint_t
)le32_to_cpu(bgd
[ibmap_idx
].inode_id
)
1065 0, fs
->blksz
, journal_buffer
);
1068 if (ext4fs_log_journal(journal_buffer
,
1069 le32_to_cpu(bgd
[ibmap_idx
].inode_id
)))
1071 prev_inode_bitmap_index
= ibmap_idx
;
1073 ext4fs_bg_free_inodes_dec(&bgd
[ibmap_idx
]);
1075 bgd
[ibmap_idx
].bg_itable_unused
=
1076 bgd
[ibmap_idx
].free_inodes
;
1077 ext4fs_sb_free_inodes_dec(fs
->sb
);
1082 free(journal_buffer
);
1085 return fs
->curr_inode_no
;
1087 free(journal_buffer
);
1095 static void alloc_single_indirect_block(struct ext2_inode
*file_inode
,
1096 unsigned int *total_remaining_blocks
,
1097 unsigned int *no_blks_reqd
)
1101 long int actual_block_no
;
1102 long int si_blockno
;
1103 /* si :single indirect */
1104 __le32
*si_buffer
= NULL
;
1105 __le32
*si_start_addr
= NULL
;
1106 struct ext_filesystem
*fs
= get_fs();
1108 if (*total_remaining_blocks
!= 0) {
1109 si_buffer
= zalloc(fs
->blksz
);
1111 printf("No Memory\n");
1114 si_start_addr
= si_buffer
;
1115 si_blockno
= ext4fs_get_new_blk_no();
1116 if (si_blockno
== -1) {
1117 printf("no block left to assign\n");
1121 debug("SIPB %ld: %u\n", si_blockno
, *total_remaining_blocks
);
1123 status
= ext4fs_devread((lbaint_t
)si_blockno
* fs
->sect_perblk
,
1124 0, fs
->blksz
, (char *)si_buffer
);
1125 memset(si_buffer
, '\0', fs
->blksz
);
1129 for (i
= 0; i
< (fs
->blksz
/ sizeof(int)); i
++) {
1130 actual_block_no
= ext4fs_get_new_blk_no();
1131 if (actual_block_no
== -1) {
1132 printf("no block left to assign\n");
1135 *si_buffer
= cpu_to_le32(actual_block_no
);
1136 debug("SIAB %u: %u\n", *si_buffer
,
1137 *total_remaining_blocks
);
1140 (*total_remaining_blocks
)--;
1141 if (*total_remaining_blocks
== 0)
1145 /* write the block to disk */
1146 put_ext4(((uint64_t) ((uint64_t)si_blockno
* (uint64_t)fs
->blksz
)),
1147 si_start_addr
, fs
->blksz
);
1148 file_inode
->b
.blocks
.indir_block
= cpu_to_le32(si_blockno
);
1151 free(si_start_addr
);
1154 static void alloc_double_indirect_block(struct ext2_inode
*file_inode
,
1155 unsigned int *total_remaining_blocks
,
1156 unsigned int *no_blks_reqd
)
1161 long int actual_block_no
;
1162 /* di:double indirect */
1163 long int di_blockno_parent
;
1164 long int di_blockno_child
;
1165 __le32
*di_parent_buffer
= NULL
;
1166 __le32
*di_child_buff
= NULL
;
1167 __le32
*di_block_start_addr
= NULL
;
1168 __le32
*di_child_buff_start
= NULL
;
1169 struct ext_filesystem
*fs
= get_fs();
1171 if (*total_remaining_blocks
!= 0) {
1172 /* double indirect parent block connecting to inode */
1173 di_blockno_parent
= ext4fs_get_new_blk_no();
1174 if (di_blockno_parent
== -1) {
1175 printf("no block left to assign\n");
1178 di_parent_buffer
= zalloc(fs
->blksz
);
1179 if (!di_parent_buffer
)
1182 di_block_start_addr
= di_parent_buffer
;
1184 debug("DIPB %ld: %u\n", di_blockno_parent
,
1185 *total_remaining_blocks
);
1187 status
= ext4fs_devread((lbaint_t
)di_blockno_parent
*
1189 fs
->blksz
, (char *)di_parent_buffer
);
1192 printf("%s: Device read error!\n", __func__
);
1195 memset(di_parent_buffer
, '\0', fs
->blksz
);
1198 * start:for each double indirect parent
1199 * block create one more block
1201 for (i
= 0; i
< (fs
->blksz
/ sizeof(int)); i
++) {
1202 di_blockno_child
= ext4fs_get_new_blk_no();
1203 if (di_blockno_child
== -1) {
1204 printf("no block left to assign\n");
1207 di_child_buff
= zalloc(fs
->blksz
);
1211 di_child_buff_start
= di_child_buff
;
1212 *di_parent_buffer
= cpu_to_le32(di_blockno_child
);
1215 debug("DICB %ld: %u\n", di_blockno_child
,
1216 *total_remaining_blocks
);
1218 status
= ext4fs_devread((lbaint_t
)di_blockno_child
*
1221 (char *)di_child_buff
);
1224 printf("%s: Device read error!\n", __func__
);
1227 memset(di_child_buff
, '\0', fs
->blksz
);
1228 /* filling of actual datablocks for each child */
1229 for (j
= 0; j
< (fs
->blksz
/ sizeof(int)); j
++) {
1230 actual_block_no
= ext4fs_get_new_blk_no();
1231 if (actual_block_no
== -1) {
1232 printf("no block left to assign\n");
1235 *di_child_buff
= cpu_to_le32(actual_block_no
);
1236 debug("DIAB %ld: %u\n", actual_block_no
,
1237 *total_remaining_blocks
);
1240 (*total_remaining_blocks
)--;
1241 if (*total_remaining_blocks
== 0)
1244 /* write the block table */
1245 put_ext4(((uint64_t) ((uint64_t)di_blockno_child
* (uint64_t)fs
->blksz
)),
1246 di_child_buff_start
, fs
->blksz
);
1247 free(di_child_buff_start
);
1248 di_child_buff_start
= NULL
;
1250 if (*total_remaining_blocks
== 0)
1253 put_ext4(((uint64_t) ((uint64_t)di_blockno_parent
* (uint64_t)fs
->blksz
)),
1254 di_block_start_addr
, fs
->blksz
);
1255 file_inode
->b
.blocks
.double_indir_block
= cpu_to_le32(di_blockno_parent
);
1258 free(di_block_start_addr
);
1261 static void alloc_triple_indirect_block(struct ext2_inode
*file_inode
,
1262 unsigned int *total_remaining_blocks
,
1263 unsigned int *no_blks_reqd
)
1268 long int actual_block_no
;
1269 /* ti: Triple Indirect */
1270 long int ti_gp_blockno
;
1271 long int ti_parent_blockno
;
1272 long int ti_child_blockno
;
1273 __le32
*ti_gp_buff
= NULL
;
1274 __le32
*ti_parent_buff
= NULL
;
1275 __le32
*ti_child_buff
= NULL
;
1276 __le32
*ti_gp_buff_start_addr
= NULL
;
1277 __le32
*ti_pbuff_start_addr
= NULL
;
1278 __le32
*ti_cbuff_start_addr
= NULL
;
1279 struct ext_filesystem
*fs
= get_fs();
1280 if (*total_remaining_blocks
!= 0) {
1281 /* triple indirect grand parent block connecting to inode */
1282 ti_gp_blockno
= ext4fs_get_new_blk_no();
1283 if (ti_gp_blockno
== -1) {
1284 printf("no block left to assign\n");
1287 ti_gp_buff
= zalloc(fs
->blksz
);
1291 ti_gp_buff_start_addr
= ti_gp_buff
;
1293 debug("TIGPB %ld: %u\n", ti_gp_blockno
,
1294 *total_remaining_blocks
);
1296 /* for each 4 byte grand parent entry create one more block */
1297 for (i
= 0; i
< (fs
->blksz
/ sizeof(int)); i
++) {
1298 ti_parent_blockno
= ext4fs_get_new_blk_no();
1299 if (ti_parent_blockno
== -1) {
1300 printf("no block left to assign\n");
1303 ti_parent_buff
= zalloc(fs
->blksz
);
1304 if (!ti_parent_buff
)
1307 ti_pbuff_start_addr
= ti_parent_buff
;
1308 *ti_gp_buff
= cpu_to_le32(ti_parent_blockno
);
1311 debug("TIPB %ld: %u\n", ti_parent_blockno
,
1312 *total_remaining_blocks
);
1314 /* for each 4 byte entry parent create one more block */
1315 for (j
= 0; j
< (fs
->blksz
/ sizeof(int)); j
++) {
1316 ti_child_blockno
= ext4fs_get_new_blk_no();
1317 if (ti_child_blockno
== -1) {
1318 printf("no block left assign\n");
1321 ti_child_buff
= zalloc(fs
->blksz
);
1325 ti_cbuff_start_addr
= ti_child_buff
;
1326 *ti_parent_buff
= cpu_to_le32(ti_child_blockno
);
1329 debug("TICB %ld: %u\n", ti_parent_blockno
,
1330 *total_remaining_blocks
);
1332 /* fill actual datablocks for each child */
1333 for (k
= 0; k
< (fs
->blksz
/ sizeof(int));
1336 ext4fs_get_new_blk_no();
1337 if (actual_block_no
== -1) {
1338 printf("no block left\n");
1339 free(ti_cbuff_start_addr
);
1342 *ti_child_buff
= cpu_to_le32(actual_block_no
);
1343 debug("TIAB %ld: %u\n", actual_block_no
,
1344 *total_remaining_blocks
);
1347 (*total_remaining_blocks
)--;
1348 if (*total_remaining_blocks
== 0)
1351 /* write the child block */
1352 put_ext4(((uint64_t) ((uint64_t)ti_child_blockno
*
1353 (uint64_t)fs
->blksz
)),
1354 ti_cbuff_start_addr
, fs
->blksz
);
1355 free(ti_cbuff_start_addr
);
1357 if (*total_remaining_blocks
== 0)
1360 /* write the parent block */
1361 put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno
* (uint64_t)fs
->blksz
)),
1362 ti_pbuff_start_addr
, fs
->blksz
);
1363 free(ti_pbuff_start_addr
);
1365 if (*total_remaining_blocks
== 0)
1368 /* write the grand parent block */
1369 put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno
* (uint64_t)fs
->blksz
)),
1370 ti_gp_buff_start_addr
, fs
->blksz
);
1371 file_inode
->b
.blocks
.triple_indir_block
= cpu_to_le32(ti_gp_blockno
);
1372 free(ti_gp_buff_start_addr
);
1376 free(ti_pbuff_start_addr
);
1378 free(ti_gp_buff_start_addr
);
1381 void ext4fs_allocate_blocks(struct ext2_inode
*file_inode
,
1382 unsigned int total_remaining_blocks
,
1383 unsigned int *total_no_of_block
)
1386 long int direct_blockno
;
1387 unsigned int no_blks_reqd
= 0;
1389 /* allocation of direct blocks */
1390 for (i
= 0; total_remaining_blocks
&& i
< INDIRECT_BLOCKS
; i
++) {
1391 direct_blockno
= ext4fs_get_new_blk_no();
1392 if (direct_blockno
== -1) {
1393 printf("no block left to assign\n");
1396 file_inode
->b
.blocks
.dir_blocks
[i
] = cpu_to_le32(direct_blockno
);
1397 debug("DB %ld: %u\n", direct_blockno
, total_remaining_blocks
);
1399 total_remaining_blocks
--;
1402 alloc_single_indirect_block(file_inode
, &total_remaining_blocks
,
1404 alloc_double_indirect_block(file_inode
, &total_remaining_blocks
,
1406 alloc_triple_indirect_block(file_inode
, &total_remaining_blocks
,
1408 *total_no_of_block
+= no_blks_reqd
;
1413 static struct ext4_extent_header
*ext4fs_get_extent_block
1414 (struct ext2_data
*data
, char *buf
,
1415 struct ext4_extent_header
*ext_block
,
1416 uint32_t fileblock
, int log2_blksz
)
1418 struct ext4_extent_idx
*index
;
1419 unsigned long long block
;
1420 int blksz
= EXT2_BLOCK_SIZE(data
);
1424 index
= (struct ext4_extent_idx
*)(ext_block
+ 1);
1426 if (le16_to_cpu(ext_block
->eh_magic
) != EXT4_EXT_MAGIC
)
1429 if (ext_block
->eh_depth
== 0)
1434 if (i
>= le16_to_cpu(ext_block
->eh_entries
))
1436 } while (fileblock
>= le32_to_cpu(index
[i
].ei_block
));
1441 block
= le16_to_cpu(index
[i
].ei_leaf_hi
);
1442 block
= (block
<< 32) + le32_to_cpu(index
[i
].ei_leaf_lo
);
1444 if (ext4fs_devread((lbaint_t
)block
<< log2_blksz
, 0, blksz
,
1446 ext_block
= (struct ext4_extent_header
*)buf
;
1452 static int ext4fs_blockgroup
1453 (struct ext2_data
*data
, int group
, struct ext2_block_group
*blkgrp
)
1456 unsigned int blkoff
, desc_per_blk
;
1457 int log2blksz
= get_fs()->dev_desc
->log2blksz
;
1459 desc_per_blk
= EXT2_BLOCK_SIZE(data
) / sizeof(struct ext2_block_group
);
1461 blkno
= le32_to_cpu(data
->sblock
.first_data_block
) + 1 +
1462 group
/ desc_per_blk
;
1463 blkoff
= (group
% desc_per_blk
) * sizeof(struct ext2_block_group
);
1465 debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
1466 group
, blkno
, blkoff
);
1468 return ext4fs_devread((lbaint_t
)blkno
<<
1469 (LOG2_BLOCK_SIZE(data
) - log2blksz
),
1470 blkoff
, sizeof(struct ext2_block_group
),
1474 int ext4fs_read_inode(struct ext2_data
*data
, int ino
, struct ext2_inode
*inode
)
1476 struct ext2_block_group blkgrp
;
1477 struct ext2_sblock
*sblock
= &data
->sblock
;
1478 struct ext_filesystem
*fs
= get_fs();
1479 int log2blksz
= get_fs()->dev_desc
->log2blksz
;
1480 int inodes_per_block
, status
;
1482 unsigned int blkoff
;
1484 /* It is easier to calculate if the first inode is 0. */
1486 status
= ext4fs_blockgroup(data
, ino
/ le32_to_cpu
1487 (sblock
->inodes_per_group
), &blkgrp
);
1491 inodes_per_block
= EXT2_BLOCK_SIZE(data
) / fs
->inodesz
;
1492 blkno
= le32_to_cpu(blkgrp
.inode_table_id
) +
1493 (ino
% le32_to_cpu(sblock
->inodes_per_group
)) / inodes_per_block
;
1494 blkoff
= (ino
% inodes_per_block
) * fs
->inodesz
;
1495 /* Read the inode. */
1496 status
= ext4fs_devread((lbaint_t
)blkno
<< (LOG2_BLOCK_SIZE(data
) -
1498 sizeof(struct ext2_inode
), (char *)inode
);
1505 long int read_allocated_block(struct ext2_inode
*inode
, int fileblock
)
1512 long int perblock_parent
;
1513 long int perblock_child
;
1514 unsigned long long start
;
1515 /* get the blocksize of the filesystem */
1516 blksz
= EXT2_BLOCK_SIZE(ext4fs_root
);
1517 log2_blksz
= LOG2_BLOCK_SIZE(ext4fs_root
)
1518 - get_fs()->dev_desc
->log2blksz
;
1520 if (le32_to_cpu(inode
->flags
) & EXT4_EXTENTS_FL
) {
1521 char *buf
= zalloc(blksz
);
1524 struct ext4_extent_header
*ext_block
;
1525 struct ext4_extent
*extent
;
1528 ext4fs_get_extent_block(ext4fs_root
, buf
,
1529 (struct ext4_extent_header
*)
1530 inode
->b
.blocks
.dir_blocks
,
1531 fileblock
, log2_blksz
);
1533 printf("invalid extent block\n");
1538 extent
= (struct ext4_extent
*)(ext_block
+ 1);
1542 if (i
>= le16_to_cpu(ext_block
->eh_entries
))
1544 } while (fileblock
>= le32_to_cpu(extent
[i
].ee_block
));
1546 fileblock
-= le32_to_cpu(extent
[i
].ee_block
);
1547 if (fileblock
>= le16_to_cpu(extent
[i
].ee_len
)) {
1552 start
= le16_to_cpu(extent
[i
].ee_start_hi
);
1553 start
= (start
<< 32) +
1554 le32_to_cpu(extent
[i
].ee_start_lo
);
1556 return fileblock
+ start
;
1559 printf("Extent Error\n");
1564 /* Direct blocks. */
1565 if (fileblock
< INDIRECT_BLOCKS
)
1566 blknr
= le32_to_cpu(inode
->b
.blocks
.dir_blocks
[fileblock
]);
1569 else if (fileblock
< (INDIRECT_BLOCKS
+ (blksz
/ 4))) {
1570 if (ext4fs_indir1_block
== NULL
) {
1571 ext4fs_indir1_block
= zalloc(blksz
);
1572 if (ext4fs_indir1_block
== NULL
) {
1573 printf("** SI ext2fs read block (indir 1)"
1574 "malloc failed. **\n");
1577 ext4fs_indir1_size
= blksz
;
1578 ext4fs_indir1_blkno
= -1;
1580 if (blksz
!= ext4fs_indir1_size
) {
1581 free(ext4fs_indir1_block
);
1582 ext4fs_indir1_block
= NULL
;
1583 ext4fs_indir1_size
= 0;
1584 ext4fs_indir1_blkno
= -1;
1585 ext4fs_indir1_block
= zalloc(blksz
);
1586 if (ext4fs_indir1_block
== NULL
) {
1587 printf("** SI ext2fs read block (indir 1):"
1588 "malloc failed. **\n");
1591 ext4fs_indir1_size
= blksz
;
1593 if ((le32_to_cpu(inode
->b
.blocks
.indir_block
) <<
1594 log2_blksz
) != ext4fs_indir1_blkno
) {
1596 ext4fs_devread((lbaint_t
)le32_to_cpu
1598 indir_block
) << log2_blksz
, 0,
1599 blksz
, (char *)ext4fs_indir1_block
);
1601 printf("** SI ext2fs read block (indir 1)"
1605 ext4fs_indir1_blkno
=
1606 le32_to_cpu(inode
->b
.blocks
.
1607 indir_block
) << log2_blksz
;
1609 blknr
= le32_to_cpu(ext4fs_indir1_block
1610 [fileblock
- INDIRECT_BLOCKS
]);
1612 /* Double indirect. */
1613 else if (fileblock
< (INDIRECT_BLOCKS
+ (blksz
/ 4 *
1614 (blksz
/ 4 + 1)))) {
1616 long int perblock
= blksz
/ 4;
1617 long int rblock
= fileblock
- (INDIRECT_BLOCKS
+ blksz
/ 4);
1619 if (ext4fs_indir1_block
== NULL
) {
1620 ext4fs_indir1_block
= zalloc(blksz
);
1621 if (ext4fs_indir1_block
== NULL
) {
1622 printf("** DI ext2fs read block (indir 2 1)"
1623 "malloc failed. **\n");
1626 ext4fs_indir1_size
= blksz
;
1627 ext4fs_indir1_blkno
= -1;
1629 if (blksz
!= ext4fs_indir1_size
) {
1630 free(ext4fs_indir1_block
);
1631 ext4fs_indir1_block
= NULL
;
1632 ext4fs_indir1_size
= 0;
1633 ext4fs_indir1_blkno
= -1;
1634 ext4fs_indir1_block
= zalloc(blksz
);
1635 if (ext4fs_indir1_block
== NULL
) {
1636 printf("** DI ext2fs read block (indir 2 1)"
1637 "malloc failed. **\n");
1640 ext4fs_indir1_size
= blksz
;
1642 if ((le32_to_cpu(inode
->b
.blocks
.double_indir_block
) <<
1643 log2_blksz
) != ext4fs_indir1_blkno
) {
1645 ext4fs_devread((lbaint_t
)le32_to_cpu
1647 double_indir_block
) << log2_blksz
,
1649 (char *)ext4fs_indir1_block
);
1651 printf("** DI ext2fs read block (indir 2 1)"
1655 ext4fs_indir1_blkno
=
1656 le32_to_cpu(inode
->b
.blocks
.double_indir_block
) <<
1660 if (ext4fs_indir2_block
== NULL
) {
1661 ext4fs_indir2_block
= zalloc(blksz
);
1662 if (ext4fs_indir2_block
== NULL
) {
1663 printf("** DI ext2fs read block (indir 2 2)"
1664 "malloc failed. **\n");
1667 ext4fs_indir2_size
= blksz
;
1668 ext4fs_indir2_blkno
= -1;
1670 if (blksz
!= ext4fs_indir2_size
) {
1671 free(ext4fs_indir2_block
);
1672 ext4fs_indir2_block
= NULL
;
1673 ext4fs_indir2_size
= 0;
1674 ext4fs_indir2_blkno
= -1;
1675 ext4fs_indir2_block
= zalloc(blksz
);
1676 if (ext4fs_indir2_block
== NULL
) {
1677 printf("** DI ext2fs read block (indir 2 2)"
1678 "malloc failed. **\n");
1681 ext4fs_indir2_size
= blksz
;
1683 if ((le32_to_cpu(ext4fs_indir1_block
[rblock
/ perblock
]) <<
1684 log2_blksz
) != ext4fs_indir2_blkno
) {
1685 status
= ext4fs_devread((lbaint_t
)le32_to_cpu
1686 (ext4fs_indir1_block
1688 perblock
]) << log2_blksz
, 0,
1690 (char *)ext4fs_indir2_block
);
1692 printf("** DI ext2fs read block (indir 2 2)"
1696 ext4fs_indir2_blkno
=
1697 le32_to_cpu(ext4fs_indir1_block
[rblock
1702 blknr
= le32_to_cpu(ext4fs_indir2_block
[rblock
% perblock
]);
1704 /* Tripple indirect. */
1706 rblock
= fileblock
- (INDIRECT_BLOCKS
+ blksz
/ 4 +
1707 (blksz
/ 4 * blksz
/ 4));
1708 perblock_child
= blksz
/ 4;
1709 perblock_parent
= ((blksz
/ 4) * (blksz
/ 4));
1711 if (ext4fs_indir1_block
== NULL
) {
1712 ext4fs_indir1_block
= zalloc(blksz
);
1713 if (ext4fs_indir1_block
== NULL
) {
1714 printf("** TI ext2fs read block (indir 2 1)"
1715 "malloc failed. **\n");
1718 ext4fs_indir1_size
= blksz
;
1719 ext4fs_indir1_blkno
= -1;
1721 if (blksz
!= ext4fs_indir1_size
) {
1722 free(ext4fs_indir1_block
);
1723 ext4fs_indir1_block
= NULL
;
1724 ext4fs_indir1_size
= 0;
1725 ext4fs_indir1_blkno
= -1;
1726 ext4fs_indir1_block
= zalloc(blksz
);
1727 if (ext4fs_indir1_block
== NULL
) {
1728 printf("** TI ext2fs read block (indir 2 1)"
1729 "malloc failed. **\n");
1732 ext4fs_indir1_size
= blksz
;
1734 if ((le32_to_cpu(inode
->b
.blocks
.triple_indir_block
) <<
1735 log2_blksz
) != ext4fs_indir1_blkno
) {
1736 status
= ext4fs_devread
1738 le32_to_cpu(inode
->b
.blocks
.triple_indir_block
)
1739 << log2_blksz
, 0, blksz
,
1740 (char *)ext4fs_indir1_block
);
1742 printf("** TI ext2fs read block (indir 2 1)"
1746 ext4fs_indir1_blkno
=
1747 le32_to_cpu(inode
->b
.blocks
.triple_indir_block
) <<
1751 if (ext4fs_indir2_block
== NULL
) {
1752 ext4fs_indir2_block
= zalloc(blksz
);
1753 if (ext4fs_indir2_block
== NULL
) {
1754 printf("** TI ext2fs read block (indir 2 2)"
1755 "malloc failed. **\n");
1758 ext4fs_indir2_size
= blksz
;
1759 ext4fs_indir2_blkno
= -1;
1761 if (blksz
!= ext4fs_indir2_size
) {
1762 free(ext4fs_indir2_block
);
1763 ext4fs_indir2_block
= NULL
;
1764 ext4fs_indir2_size
= 0;
1765 ext4fs_indir2_blkno
= -1;
1766 ext4fs_indir2_block
= zalloc(blksz
);
1767 if (ext4fs_indir2_block
== NULL
) {
1768 printf("** TI ext2fs read block (indir 2 2)"
1769 "malloc failed. **\n");
1772 ext4fs_indir2_size
= blksz
;
1774 if ((le32_to_cpu(ext4fs_indir1_block
[rblock
/
1775 perblock_parent
]) <<
1777 != ext4fs_indir2_blkno
) {
1778 status
= ext4fs_devread((lbaint_t
)le32_to_cpu
1779 (ext4fs_indir1_block
1781 perblock_parent
]) <<
1782 log2_blksz
, 0, blksz
,
1783 (char *)ext4fs_indir2_block
);
1785 printf("** TI ext2fs read block (indir 2 2)"
1789 ext4fs_indir2_blkno
=
1790 le32_to_cpu(ext4fs_indir1_block
[rblock
/
1795 if (ext4fs_indir3_block
== NULL
) {
1796 ext4fs_indir3_block
= zalloc(blksz
);
1797 if (ext4fs_indir3_block
== NULL
) {
1798 printf("** TI ext2fs read block (indir 2 2)"
1799 "malloc failed. **\n");
1802 ext4fs_indir3_size
= blksz
;
1803 ext4fs_indir3_blkno
= -1;
1805 if (blksz
!= ext4fs_indir3_size
) {
1806 free(ext4fs_indir3_block
);
1807 ext4fs_indir3_block
= NULL
;
1808 ext4fs_indir3_size
= 0;
1809 ext4fs_indir3_blkno
= -1;
1810 ext4fs_indir3_block
= zalloc(blksz
);
1811 if (ext4fs_indir3_block
== NULL
) {
1812 printf("** TI ext2fs read block (indir 2 2)"
1813 "malloc failed. **\n");
1816 ext4fs_indir3_size
= blksz
;
1818 if ((le32_to_cpu(ext4fs_indir2_block
[rblock
1821 log2_blksz
) != ext4fs_indir3_blkno
) {
1823 ext4fs_devread((lbaint_t
)le32_to_cpu
1824 (ext4fs_indir2_block
1825 [(rblock
/ perblock_child
)
1826 % (blksz
/ 4)]) << log2_blksz
, 0,
1827 blksz
, (char *)ext4fs_indir3_block
);
1829 printf("** TI ext2fs read block (indir 2 2)"
1833 ext4fs_indir3_blkno
=
1834 le32_to_cpu(ext4fs_indir2_block
[(rblock
/
1841 blknr
= le32_to_cpu(ext4fs_indir3_block
1842 [rblock
% perblock_child
]);
1844 debug("read_allocated_block %ld\n", blknr
);
1850 * ext4fs_reinit_global() - Reinitialize values of ext4 write implementation's
1853 * This function assures that for a file with the same name but different size
1854 * the sequential store on the ext4 filesystem will be correct.
1856 * In this function the global data, responsible for internal representation
1857 * of the ext4 data are initialized to the reset state. Without this, during
1858 * replacement of the smaller file with the bigger truncation of new file was
1861 void ext4fs_reinit_global(void)
1863 if (ext4fs_indir1_block
!= NULL
) {
1864 free(ext4fs_indir1_block
);
1865 ext4fs_indir1_block
= NULL
;
1866 ext4fs_indir1_size
= 0;
1867 ext4fs_indir1_blkno
= -1;
1869 if (ext4fs_indir2_block
!= NULL
) {
1870 free(ext4fs_indir2_block
);
1871 ext4fs_indir2_block
= NULL
;
1872 ext4fs_indir2_size
= 0;
1873 ext4fs_indir2_blkno
= -1;
1875 if (ext4fs_indir3_block
!= NULL
) {
1876 free(ext4fs_indir3_block
);
1877 ext4fs_indir3_block
= NULL
;
1878 ext4fs_indir3_size
= 0;
1879 ext4fs_indir3_blkno
= -1;
1882 void ext4fs_close(void)
1884 if ((ext4fs_file
!= NULL
) && (ext4fs_root
!= NULL
)) {
1885 ext4fs_free_node(ext4fs_file
, &ext4fs_root
->diropen
);
1888 if (ext4fs_root
!= NULL
) {
1893 ext4fs_reinit_global();
1896 int ext4fs_iterate_dir(struct ext2fs_node
*dir
, char *name
,
1897 struct ext2fs_node
**fnode
, int *ftype
)
1899 unsigned int fpos
= 0;
1902 struct ext2fs_node
*diro
= (struct ext2fs_node
*) dir
;
1906 printf("Iterate dir %s\n", name
);
1907 #endif /* of DEBUG */
1908 if (!diro
->inode_read
) {
1909 status
= ext4fs_read_inode(diro
->data
, diro
->ino
, &diro
->inode
);
1913 /* Search the file. */
1914 while (fpos
< le32_to_cpu(diro
->inode
.size
)) {
1915 struct ext2_dirent dirent
;
1917 status
= ext4fs_read_file(diro
, fpos
,
1918 sizeof(struct ext2_dirent
),
1919 (char *)&dirent
, &actread
);
1923 if (dirent
.direntlen
== 0) {
1924 printf("Failed to iterate over directory %s\n", name
);
1928 if (dirent
.namelen
!= 0) {
1929 char filename
[dirent
.namelen
+ 1];
1930 struct ext2fs_node
*fdiro
;
1931 int type
= FILETYPE_UNKNOWN
;
1933 status
= ext4fs_read_file(diro
,
1935 sizeof(struct ext2_dirent
),
1936 dirent
.namelen
, filename
,
1941 fdiro
= zalloc(sizeof(struct ext2fs_node
));
1945 fdiro
->data
= diro
->data
;
1946 fdiro
->ino
= le32_to_cpu(dirent
.inode
);
1948 filename
[dirent
.namelen
] = '\0';
1950 if (dirent
.filetype
!= FILETYPE_UNKNOWN
) {
1951 fdiro
->inode_read
= 0;
1953 if (dirent
.filetype
== FILETYPE_DIRECTORY
)
1954 type
= FILETYPE_DIRECTORY
;
1955 else if (dirent
.filetype
== FILETYPE_SYMLINK
)
1956 type
= FILETYPE_SYMLINK
;
1957 else if (dirent
.filetype
== FILETYPE_REG
)
1958 type
= FILETYPE_REG
;
1960 status
= ext4fs_read_inode(diro
->data
,
1968 fdiro
->inode_read
= 1;
1970 if ((le16_to_cpu(fdiro
->inode
.mode
) &
1971 FILETYPE_INO_MASK
) ==
1972 FILETYPE_INO_DIRECTORY
) {
1973 type
= FILETYPE_DIRECTORY
;
1974 } else if ((le16_to_cpu(fdiro
->inode
.mode
)
1975 & FILETYPE_INO_MASK
) ==
1976 FILETYPE_INO_SYMLINK
) {
1977 type
= FILETYPE_SYMLINK
;
1978 } else if ((le16_to_cpu(fdiro
->inode
.mode
)
1979 & FILETYPE_INO_MASK
) ==
1981 type
= FILETYPE_REG
;
1985 printf("iterate >%s<\n", filename
);
1986 #endif /* of DEBUG */
1987 if ((name
!= NULL
) && (fnode
!= NULL
)
1988 && (ftype
!= NULL
)) {
1989 if (strcmp(filename
, name
) == 0) {
1995 if (fdiro
->inode_read
== 0) {
1996 status
= ext4fs_read_inode(diro
->data
,
2004 fdiro
->inode_read
= 1;
2007 case FILETYPE_DIRECTORY
:
2010 case FILETYPE_SYMLINK
:
2021 le32_to_cpu(fdiro
->inode
.size
),
2026 fpos
+= le16_to_cpu(dirent
.direntlen
);
2031 static char *ext4fs_read_symlink(struct ext2fs_node
*node
)
2034 struct ext2fs_node
*diro
= node
;
2038 if (!diro
->inode_read
) {
2039 status
= ext4fs_read_inode(diro
->data
, diro
->ino
, &diro
->inode
);
2043 symlink
= zalloc(le32_to_cpu(diro
->inode
.size
) + 1);
2047 if (le32_to_cpu(diro
->inode
.size
) < sizeof(diro
->inode
.b
.symlink
)) {
2048 strncpy(symlink
, diro
->inode
.b
.symlink
,
2049 le32_to_cpu(diro
->inode
.size
));
2051 status
= ext4fs_read_file(diro
, 0,
2052 le32_to_cpu(diro
->inode
.size
),
2054 if ((status
< 0) || (actread
== 0)) {
2059 symlink
[le32_to_cpu(diro
->inode
.size
)] = '\0';
2063 static int ext4fs_find_file1(const char *currpath
,
2064 struct ext2fs_node
*currroot
,
2065 struct ext2fs_node
**currfound
, int *foundtype
)
2067 char fpath
[strlen(currpath
) + 1];
2071 int type
= FILETYPE_DIRECTORY
;
2072 struct ext2fs_node
*currnode
= currroot
;
2073 struct ext2fs_node
*oldnode
= currroot
;
2075 strncpy(fpath
, currpath
, strlen(currpath
) + 1);
2077 /* Remove all leading slashes. */
2078 while (*name
== '/')
2082 *currfound
= currnode
;
2089 /* Extract the actual part from the pathname. */
2090 next
= strchr(name
, '/');
2092 /* Remove all leading slashes. */
2093 while (*next
== '/')
2097 if (type
!= FILETYPE_DIRECTORY
) {
2098 ext4fs_free_node(currnode
, currroot
);
2104 /* Iterate over the directory. */
2105 found
= ext4fs_iterate_dir(currnode
, name
, &currnode
, &type
);
2112 /* Read in the symlink and follow it. */
2113 if (type
== FILETYPE_SYMLINK
) {
2116 /* Test if the symlink does not loop. */
2117 if (++symlinknest
== 8) {
2118 ext4fs_free_node(currnode
, currroot
);
2119 ext4fs_free_node(oldnode
, currroot
);
2123 symlink
= ext4fs_read_symlink(currnode
);
2124 ext4fs_free_node(currnode
, currroot
);
2127 ext4fs_free_node(oldnode
, currroot
);
2131 debug("Got symlink >%s<\n", symlink
);
2133 if (symlink
[0] == '/') {
2134 ext4fs_free_node(oldnode
, currroot
);
2135 oldnode
= &ext4fs_root
->diropen
;
2138 /* Lookup the node the symlink points to. */
2139 status
= ext4fs_find_file1(symlink
, oldnode
,
2145 ext4fs_free_node(oldnode
, currroot
);
2150 ext4fs_free_node(oldnode
, currroot
);
2152 /* Found the node! */
2153 if (!next
|| *next
== '\0') {
2154 *currfound
= currnode
;
2163 int ext4fs_find_file(const char *path
, struct ext2fs_node
*rootnode
,
2164 struct ext2fs_node
**foundnode
, int expecttype
)
2167 int foundtype
= FILETYPE_DIRECTORY
;
2173 status
= ext4fs_find_file1(path
, rootnode
, foundnode
, &foundtype
);
2177 /* Check if the node that was found was of the expected type. */
2178 if ((expecttype
== FILETYPE_REG
) && (foundtype
!= expecttype
))
2180 else if ((expecttype
== FILETYPE_DIRECTORY
)
2181 && (foundtype
!= expecttype
))
2187 int ext4fs_open(const char *filename
, loff_t
*len
)
2189 struct ext2fs_node
*fdiro
= NULL
;
2192 if (ext4fs_root
== NULL
)
2196 status
= ext4fs_find_file(filename
, &ext4fs_root
->diropen
, &fdiro
,
2201 if (!fdiro
->inode_read
) {
2202 status
= ext4fs_read_inode(fdiro
->data
, fdiro
->ino
,
2207 *len
= le32_to_cpu(fdiro
->inode
.size
);
2208 ext4fs_file
= fdiro
;
2212 ext4fs_free_node(fdiro
, &ext4fs_root
->diropen
);
2217 int ext4fs_mount(unsigned part_length
)
2219 struct ext2_data
*data
;
2221 struct ext_filesystem
*fs
= get_fs();
2222 data
= zalloc(SUPERBLOCK_SIZE
);
2226 /* Read the superblock. */
2227 status
= ext4_read_superblock((char *)&data
->sblock
);
2232 /* Make sure this is an ext2 filesystem. */
2233 if (le16_to_cpu(data
->sblock
.magic
) != EXT2_MAGIC
)
2237 * The 64bit feature was enabled when metadata_csum was enabled
2238 * and we do not support metadata_csum (and cannot reliably find
2239 * files when it is set. Refuse to mount.
2241 if (le32_to_cpu(data
->sblock
.feature_incompat
) & EXT4_FEATURE_INCOMPAT_64BIT
) {
2242 printf("Unsupported feature found (64bit, possibly metadata_csum), not mounting\n");
2246 if (le32_to_cpu(data
->sblock
.revision_level
) == 0)
2249 fs
->inodesz
= le16_to_cpu(data
->sblock
.inode_size
);
2251 debug("EXT2 rev %d, inode_size %d\n",
2252 le32_to_cpu(data
->sblock
.revision_level
), fs
->inodesz
);
2254 data
->diropen
.data
= data
;
2255 data
->diropen
.ino
= 2;
2256 data
->diropen
.inode_read
= 1;
2257 data
->inode
= &data
->diropen
.inode
;
2259 status
= ext4fs_read_inode(data
, 2, data
->inode
);
2267 printf("Failed to mount ext2 filesystem...\n");