[U-Boot] [PATCH v2 0/5] ext4: endianess fixes

From: Michael Walle michael.walle@kontron.com
This patch series fixes write support on big-endianness architectures.
Changes: v2: - instead of INC_X/DEC_X macros, use inline functions per structure field. Suggested by Stefan Brüns. (patch 0003) - optimize "while (dir->direntlen)" loops. Suggested by Stefan Brüns (patch 0005)
Michael Walle (5): ext4: change structure fields to __le/__be types ext4: use kernel names for byte swaps ext4: fix endianess problems in ext4 write support ext4: fix wrong usage of le32_to_cpu() ext4: optimize direntlen loops
fs/ext4/ext4_common.c | 367 ++++++++++++++++++++++++++----------------------- fs/ext4/ext4_common.h | 4 +- fs/ext4/ext4_journal.c | 15 +- fs/ext4/ext4_journal.h | 44 +++--- fs/ext4/ext4_write.c | 222 +++++++++++++++++------------- fs/ext4/ext4fs.c | 2 +- include/ext_common.h | 140 +++++++++---------- 7 files changed, 425 insertions(+), 369 deletions(-)

Change all the types of ext2/4 fields to little endian types and all the JBD fields to big endian types. Now we can use sparse (make C=1) to check for statements where we need byteswaps.
Signed-off-by: Michael Walle michael@walle.cc --- fs/ext4/ext4_journal.h | 40 +++++++-------- include/ext_common.h | 136 ++++++++++++++++++++++++------------------------- 2 files changed, 88 insertions(+), 88 deletions(-)
diff --git a/fs/ext4/ext4_journal.h b/fs/ext4/ext4_journal.h index d926094..d54165c 100644 --- a/fs/ext4/ext4_journal.h +++ b/fs/ext4/ext4_journal.h @@ -49,9 +49,9 @@ struct dirty_blocks {
/* Standard header for all descriptor blocks: */ struct journal_header_t { - __u32 h_magic; - __u32 h_blocktype; - __u32 h_sequence; + __be32 h_magic; + __be32 h_blocktype; + __be32 h_sequence; };
/* The journal superblock. All fields are in big-endian byte order. */ @@ -60,35 +60,35 @@ struct journal_superblock_t { struct journal_header_t s_header;
/* Static information describing the journal */ - __u32 s_blocksize; /* journal device blocksize */ - __u32 s_maxlen; /* total blocks in journal file */ - __u32 s_first; /* first block of log information */ + __be32 s_blocksize; /* journal device blocksize */ + __be32 s_maxlen; /* total blocks in journal file */ + __be32 s_first; /* first block of log information */
/* Dynamic information describing the current state of the log */ - __u32 s_sequence; /* first commit ID expected in log */ - __u32 s_start; /* blocknr of start of log */ + __be32 s_sequence; /* first commit ID expected in log */ + __be32 s_start; /* blocknr of start of log */
/* Error value, as set by journal_abort(). */ - __s32 s_errno; + __be32 s_errno;
/* Remaining fields are only valid in a version-2 superblock */ - __u32 s_feature_compat; /* compatible feature set */ - __u32 s_feature_incompat; /* incompatible feature set */ - __u32 s_feature_ro_compat; /* readonly-compatible feature set */ + __be32 s_feature_compat; /* compatible feature set */ + __be32 s_feature_incompat; /* incompatible feature set */ + __be32 s_feature_ro_compat; /* readonly-compatible feature set */ /* 0x0030 */ __u8 s_uuid[16]; /* 128-bit uuid for journal */
/* 0x0040 */ - __u32 s_nr_users; /* Nr of filesystems sharing log */ + __be32 s_nr_users; /* Nr of filesystems sharing log */
- __u32 s_dynsuper; /* Blocknr of dynamic superblock copy */ + __be32 s_dynsuper; /* Blocknr of dynamic superblock copy */
/* 0x0048 */ - __u32 s_max_transaction; /* Limit of journal blocks per trans. */ - __u32 s_max_trans_data; /* Limit of data blocks per trans. */ + __be32 s_max_transaction; /* Limit of journal blocks per trans. */ + __be32 s_max_trans_data; /* Limit of data blocks per trans. */
/* 0x0050 */ - __u32 s_padding[44]; + __be32 s_padding[44];
/* 0x0100 */ __u8 s_users[16 * 48]; /* ids of all fs'es sharing the log */ @@ -96,13 +96,13 @@ struct journal_superblock_t { } ;
struct ext3_journal_block_tag { - uint32_t block; - uint32_t flags; + __be32 block; + __be32 flags; };
struct journal_revoke_header_t { struct journal_header_t r_header; - int r_count; /* Count of bytes used in the block */ + __be32 r_count; /* Count of bytes used in the block */ };
struct revoke_blk_list { diff --git a/include/ext_common.h b/include/ext_common.h index 6cddf16..c12e526 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -66,92 +66,92 @@
/* The ext2 superblock. */ struct ext2_sblock { - uint32_t total_inodes; - uint32_t total_blocks; - uint32_t reserved_blocks; - uint32_t free_blocks; - uint32_t free_inodes; - uint32_t first_data_block; - uint32_t log2_block_size; - uint32_t log2_fragment_size; - uint32_t blocks_per_group; - uint32_t fragments_per_group; - uint32_t inodes_per_group; - uint32_t mtime; - uint32_t utime; - uint16_t mnt_count; - uint16_t max_mnt_count; - uint16_t magic; - uint16_t fs_state; - uint16_t error_handling; - uint16_t minor_revision_level; - uint32_t lastcheck; - uint32_t checkinterval; - uint32_t creator_os; - uint32_t revision_level; - uint16_t uid_reserved; - uint16_t gid_reserved; - uint32_t first_inode; - uint16_t inode_size; - uint16_t block_group_number; - uint32_t feature_compatibility; - uint32_t feature_incompat; - uint32_t feature_ro_compat; - uint32_t unique_id[4]; + __le32 total_inodes; + __le32 total_blocks; + __le32 reserved_blocks; + __le32 free_blocks; + __le32 free_inodes; + __le32 first_data_block; + __le32 log2_block_size; + __le32 log2_fragment_size; + __le32 blocks_per_group; + __le32 fragments_per_group; + __le32 inodes_per_group; + __le32 mtime; + __le32 utime; + __le16 mnt_count; + __le16 max_mnt_count; + __le16 magic; + __le16 fs_state; + __le16 error_handling; + __le16 minor_revision_level; + __le32 lastcheck; + __le32 checkinterval; + __le32 creator_os; + __le32 revision_level; + __le16 uid_reserved; + __le16 gid_reserved; + __le32 first_inode; + __le16 inode_size; + __le16 block_group_number; + __le32 feature_compatibility; + __le32 feature_incompat; + __le32 feature_ro_compat; + __le32 unique_id[4]; char volume_name[16]; char last_mounted_on[64]; - uint32_t compression_info; + __le32 compression_info; };
struct ext2_block_group { - __u32 block_id; /* Blocks bitmap block */ - __u32 inode_id; /* Inodes bitmap block */ - __u32 inode_table_id; /* Inodes table block */ - __u16 free_blocks; /* Free blocks count */ - __u16 free_inodes; /* Free inodes count */ - __u16 used_dir_cnt; /* Directories count */ - __u16 bg_flags; - __u32 bg_reserved[2]; - __u16 bg_itable_unused; /* Unused inodes count */ - __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/ + __le32 block_id; /* Blocks bitmap block */ + __le32 inode_id; /* Inodes bitmap block */ + __le32 inode_table_id; /* Inodes table block */ + __le16 free_blocks; /* Free blocks count */ + __le16 free_inodes; /* Free inodes count */ + __le16 used_dir_cnt; /* Directories count */ + __le16 bg_flags; + __le32 bg_reserved[2]; + __le16 bg_itable_unused; /* Unused inodes count */ + __le16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/ };
/* The ext2 inode. */ struct ext2_inode { - uint16_t mode; - uint16_t uid; - uint32_t size; - uint32_t atime; - uint32_t ctime; - uint32_t mtime; - uint32_t dtime; - uint16_t gid; - uint16_t nlinks; - uint32_t blockcnt; /* Blocks of 512 bytes!! */ - uint32_t flags; - uint32_t osd1; + __le16 mode; + __le16 uid; + __le32 size; + __le32 atime; + __le32 ctime; + __le32 mtime; + __le32 dtime; + __le16 gid; + __le16 nlinks; + __le32 blockcnt; /* Blocks of 512 bytes!! */ + __le32 flags; + __le32 osd1; union { struct datablocks { - uint32_t dir_blocks[INDIRECT_BLOCKS]; - uint32_t indir_block; - uint32_t double_indir_block; - uint32_t triple_indir_block; + __le32 dir_blocks[INDIRECT_BLOCKS]; + __le32 indir_block; + __le32 double_indir_block; + __le32 triple_indir_block; } blocks; char symlink[60]; } b; - uint32_t version; - uint32_t acl; - uint32_t dir_acl; - uint32_t fragment_addr; - uint32_t osd2[3]; + __le32 version; + __le32 acl; + __le32 dir_acl; + __le32 fragment_addr; + __le32 osd2[3]; };
/* The header of an ext2 directory entry. */ struct ext2_dirent { - uint32_t inode; - uint16_t direntlen; - uint8_t namelen; - uint8_t filetype; + __le32 inode; + __le16 direntlen; + __u8 namelen; + __u8 filetype; };
struct ext2fs_node {

Instead of __{be,le}{16,32}_to_cpu use {be,le}{16,32}_to_cpu.
Signed-off-by: Michael Walle michael@walle.cc --- fs/ext4/ext4_common.c | 90 +++++++++++++++++++++++++-------------------------- fs/ext4/ext4_write.c | 14 ++++---- fs/ext4/ext4fs.c | 2 +- include/ext_common.h | 4 +-- 4 files changed, 55 insertions(+), 55 deletions(-)
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index eb49fce..e8ed30a 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -1454,7 +1454,7 @@ static int ext4fs_blockgroup
desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
- blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 + + blkno = le32_to_cpu(data->sblock.first_data_block) + 1 + group / desc_per_blk; blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
@@ -1479,14 +1479,14 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
/* It is easier to calculate if the first inode is 0. */ ino--; - status = ext4fs_blockgroup(data, ino / __le32_to_cpu + status = ext4fs_blockgroup(data, ino / le32_to_cpu (sblock->inodes_per_group), &blkgrp); if (status == 0) return 0;
inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz; - blkno = __le32_to_cpu(blkgrp.inode_table_id) + - (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; + blkno = le32_to_cpu(blkgrp.inode_table_id) + + (ino % le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; blkoff = (ino % inodes_per_block) * fs->inodesz; /* Read the inode. */ status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) - @@ -1559,7 +1559,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock)
/* Direct blocks. */ if (fileblock < INDIRECT_BLOCKS) - blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]); + blknr = le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
/* Indirect. */ else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) { @@ -1586,10 +1586,10 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) } ext4fs_indir1_size = blksz; } - if ((__le32_to_cpu(inode->b.blocks.indir_block) << + if ((le32_to_cpu(inode->b.blocks.indir_block) << log2_blksz) != ext4fs_indir1_blkno) { status = - ext4fs_devread((lbaint_t)__le32_to_cpu + ext4fs_devread((lbaint_t)le32_to_cpu (inode->b.blocks. indir_block) << log2_blksz, 0, blksz, (char *)ext4fs_indir1_block); @@ -1599,10 +1599,10 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) return 0; } ext4fs_indir1_blkno = - __le32_to_cpu(inode->b.blocks. + le32_to_cpu(inode->b.blocks. indir_block) << log2_blksz; } - blknr = __le32_to_cpu(ext4fs_indir1_block + blknr = le32_to_cpu(ext4fs_indir1_block [fileblock - INDIRECT_BLOCKS]); } /* Double indirect. */ @@ -1635,10 +1635,10 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) } ext4fs_indir1_size = blksz; } - if ((__le32_to_cpu(inode->b.blocks.double_indir_block) << + if ((le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz) != ext4fs_indir1_blkno) { status = - ext4fs_devread((lbaint_t)__le32_to_cpu + ext4fs_devread((lbaint_t)le32_to_cpu (inode->b.blocks. double_indir_block) << log2_blksz, 0, blksz, @@ -1649,7 +1649,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) return -1; } ext4fs_indir1_blkno = - __le32_to_cpu(inode->b.blocks.double_indir_block) << + le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz; }
@@ -1676,9 +1676,9 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) } ext4fs_indir2_size = blksz; } - if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << + if ((le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << log2_blksz) != ext4fs_indir2_blkno) { - status = ext4fs_devread((lbaint_t)__le32_to_cpu + status = ext4fs_devread((lbaint_t)le32_to_cpu (ext4fs_indir1_block [rblock / perblock]) << log2_blksz, 0, @@ -1690,12 +1690,12 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) return -1; } ext4fs_indir2_blkno = - __le32_to_cpu(ext4fs_indir1_block[rblock + le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << log2_blksz; } - blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]); + blknr = le32_to_cpu(ext4fs_indir2_block[rblock % perblock]); } /* Tripple indirect. */ else { @@ -1727,11 +1727,11 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) } ext4fs_indir1_size = blksz; } - if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) << + if ((le32_to_cpu(inode->b.blocks.triple_indir_block) << log2_blksz) != ext4fs_indir1_blkno) { status = ext4fs_devread ((lbaint_t) - __le32_to_cpu(inode->b.blocks.triple_indir_block) + le32_to_cpu(inode->b.blocks.triple_indir_block) << log2_blksz, 0, blksz, (char *)ext4fs_indir1_block); if (status == 0) { @@ -1740,7 +1740,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) return -1; } ext4fs_indir1_blkno = - __le32_to_cpu(inode->b.blocks.triple_indir_block) << + le32_to_cpu(inode->b.blocks.triple_indir_block) << log2_blksz; }
@@ -1767,11 +1767,11 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) } ext4fs_indir2_size = blksz; } - if ((__le32_to_cpu(ext4fs_indir1_block[rblock / + if ((le32_to_cpu(ext4fs_indir1_block[rblock / perblock_parent]) << log2_blksz) != ext4fs_indir2_blkno) { - status = ext4fs_devread((lbaint_t)__le32_to_cpu + status = ext4fs_devread((lbaint_t)le32_to_cpu (ext4fs_indir1_block [rblock / perblock_parent]) << @@ -1783,7 +1783,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) return -1; } ext4fs_indir2_blkno = - __le32_to_cpu(ext4fs_indir1_block[rblock / + le32_to_cpu(ext4fs_indir1_block[rblock / perblock_parent]) << log2_blksz; } @@ -1811,12 +1811,12 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) } ext4fs_indir3_size = blksz; } - if ((__le32_to_cpu(ext4fs_indir2_block[rblock + if ((le32_to_cpu(ext4fs_indir2_block[rblock / perblock_child]) << log2_blksz) != ext4fs_indir3_blkno) { status = - ext4fs_devread((lbaint_t)__le32_to_cpu + ext4fs_devread((lbaint_t)le32_to_cpu (ext4fs_indir2_block [(rblock / perblock_child) % (blksz / 4)]) << log2_blksz, 0, @@ -1827,14 +1827,14 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) return -1; } ext4fs_indir3_blkno = - __le32_to_cpu(ext4fs_indir2_block[(rblock / + le32_to_cpu(ext4fs_indir2_block[(rblock / perblock_child) % (blksz / 4)]) << log2_blksz; }
- blknr = __le32_to_cpu(ext4fs_indir3_block + blknr = le32_to_cpu(ext4fs_indir3_block [rblock % perblock_child]); } debug("read_allocated_block %ld\n", blknr); @@ -1907,7 +1907,7 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, return 0; } /* Search the file. */ - while (fpos < __le32_to_cpu(diro->inode.size)) { + while (fpos < le32_to_cpu(diro->inode.size)) { struct ext2_dirent dirent;
status = ext4fs_read_file(diro, fpos, @@ -1939,7 +1939,7 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, return 0;
fdiro->data = diro->data; - fdiro->ino = __le32_to_cpu(dirent.inode); + fdiro->ino = le32_to_cpu(dirent.inode);
filename[dirent.namelen] = '\0';
@@ -1954,7 +1954,7 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, type = FILETYPE_REG; } else { status = ext4fs_read_inode(diro->data, - __le32_to_cpu + le32_to_cpu (dirent.inode), &fdiro->inode); if (status == 0) { @@ -1963,15 +1963,15 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, } fdiro->inode_read = 1;
- if ((__le16_to_cpu(fdiro->inode.mode) & + if ((le16_to_cpu(fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY) { type = FILETYPE_DIRECTORY; - } else if ((__le16_to_cpu(fdiro->inode.mode) + } else if ((le16_to_cpu(fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK) { type = FILETYPE_SYMLINK; - } else if ((__le16_to_cpu(fdiro->inode.mode) + } else if ((le16_to_cpu(fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_REG) { type = FILETYPE_REG; @@ -1990,7 +1990,7 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, } else { if (fdiro->inode_read == 0) { status = ext4fs_read_inode(diro->data, - __le32_to_cpu( + le32_to_cpu( dirent.inode), &fdiro->inode); if (status == 0) { @@ -2014,12 +2014,12 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, break; } printf("%10u %s\n", - __le32_to_cpu(fdiro->inode.size), + le32_to_cpu(fdiro->inode.size), filename); } free(fdiro); } - fpos += __le16_to_cpu(dirent.direntlen); + fpos += le16_to_cpu(dirent.direntlen); } return 0; } @@ -2036,23 +2036,23 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node) if (status == 0) return 0; } - symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1); + symlink = zalloc(le32_to_cpu(diro->inode.size) + 1); if (!symlink) return 0;
- if (__le32_to_cpu(diro->inode.size) < sizeof(diro->inode.b.symlink)) { + if (le32_to_cpu(diro->inode.size) < sizeof(diro->inode.b.symlink)) { strncpy(symlink, diro->inode.b.symlink, - __le32_to_cpu(diro->inode.size)); + le32_to_cpu(diro->inode.size)); } else { status = ext4fs_read_file(diro, 0, - __le32_to_cpu(diro->inode.size), + le32_to_cpu(diro->inode.size), symlink, &actread); if ((status < 0) || (actread == 0)) { free(symlink); return 0; } } - symlink[__le32_to_cpu(diro->inode.size)] = '\0'; + symlink[le32_to_cpu(diro->inode.size)] = '\0'; return symlink; }
@@ -2200,7 +2200,7 @@ int ext4fs_open(const char *filename, loff_t *len) if (status == 0) goto fail; } - *len = __le32_to_cpu(fdiro->inode.size); + *len = le32_to_cpu(fdiro->inode.size); ext4fs_file = fdiro;
return 0; @@ -2226,7 +2226,7 @@ int ext4fs_mount(unsigned part_length) goto fail;
/* Make sure this is an ext2 filesystem. */ - if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC) + if (le16_to_cpu(data->sblock.magic) != EXT2_MAGIC) goto fail;
/* @@ -2239,13 +2239,13 @@ int ext4fs_mount(unsigned part_length) goto fail; }
- if (__le32_to_cpu(data->sblock.revision_level == 0)) + if (le32_to_cpu(data->sblock.revision_level == 0)) fs->inodesz = 128; else - fs->inodesz = __le16_to_cpu(data->sblock.inode_size); + fs->inodesz = le16_to_cpu(data->sblock.inode_size);
debug("EXT2 rev %d, inode_size %d\n", - __le32_to_cpu(data->sblock.revision_level), fs->inodesz); + le32_to_cpu(data->sblock.revision_level), fs->inodesz);
data->diropen.data = data; data->diropen.ino = 2; diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index e027916..1169ee3 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -520,8 +520,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 % le32_to_cpu(inode_per_grp)) / inodes_per_block;
/* get the offset of the inode */ blkoff = ((inodeno) % inodes_per_block) * fs->inodesz; @@ -744,7 +744,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode, { int i; int blockcnt; - unsigned int filesize = __le32_to_cpu(file_inode->size); + unsigned int 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; @@ -909,8 +909,8 @@ int ext4fs_write(const char *fname, unsigned char *buffer, goto fail; ibmap_idx = inodeno / 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((lbaint_t)itable_blkno * fs->sect_perblk, 0, fs->blksz, @@ -928,9 +928,9 @@ int ext4fs_write(const char *fname, unsigned char *buffer, } ibmap_idx = parent_inodeno / 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); diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index 43c8897..3078737 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -55,7 +55,7 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, int log2blksz = fs->dev_desc->log2blksz; int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz; int blocksize = (1 << (log2_fs_blocksize + log2blksz)); - unsigned int filesize = __le32_to_cpu(node->inode.size); + unsigned int filesize = le32_to_cpu(node->inode.size); lbaint_t previous_block_number = -1; lbaint_t delayed_start = 0; lbaint_t delayed_extent = 0; diff --git a/include/ext_common.h b/include/ext_common.h index c12e526..3220091 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -49,10 +49,10 @@ #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
/* Log2 size of ext2 block in bytes. */ -#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \ +#define LOG2_BLOCK_SIZE(data) (le32_to_cpu \ (data->sblock.log2_block_size) \ + EXT2_MIN_BLOCK_LOG_SIZE) -#define INODE_SIZE_FILESYSTEM(data) (__le32_to_cpu \ +#define INODE_SIZE_FILESYSTEM(data) (le32_to_cpu \ (data->sblock.inode_size))
#define EXT2_FT_DIR 2

All fields were accessed directly instead of using the proper byte swap functions. Thus, ext4 write support was only usable on little-endian architectures. Fix this.
Signed-off-by: Michael Walle michael@walle.cc Reviewed-by: Stefan Brüns stefan.bruens@rwth-aachen.de Tested-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- fs/ext4/ext4_common.c | 277 +++++++++++++++++++++++++++---------------------- fs/ext4/ext4_common.h | 4 +- fs/ext4/ext4_journal.c | 15 +-- fs/ext4/ext4_journal.h | 4 +- fs/ext4/ext4_write.c | 212 ++++++++++++++++++++----------------- include/ext_common.h | 2 +- 6 files changed, 285 insertions(+), 229 deletions(-)
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index e8ed30a..567350f 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -33,20 +33,40 @@
struct ext2_data *ext4fs_root; struct ext2fs_node *ext4fs_file; -uint32_t *ext4fs_indir1_block; +__le32 *ext4fs_indir1_block; int ext4fs_indir1_size; int ext4fs_indir1_blkno = -1; -uint32_t *ext4fs_indir2_block; +__le32 *ext4fs_indir2_block; int ext4fs_indir2_size; int ext4fs_indir2_blkno = -1;
-uint32_t *ext4fs_indir3_block; +__le32 *ext4fs_indir3_block; int ext4fs_indir3_size; int ext4fs_indir3_blkno = -1; struct ext2_inode *g_parent_inode; static int symlinknest;
#if defined(CONFIG_EXT4_WRITE) +static inline void ext4fs_sb_free_inodes_dec(struct ext2_sblock *sb) +{ + sb->free_inodes = cpu_to_le32(le32_to_cpu(sb->free_inodes) - 1); +} + +static inline void ext4fs_bg_free_inodes_dec(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_dec(struct ext2_block_group *bg) +{ + bg->free_blocks = cpu_to_le16(le16_to_cpu(bg->free_blocks) - 1); +} + +static inline void ext4fs_bg_itable_unused_dec(struct ext2_block_group *bg) +{ + bg->bg_itable_unused = cpu_to_le16(le16_to_cpu(bg->bg_itable_unused) - 1); +} + uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n) { uint32_t res = size / n; @@ -112,7 +132,7 @@ static int _get_new_inode_no(unsigned char *buffer) while (*ptr == 255) { ptr++; count += 8; - if (count > ext4fs_root->sblock.inodes_per_group) + if (count > le32_to_cpu(ext4fs_root->sblock.inodes_per_group)) return -1; }
@@ -249,7 +269,7 @@ int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index) unsigned char *ptr = buffer; unsigned char operand;
- inode_no -= (index * ext4fs_root->sblock.inodes_per_group); + inode_no -= (index * le32_to_cpu(ext4fs_root->sblock.inodes_per_group)); i = inode_no / 8; remainder = inode_no % 8; if (remainder == 0) { @@ -274,7 +294,7 @@ void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index) unsigned char *ptr = buffer; unsigned char operand;
- inode_no -= (index * ext4fs_root->sblock.inodes_per_group); + inode_no -= (index * le32_to_cpu(ext4fs_root->sblock.inodes_per_group)); i = inode_no / 8; remainder = inode_no % 8; if (remainder == 0) { @@ -289,19 +309,20 @@ void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index) *ptr = *ptr & ~(operand); }
-int ext4fs_checksum_update(unsigned int i) +uint16_t ext4fs_checksum_update(uint32_t i) { struct ext2_block_group *desc; struct ext_filesystem *fs = get_fs(); - __u16 crc = 0; + uint16_t crc = 0; + __le32 le32_i = cpu_to_le32(i);
desc = (struct ext2_block_group *)&fs->bgd[i]; - if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { + if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { int offset = offsetof(struct ext2_block_group, bg_checksum);
crc = ext2fs_crc16(~0, fs->sb->unique_id, sizeof(fs->sb->unique_id)); - crc = ext2fs_crc16(crc, &i, sizeof(i)); + crc = ext2fs_crc16(crc, &le32_i, sizeof(le32_i)); crc = ext2fs_crc16(crc, desc, offset); offset += sizeof(desc->bg_checksum); /* skip checksum */ assert(offset == sizeof(*desc)); @@ -322,7 +343,7 @@ static int check_void_in_dentry(struct ext2_dirent *dir, char *filename)
dentry_length = sizeof(struct ext2_dirent) + dir->namelen + padding_factor; - sizeof_void_space = dir->direntlen - dentry_length; + sizeof_void_space = le16_to_cpu(dir->direntlen) - dentry_length; if (sizeof_void_space == 0) return 0;
@@ -333,7 +354,7 @@ static int check_void_in_dentry(struct ext2_dirent *dir, char *filename) new_entry_byte_reqd = strlen(filename) + sizeof(struct ext2_dirent) + padding_factor; if (sizeof_void_space >= new_entry_byte_reqd) { - dir->direntlen = dentry_length; + dir->direntlen = cpu_to_le16(dentry_length); return sizeof_void_space; }
@@ -360,6 +381,9 @@ void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type) /* directory entry */ struct ext2_dirent *dir; char *temp_dir = NULL; + uint32_t new_blk_no; + uint32_t new_size; + uint32_t new_blockcnt;
zero_buffer = zalloc(fs->blksz); if (!zero_buffer) { @@ -396,7 +420,7 @@ restart: goto fail; dir = (struct ext2_dirent *)root_first_block_buffer; totalbytes = 0; - while (dir->direntlen > 0) { + while (le16_to_cpu(dir->direntlen) > 0) { /* * blocksize-totalbytes because last directory length * i.e. dir->direntlen is free availble space in the @@ -405,7 +429,7 @@ restart: */
/* traversing the each directory entry */ - if (fs->blksz - totalbytes == dir->direntlen) { + if (fs->blksz - totalbytes == le16_to_cpu(dir->direntlen)) { if (strlen(filename) % 4 != 0) padding_factor = 4 - (strlen(filename) % 4);
@@ -430,32 +454,34 @@ restart: printf("Directory exceeds limit\n"); goto fail; } - g_parent_inode->b.blocks.dir_blocks - [direct_blk_idx] = ext4fs_get_new_blk_no(); - if (g_parent_inode->b.blocks.dir_blocks - [direct_blk_idx] == -1) { + new_blk_no = ext4fs_get_new_blk_no(); + if (new_blk_no == -1) { printf("no block left to assign\n"); goto fail; } - put_ext4(((uint64_t) - ((uint64_t)g_parent_inode->b. - blocks.dir_blocks[direct_blk_idx] * - (uint64_t)fs->blksz)), zero_buffer, fs->blksz); - g_parent_inode->size = - g_parent_inode->size + fs->blksz; - g_parent_inode->blockcnt = - g_parent_inode->blockcnt + fs->sect_perblk; + put_ext4((uint64_t)new_blk_no * fs->blksz, zero_buffer, fs->blksz); + g_parent_inode->b.blocks.dir_blocks[direct_blk_idx] = + cpu_to_le32(new_blk_no); + + new_size = le32_to_cpu(g_parent_inode->size); + new_size += fs->blksz; + g_parent_inode->size = cpu_to_le32(new_size); + + new_blockcnt = le32_to_cpu(g_parent_inode->blockcnt); + new_blockcnt += fs->sect_perblk; + g_parent_inode->blockcnt = cpu_to_le32(new_blockcnt); + if (ext4fs_put_metadata (root_first_block_buffer, first_block_no_of_root)) goto fail; goto restart; } - dir->direntlen = last_entry_dirlen; + dir->direntlen = cpu_to_le16(last_entry_dirlen); break; }
- templength = dir->direntlen; + templength = le16_to_cpu(dir->direntlen); totalbytes = totalbytes + templength; sizeof_void_space = check_void_in_dentry(dir, filename); if (sizeof_void_space) @@ -465,7 +491,7 @@ restart: }
/* make a pointer ready for creating next directory entry */ - templength = dir->direntlen; + templength = le16_to_cpu(dir->direntlen); totalbytes = totalbytes + templength; dir = (struct ext2_dirent *)((char *)dir + templength);
@@ -475,11 +501,11 @@ restart: printf("no inode left to assign\n"); goto fail; } - dir->inode = inodeno; + dir->inode = cpu_to_le32(inodeno); if (sizeof_void_space) - dir->direntlen = sizeof_void_space; + dir->direntlen = cpu_to_le16(sizeof_void_space); else - dir->direntlen = fs->blksz - totalbytes; + dir->direntlen = cpu_to_le16(fs->blksz - totalbytes);
dir->namelen = strlen(filename); dir->filetype = FILETYPE_REG; /* regular file */ @@ -534,7 +560,7 @@ static int search_dir(struct ext2_inode *parent_inode, char *dirname) dir = (struct ext2_dirent *)block_buffer; ptr = (char *)dir; totalbytes = 0; - while (dir->direntlen >= 0) { + while (le16_to_cpu(dir->direntlen) >= 0) { /* * blocksize-totalbytes because last directory * length i.e.,*dir->direntlen is free availble @@ -542,23 +568,23 @@ static int search_dir(struct ext2_inode *parent_inode, char *dirname) * it is a last entry of directory entry */ if (strlen(dirname) == dir->namelen) { - if (strncmp(dirname, ptr + - sizeof(struct ext2_dirent), - dir->namelen) == 0) { - previous_dir->direntlen += - dir->direntlen; - inodeno = dir->inode; + if (strncmp(dirname, ptr + sizeof(struct ext2_dirent), dir->namelen) == 0) { + uint16_t new_len; + new_len = le16_to_cpu(previous_dir->direntlen); + new_len += le16_to_cpu(dir->direntlen); + previous_dir->direntlen = cpu_to_le16(new_len); + inodeno = le32_to_cpu(dir->inode); dir->inode = 0; found = 1; break; } }
- if (fs->blksz - totalbytes == dir->direntlen) + if (fs->blksz - totalbytes == le16_to_cpu(dir->direntlen)) break;
/* traversing the each directory entry */ - templength = dir->direntlen; + templength = le16_to_cpu(dir->direntlen); totalbytes = totalbytes + templength; previous_dir = dir; dir = (struct ext2_dirent *)((char *)dir + templength); @@ -720,7 +746,7 @@ end:
if (matched_inode_no != -1) { ext4fs_iget(matched_inode_no, &temp_inode); - if (temp_inode.mode & S_IFDIR) { + if (le16_to_cpu(temp_inode.mode) & S_IFDIR) { printf("It is a Directory\n"); result_inode_no = -1; goto fail; @@ -780,7 +806,7 @@ static int check_filename(char *filename, unsigned int blknr) dir = (struct ext2_dirent *)root_first_block_buffer; ptr = (char *)dir; totalbytes = 0; - while (dir->direntlen >= 0) { + while (le16_to_cpu(dir->direntlen) >= 0) { /* * blocksize-totalbytes because last * directory length i.e., *dir->direntlen @@ -790,20 +816,23 @@ static int check_filename(char *filename, unsigned int blknr) if (strlen(filename) == dir->namelen) { if (strncmp(filename, ptr + sizeof(struct ext2_dirent), dir->namelen) == 0) { + uint16_t new_len; printf("file found deleting\n"); - previous_dir->direntlen += dir->direntlen; - inodeno = dir->inode; + new_len = le16_to_cpu(previous_dir->direntlen); + new_len += le16_to_cpu(dir->direntlen); + previous_dir->direntlen = cpu_to_le16(new_len); + inodeno = le32_to_cpu(dir->inode); dir->inode = 0; found = 1; break; } }
- if (fs->blksz - totalbytes == dir->direntlen) + if (fs->blksz - totalbytes == le16_to_cpu(dir->direntlen)) break;
/* traversing the each directory entry */ - templength = dir->direntlen; + templength = le16_to_cpu(dir->direntlen); totalbytes = totalbytes + templength; previous_dir = dir; dir = (struct ext2_dirent *)((char *)dir + templength); @@ -843,14 +872,14 @@ int ext4fs_filename_check(char *filename) return -1; }
-long int ext4fs_get_new_blk_no(void) +uint32_t ext4fs_get_new_blk_no(void) { short i; short status; int remainder; unsigned int bg_idx; static int prev_bg_bitmap_index = -1; - unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; + unsigned int blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group); struct ext_filesystem *fs = get_fs(); char *journal_buffer = zalloc(fs->blksz); char *zero_buffer = zalloc(fs->blksz); @@ -860,14 +889,13 @@ long int ext4fs_get_new_blk_no(void)
if (fs->first_pass_bbmap == 0) { for (i = 0; i < fs->no_blkgrp; i++) { - 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)), + if (le16_to_cpu(bgd[i].free_blocks)) { + if (le16_to_cpu(bgd[i].bg_flags) & EXT4_BG_BLOCK_UNINIT) { + uint16_t new_flags; + put_ext4((uint64_t)le32_to_cpu(bgd[i].block_id) * fs->blksz, zero_buffer, fs->blksz); - bgd[i].bg_flags = - bgd[i]. - bg_flags & ~EXT4_BG_BLOCK_UNINIT; + new_flags = le16_to_cpu(bgd[i].bg_flags) & ~EXT4_BG_BLOCK_UNINIT; + bgd[i].bg_flags = cpu_to_le16(new_flags); memcpy(fs->blk_bmaps[i], zero_buffer, fs->blksz); } @@ -879,17 +907,17 @@ long int ext4fs_get_new_blk_no(void) fs->curr_blkno = fs->curr_blkno + (i * fs->blksz * 8); fs->first_pass_bbmap++; - bgd[i].free_blocks--; - fs->sb->free_blocks--; - status = ext4fs_devread((lbaint_t) - bgd[i].block_id * + ext4fs_bg_free_blocks_dec(&bgd[i]); + ext4fs_sb_free_inodes_dec(fs->sb); + status = ext4fs_devread( + (lbaint_t)le32_to_cpu(bgd[i].block_id) * fs->sect_perblk, 0, fs->blksz, journal_buffer); if (status == 0) goto fail; if (ext4fs_log_journal(journal_buffer, - bgd[i].block_id)) + le32_to_cpu(bgd[i].block_id))) goto fail; goto success; } else { @@ -923,13 +951,14 @@ restart: goto restart; }
- if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) { + if (le16_to_cpu(bgd[bg_idx].bg_flags) & EXT4_BG_BLOCK_UNINIT) { + uint16_t new_flags; memset(zero_buffer, '\0', fs->blksz); - put_ext4(((uint64_t) ((uint64_t)bgd[bg_idx].block_id * - (uint64_t)fs->blksz)), zero_buffer, fs->blksz); + put_ext4((uint64_t)le32_to_cpu(bgd[bg_idx].block_id) * fs->blksz, + zero_buffer, fs->blksz); memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz); - bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags & - ~EXT4_BG_BLOCK_UNINIT; + new_flags = le16_to_cpu(bgd[bg_idx].bg_flags) & ~EXT4_BG_BLOCK_UNINIT; + bgd[bg_idx].bg_flags = cpu_to_le16(new_flags); }
if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx], @@ -942,19 +971,20 @@ restart: /* journal backup */ if (prev_bg_bitmap_index != bg_idx) { memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread((lbaint_t)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_bitmap_index = bg_idx; } - bgd[bg_idx].free_blocks--; - fs->sb->free_blocks--; + ext4fs_bg_free_blocks_dec(&bgd[bg_idx]); + ext4fs_sb_free_inodes_dec(fs->sb); goto success; } success: @@ -975,7 +1005,7 @@ int ext4fs_get_new_inode_no(void) short status; unsigned int ibmap_idx; static int prev_inode_bitmap_index = -1; - unsigned int inodes_per_grp = ext4fs_root->sblock.inodes_per_group; + unsigned int inodes_per_grp = le32_to_cpu(ext4fs_root->sblock.inodes_per_group); struct ext_filesystem *fs = get_fs(); char *journal_buffer = zalloc(fs->blksz); char *zero_buffer = zalloc(fs->blksz); @@ -990,13 +1020,12 @@ int ext4fs_get_new_inode_no(void) 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) - ((uint64_t)bgd[i].inode_id * - (uint64_t)fs->blksz)), + if (le16_to_cpu(bgd[i].bg_flags) & EXT4_BG_INODE_UNINIT) { + int new_flags; + put_ext4((uint64_t)le32_to_cpu(bgd[i].inode_id) * fs->blksz, zero_buffer, fs->blksz); - bgd[i].bg_flags = bgd[i].bg_flags & - ~EXT4_BG_INODE_UNINIT; + new_flags = le16_to_cpu(bgd[i].bg_flags) & ~EXT4_BG_INODE_UNINIT; + bgd[i].bg_flags = cpu_to_le16(new_flags); memcpy(fs->inode_bmaps[i], zero_buffer, fs->blksz); } @@ -1008,18 +1037,18 @@ int ext4fs_get_new_inode_no(void) fs->curr_inode_no = fs->curr_inode_no + (i * inodes_per_grp); fs->first_pass_ibmap++; - bgd[i].free_inodes--; - bgd[i].bg_itable_unused--; - fs->sb->free_inodes--; - status = ext4fs_devread((lbaint_t) - bgd[i].inode_id * + ext4fs_bg_free_inodes_dec(&bgd[i]); + ext4fs_bg_itable_unused_dec(&bgd[i]); + ext4fs_sb_free_inodes_dec(fs->sb); + status = ext4fs_devread( + (lbaint_t)le32_to_cpu(bgd[i].inode_id) * fs->sect_perblk, 0, fs->blksz, journal_buffer); if (status == 0) goto fail; if (ext4fs_log_journal(journal_buffer, - bgd[i].inode_id)) + le32_to_cpu(bgd[i].inode_id))) goto fail; goto success; } else @@ -1031,13 +1060,13 @@ restart: fs->curr_inode_no++; /* get the blockbitmap index respective to blockno */ ibmap_idx = fs->curr_inode_no / inodes_per_grp; - if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) { + if (le16_to_cpu(bgd[ibmap_idx].bg_flags) & EXT4_BG_INODE_UNINIT) { + int new_flags; memset(zero_buffer, '\0', fs->blksz); - put_ext4(((uint64_t) ((uint64_t)bgd[ibmap_idx].inode_id * - (uint64_t)fs->blksz)), zero_buffer, - fs->blksz); - bgd[ibmap_idx].bg_flags = - bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT; + put_ext4((uint64_t)le32_to_cpu(bgd[ibmap_idx].inode_id) * fs->blksz, + zero_buffer, fs->blksz); + new_flags = le16_to_cpu(bgd[ibmap_idx].bg_flags) & ~EXT4_BG_INODE_UNINIT; + bgd[ibmap_idx].bg_flags = cpu_to_le16(new_flags); memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer, fs->blksz); } @@ -1053,14 +1082,14 @@ restart: /* journal backup */ if (prev_inode_bitmap_index != ibmap_idx) { memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread((lbaint_t) - 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)) + le32_to_cpu(bgd[ibmap_idx].inode_id))) goto fail; prev_inode_bitmap_index = ibmap_idx; } @@ -1068,9 +1097,9 @@ restart: 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--; + ext4fs_bg_free_inodes_dec(&bgd[ibmap_idx]); + ext4fs_bg_itable_unused_dec(&bgd[ibmap_idx]); + ext4fs_sb_free_inodes_dec(fs->sb); goto success; }
@@ -1097,8 +1126,8 @@ static void alloc_single_indirect_block(struct ext2_inode *file_inode, long int actual_block_no; long int si_blockno; /* si :single indirect */ - unsigned int *si_buffer = NULL; - unsigned int *si_start_addr = NULL; + __le32 *si_buffer = NULL; + __le32 *si_start_addr = NULL; struct ext_filesystem *fs = get_fs();
if (*total_remaining_blocks != 0) { @@ -1128,7 +1157,7 @@ static void alloc_single_indirect_block(struct ext2_inode *file_inode, printf("no block left to assign\n"); goto fail; } - *si_buffer = actual_block_no; + *si_buffer = cpu_to_le32(actual_block_no); debug("SIAB %u: %u\n", *si_buffer, *total_remaining_blocks);
@@ -1141,7 +1170,7 @@ static void alloc_single_indirect_block(struct ext2_inode *file_inode, /* write the block to disk */ 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; + file_inode->b.blocks.indir_block = cpu_to_le32(si_blockno); } fail: free(si_start_addr); @@ -1158,10 +1187,10 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, /* di:double indirect */ long int di_blockno_parent; long int di_blockno_child; - unsigned int *di_parent_buffer = NULL; - unsigned int *di_child_buff = NULL; - unsigned int *di_block_start_addr = NULL; - unsigned int *di_child_buff_start = NULL; + __le32 *di_parent_buffer = NULL; + __le32 *di_child_buff = NULL; + __le32 *di_block_start_addr = NULL; + __le32 *di_child_buff_start = NULL; struct ext_filesystem *fs = get_fs();
if (*total_remaining_blocks != 0) { @@ -1205,7 +1234,7 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, goto fail;
di_child_buff_start = di_child_buff; - *di_parent_buffer = di_blockno_child; + *di_parent_buffer = cpu_to_le32(di_blockno_child); di_parent_buffer++; (*no_blks_reqd)++; debug("DICB %ld: %u\n", di_blockno_child, @@ -1228,7 +1257,7 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, printf("no block left to assign\n"); goto fail; } - *di_child_buff = actual_block_no; + *di_child_buff = cpu_to_le32(actual_block_no); debug("DIAB %ld: %u\n", actual_block_no, *total_remaining_blocks);
@@ -1248,7 +1277,7 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode, } 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; + file_inode->b.blocks.double_indir_block = cpu_to_le32(di_blockno_parent); } fail: free(di_block_start_addr); @@ -1266,12 +1295,12 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, long int ti_gp_blockno; long int ti_parent_blockno; long int ti_child_blockno; - unsigned int *ti_gp_buff = NULL; - unsigned int *ti_parent_buff = NULL; - unsigned int *ti_child_buff = NULL; - unsigned int *ti_gp_buff_start_addr = NULL; - unsigned int *ti_pbuff_start_addr = NULL; - unsigned int *ti_cbuff_start_addr = NULL; + __le32 *ti_gp_buff = NULL; + __le32 *ti_parent_buff = NULL; + __le32 *ti_child_buff = NULL; + __le32 *ti_gp_buff_start_addr = NULL; + __le32 *ti_pbuff_start_addr = NULL; + __le32 *ti_cbuff_start_addr = NULL; struct ext_filesystem *fs = get_fs(); if (*total_remaining_blocks != 0) { /* triple indirect grand parent block connecting to inode */ @@ -1301,7 +1330,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, goto fail;
ti_pbuff_start_addr = ti_parent_buff; - *ti_gp_buff = ti_parent_blockno; + *ti_gp_buff = cpu_to_le32(ti_parent_blockno); ti_gp_buff++; (*no_blks_reqd)++; debug("TIPB %ld: %u\n", ti_parent_blockno, @@ -1319,7 +1348,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, goto fail1;
ti_cbuff_start_addr = ti_child_buff; - *ti_parent_buff = ti_child_blockno; + *ti_parent_buff = cpu_to_le32(ti_child_blockno); ti_parent_buff++; (*no_blks_reqd)++; debug("TICB %ld: %u\n", ti_parent_blockno, @@ -1335,7 +1364,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, free(ti_cbuff_start_addr); goto fail1; } - *ti_child_buff = actual_block_no; + *ti_child_buff = cpu_to_le32(actual_block_no); debug("TIAB %ld: %u\n", actual_block_no, *total_remaining_blocks);
@@ -1364,7 +1393,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode, /* write the grand parent block */ 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; + file_inode->b.blocks.triple_indir_block = cpu_to_le32(ti_gp_blockno); free(ti_gp_buff_start_addr); return; } @@ -1389,7 +1418,7 @@ void ext4fs_allocate_blocks(struct ext2_inode *file_inode, printf("no block left to assign\n"); return; } - file_inode->b.blocks.dir_blocks[i] = direct_blockno; + file_inode->b.blocks.dir_blocks[i] = cpu_to_le32(direct_blockno); debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks);
total_remaining_blocks--; @@ -1420,7 +1449,7 @@ static struct ext4_extent_header *ext4fs_get_extent_block index = (struct ext4_extent_idx *)(ext_block + 1);
if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) - return 0; + return NULL;
if (ext_block->eh_depth == 0) return ext_block; @@ -1432,7 +1461,7 @@ static struct ext4_extent_header *ext4fs_get_extent_block } while (fileblock >= le32_to_cpu(index[i].ei_block));
if (--i < 0) - return 0; + return NULL;
block = le16_to_cpu(index[i].ei_leaf_hi); block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); @@ -1441,7 +1470,7 @@ static struct ext4_extent_header *ext4fs_get_extent_block buf)) ext_block = (struct ext4_extent_header *)buf; else - return 0; + return NULL; } }
@@ -2034,11 +2063,11 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node) if (!diro->inode_read) { status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); if (status == 0) - return 0; + return NULL; } symlink = zalloc(le32_to_cpu(diro->inode.size) + 1); if (!symlink) - return 0; + return NULL;
if (le32_to_cpu(diro->inode.size) < sizeof(diro->inode.b.symlink)) { strncpy(symlink, diro->inode.b.symlink, @@ -2049,7 +2078,7 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node) symlink, &actread); if ((status < 0) || (actread == 0)) { free(symlink); - return 0; + return NULL; } } symlink[le32_to_cpu(diro->inode.size)] = '\0'; @@ -2234,7 +2263,7 @@ int ext4fs_mount(unsigned part_length) * and we do not support metadata_csum (and cannot reliably find * files when it is set. Refuse to mount. */ - if (data->sblock.feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) { + if (le32_to_cpu(data->sblock.feature_incompat) & EXT4_FEATURE_INCOMPAT_64BIT) { printf("Unsupported feature found (64bit, possibly metadata_csum), not mounting\n"); goto fail; } diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h index 48fd2ac..370a717 100644 --- a/fs/ext4/ext4_common.h +++ b/fs/ext4/ext4_common.h @@ -59,10 +59,10 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
#if defined(CONFIG_EXT4_WRITE) uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n); -int ext4fs_checksum_update(unsigned int i); +uint16_t ext4fs_checksum_update(unsigned int i); int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags); void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type); -long int ext4fs_get_new_blk_no(void); +uint32_t ext4fs_get_new_blk_no(void); int ext4fs_get_new_inode_no(void); void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index); diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c index 3f61335..cf14049 100644 --- a/fs/ext4/ext4_journal.c +++ b/fs/ext4/ext4_journal.c @@ -151,7 +151,7 @@ int ext4fs_log_gdt(char *gd_table) * journal_buffer -- Buffer containing meta data * blknr -- Block number on disk of the meta data buffer */ -int ext4fs_log_journal(char *journal_buffer, long int blknr) +int ext4fs_log_journal(char *journal_buffer, uint32_t blknr) { struct ext_filesystem *fs = get_fs(); short i; @@ -183,7 +183,7 @@ int ext4fs_log_journal(char *journal_buffer, long int blknr) * metadata_buffer -- Buffer containing meta data * blknr -- Block number on disk of the meta data buffer */ -int ext4fs_put_metadata(char *metadata_buffer, long int blknr) +int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr) { struct ext_filesystem *fs = get_fs(); if (!metadata_buffer) { @@ -215,7 +215,7 @@ void print_revoke_blks(char *revk_blk) printf("total bytes %d\n", max);
while (offset < max) { - blocknr = be32_to_cpu(*((long int *)(revk_blk + offset))); + blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset))); printf("revoke blknr is %ld\n", blocknr); offset += 4; } @@ -302,7 +302,7 @@ int check_blknr_for_revoke(long int blknr, int sequence_no) max = be32_to_cpu(header->r_count);
while (offset < max) { - blocknr = be32_to_cpu(*((long int *) + blocknr = be32_to_cpu(*((__be32 *) (revk_blk + offset))); if (blocknr == blknr) goto found; @@ -420,7 +420,7 @@ int ext4fs_check_journal_state(int recovery_flag) temp_buff); jsb = (struct journal_superblock_t *) temp_buff;
- if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) { + if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) { if (recovery_flag == RECOVER) printf("Recovery required\n"); } else { @@ -517,11 +517,14 @@ int ext4fs_check_journal_state(int recovery_flag)
end: if (recovery_flag == RECOVER) { + uint32_t new_feature_incompat; jsb->s_start = cpu_to_be32(1); jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1); /* get the superblock */ ext4_read_superblock((char *)fs->sb); - fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER; + 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);
/* Update the super block */ put_ext4((uint64_t) (SUPERBLOCK_SIZE), diff --git a/fs/ext4/ext4_journal.h b/fs/ext4/ext4_journal.h index d54165c..3d05ad5 100644 --- a/fs/ext4/ext4_journal.h +++ b/fs/ext4/ext4_journal.h @@ -115,8 +115,8 @@ extern struct ext2_data *ext4fs_root; int ext4fs_init_journal(void); int ext4fs_log_gdt(char *gd_table); int ext4fs_check_journal_state(int recovery_flag); -int ext4fs_log_journal(char *journal_buffer, long int blknr); -int ext4fs_put_metadata(char *metadata_buffer, long int blknr); +int ext4fs_log_journal(char *journal_buffer, uint32_t blknr); +int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr); void ext4fs_update_journal(void); void ext4fs_dump_metadata(void); void ext4fs_push_revoke_blk(char *buffer); diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index 1169ee3..3194595 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -28,6 +28,26 @@ #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; @@ -40,14 +60,14 @@ 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)((uint64_t)fs->bgd[i].block_id * (uint64_t)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) ((uint64_t)fs->bgd[i].inode_id * (uint64_t)fs->blksz), + put_ext4((uint64_t)le32_to_cpu(fs->bgd[i].inode_id) * fs->blksz, fs->inode_bmaps[i], fs->blksz); }
@@ -99,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) { @@ -115,8 +135,8 @@ 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; + 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; @@ -124,18 +144,18 @@ static void delete_single_indirect_block(struct ext2_inode *inode) 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((lbaint_t)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; } @@ -149,10 +169,10 @@ 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; + uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group); unsigned int *di_buffer = NULL; unsigned int *DIB_start_addr = NULL; struct ext2_block_group *bgd = NULL; @@ -172,7 +192,7 @@ static void delete_double_indirect_block(struct ext2_inode *inode) return; } DIB_start_addr = (unsigned int *)di_buffer; - blknr = inode->b.blocks.double_indir_block; + 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++) { @@ -189,12 +209,12 @@ static void delete_double_indirect_block(struct ext2_inode *inode) ext4fs_reset_block_bmap(*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((lbaint_t) - 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); @@ -202,14 +222,14 @@ 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; + 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; @@ -217,23 +237,23 @@ static void delete_double_indirect_block(struct ext2_inode *inode) 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((lbaint_t)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); @@ -245,10 +265,10 @@ 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; + uint32_t blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group); unsigned int *tigp_buffer = NULL; unsigned int *tib_start_addr = NULL; unsigned int *tip_buffer = NULL; @@ -270,7 +290,7 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) return; } tib_start_addr = (unsigned int *)tigp_buffer; - blknr = inode->b.blocks.triple_indir_block; + 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++) { @@ -300,14 +320,13 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) 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( - (lbaint_t) - bgd[bg_idx].block_id * + (lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) * fs->sect_perblk, 0, fs->blksz, journal_buffer); @@ -315,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; } @@ -338,28 +356,28 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) 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((lbaint_t) - 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; + 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; @@ -367,23 +385,24 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) 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((lbaint_t)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); @@ -402,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(); @@ -423,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) { @@ -450,20 +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((lbaint_t) - 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; } @@ -479,8 +498,8 @@ 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); @@ -494,20 +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((lbaint_t) - 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; } @@ -521,7 +540,7 @@ 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; + (inodeno % inode_per_grp) / inodes_per_block;
/* get the offset of the inode */ blkoff = ((inodeno) % inodes_per_block) * fs->inodesz; @@ -550,15 +569,15 @@ 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((lbaint_t)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(); @@ -585,7 +604,7 @@ 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 */ @@ -606,9 +625,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); @@ -630,7 +649,8 @@ int ext4fs_init(void)
for (i = 0; i < fs->no_blkgrp; i++) { status = - ext4fs_devread((lbaint_t)fs->bgd[i].block_id * + 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) @@ -648,7 +668,8 @@ int ext4fs_init(void) }
for (i = 0; i < fs->no_blkgrp; i++) { - status = ext4fs_devread((lbaint_t)fs->bgd[i].inode_id * + status = ext4fs_devread( + (lbaint_t)le32_to_cpu(fs->bgd[i].inode_id) * fs->sect_perblk, 0, fs->blksz, (char *)fs->inode_bmaps[i]); @@ -663,9 +684,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: @@ -679,8 +700,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); @@ -692,7 +714,7 @@ void ext4fs_deinit(void) 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); + 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); @@ -701,7 +723,9 @@ void ext4fs_deinit(void)
/* get the superblock */ ext4_read_superblock((char *)fs->sb); - fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; + 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); @@ -744,7 +768,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode, { int i; int blockcnt; - 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; @@ -878,7 +902,7 @@ 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; } @@ -889,25 +913,25 @@ int ext4fs_write(const char *fname, unsigned char *buffer, 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) >> - fs->dev_desc->log2blksz; + 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)) / @@ -926,7 +950,7 @@ 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_inodeno % diff --git a/include/ext_common.h b/include/ext_common.h index 3220091..4cd2aa7 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -52,7 +52,7 @@ #define LOG2_BLOCK_SIZE(data) (le32_to_cpu \ (data->sblock.log2_block_size) \ + EXT2_MIN_BLOCK_LOG_SIZE) -#define INODE_SIZE_FILESYSTEM(data) (le32_to_cpu \ +#define INODE_SIZE_FILESYSTEM(data) (le16_to_cpu \ (data->sblock.inode_size))
#define EXT2_FT_DIR 2

le32_to_cpu() must only convert the revision_level and not the boolean result.
Signed-off-by: Michael Walle michael@walle.cc --- fs/ext4/ext4_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 567350f..4a003cf 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -2268,7 +2268,7 @@ int ext4fs_mount(unsigned part_length) goto fail; }
- if (le32_to_cpu(data->sblock.revision_level == 0)) + if (le32_to_cpu(data->sblock.revision_level) == 0) fs->inodesz = 128; else fs->inodesz = le16_to_cpu(data->sblock.inode_size);

direntlen is always >= 8. Therefore, the loop condition is always true.
Signed-off-by: Michael Walle michael@walle.cc Suggested-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- fs/ext4/ext4_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 4a003cf..9430a3b 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -420,7 +420,7 @@ restart: goto fail; dir = (struct ext2_dirent *)root_first_block_buffer; totalbytes = 0; - while (le16_to_cpu(dir->direntlen) > 0) { + while (true) { /* * blocksize-totalbytes because last directory length * i.e. dir->direntlen is free availble space in the @@ -560,7 +560,7 @@ static int search_dir(struct ext2_inode *parent_inode, char *dirname) dir = (struct ext2_dirent *)block_buffer; ptr = (char *)dir; totalbytes = 0; - while (le16_to_cpu(dir->direntlen) >= 0) { + while (true) { /* * blocksize-totalbytes because last directory * length i.e.,*dir->direntlen is free availble @@ -806,7 +806,7 @@ static int check_filename(char *filename, unsigned int blknr) dir = (struct ext2_dirent *)root_first_block_buffer; ptr = (char *)dir; totalbytes = 0; - while (le16_to_cpu(dir->direntlen) >= 0) { + while (true) { /* * blocksize-totalbytes because last * directory length i.e., *dir->direntlen

On Dienstag, 23. August 2016 10:27:42 CEST Michael Walle wrote:
direntlen is always >= 8. Therefore, the loop condition is always true.
Signed-off-by: Michael Walle michael@walle.cc Suggested-by: Stefan Brüns stefan.bruens@rwth-aachen.de
Thinking again about it, direntlen is read from disk, and as any outside data should be untrusted. In case the direntlen is 0, we get an infinite loop here.
Also see commit 54d68e9333ff65d135faac68fa01be4276f1371f : fs: ext4: Prevent infinite loop in ext4fs_iterate_dir
So better drop this patch.
Kind regards,
Stefan
participants (2)
-
Michael Walle
-
Stefan Bruens