X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=fs%2Fext4%2Fext4_common.c;h=33d69c9c71f07819c73678c2efc7abc175a8c607;hb=415548d88446134549917aae026f53dbbee36fd2;hp=083e45eed5996ec996ece02a9371f34ee7e31ddc;hpb=ed34f34dbaf206dfe223f4bc2147d600fe1b0f58;p=u-boot diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 083e45eed5..33d69c9c71 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -16,19 +16,7 @@ * * ext4write : Based on generic ext4 protocol. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -56,7 +44,7 @@ int ext4fs_indir3_blkno = -1; struct ext2_inode *g_parent_inode; static int symlinknest; -#if defined(CONFIG_CMD_EXT4_WRITE) +#if defined(CONFIG_EXT4_WRITE) uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n) { uint32_t res = size / n; @@ -71,20 +59,20 @@ void put_ext4(uint64_t off, void *buf, uint32_t size) uint64_t startblock; uint64_t remainder; unsigned char *temp_ptr = NULL; - unsigned char sec_buf[SECTOR_SIZE]; struct ext_filesystem *fs = get_fs(); + int log2blksz = fs->dev_desc->log2blksz; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz); - startblock = off / (uint64_t)SECTOR_SIZE; + startblock = off >> log2blksz; startblock += part_offset; - remainder = off % (uint64_t)SECTOR_SIZE; - remainder &= SECTOR_SIZE - 1; + remainder = off & (uint64_t)(fs->dev_desc->blksz - 1); if (fs->dev_desc == NULL) return; - if ((startblock + (size / SECTOR_SIZE)) > + if ((startblock + (size >> log2blksz)) > (part_offset + fs->total_sect)) { - printf("part_offset is %lu\n", part_offset); + printf("part_offset is " LBAFU "\n", part_offset); printf("total_sector is %llu\n", fs->total_sect); printf("error: overflow occurs\n"); return; @@ -101,10 +89,10 @@ void put_ext4(uint64_t off, void *buf, uint32_t size) startblock, 1, sec_buf); } } else { - if (size / SECTOR_SIZE != 0) { + if (size >> log2blksz != 0) { fs->dev_desc->block_write(fs->dev_desc->dev, startblock, - size / SECTOR_SIZE, + size >> log2blksz, (unsigned long *)buf); } else { fs->dev_desc->block_read(fs->dev_desc->dev, @@ -314,7 +302,7 @@ int ext4fs_checksum_update(unsigned int i) struct ext_filesystem *fs = get_fs(); __u16 crc = 0; - desc = (struct ext2_block_group *)&fs->gd[i]; + desc = (struct ext2_block_group *)&fs->bgd[i]; if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { int offset = offsetof(struct ext2_block_group, bg_checksum); @@ -378,7 +366,6 @@ void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type) struct ext_filesystem *fs = get_fs(); /* directory entry */ struct ext2_dirent *dir; - char *ptr = NULL; char *temp_dir = NULL; zero_buffer = zalloc(fs->blksz); @@ -406,7 +393,7 @@ restart: previous_blknr = root_blknr; } - status = ext4fs_devread(first_block_no_of_root + status = ext4fs_devread((lbaint_t)first_block_no_of_root * fs->sect_perblk, 0, fs->blksz, root_first_block_buffer); if (status == 0) @@ -415,7 +402,6 @@ restart: if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) goto fail; dir = (struct ext2_dirent *)root_first_block_buffer; - ptr = (char *)dir; totalbytes = 0; while (dir->direntlen > 0) { /* @@ -459,9 +445,9 @@ restart: goto fail; } put_ext4(((uint64_t) - (g_parent_inode->b. + ((uint64_t)g_parent_inode->b. blocks.dir_blocks[direct_blk_idx] * - fs->blksz)), zero_buffer, fs->blksz); + (uint64_t)fs->blksz)), zero_buffer, fs->blksz); g_parent_inode->size = g_parent_inode->size + fs->blksz; g_parent_inode->blockcnt = @@ -483,14 +469,12 @@ restart: break; dir = (struct ext2_dirent *)((char *)dir + templength); - ptr = (char *)dir; } /* make a pointer ready for creating next directory entry */ templength = dir->direntlen; totalbytes = totalbytes + templength; dir = (struct ext2_dirent *)((char *)dir + templength); - ptr = (char *)dir; /* get the next available inode number */ inodeno = ext4fs_get_new_inode_no(); @@ -549,7 +533,7 @@ static int search_dir(struct ext2_inode *parent_inode, char *dirname) if (!block_buffer) goto fail; - status = ext4fs_devread(blknr * fs->sect_perblk, + status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz, (char *)block_buffer); if (status == 0) goto fail; @@ -787,7 +771,7 @@ static int check_filename(char *filename, unsigned int blknr) if (!root_first_block_buffer) return -ENOMEM; root_first_block_addr = root_first_block_buffer; - status = ext4fs_devread(first_block_no_of_root * + status = ext4fs_devread((lbaint_t)first_block_no_of_root * fs->sect_perblk, 0, fs->blksz, root_first_block_buffer); if (status == 0) @@ -874,17 +858,17 @@ long int ext4fs_get_new_blk_no(void) char *zero_buffer = zalloc(fs->blksz); if (!journal_buffer || !zero_buffer) goto fail; - struct ext2_block_group *gd = (struct ext2_block_group *)fs->gdtable; + struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; if (fs->first_pass_bbmap == 0) { for (i = 0; i < fs->no_blkgrp; i++) { - if (gd[i].free_blocks) { - if (gd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) { - put_ext4(((uint64_t) (gd[i].block_id * - fs->blksz)), + if (bgd[i].free_blocks) { + if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) { + put_ext4(((uint64_t) ((uint64_t)bgd[i].block_id * + (uint64_t)fs->blksz)), zero_buffer, fs->blksz); - gd[i].bg_flags = - gd[i]. + bgd[i].bg_flags = + bgd[i]. bg_flags & ~EXT4_BG_BLOCK_UNINIT; memcpy(fs->blk_bmaps[i], zero_buffer, fs->blksz); @@ -897,16 +881,17 @@ long int ext4fs_get_new_blk_no(void) fs->curr_blkno = fs->curr_blkno + (i * fs->blksz * 8); fs->first_pass_bbmap++; - gd[i].free_blocks--; + bgd[i].free_blocks--; fs->sb->free_blocks--; - status = ext4fs_devread(gd[i].block_id * + status = ext4fs_devread((lbaint_t) + bgd[i].block_id * fs->sect_perblk, 0, fs->blksz, journal_buffer); if (status == 0) goto fail; if (ext4fs_log_journal(journal_buffer, - gd[i].block_id)) + bgd[i].block_id)) goto fail; goto success; } else { @@ -919,10 +904,8 @@ long int ext4fs_get_new_blk_no(void) restart: fs->curr_blkno++; /* get the blockbitmap index respective to blockno */ - if (fs->blksz != 1024) { - bg_idx = fs->curr_blkno / blk_per_grp; - } else { - bg_idx = fs->curr_blkno / blk_per_grp; + bg_idx = fs->curr_blkno / blk_per_grp; + if (fs->blksz == 1024) { remainder = fs->curr_blkno % blk_per_grp; if (!remainder) bg_idx--; @@ -935,19 +918,19 @@ restart: if (bg_idx >= fs->no_blkgrp) goto fail; - if (gd[bg_idx].free_blocks == 0) { + if (bgd[bg_idx].free_blocks == 0) { debug("block group %u is full. Skipping\n", bg_idx); fs->curr_blkno = fs->curr_blkno + blk_per_grp; fs->curr_blkno--; goto restart; } - if (gd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) { + if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) { memset(zero_buffer, '\0', fs->blksz); - put_ext4(((uint64_t) (gd[bg_idx].block_id * fs->blksz)), - zero_buffer, fs->blksz); + put_ext4(((uint64_t) ((uint64_t)bgd[bg_idx].block_id * + (uint64_t)fs->blksz)), zero_buffer, fs->blksz); memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz); - gd[bg_idx].bg_flags = gd[bg_idx].bg_flags & + bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags & ~EXT4_BG_BLOCK_UNINIT; } @@ -961,18 +944,18 @@ restart: /* journal backup */ if (prev_bg_bitmap_index != bg_idx) { memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread(gd[bg_idx].block_id + status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id * fs->sect_perblk, 0, fs->blksz, journal_buffer); if (status == 0) goto fail; if (ext4fs_log_journal(journal_buffer, - gd[bg_idx].block_id)) + bgd[bg_idx].block_id)) goto fail; prev_bg_bitmap_index = bg_idx; } - gd[bg_idx].free_blocks--; + bgd[bg_idx].free_blocks--; fs->sb->free_blocks--; goto success; } @@ -1000,19 +983,21 @@ int ext4fs_get_new_inode_no(void) char *zero_buffer = zalloc(fs->blksz); if (!journal_buffer || !zero_buffer) goto fail; - struct ext2_block_group *gd = (struct ext2_block_group *)fs->gdtable; + struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; if (fs->first_pass_ibmap == 0) { for (i = 0; i < fs->no_blkgrp; i++) { - if (gd[i].free_inodes) { - if (gd[i].bg_itable_unused != gd[i].free_inodes) - gd[i].bg_itable_unused = - gd[i].free_inodes; - if (gd[i].bg_flags & EXT4_BG_INODE_UNINIT) { + if (bgd[i].free_inodes) { + if (bgd[i].bg_itable_unused != + bgd[i].free_inodes) + bgd[i].bg_itable_unused = + bgd[i].free_inodes; + if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) { put_ext4(((uint64_t) - (gd[i].inode_id * fs->blksz)), + ((uint64_t)bgd[i].inode_id * + (uint64_t)fs->blksz)), zero_buffer, fs->blksz); - gd[i].bg_flags = gd[i].bg_flags & + bgd[i].bg_flags = bgd[i].bg_flags & ~EXT4_BG_INODE_UNINIT; memcpy(fs->inode_bmaps[i], zero_buffer, fs->blksz); @@ -1025,17 +1010,18 @@ int ext4fs_get_new_inode_no(void) fs->curr_inode_no = fs->curr_inode_no + (i * inodes_per_grp); fs->first_pass_ibmap++; - gd[i].free_inodes--; - gd[i].bg_itable_unused--; + bgd[i].free_inodes--; + bgd[i].bg_itable_unused--; fs->sb->free_inodes--; - status = ext4fs_devread(gd[i].inode_id * + status = ext4fs_devread((lbaint_t) + bgd[i].inode_id * fs->sect_perblk, 0, fs->blksz, journal_buffer); if (status == 0) goto fail; if (ext4fs_log_journal(journal_buffer, - gd[i].inode_id)) + bgd[i].inode_id)) goto fail; goto success; } else @@ -1047,13 +1033,13 @@ restart: fs->curr_inode_no++; /* get the blockbitmap index respective to blockno */ ibmap_idx = fs->curr_inode_no / inodes_per_grp; - if (gd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) { + if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) { memset(zero_buffer, '\0', fs->blksz); - put_ext4(((uint64_t) (gd[ibmap_idx].inode_id * - fs->blksz)), zero_buffer, + put_ext4(((uint64_t) ((uint64_t)bgd[ibmap_idx].inode_id * + (uint64_t)fs->blksz)), zero_buffer, fs->blksz); - gd[ibmap_idx].bg_flags = - gd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT; + bgd[ibmap_idx].bg_flags = + bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT; memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer, fs->blksz); } @@ -1069,21 +1055,23 @@ restart: /* journal backup */ if (prev_inode_bitmap_index != ibmap_idx) { memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread(gd[ibmap_idx].inode_id + status = ext4fs_devread((lbaint_t) + bgd[ibmap_idx].inode_id * fs->sect_perblk, 0, fs->blksz, journal_buffer); if (status == 0) goto fail; if (ext4fs_log_journal(journal_buffer, - gd[ibmap_idx].inode_id)) + bgd[ibmap_idx].inode_id)) goto fail; prev_inode_bitmap_index = ibmap_idx; } - if (gd[ibmap_idx].bg_itable_unused != gd[ibmap_idx].free_inodes) - gd[ibmap_idx].bg_itable_unused = - gd[ibmap_idx].free_inodes; - gd[ibmap_idx].free_inodes--; - gd[ibmap_idx].bg_itable_unused--; + if (bgd[ibmap_idx].bg_itable_unused != + bgd[ibmap_idx].free_inodes) + bgd[ibmap_idx].bg_itable_unused = + bgd[ibmap_idx].free_inodes; + bgd[ibmap_idx].free_inodes--; + bgd[ibmap_idx].bg_itable_unused--; fs->sb->free_inodes--; goto success; } @@ -1130,7 +1118,7 @@ static void alloc_single_indirect_block(struct ext2_inode *file_inode, (*no_blks_reqd)++; debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks); - status = ext4fs_devread(si_blockno * fs->sect_perblk, + status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk, 0, fs->blksz, (char *)si_buffer); memset(si_buffer, '\0', fs->blksz); if (status == 0) @@ -1153,7 +1141,7 @@ static void alloc_single_indirect_block(struct ext2_inode *file_inode, } /* write the block to disk */ - put_ext4(((uint64_t) (si_blockno * fs->blksz)), + put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)), si_start_addr, fs->blksz); file_inode->b.blocks.indir_block = si_blockno; } @@ -1194,9 +1182,14 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, debug("DIPB %ld: %u\n", di_blockno_parent, *total_remaining_blocks); - status = ext4fs_devread(di_blockno_parent * + status = ext4fs_devread((lbaint_t)di_blockno_parent * fs->sect_perblk, 0, fs->blksz, (char *)di_parent_buffer); + + if (!status) { + printf("%s: Device read error!\n", __func__); + goto fail; + } memset(di_parent_buffer, '\0', fs->blksz); /* @@ -1220,10 +1213,15 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, debug("DICB %ld: %u\n", di_blockno_child, *total_remaining_blocks); - status = ext4fs_devread(di_blockno_child * + status = ext4fs_devread((lbaint_t)di_blockno_child * fs->sect_perblk, 0, fs->blksz, (char *)di_child_buff); + + if (!status) { + printf("%s: Device read error!\n", __func__); + goto fail; + } memset(di_child_buff, '\0', fs->blksz); /* filling of actual datablocks for each child */ for (j = 0; j < (fs->blksz / sizeof(int)); j++) { @@ -1242,7 +1240,7 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, break; } /* write the block table */ - put_ext4(((uint64_t) (di_blockno_child * fs->blksz)), + put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)), di_child_buff_start, fs->blksz); free(di_child_buff_start); di_child_buff_start = NULL; @@ -1250,7 +1248,7 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, if (*total_remaining_blocks == 0) break; } - put_ext4(((uint64_t) (di_blockno_parent * fs->blksz)), + put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)), di_block_start_addr, fs->blksz); file_inode->b.blocks.double_indir_block = di_blockno_parent; } @@ -1348,8 +1346,8 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, break; } /* write the child block */ - put_ext4(((uint64_t) (ti_child_blockno * - fs->blksz)), + put_ext4(((uint64_t) ((uint64_t)ti_child_blockno * + (uint64_t)fs->blksz)), ti_cbuff_start_addr, fs->blksz); free(ti_cbuff_start_addr); @@ -1357,7 +1355,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, break; } /* write the parent block */ - put_ext4(((uint64_t) (ti_parent_blockno * fs->blksz)), + put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)), ti_pbuff_start_addr, fs->blksz); free(ti_pbuff_start_addr); @@ -1365,7 +1363,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, break; } /* write the grand parent block */ - put_ext4(((uint64_t) (ti_gp_blockno * fs->blksz)), + put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)), ti_gp_buff_start_addr, fs->blksz); file_inode->b.blocks.triple_indir_block = ti_gp_blockno; } @@ -1382,7 +1380,7 @@ void ext4fs_allocate_blocks(struct ext2_inode *file_inode, unsigned int no_blks_reqd = 0; /* allocation of direct blocks */ - for (i = 0; i < INDIRECT_BLOCKS; i++) { + for (i = 0; total_remaining_blocks && i < INDIRECT_BLOCKS; i++) { direct_blockno = ext4fs_get_new_blk_no(); if (direct_blockno == -1) { printf("no block left to assign\n"); @@ -1392,8 +1390,6 @@ void ext4fs_allocate_blocks(struct ext2_inode *file_inode, debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks); total_remaining_blocks--; - if (total_remaining_blocks == 0) - break; } alloc_single_indirect_block(file_inode, &total_remaining_blocks, @@ -1414,13 +1410,13 @@ static struct ext4_extent_header *ext4fs_get_extent_block { struct ext4_extent_idx *index; unsigned long long block; - struct ext_filesystem *fs = get_fs(); + int blksz = EXT2_BLOCK_SIZE(data); int i; while (1) { index = (struct ext4_extent_idx *)(ext_block + 1); - if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) + if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) return 0; if (ext_block->eh_depth == 0) @@ -1428,17 +1424,18 @@ static struct ext4_extent_header *ext4fs_get_extent_block i = -1; do { i++; - if (i >= le32_to_cpu(ext_block->eh_entries)) + if (i >= le16_to_cpu(ext_block->eh_entries)) break; - } while (fileblock > le32_to_cpu(index[i].ei_block)); + } while (fileblock >= le32_to_cpu(index[i].ei_block)); if (--i < 0) return 0; - block = le32_to_cpu(index[i].ei_leaf_hi); + block = le16_to_cpu(index[i].ei_leaf_hi); block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); - if (ext4fs_devread(block << log2_blksz, 0, fs->blksz, buf)) + if (ext4fs_devread((lbaint_t)block << log2_blksz, 0, blksz, + buf)) ext_block = (struct ext4_extent_header *)buf; else return 0; @@ -1450,6 +1447,7 @@ static int ext4fs_blockgroup { long int blkno; unsigned int blkoff, desc_per_blk; + int log2blksz = get_fs()->dev_desc->log2blksz; desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group); @@ -1460,7 +1458,8 @@ static int ext4fs_blockgroup debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", group, blkno, blkoff); - return ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), + return ext4fs_devread((lbaint_t)blkno << + (LOG2_BLOCK_SIZE(data) - log2blksz), blkoff, sizeof(struct ext2_block_group), (char *)blkgrp); } @@ -1470,6 +1469,7 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) struct ext2_block_group blkgrp; struct ext2_sblock *sblock = &data->sblock; struct ext_filesystem *fs = get_fs(); + int log2blksz = get_fs()->dev_desc->log2blksz; int inodes_per_block, status; long int blkno; unsigned int blkoff; @@ -1486,7 +1486,8 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; blkoff = (ino % inodes_per_block) * fs->inodesz; /* Read the inode. */ - status = ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), blkoff, + status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) - + log2blksz), blkoff, sizeof(struct ext2_inode), (char *)inode); if (status == 0) return 0; @@ -1506,7 +1507,9 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) unsigned long long start; /* get the blocksize of the filesystem */ blksz = EXT2_BLOCK_SIZE(ext4fs_root); - log2_blksz = LOG2_EXT2_BLOCK_SIZE(ext4fs_root); + log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root) + - get_fs()->dev_desc->log2blksz; + if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { char *buf = zalloc(blksz); if (!buf) @@ -1514,11 +1517,11 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) struct ext4_extent_header *ext_block; struct ext4_extent *extent; int i = -1; - ext_block = ext4fs_get_extent_block(ext4fs_root, buf, - (struct ext4_extent_header - *)inode->b. - blocks.dir_blocks, - fileblock, log2_blksz); + ext_block = + ext4fs_get_extent_block(ext4fs_root, buf, + (struct ext4_extent_header *) + inode->b.blocks.dir_blocks, + fileblock, log2_blksz); if (!ext_block) { printf("invalid extent block\n"); free(buf); @@ -1529,17 +1532,17 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) do { i++; - if (i >= le32_to_cpu(ext_block->eh_entries)) + if (i >= le16_to_cpu(ext_block->eh_entries)) break; } while (fileblock >= le32_to_cpu(extent[i].ee_block)); if (--i >= 0) { fileblock -= le32_to_cpu(extent[i].ee_block); - if (fileblock >= le32_to_cpu(extent[i].ee_len)) { + if (fileblock >= le16_to_cpu(extent[i].ee_len)) { free(buf); return 0; } - start = le32_to_cpu(extent[i].ee_start_hi); + start = le16_to_cpu(extent[i].ee_start_hi); start = (start << 32) + le32_to_cpu(extent[i].ee_start_lo); free(buf); @@ -1583,7 +1586,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) if ((__le32_to_cpu(inode->b.blocks.indir_block) << log2_blksz) != ext4fs_indir1_blkno) { status = - ext4fs_devread(__le32_to_cpu + ext4fs_devread((lbaint_t)__le32_to_cpu (inode->b.blocks. indir_block) << log2_blksz, 0, blksz, (char *)ext4fs_indir1_block); @@ -1632,7 +1635,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) if ((__le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz) != ext4fs_indir1_blkno) { status = - ext4fs_devread(__le32_to_cpu + ext4fs_devread((lbaint_t)__le32_to_cpu (inode->b.blocks. double_indir_block) << log2_blksz, 0, blksz, @@ -1672,7 +1675,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) } if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << log2_blksz) != ext4fs_indir2_blkno) { - status = ext4fs_devread(__le32_to_cpu + status = ext4fs_devread((lbaint_t)__le32_to_cpu (ext4fs_indir1_block [rblock / perblock]) << log2_blksz, 0, @@ -1724,7 +1727,8 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) << log2_blksz) != ext4fs_indir1_blkno) { status = ext4fs_devread - (__le32_to_cpu(inode->b.blocks.triple_indir_block) + ((lbaint_t) + __le32_to_cpu(inode->b.blocks.triple_indir_block) << log2_blksz, 0, blksz, (char *)ext4fs_indir1_block); if (status == 0) { @@ -1764,7 +1768,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) perblock_parent]) << log2_blksz) != ext4fs_indir2_blkno) { - status = ext4fs_devread(__le32_to_cpu + status = ext4fs_devread((lbaint_t)__le32_to_cpu (ext4fs_indir1_block [rblock / perblock_parent]) << @@ -1809,7 +1813,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) perblock_child]) << log2_blksz) != ext4fs_indir3_blkno) { status = - ext4fs_devread(__le32_to_cpu + ext4fs_devread((lbaint_t)__le32_to_cpu (ext4fs_indir2_block [(rblock / perblock_child) % (blksz / 4)]) << log2_blksz, 0, @@ -1830,21 +1834,25 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) blknr = __le32_to_cpu(ext4fs_indir3_block [rblock % perblock_child]); } - debug("ext4fs_read_block %ld\n", blknr); + debug("read_allocated_block %ld\n", blknr); return blknr; } -void ext4fs_close(void) +/** + * ext4fs_reinit_global() - Reinitialize values of ext4 write implementation's + * global pointers + * + * This function assures that for a file with the same name but different size + * the sequential store on the ext4 filesystem will be correct. + * + * In this function the global data, responsible for internal representation + * of the ext4 data are initialized to the reset state. Without this, during + * replacement of the smaller file with the bigger truncation of new file was + * performed. + */ +void ext4fs_reinit_global(void) { - if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) { - ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen); - ext4fs_file = NULL; - } - if (ext4fs_root != NULL) { - free(ext4fs_root); - ext4fs_root = NULL; - } if (ext4fs_indir1_block != NULL) { free(ext4fs_indir1_block); ext4fs_indir1_block = NULL; @@ -1864,6 +1872,19 @@ void ext4fs_close(void) ext4fs_indir3_blkno = -1; } } +void ext4fs_close(void) +{ + if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) { + ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen); + ext4fs_file = NULL; + } + if (ext4fs_root != NULL) { + free(ext4fs_root); + ext4fs_root = NULL; + } + + ext4fs_reinit_global(); +} int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, struct ext2fs_node **fnode, int *ftype) @@ -2184,13 +2205,12 @@ int ext4fs_mount(unsigned part_length) struct ext2_data *data; int status; struct ext_filesystem *fs = get_fs(); - data = zalloc(sizeof(struct ext2_data)); + data = zalloc(SUPERBLOCK_SIZE); if (!data) return 0; /* Read the superblock. */ - status = ext4fs_devread(1 * 2, 0, sizeof(struct ext2_sblock), - (char *)&data->sblock); + status = ext4_read_superblock((char *)&data->sblock); if (status == 0) goto fail;