]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - fs/ext4/ext4_write.c
ext4: Use correct value for inode size even on revision 0 filesystems
[karo-tx-uboot.git] / fs / ext4 / ext4_write.c
index c4e399ccfae55843bd786611d79c539470288048..a438be0d6e33a6a8e991964c8002200691a3e0aa 100644 (file)
  *
  * 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 <common.h>
+#include <memalign.h>
 #include <linux/stat.h>
 #include <div64.h>
 #include "ext4_common.h"
 
+static inline void ext4fs_sb_free_inodes_inc(struct ext2_sblock *sb)
+{
+       sb->free_inodes = cpu_to_le32(le32_to_cpu(sb->free_inodes) + 1);
+}
+
+static inline void ext4fs_sb_free_blocks_inc(struct ext2_sblock *sb)
+{
+       sb->free_blocks = cpu_to_le32(le32_to_cpu(sb->free_blocks) + 1);
+}
+
+static inline void ext4fs_bg_free_inodes_inc(struct ext2_block_group *bg)
+{
+       bg->free_inodes = cpu_to_le16(le16_to_cpu(bg->free_inodes) + 1);
+}
+
+static inline void ext4fs_bg_free_blocks_inc(struct ext2_block_group *bg)
+{
+       bg->free_blocks = cpu_to_le16(le16_to_cpu(bg->free_blocks) + 1);
+}
+
 static void ext4fs_update(void)
 {
        short i;
@@ -51,19 +60,19 @@ static void ext4fs_update(void)
 
        /* update block groups */
        for (i = 0; i < fs->no_blkgrp; i++) {
-               fs->bgd[i].bg_checksum = ext4fs_checksum_update(i);
-               put_ext4((uint64_t)(fs->bgd[i].block_id * fs->blksz),
+               fs->bgd[i].bg_checksum = cpu_to_le16(ext4fs_checksum_update(i));
+               put_ext4((uint64_t)le32_to_cpu(fs->bgd[i].block_id) * fs->blksz,
                         fs->blk_bmaps[i], fs->blksz);
        }
 
        /* update inode table groups */
        for (i = 0; i < fs->no_blkgrp; i++) {
-               put_ext4((uint64_t) (fs->bgd[i].inode_id * fs->blksz),
+               put_ext4((uint64_t)le32_to_cpu(fs->bgd[i].inode_id) * fs->blksz,
                         fs->inode_bmaps[i], fs->blksz);
        }
 
        /* update the block group descriptor table */
-       put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz),
+       put_ext4((uint64_t)((uint64_t)fs->gdtable_blkno * (uint64_t)fs->blksz),
                 (struct ext2_block_group *)fs->gdtable,
                 (fs->blksz * fs->no_blk_pergdt));
 
@@ -88,8 +97,8 @@ int ext4fs_get_bgdtable(void)
        if (!fs->gdtable)
                return -ENOMEM;
        /* read the group descriptor table */
-       status = ext4fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0,
-                               fs->blksz * fs->no_blk_pergdt, fs->gdtable);
+       status = ext4fs_devread((lbaint_t)fs->gdtable_blkno * fs->sect_perblk,
+                               0, fs->blksz * fs->no_blk_pergdt, fs->gdtable);
        if (status == 0)
                goto fail;
 
@@ -110,11 +119,11 @@ static void delete_single_indirect_block(struct ext2_inode *inode)
 {
        struct ext2_block_group *bgd = NULL;
        static int prev_bg_bmap_idx = -1;
-       long int blknr;
+       uint32_t blknr;
        int remainder;
        int bg_idx;
        int status;
-       unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
+       uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
        struct ext_filesystem *fs = get_fs();
        char *journal_buffer = zalloc(fs->blksz);
        if (!journal_buffer) {
@@ -126,29 +135,27 @@ static void delete_single_indirect_block(struct ext2_inode *inode)
 
        /* deleting the single indirect block associated with inode */
        if (inode->b.blocks.indir_block != 0) {
-               debug("SIPB releasing %u\n", inode->b.blocks.indir_block);
-               blknr = inode->b.blocks.indir_block;
-               if (fs->blksz != 1024) {
-                       bg_idx = blknr / blk_per_grp;
-               } else {
-                       bg_idx = blknr / blk_per_grp;
+               blknr = le32_to_cpu(inode->b.blocks.indir_block);
+               debug("SIPB releasing %u\n", blknr);
+               bg_idx = blknr / blk_per_grp;
+               if (fs->blksz == 1024) {
                        remainder = blknr % blk_per_grp;
                        if (!remainder)
                                bg_idx--;
                }
                ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
-               bgd[bg_idx].free_blocks++;
-               fs->sb->free_blocks++;
+               ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+               ext4fs_sb_free_blocks_inc(fs->sb);
                /* journal backup */
                if (prev_bg_bmap_idx != bg_idx) {
-                       status =
-                           ext4fs_devread(bgd[bg_idx].block_id *
+                       status = ext4fs_devread(
+                                          (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) *
                                           fs->sect_perblk, 0, fs->blksz,
                                           journal_buffer);
                        if (status == 0)
                                goto fail;
                        if (ext4fs_log_journal
-                           (journal_buffer, bgd[bg_idx].block_id))
+                           (journal_buffer, le32_to_cpu(bgd[bg_idx].block_id)))
                                goto fail;
                        prev_bg_bmap_idx = bg_idx;
                }
@@ -162,12 +169,12 @@ static void delete_double_indirect_block(struct ext2_inode *inode)
        int i;
        short status;
        static int prev_bg_bmap_idx = -1;
-       long int blknr;
+       uint32_t blknr;
        int remainder;
        int bg_idx;
-       unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
-       unsigned int *di_buffer = NULL;
-       unsigned int *DIB_start_addr = NULL;
+       uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
+       __le32 *di_buffer = NULL;
+       void *dib_start_addr = NULL;
        struct ext2_block_group *bgd = NULL;
        struct ext_filesystem *fs = get_fs();
        char *journal_buffer = zalloc(fs->blksz);
@@ -184,31 +191,30 @@ static void delete_double_indirect_block(struct ext2_inode *inode)
                        printf("No memory\n");
                        return;
                }
-               DIB_start_addr = (unsigned int *)di_buffer;
-               blknr = inode->b.blocks.double_indir_block;
-               status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
-                                       (char *)di_buffer);
+               dib_start_addr = di_buffer;
+               blknr = le32_to_cpu(inode->b.blocks.double_indir_block);
+               status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
+                                       fs->blksz, (char *)di_buffer);
                for (i = 0; i < fs->blksz / sizeof(int); i++) {
                        if (*di_buffer == 0)
                                break;
 
                        debug("DICB releasing %u\n", *di_buffer);
-                       if (fs->blksz != 1024) {
-                               bg_idx = (*di_buffer) / blk_per_grp;
-                       } else {
-                               bg_idx = (*di_buffer) / blk_per_grp;
-                               remainder = (*di_buffer) % blk_per_grp;
+                       bg_idx = le32_to_cpu(*di_buffer) / blk_per_grp;
+                       if (fs->blksz == 1024) {
+                               remainder = le32_to_cpu(*di_buffer) % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
                        }
-                       ext4fs_reset_block_bmap(*di_buffer,
+                       ext4fs_reset_block_bmap(le32_to_cpu(*di_buffer),
                                        fs->blk_bmaps[bg_idx], bg_idx);
                        di_buffer++;
-                       bgd[bg_idx].free_blocks++;
-                       fs->sb->free_blocks++;
+                       ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+                       ext4fs_sb_free_blocks_inc(fs->sb);
                        /* journal backup */
                        if (prev_bg_bmap_idx != bg_idx) {
-                               status = ext4fs_devread(bgd[bg_idx].block_id
+                               status = ext4fs_devread(
+                                                       (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id)
                                                        * fs->sect_perblk, 0,
                                                        fs->blksz,
                                                        journal_buffer);
@@ -216,43 +222,41 @@ static void delete_double_indirect_block(struct ext2_inode *inode)
                                        goto fail;
 
                                if (ext4fs_log_journal(journal_buffer,
-                                                       bgd[bg_idx].block_id))
+                                                       le32_to_cpu(bgd[bg_idx].block_id)))
                                        goto fail;
                                prev_bg_bmap_idx = bg_idx;
                        }
                }
 
                /* removing the parent double indirect block */
-               blknr = inode->b.blocks.double_indir_block;
-               if (fs->blksz != 1024) {
-                       bg_idx = blknr / blk_per_grp;
-               } else {
-                       bg_idx = blknr / blk_per_grp;
+               blknr = le32_to_cpu(inode->b.blocks.double_indir_block);
+               bg_idx = blknr / blk_per_grp;
+               if (fs->blksz == 1024) {
                        remainder = blknr % blk_per_grp;
                        if (!remainder)
                                bg_idx--;
                }
                ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
-               bgd[bg_idx].free_blocks++;
-               fs->sb->free_blocks++;
+               ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+               ext4fs_sb_free_blocks_inc(fs->sb);
                /* journal backup */
                if (prev_bg_bmap_idx != bg_idx) {
                        memset(journal_buffer, '\0', fs->blksz);
-                       status = ext4fs_devread(bgd[bg_idx].block_id *
+                       status = ext4fs_devread((lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) *
                                                fs->sect_perblk, 0, fs->blksz,
                                                journal_buffer);
                        if (status == 0)
                                goto fail;
 
                        if (ext4fs_log_journal(journal_buffer,
-                                               bgd[bg_idx].block_id))
+                                               le32_to_cpu(bgd[bg_idx].block_id)))
                                goto fail;
                        prev_bg_bmap_idx = bg_idx;
                }
-               debug("DIPB releasing %ld\n", blknr);
+               debug("DIPB releasing %d\n", blknr);
        }
 fail:
-       free(DIB_start_addr);
+       free(dib_start_addr);
        free(journal_buffer);
 }
 
@@ -261,14 +265,14 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
        int i, j;
        short status;
        static int prev_bg_bmap_idx = -1;
-       long int blknr;
+       uint32_t blknr;
        int remainder;
        int bg_idx;
-       unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
-       unsigned int *tigp_buffer = NULL;
-       unsigned int *tib_start_addr = NULL;
-       unsigned int *tip_buffer = NULL;
-       unsigned int *tipb_start_addr = NULL;
+       uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
+       __le32 *tigp_buffer = NULL;
+       void *tib_start_addr = NULL;
+       __le32 *tip_buffer = NULL;
+       void *tipb_start_addr = NULL;
        struct ext2_block_group *bgd = NULL;
        struct ext_filesystem *fs = get_fs();
        char *journal_buffer = zalloc(fs->blksz);
@@ -285,10 +289,10 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                        printf("No memory\n");
                        return;
                }
-               tib_start_addr = (unsigned int *)tigp_buffer;
-               blknr = inode->b.blocks.triple_indir_block;
-               status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
-                                       (char *)tigp_buffer);
+               tib_start_addr = tigp_buffer;
+               blknr = le32_to_cpu(inode->b.blocks.triple_indir_block);
+               status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
+                                       fs->blksz, (char *)tigp_buffer);
                for (i = 0; i < fs->blksz / sizeof(int); i++) {
                        if (*tigp_buffer == 0)
                                break;
@@ -297,35 +301,32 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                        tip_buffer = zalloc(fs->blksz);
                        if (!tip_buffer)
                                goto fail;
-                       tipb_start_addr = (unsigned int *)tip_buffer;
-                       status = ext4fs_devread((*tigp_buffer) *
+                       tipb_start_addr = tip_buffer;
+                       status = ext4fs_devread((lbaint_t)le32_to_cpu(*tigp_buffer) *
                                                fs->sect_perblk, 0, fs->blksz,
                                                (char *)tip_buffer);
                        for (j = 0; j < fs->blksz / sizeof(int); j++) {
-                               if (*tip_buffer == 0)
+                               if (le32_to_cpu(*tip_buffer) == 0)
                                        break;
-                               if (fs->blksz != 1024) {
-                                       bg_idx = (*tip_buffer) / blk_per_grp;
-                               } else {
-                                       bg_idx = (*tip_buffer) / blk_per_grp;
-
-                                       remainder = (*tip_buffer) % blk_per_grp;
+                               bg_idx = le32_to_cpu(*tip_buffer) / blk_per_grp;
+                               if (fs->blksz == 1024) {
+                                       remainder = le32_to_cpu(*tip_buffer) % blk_per_grp;
                                        if (!remainder)
                                                bg_idx--;
                                }
 
-                               ext4fs_reset_block_bmap(*tip_buffer,
+                               ext4fs_reset_block_bmap(le32_to_cpu(*tip_buffer),
                                                        fs->blk_bmaps[bg_idx],
                                                        bg_idx);
 
                                tip_buffer++;
-                               bgd[bg_idx].free_blocks++;
-                               fs->sb->free_blocks++;
+                               ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+                               ext4fs_sb_free_blocks_inc(fs->sb);
                                /* journal backup */
                                if (prev_bg_bmap_idx != bg_idx) {
                                        status =
                                            ext4fs_devread(
-                                                       bgd[bg_idx].block_id *
+                                                       (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) *
                                                        fs->sect_perblk, 0,
                                                        fs->blksz,
                                                        journal_buffer);
@@ -333,8 +334,7 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                                                goto fail;
 
                                        if (ext4fs_log_journal(journal_buffer,
-                                                              bgd[bg_idx].
-                                                              block_id))
+                                                              le32_to_cpu(bgd[bg_idx].block_id)))
                                                goto fail;
                                        prev_bg_bmap_idx = bg_idx;
                                }
@@ -346,66 +346,63 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)
                         * removing the grand parent blocks
                         * which is connected to inode
                         */
-                       if (fs->blksz != 1024) {
-                               bg_idx = (*tigp_buffer) / blk_per_grp;
-                       } else {
-                               bg_idx = (*tigp_buffer) / blk_per_grp;
-
-                               remainder = (*tigp_buffer) % blk_per_grp;
+                       bg_idx = le32_to_cpu(*tigp_buffer) / blk_per_grp;
+                       if (fs->blksz == 1024) {
+                               remainder = le32_to_cpu(*tigp_buffer) % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
                        }
-                       ext4fs_reset_block_bmap(*tigp_buffer,
+                       ext4fs_reset_block_bmap(le32_to_cpu(*tigp_buffer),
                                                fs->blk_bmaps[bg_idx], bg_idx);
 
                        tigp_buffer++;
-                       bgd[bg_idx].free_blocks++;
-                       fs->sb->free_blocks++;
+                       ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+                       ext4fs_sb_free_blocks_inc(fs->sb);
                        /* journal backup */
                        if (prev_bg_bmap_idx != bg_idx) {
                                memset(journal_buffer, '\0', fs->blksz);
                                status =
-                                   ext4fs_devread(bgd[bg_idx].block_id *
+                                   ext4fs_devread(
+                                                  (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) *
                                                   fs->sect_perblk, 0,
                                                   fs->blksz, journal_buffer);
                                if (status == 0)
                                        goto fail;
 
                                if (ext4fs_log_journal(journal_buffer,
-                                                       bgd[bg_idx].block_id))
+                                                       le32_to_cpu(bgd[bg_idx].block_id)))
                                        goto fail;
                                prev_bg_bmap_idx = bg_idx;
                        }
                }
 
                /* removing the grand parent triple indirect block */
-               blknr = inode->b.blocks.triple_indir_block;
-               if (fs->blksz != 1024) {
-                       bg_idx = blknr / blk_per_grp;
-               } else {
-                       bg_idx = blknr / blk_per_grp;
+               blknr = le32_to_cpu(inode->b.blocks.triple_indir_block);
+               bg_idx = blknr / blk_per_grp;
+               if (fs->blksz == 1024) {
                        remainder = blknr % blk_per_grp;
                        if (!remainder)
                                bg_idx--;
                }
                ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
-               bgd[bg_idx].free_blocks++;
-               fs->sb->free_blocks++;
+               ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+               ext4fs_sb_free_blocks_inc(fs->sb);
                /* journal backup */
                if (prev_bg_bmap_idx != bg_idx) {
                        memset(journal_buffer, '\0', fs->blksz);
-                       status = ext4fs_devread(bgd[bg_idx].block_id *
+                       status = ext4fs_devread(
+                                               (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) *
                                                fs->sect_perblk, 0, fs->blksz,
                                                journal_buffer);
                        if (status == 0)
                                goto fail;
 
                        if (ext4fs_log_journal(journal_buffer,
-                                               bgd[bg_idx].block_id))
+                                               le32_to_cpu(bgd[bg_idx].block_id)))
                                goto fail;
                        prev_bg_bmap_idx = bg_idx;
                }
-               debug("tigp buffer itself releasing %ld\n", blknr);
+               debug("tigp buffer itself releasing %d\n", blknr);
        }
 fail:
        free(tib_start_addr);
@@ -424,14 +421,14 @@ static int ext4fs_delete_file(int inodeno)
        int ibmap_idx;
        char *read_buffer = NULL;
        char *start_block_address = NULL;
-       unsigned int no_blocks;
+       uint32_t no_blocks;
 
        static int prev_bg_bmap_idx = -1;
        unsigned int inodes_per_block;
-       long int blkno;
+       uint32_t blkno;
        unsigned int blkoff;
-       unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group;
-       unsigned int inode_per_grp = ext4fs_root->sblock.inodes_per_group;
+       uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
+       uint32_t inode_per_grp = le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
        struct ext2_inode *inode_buffer = NULL;
        struct ext2_block_group *bgd = NULL;
        struct ext_filesystem *fs = get_fs();
@@ -445,8 +442,8 @@ static int ext4fs_delete_file(int inodeno)
                goto fail;
 
        /* read the block no allocated to a file */
-       no_blocks = inode.size / fs->blksz;
-       if (inode.size % fs->blksz)
+       no_blocks = le32_to_cpu(inode.size) / fs->blksz;
+       if (le32_to_cpu(inode.size) % fs->blksz)
                no_blocks++;
 
        if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) {
@@ -461,10 +458,8 @@ static int ext4fs_delete_file(int inodeno)
 
                for (i = 0; i < no_blocks; i++) {
                        blknr = read_allocated_block(&(node_inode->inode), i);
-                       if (fs->blksz != 1024) {
-                               bg_idx = blknr / blk_per_grp;
-                       } else {
-                               bg_idx = blknr / blk_per_grp;
+                       bg_idx = blknr / blk_per_grp;
+                       if (fs->blksz == 1024) {
                                remainder = blknr % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
@@ -474,19 +469,20 @@ static int ext4fs_delete_file(int inodeno)
                        debug("EXT4_EXTENTS Block releasing %ld: %d\n",
                              blknr, bg_idx);
 
-                       bgd[bg_idx].free_blocks++;
-                       fs->sb->free_blocks++;
+                       ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+                       ext4fs_sb_free_blocks_inc(fs->sb);
 
                        /* journal backup */
                        if (prev_bg_bmap_idx != bg_idx) {
                                status =
-                                   ext4fs_devread(bgd[bg_idx].block_id *
+                                   ext4fs_devread(
+                                                  (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) *
                                                   fs->sect_perblk, 0,
                                                   fs->blksz, journal_buffer);
                                if (status == 0)
                                        goto fail;
                                if (ext4fs_log_journal(journal_buffer,
-                                                       bgd[bg_idx].block_id))
+                                                       le32_to_cpu(bgd[bg_idx].block_id)))
                                        goto fail;
                                prev_bg_bmap_idx = bg_idx;
                        }
@@ -502,15 +498,13 @@ static int ext4fs_delete_file(int inodeno)
                delete_triple_indirect_block(&inode);
 
                /* read the block no allocated to a file */
-               no_blocks = inode.size / fs->blksz;
-               if (inode.size % fs->blksz)
+               no_blocks = le32_to_cpu(inode.size) / fs->blksz;
+               if (le32_to_cpu(inode.size) % fs->blksz)
                        no_blocks++;
                for (i = 0; i < no_blocks; i++) {
                        blknr = read_allocated_block(&inode, i);
-                       if (fs->blksz != 1024) {
-                               bg_idx = blknr / blk_per_grp;
-                       } else {
-                               bg_idx = blknr / blk_per_grp;
+                       bg_idx = blknr / blk_per_grp;
+                       if (fs->blksz == 1024) {
                                remainder = blknr % blk_per_grp;
                                if (!remainder)
                                        bg_idx--;
@@ -519,19 +513,20 @@ static int ext4fs_delete_file(int inodeno)
                                                bg_idx);
                        debug("ActualB releasing %ld: %d\n", blknr, bg_idx);
 
-                       bgd[bg_idx].free_blocks++;
-                       fs->sb->free_blocks++;
+                       ext4fs_bg_free_blocks_inc(&bgd[bg_idx]);
+                       ext4fs_sb_free_blocks_inc(fs->sb);
                        /* journal backup */
                        if (prev_bg_bmap_idx != bg_idx) {
                                memset(journal_buffer, '\0', fs->blksz);
-                               status = ext4fs_devread(bgd[bg_idx].block_id
+                               status = ext4fs_devread(
+                                                       (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id)
                                                        * fs->sect_perblk,
                                                        0, fs->blksz,
                                                        journal_buffer);
                                if (status == 0)
                                        goto fail;
                                if (ext4fs_log_journal(journal_buffer,
-                                               bgd[bg_idx].block_id))
+                                               le32_to_cpu(bgd[bg_idx].block_id)))
                                        goto fail;
                                prev_bg_bmap_idx = bg_idx;
                        }
@@ -544,8 +539,8 @@ static int ext4fs_delete_file(int inodeno)
 
        /* get the block no */
        inodeno--;
-       blkno = __le32_to_cpu(bgd[ibmap_idx].inode_table_id) +
-               (inodeno % __le32_to_cpu(inode_per_grp)) / inodes_per_block;
+       blkno = le32_to_cpu(bgd[ibmap_idx].inode_table_id) +
+               (inodeno % inode_per_grp) / inodes_per_block;
 
        /* get the offset of the inode */
        blkoff = ((inodeno) % inodes_per_block) * fs->inodesz;
@@ -555,7 +550,7 @@ static int ext4fs_delete_file(int inodeno)
        if (!read_buffer)
                goto fail;
        start_block_address = read_buffer;
-       status = ext4fs_devread(blkno * fs->sect_perblk,
+       status = ext4fs_devread((lbaint_t)blkno * fs->sect_perblk,
                                0, fs->blksz, read_buffer);
        if (status == 0)
                goto fail;
@@ -574,19 +569,20 @@ static int ext4fs_delete_file(int inodeno)
        /* update the respective inode bitmaps */
        inodeno++;
        ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx);
-       bgd[ibmap_idx].free_inodes++;
-       fs->sb->free_inodes++;
+       ext4fs_bg_free_inodes_inc(&bgd[ibmap_idx]);
+       ext4fs_sb_free_inodes_inc(fs->sb);
        /* journal backup */
        memset(journal_buffer, '\0', fs->blksz);
-       status = ext4fs_devread(bgd[ibmap_idx].inode_id *
+       status = ext4fs_devread((lbaint_t)le32_to_cpu(bgd[ibmap_idx].inode_id) *
                                fs->sect_perblk, 0, fs->blksz, journal_buffer);
        if (status == 0)
                goto fail;
-       if (ext4fs_log_journal(journal_buffer, bgd[ibmap_idx].inode_id))
+       if (ext4fs_log_journal(journal_buffer, le32_to_cpu(bgd[ibmap_idx].inode_id)))
                goto fail;
 
        ext4fs_update();
        ext4fs_deinit();
+       ext4fs_reinit_global();
 
        if (ext4fs_init() != 0) {
                printf("error in File System init\n");
@@ -608,20 +604,18 @@ int ext4fs_init(void)
 {
        short status;
        int i;
-       unsigned int real_free_blocks = 0;
+       uint32_t real_free_blocks = 0;
        struct ext_filesystem *fs = get_fs();
 
        /* populate fs */
        fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root);
-       fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root);
-       fs->sect_perblk = fs->blksz / SECTOR_SIZE;
+       fs->sect_perblk = fs->blksz >> fs->dev_desc->log2blksz;
 
        /* get the superblock */
        fs->sb = zalloc(SUPERBLOCK_SIZE);
        if (!fs->sb)
                return -ENOMEM;
-       if (!ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE,
-                       (char *)fs->sb))
+       if (!ext4_read_superblock((char *)fs->sb))
                goto fail;
 
        /* init journal */
@@ -630,9 +624,9 @@ int ext4fs_init(void)
 
        /* get total no of blockgroups */
        fs->no_blkgrp = (uint32_t)ext4fs_div_roundup(
-                       (ext4fs_root->sblock.total_blocks -
-                       ext4fs_root->sblock.first_data_block),
-                       ext4fs_root->sblock.blocks_per_group);
+                       le32_to_cpu(ext4fs_root->sblock.total_blocks)
+                       - le32_to_cpu(ext4fs_root->sblock.first_data_block),
+                       le32_to_cpu(ext4fs_root->sblock.blocks_per_group));
 
        /* get the block group descriptor table */
        fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1);
@@ -654,7 +648,9 @@ int ext4fs_init(void)
 
        for (i = 0; i < fs->no_blkgrp; i++) {
                status =
-                   ext4fs_devread(fs->bgd[i].block_id * fs->sect_perblk, 0,
+                   ext4fs_devread(
+                                  (lbaint_t)le32_to_cpu(fs->bgd[i].block_id) *
+                                  fs->sect_perblk, 0,
                                   fs->blksz, (char *)fs->blk_bmaps[i]);
                if (status == 0)
                        goto fail;
@@ -671,7 +667,9 @@ int ext4fs_init(void)
        }
 
        for (i = 0; i < fs->no_blkgrp; i++) {
-               status = ext4fs_devread(fs->bgd[i].inode_id * fs->sect_perblk,
+               status = ext4fs_devread(
+                                       (lbaint_t)le32_to_cpu(fs->bgd[i].inode_id) *
+                                       fs->sect_perblk,
                                        0, fs->blksz,
                                        (char *)fs->inode_bmaps[i]);
                if (status == 0)
@@ -685,9 +683,9 @@ int ext4fs_init(void)
         * reboot of a linux kernel
         */
        for (i = 0; i < fs->no_blkgrp; i++)
-               real_free_blocks = real_free_blocks + fs->bgd[i].free_blocks;
-       if (real_free_blocks != fs->sb->free_blocks)
-               fs->sb->free_blocks = real_free_blocks;
+               real_free_blocks = real_free_blocks + le16_to_cpu(fs->bgd[i].free_blocks);
+       if (real_free_blocks != le32_to_cpu(fs->sb->free_blocks))
+               fs->sb->free_blocks = cpu_to_le32(real_free_blocks);
 
        return 0;
 fail:
@@ -701,8 +699,9 @@ void ext4fs_deinit(void)
        int i;
        struct ext2_inode inode_journal;
        struct journal_superblock_t *jsb;
-       long int blknr;
+       uint32_t blknr;
        struct ext_filesystem *fs = get_fs();
+       uint32_t new_feature_incompat;
 
        /* free journal */
        char *temp_buff = zalloc(fs->blksz);
@@ -711,19 +710,21 @@ void ext4fs_deinit(void)
                                  &inode_journal);
                blknr = read_allocated_block(&inode_journal,
                                        EXT2_JOURNAL_SUPERBLOCK);
-               ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
+               ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
                               temp_buff);
                jsb = (struct journal_superblock_t *)temp_buff;
-               jsb->s_start = cpu_to_be32(0);
-               put_ext4((uint64_t) (blknr * fs->blksz),
+               jsb->s_start = 0;
+               put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
                         (struct journal_superblock_t *)temp_buff, fs->blksz);
                free(temp_buff);
        }
        ext4fs_free_journal();
 
        /* get the superblock */
-       ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, (char *)fs->sb);
-       fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+       ext4_read_superblock((char *)fs->sb);
+       new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
+       new_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+       fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
        put_ext4((uint64_t)(SUPERBLOCK_SIZE),
                 (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE);
        free(fs->sb);
@@ -766,9 +767,10 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
 {
        int i;
        int blockcnt;
-       int log2blocksize = LOG2_EXT2_BLOCK_SIZE(ext4fs_root);
-       unsigned int filesize = __le32_to_cpu(file_inode->size);
+       uint32_t filesize = le32_to_cpu(file_inode->size);
        struct ext_filesystem *fs = get_fs();
+       int log2blksz = fs->dev_desc->log2blksz;
+       int log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_root) - log2blksz;
        int previous_block_number = -1;
        int delayed_start = 0;
        int delayed_extent = 0;
@@ -789,16 +791,16 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
                if (blknr < 0)
                        return -1;
 
-               blknr = blknr << log2blocksize;
+               blknr = blknr << log2_fs_blocksize;
 
                if (blknr) {
                        if (previous_block_number != -1) {
                                if (delayed_next == blknr) {
                                        delayed_extent += blockend;
-                                       delayed_next += blockend >> SECTOR_BITS;
+                                       delayed_next += blockend >> log2blksz;
                                } else {        /* spill */
-                                       put_ext4((uint64_t) (delayed_start *
-                                                            SECTOR_SIZE),
+                                       put_ext4((uint64_t)
+                                                ((uint64_t)delayed_start << log2blksz),
                                                 delayed_buf,
                                                 (uint32_t) delayed_extent);
                                        previous_block_number = blknr;
@@ -806,7 +808,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
                                        delayed_extent = blockend;
                                        delayed_buf = buf;
                                        delayed_next = blknr +
-                                           (blockend >> SECTOR_BITS);
+                                           (blockend >> log2blksz);
                                }
                        } else {
                                previous_block_number = blknr;
@@ -814,13 +816,14 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
                                delayed_extent = blockend;
                                delayed_buf = buf;
                                delayed_next = blknr +
-                                   (blockend >> SECTOR_BITS);
+                                   (blockend >> log2blksz);
                        }
                } else {
                        if (previous_block_number != -1) {
                                /* spill */
-                               put_ext4((uint64_t) (delayed_start *
-                                                    SECTOR_SIZE), delayed_buf,
+                               put_ext4((uint64_t) ((uint64_t)delayed_start <<
+                                                    log2blksz),
+                                        delayed_buf,
                                         (uint32_t) delayed_extent);
                                previous_block_number = -1;
                        }
@@ -830,7 +833,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
        }
        if (previous_block_number != -1) {
                /* spill */
-               put_ext4((uint64_t) (delayed_start * SECTOR_SIZE),
+               put_ext4((uint64_t) ((uint64_t)delayed_start << log2blksz),
                         delayed_buf, (uint32_t) delayed_extent);
                previous_block_number = -1;
        }
@@ -861,7 +864,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
        unsigned int ibmap_idx;
        struct ext_filesystem *fs = get_fs();
        ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
-       memset(filename, 0x00, sizeof(filename));
+       memset(filename, 0x00, 256);
 
        g_parent_inode = zalloc(sizeof(struct ext2_inode));
        if (!g_parent_inode)
@@ -877,8 +880,13 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
                goto fail;
        if (ext4fs_iget(parent_inodeno, g_parent_inode))
                goto fail;
+       /* do not mess up a directory using hash trees */
+       if (le32_to_cpu(g_parent_inode->flags) & EXT4_INDEX_FL) {
+               printf("hash tree directory\n");
+               goto fail;
+       }
        /* check if the filename is already present in root */
-       existing_file_inodeno = ext4fs_filename_check(filename);
+       existing_file_inodeno = ext4fs_filename_unlink(filename);
        if (existing_file_inodeno != -1) {
                ret = ext4fs_delete_file(existing_file_inodeno);
                fs->first_pass_bbmap = 0;
@@ -898,41 +906,45 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
        }
        blocks_remaining = blks_reqd_for_file;
        /* test for available space in partition */
-       if (fs->sb->free_blocks < blks_reqd_for_file) {
+       if (le32_to_cpu(fs->sb->free_blocks) < blks_reqd_for_file) {
                printf("Not enough space on partition !!!\n");
                goto fail;
        }
 
-       ext4fs_update_parent_dentry(filename, &inodeno, FILETYPE_REG);
+       inodeno = ext4fs_update_parent_dentry(filename, FILETYPE_REG);
+       if (inodeno == -1)
+               goto fail;
        /* prepare file inode */
        inode_buffer = zalloc(fs->inodesz);
        if (!inode_buffer)
                goto fail;
        file_inode = (struct ext2_inode *)inode_buffer;
-       file_inode->mode = S_IFREG | S_IRWXU |
-           S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH;
+       file_inode->mode = cpu_to_le16(S_IFREG | S_IRWXU |
+           S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH);
        /* ToDo: Update correct time */
-       file_inode->mtime = timestamp;
-       file_inode->atime = timestamp;
-       file_inode->ctime = timestamp;
-       file_inode->nlinks = 1;
-       file_inode->size = sizebytes;
+       file_inode->mtime = cpu_to_le32(timestamp);
+       file_inode->atime = cpu_to_le32(timestamp);
+       file_inode->ctime = cpu_to_le32(timestamp);
+       file_inode->nlinks = cpu_to_le16(1);
+       file_inode->size = cpu_to_le32(sizebytes);
 
        /* Allocate data blocks */
        ext4fs_allocate_blocks(file_inode, blocks_remaining,
                               &blks_reqd_for_file);
-       file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) / SECTOR_SIZE;
+       file_inode->blockcnt = cpu_to_le32((blks_reqd_for_file * fs->blksz) >>
+               fs->dev_desc->log2blksz);
 
        temp_ptr = zalloc(fs->blksz);
        if (!temp_ptr)
                goto fail;
-       ibmap_idx = inodeno / ext4fs_root->sblock.inodes_per_group;
+       ibmap_idx = inodeno / le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
        inodeno--;
-       itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
-                       (inodeno % __le32_to_cpu(sblock->inodes_per_group)) /
+       itable_blkno = le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
+                       (inodeno % le32_to_cpu(sblock->inodes_per_group)) /
                        inodes_per_block;
        blkoff = (inodeno % inodes_per_block) * fs->inodesz;
-       ext4fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr);
+       ext4fs_devread((lbaint_t)itable_blkno * fs->sect_perblk, 0, fs->blksz,
+                      temp_ptr);
        if (ext4fs_log_journal(temp_ptr, itable_blkno))
                goto fail;
 
@@ -944,15 +956,15 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
                printf("Error in copying content\n");
                goto fail;
        }
-       ibmap_idx = parent_inodeno / ext4fs_root->sblock.inodes_per_group;
+       ibmap_idx = parent_inodeno / le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
        parent_inodeno--;
-       parent_itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
+       parent_itable_blkno = le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) +
            (parent_inodeno %
-            __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
+            le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
        blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz;
        if (parent_itable_blkno != itable_blkno) {
                memset(temp_ptr, '\0', fs->blksz);
-               ext4fs_devread(parent_itable_blkno * fs->sect_perblk,
+               ext4fs_devread((lbaint_t)parent_itable_blkno * fs->sect_perblk,
                               0, fs->blksz, temp_ptr);
                if (ext4fs_log_journal(temp_ptr, parent_itable_blkno))
                        goto fail;
@@ -961,7 +973,6 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
                        sizeof(struct ext2_inode));
                if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno))
                        goto fail;
-               free(temp_ptr);
        } else {
                /*
                 * If parent and child fall in same inode table block
@@ -972,7 +983,6 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
                gd_index--;
                if (ext4fs_put_metadata(temp_ptr, itable_blkno))
                        goto fail;
-               free(temp_ptr);
        }
        ext4fs_update();
        ext4fs_deinit();
@@ -983,6 +993,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
        fs->curr_inode_no = 0;
        free(inode_buffer);
        free(g_parent_inode);
+       free(temp_ptr);
        g_parent_inode = NULL;
 
        return 0;
@@ -990,7 +1001,34 @@ fail:
        ext4fs_deinit();
        free(inode_buffer);
        free(g_parent_inode);
+       free(temp_ptr);
        g_parent_inode = NULL;
 
        return -1;
 }
+
+int ext4_write_file(const char *filename, void *buf, loff_t offset,
+                   loff_t len, loff_t *actwrite)
+{
+       int ret;
+
+       if (offset != 0) {
+               printf("** Cannot support non-zero offset **\n");
+               return -1;
+       }
+
+       ret = ext4fs_write(filename, buf, len);
+       if (ret) {
+               printf("** Error ext4fs_write() **\n");
+               goto fail;
+       }
+
+       *actwrite = len;
+
+       return 0;
+
+fail:
+       *actwrite = 0;
+
+       return -1;
+}