public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Michael Walle <michael@walle.cc>
To: u-boot@lists.denx.de
Subject: [U-Boot] [RFC PATCH 3/4] ext4: fix endianess problems in ext4 write support
Date: Tue, 16 Aug 2016 11:30:03 +0200	[thread overview]
Message-ID: <2a4ae1787be659033246cd368af890a7@walle.cc> (raw)
In-Reply-To: <2198104.q3j2TPqOcn@pebbles.site>

Am 2016-08-14 03:50, schrieb Stefan Bruens:
> On Freitag, 12. August 2016 15:16:20 CEST Michael Walle wrote:
>> 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>
> 
> I have tested this on sandbox (x86_64), no regressions found. Some 
> remarks
> below.
> 
> Reviewed-by: Stefan Br?ns <stefan.bruens@rwth-aachen.de>
> Tested-by: Stefan Br?ns <stefan.bruens@rwth-aachen.de>
> 
>> ---
>> 
>> Ok this patch is huge, please comment. I know, checkpatch fails 
>> because
>> there are longer lines than 80 characters. I don't want do be rude, 
>> but the
>> coding style is awful :/ Eg.
>> 
>> http://git.denx.de/?p=u-boot.git;a=blob;f=fs/ext4/ext4_common.c;h=eb49fce04
>> c5a290e839575945da722bc97d2f670;hb=HEAD#l440
>> http://git.denx.de/?p=u-boot.git;a=blob;f=fs/ext4/ext4_write.c;h=e027916763
>> f9b52937c7fe13f1698b67b94eb901;hb=HEAD#l137
>> 
>> Many ugly places seems to come from the 80 characters limit. Most of 
>> the
>> code looks like its right-aligned. I know there is a valid point for 
>> having
>> this limit, eg refactor code into small functions. And frankly, the 
>> ext4
>> write code badly needs such a refactoring. But I won't and can't do 
>> it. I
>> can resend a new version which meet the 80 character restriction, but 
>> it
>> won't make the code easier to read. And believe me, it is already hard 
>> to
>> do it.
>> 
>> Ok, back to business. Sparse really helped to find the places where 
>> the
>> byteswaps were missing once you annotated it correctly with the
>> __le16/__le32 types. If someone want to do check again, just run
>>  make C=1
>> See Documentation/sparse.txt in the linux kernel for more information. 
>> I've
>> done a short test, to verify I can (over)write a 700kB file. No 
>> cornertests
>> etc.
>> 
>>  fs/ext4/ext4_common.c  | 260
>> ++++++++++++++++++++++++++----------------------- 
>> fs/ext4/ext4_common.h  |
>>  4 +-
>>  fs/ext4/ext4_journal.c |  15 +--
>>  fs/ext4/ext4_journal.h |   4 +-
>>  fs/ext4/ext4_write.c   | 195 +++++++++++++++++++------------------
>>  include/ext_common.h   |   2 +-
>>  6 files changed, 251 insertions(+), 229 deletions(-)
>> 
>> diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
>> index e8ed30a..4eb4e18 100644
>> --- a/fs/ext4/ext4_common.c
>> +++ b/fs/ext4/ext4_common.c
>> @@ -33,19 +33,22 @@
>> 
>>  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;
>> 
>> +#define DEC_LE16(x) (x = cpu_to_le16(le16_to_cpu(x) - 1))
>> +#define DEC_LE32(x) (x = cpu_to_le32(le32_to_cpu(x) - 1))
> 
> I would prefer a static function *per variable/field* - this will make 
> it
> easier to manipulate any high/low split counts for FEATURE_64BIT. Same 
> for the
> INC_xxx in ext4_write.c

ok, sounds right ;)

>> @@ -360,6 +364,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 +403,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) {
> 
> direntlen is at least 8, so this is "while (true) {"

I'll put this and all remarks below, into a separate patch, because I 
want this patch to only fix the endianess problem without any functional 
changes.

-michael

> 
>>  		/*
>>  		 * blocksize-totalbytes because last directory length
>>  		 * i.e. dir->direntlen is free availble space in the
>> @@ -405,7 +412,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 +437,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);
> 
> This is (already was) broken if the directory uses extents, we have to 
> fix
> this (in a seperate patch).
> 
>> +
>> +				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)
> 
>> @@ -534,7 +543,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) {
> 
> dito, "while (true) { "
> 
> 
>> @@ -780,7 +789,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) {
> 
> dito
> 
>> @@ -2234,7 +2246,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;
>>  	}
> 
> This should have a if ((data->sblock.revision_level !=0) && ... in 
> front,
> features are not defined for revision 0. Applies to other places as 
> well ...
> 
>> 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 (fs->sb->revision_level != 0) && ..

  reply	other threads:[~2016-08-16  9:30 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-12 13:16 [U-Boot] [PATCH 1/4] ext4: change structure fields to __le/__be types Michael Walle
2016-08-12 13:16 ` [U-Boot] [PATCH 2/4] ext4: use kernel names for byte swaps Michael Walle
2016-08-12 13:16 ` [U-Boot] [RFC PATCH 3/4] ext4: fix endianess problems in ext4 write support Michael Walle
2016-08-14  1:50   ` Stefan Bruens
2016-08-16  9:30     ` Michael Walle [this message]
2016-08-16 11:41     ` Michael Walle
2016-08-16 17:05       ` Brüns, Stefan
2016-08-12 13:16 ` [U-Boot] [PATCH 4/4] ext4: fix wrong usage of le32_to_cpu() Michael Walle

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2a4ae1787be659033246cd368af890a7@walle.cc \
    --to=michael@walle.cc \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox