fs:ext4: Fixes and code cleanup
cover fs:ext4: Fixes and code cleanup
This code fixes problem with storing file with the same name multiple times on the same ext4 fs (with different sizes).
Code reorganization and cleanup is also included.
Lukasz Majewski (2):
fs:ext4:cleanup: Remove superfluous code fs:ext4:write:fix: Reinitialize global variables after updating a
file
fs/ext4/ext4_common.c | 29 +++++++++++++++------------- fs/ext4/ext4_write.c | 51 +++++++++++++++++-------------------------------- include/ext4fs.h | 1 + 3 files changed, 34 insertions(+), 47 deletions(-)
Signature · 1 line
1.7.10.4
PATCH 1/2 fs:ext4:cleanup: Remove superfluous code
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
--- fs/ext4/ext4_common.c | 6 ++---- fs/ext4/ext4_write.c | 50 ++++++++++++++++--------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-)
fs/ext4/ext4_common.c +2 -4
@@ -904,10 +904,8 @@ long int ext4fs_get_new_blk_no(void) restart: fs->curr_blkno++;/* get the blockbitmap index respective to blockno */ -if (fs->blksz !=1024 ) { - bg_idx = fs->curr_blkno / blk_per_grp; - }else { - bg_idx = fs->curr_blkno / blk_per_grp; + bg_idx = fs->curr_blkno / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = fs->curr_blkno % blk_per_grp;if (!remainder) bg_idx--;
fs/ext4/ext4_write.c +16 -34
98 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH 1/2 fs:ext4:cleanup: Remove superfluous code
Quoted 6 lines · Lukasz Majewski
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
Signed-off-by Lukasz Majewski <[email protected]>
Quoted 9 lines
--- fs/ext4/ext4_common.c | 6 ++---- fs/ext4/ext4_write.c | 50 ++++++++++++++++--------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-)fs/ext4/ext4_common.c +0
-0
[snip]
fs/ext4/ext4_common.c static void delete_double_indirect_block(struct ext2_inode *inode) · line 182
Quoted 9 lines
fs/ext4/ext4_common.c +1
-4@@ -181,10 +179,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode)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; + bg_idx = (*di_buffer) / blk_per_grp;
You don't need the brackets here (or below).
Quoted 87 lines
fs/ext4/ext4_common.c +13
-27+if (fs->blksz ==1024 ) { remainder = (*di_buffer) % blk_per_grp;if (!remainder) bg_idx--;@@ -213,10 +209,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode)/* 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; + bg_idx = blknr / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = blknr % blk_per_grp;if (!remainder) bg_idx--;@@ -293,11 +287,8 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)for (j =0 ; j < fs->blksz /sizeof (int ); j++) {if (*tip_buffer ==0 )break ; -if (fs->blksz !=1024 ) { - bg_idx = (*tip_buffer) / blk_per_grp; - }else { - bg_idx = (*tip_buffer) / blk_per_grp; - + bg_idx = (*tip_buffer) / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = (*tip_buffer) % blk_per_grp;if (!remainder) bg_idx--;@@ -336,11 +327,8 @@ 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; - + bg_idx = (*tigp_buffer) / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = (*tigp_buffer) % blk_per_grp;if (!remainder) bg_idx--;@@ -371,10 +359,8 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)/* 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; + bg_idx = blknr / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = blknr % blk_per_grp;if (!remainder) bg_idx--;@@ -452,10 +438,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--;@@ -499,10 +483,8 @@ static int ext4fs_delete_file(int inodeno) 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--; --1.7.10.4
PATCH 1/2 fs:ext4:cleanup: Remove superfluous code
Hi Simon,
Quoted 26 lines
Quoted 6 lines · Lukasz Majewski
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
Signed-off-by Lukasz Majewski <[email protected]>Reviewed-by Simon Glass <[email protected]>Quoted 10 lines
--- fs/ext4/ext4_common.c | 6 ++---- fs/ext4/ext4_write.c | 50++++++++++++++++--------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-)
fs/ext4/ext4_common.c +0
-0[snip]
Quoted 3 lines
fs/ext4/ext4_common.c +0
-0@@ -181,10 +179,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode) break;
Quoted 8 lines
fs/ext4/ext4_common.c static void · line 182
Quoted 6 lines
fs/ext4/ext4_common.c +1
-4debug ("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; + bg_idx = (*di_buffer) / blk_per_grp;You don't need the brackets here (or below).
Maybe the GIT formatting is a bit misleading, but I've double checked and it seems that those parenthesis are necessary here.
Quoted 95 lines
Quoted 95 lines
fs/ext4/ext4_common.c +3
-4+if (fs->blksz ==1024 ) { remainder = (*di_buffer) % blk_per_grp;if (!remainder) bg_idx--;@@ -213,10 +209,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode)/* 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; + bg_idx = blknr / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = blknr % blk_per_grp;if (!remainder)bg_idx--;fs/ext4/ext4_common.c +0
-4@@ -293,11 +287,8 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) for (j = 0; j < fs->blksz / sizeof(int); j++) { if (*tip_buffer == 0)break ; -if (fs->blksz !=1024 ) { - bg_idx = (*tip_buffer) / blk_per_grp; - }else { - bg_idx = (*tip_buffer) /
blk_per_grp; -
+bg_idx= (*tip_buffer) /blk_per_grp;
+ if (fs->blksz== 1024) {
remainder = (*tip_buffer) %blk_per_grp; if (!remainder)bg_idx--;fs/ext4/ext4_common.c +0
-4@@ -336,11 +327,8 @@ static voiddelete_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; -fs/ext4/ext4_common.c +2
-0+ bg_idx = (*tigp_buffer) / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = (*tigp_buffer) %
blk_per_grp; if (!remainder)bg_idx--;fs/ext4/ext4_common.c +2
-4@@ -371,10 +359,8 @@ static void delete_triple_indirect_block(struct ext2_inode *inode)/* 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; + bg_idx = blknr / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = blknr % blk_per_grp;if (!remainder)bg_idx--;fs/ext4/ext4_common.c +2
-4@@ -452,10 +438,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--;fs/ext4/ext4_common.c +2
-5@@ -499,10 +483,8 @@ static int ext4fs_delete_file(int inodeno) 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--; --1.7.10.4
Signature · 5 lines
Best regards, Lukasz Majewski Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
PATCH 1/2 fs:ext4:cleanup: Remove superfluous code
Hi Lukasz,
Quoted 37 lines · Lukasz Majewski
Hi Simon,
Quoted 26 lines
Quoted 6 lines · Lukasz Majewski
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
Signed-off-by Lukasz Majewski <[email protected]>Reviewed-by Simon Glass <[email protected]>Quoted 10 lines
--- fs/ext4/ext4_common.c | 6 ++---- fs/ext4/ext4_write.c | 50++++++++++++++++--------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-)
fs/ext4/ext4_common.c +0
-0[snip]
Quoted 3 lines
fs/ext4/ext4_common.c +0
-0@@ -181,10 +179,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode) break;Quoted 8 lines
fs/ext4/ext4_common.c static void · line 182
Quoted 6 lines
fs/ext4/ext4_common.c +1
-4debug ("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; + bg_idx = (*di_buffer) / blk_per_grp;You don't need the brackets here (or below).
Quoted 2 lines
Maybe the GIT formatting is a bit misleading, but I've double checked and it seems that those parenthesis are necessary here.
OK. What is di_buffer such that (*di_buffer) works but *di_buffer doesn't?
Regards,
Simon
PATCH 1/2 fs:ext4:cleanup: Remove superfluous code
Quoted 43 lines · On Mon, 5 May 2014 08:24:22 -0600 Simon Glass <[email protected]> wrote:
Hi Lukasz,
Quoted 39 lines · Lukasz Majewski
Hi Simon,
Quoted 36 lines
Quoted 6 lines · Lukasz Majewski
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
Signed-off-by Lukasz Majewski <[email protected]>Reviewed-by Simon Glass <[email protected]>Quoted 10 lines
--- fs/ext4/ext4_common.c | 6 ++---- fs/ext4/ext4_write.c | 50++++++++++++++++--------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-)
fs/ext4/ext4_common.c +0
-0[snip]
fs/ext4/ext4_common.c static void · line 184
Quoted 11 lines
fs/ext4/ext4_common.c +1
-4@@ -181,10 +179,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode) 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; + bg_idx = (*di_buffer) / blk_per_grp;You don't need the brackets here (or below).
Quoted 5 lines
Quoted 2 lines
Maybe the GIT formatting is a bit misleading, but I've double checked and it seems that those parenthesis are necessary here.
OK. What is
di_buffersuch that (*di_buffer) works but*di_bufferdoesn't?
It is hard to admit :-), but I've misunderstood you. I thought that you are talking about the {} parentheses.
I will check the code tomorrow and prepare proper patch.
Quoted 3 lines
Regards,
Simon
Best regards,
Lukasz Majewski
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140505/417aecc9/attachment.pgp>
PATCH 1/2 fs:ext4:cleanup: Remove superfluous code
Hi Lukasz,
Quoted 49 lines · Lukasz Majewski
Quoted 46 lines · On Mon, 5 May 2014 08:24:22 -0600 Simon Glass <[email protected]> wrote:
Hi Lukasz,
Quoted 41 lines · Lukasz Majewski
Hi Simon,
Quoted 26 lines
Quoted 6 lines · Lukasz Majewski
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
Signed-off-by Lukasz Majewski <[email protected]>Reviewed-by Simon Glass <[email protected]>Quoted 10 lines
--- fs/ext4/ext4_common.c | 6 ++---- fs/ext4/ext4_write.c | 50++++++++++++++++--------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-)
fs/ext4/ext4_common.c +0
-0[snip]
Quoted 3 lines
fs/ext4/ext4_common.c +0
-0@@ -181,10 +179,8 @@ static void delete_double_indirect_block(struct ext2_inode *inode) break;Quoted 10 lines
fs/ext4/ext4_common.c static void · line 184
Quoted 8 lines
fs/ext4/ext4_common.c +1
-4debug ("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; + bg_idx = (*di_buffer) / blk_per_grp;You don't need the brackets here (or below).
Maybe the GIT formatting is a bit misleading, but I've double checked and it seems that those parenthesis are necessary here.
Quoted 7 lines
Quoted 2 lines
OK. What is
di_buffersuch that (*di_buffer) works but*di_bufferdoesn't?It is hard to admit :-), but I've misunderstood you. I thought that you are talking about the {} parentheses.
I will check the code tomorrow and prepare proper patch.
Ah, sorry I wasn't at all clear on that.
Regards,
Simon
PATCH 2/2 fs:ext4:write:fix: Reinitialize global variables after updating a file
In reply to Lukasz MajewskiThis bug shows up when file stored on the ext4 file system is updated.
The ext4fs_delete_file() is responsible for deleting file's (e.g. uImage) data.
However some global data (especially ext4fs_indir2_block), which is used during file deletion are left unchanged.
The ext4fs_indir2_block pointer stores reference to old ext4 double indirect allocated blocks. When it is unchanged, after file deletion, ext4fs_write_file() uses the same pointer (since it is already initialized
- i.e. not NULL) to return number of blocks to write. This trunks larger file when previous one was smaller.
Lets consider following scenario:
1. Flash target with ext4 formatted boot.img (which has uImage [*] on itself)
2. Developer wants to upload their custom uImage [**]
- When new uImage [**] is smaller than the [*] - everything works correctly - we are able to store the whole smaller file with corrupted ext4fs_indir2_block pointer
- When new uImage [**] is larger than the [*] - theCRC is corrupted, since truncation on data stored at eMMC was done.
3. When uImage CRC error appears, then reboot and THOR/DFU reflashing causes proper setting of ext4fs_indir2_block() and after that uImage[**] is successfully stored (correct uImage [*] metadata is stored at an eMMC on the first flashing).
Due to above the bug was very difficult to reproduce.
This patch sets default values for all ext4fs_indir* pointers/variables.
--- fs/ext4/ext4_common.c | 23 ++++++++++++++--------- fs/ext4/ext4_write.c | 1 + include/ext4fs.h | 1 + 3 files changed, 16 insertions(+), 9 deletions(-)
fs/ext4/ext4_common.c +14 -9
@@ -1841,16 +1841,8 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock)return blknr; } -void ext4fs_close (void ) +void ext4fs_reinit_global (void ) { -if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { -ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); - ext4fs_file =NULL ; - } -if (ext4fs_root !=NULL ) { -free (ext4fs_root); - ext4fs_root =NULL ; - }if (ext4fs_indir1_block !=NULL ) {free (ext4fs_indir1_block); ext4fs_indir1_block =NULL ;
@@ -1870,6 +1862,19 @@ void ext4fs_close(void) ext4fs_indir3_blkno =-1 ; } } +void ext4fs_close (void ) +{ +if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { +ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); + ext4fs_file =NULL ; + } +if (ext4fs_root !=NULL ) { +free (ext4fs_root); + ext4fs_root =NULL ; + } + +ext4fs_reinit_global (); +}int ext4fs_iterate_dir (struct ext2fs_node *dir,char *name,struct ext2fs_node **fnode,int *ftype)
fs/ext4/ext4_write.c +1 -0
@@ -562,6 +562,7 @@ static int ext4fs_delete_file(int inodeno)ext4fs_update ();ext4fs_deinit (); +ext4fs_reinit_global ();if (ext4fs_init () !=0 ) {printf ("error in File System init\n" );
include/ext4fs.h +1 -0
@@ -133,6 +133,7 @@ int ext4fs_open(const char *filename);int ext4fs_read (char *buf,unsigned len);int ext4fs_mount (unsigned part_length);void ext4fs_close (void ); +void ext4fs_reinit_global (void );int ext4fs_ls (const char *dirname);int ext4fs_exists (const char *filename);void ext4fs_free_node (struct ext2fs_node *node,struct ext2fs_node *currroot);
Signature · 1 line
1.7.10.4
PATCH 2/2 fs:ext4:write:fix: Reinitialize global variables after updating a file
Hi Lukasz,
Quoted 27 lines · Lukasz Majewski
This bug shows up when file stored on the ext4 file system is updated.
The
ext4fs_delete_file()is responsible for deleting file's (e.g. uImage) data.
However some global data (especiallyext4fs_indir2_block), which is used during file deletion are left unchanged.The
ext4fs_indir2_blockpointer stores reference to old ext4 double indirect allocated blocks. When it is unchanged, after file deletion,ext4fs_write_file()uses the same pointer (since it is already initialized
- i.e. not NULL) to return number of blocks to write. This trunks larger file when previous one was smaller.Lets consider following scenario:
1. Flash target with ext4 formatted boot.img (which has uImage [*] on itself)
2. Developer wants to upload their custom uImage [**]
- When new uImage [**] is smaller than the [*] - everything works correctly - we are able to store the whole smaller file with corruptedext4fs_indir2_blockpointer
- When new uImage [**] is larger than the [*] - theCRC is corrupted, since truncation on data stored at eMMC was done.
3. When uImage CRC error appears, then reboot and THOR/DFU reflashing causes proper setting ofext4fs_indir2_block()and after that uImage[**] is successfully stored (correct uImage [*] metadata is stored at an eMMC on the first flashing).
Quoted 1 line
Due to above the bug was very difficult to reproduce.
I wonder if a sandbox test would be a good idea? You could fairly easy mkfs in a loopback file and write a U-Boot script to operate on it. See test/ for some examples.
Quoted 68 lines
This patch sets default values for all ext4fs_indir* pointers/variables.
Signed-off-by Lukasz Majewski <[email protected]>--- fs/ext4/ext4_common.c | 23 ++++++++++++++--------- fs/ext4/ext4_write.c | 1 + include/ext4fs.h | 1 + 3 files changed, 16 insertions(+), 9 deletions(-)fs/ext4/ext4_common.c +14
-9@@ -1841,16 +1841,8 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock)return blknr; } -void ext4fs_close (void ) +void ext4fs_reinit_global (void ) { -if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { -ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); - ext4fs_file =NULL ; - } -if (ext4fs_root !=NULL ) { -free (ext4fs_root); - ext4fs_root =NULL ; - }if (ext4fs_indir1_block !=NULL ) {free (ext4fs_indir1_block); ext4fs_indir1_block =NULL ;@@ -1870,6 +1862,19 @@ void ext4fs_close(void) ext4fs_indir3_blkno =-1 ; } } +void ext4fs_close (void ) +{ +if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { +ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); + ext4fs_file =NULL ; + } +if (ext4fs_root !=NULL ) { +free (ext4fs_root); + ext4fs_root =NULL ; + } + +ext4fs_reinit_global (); +}int ext4fs_iterate_dir (struct ext2fs_node *dir,char *name,struct ext2fs_node **fnode,int *ftype)fs/ext4/ext4_write.c +1
-0@@ -562,6 +562,7 @@ static int ext4fs_delete_file(int inodeno)ext4fs_update ();ext4fs_deinit (); +ext4fs_reinit_global ();if (ext4fs_init () !=0 ) {printf ("error in File System init\n" );include/ext4fs.h +0
-0
include/ext4fs.h int ext4fs_open(const char *filename); · line 136
Quoted 4 lines
include/ext4fs.h +1
-0@@ -133,6 +133,7 @@ int ext4fs_open(const char *filename);int ext4fs_read (char *buf,unsigned len);int ext4fs_mount (unsigned part_length);void ext4fs_close (void ); +void ext4fs_reinit_global (void );
Can we have a comment as to what this function does?
Quoted 6 lines
include/ext4fs.h +0
-1int ext4fs_ls (const char *dirname);int ext4fs_exists (const char *filename);void ext4fs_free_node (struct ext2fs_node *node,struct ext2fs_node *currroot); --1.7.10.4
Regards,
Simon
PATCH 2/2 fs:ext4:write:fix: Reinitialize global variables after updating a file
Hi Simon,
Quoted 33 lines
Hi Lukasz,
Quoted 29 lines · Lukasz Majewski
This bug shows up when file stored on the ext4 file system is updated.
The
ext4fs_delete_file()is responsible for deleting file's (e.g. uImage) data.
However some global data (especiallyext4fs_indir2_block), which is used during file deletion are left unchanged.The
ext4fs_indir2_blockpointer stores reference to old ext4 double indirect allocated blocks. When it is unchanged, after file deletion,ext4fs_write_file()uses the same pointer (since it is already initialized
- i.e. not NULL) to return number of blocks to write. This trunks larger file when previous one was smaller.Lets consider following scenario:
1. Flash target with ext4 formatted boot.img (which has uImage [*] on itself) 2. Developer wants to upload their custom uImage [**]
- When new uImage [**] is smaller than the [*] - everything
works correctly - we are able to store the whole smaller file with corruptedext4fs_indir2_blockpointer
- When new uImage [**] is larger than the [*] - theCRC is
corrupted, since truncation on data stored at eMMC was done.
3. When uImage CRC error appears, then reboot and THOR/DFU reflashing causes proper setting ofext4fs_indir2_block()and after that uImage[**] is successfully stored (correct uImage [*] metadata is stored at an eMMC on the first flashing).
Quoted 5 lines
Quoted 1 line
Due to above the bug was very difficult to reproduce.
I wonder if a sandbox test would be a good idea? You could fairly easy mkfs in a loopback file and write a U-Boot script to operate on it. See test/ for some examples.
If my time budget allows, I will try to add test to sandbox.
Quoted 65 lines
Quoted 65 lines
This patch sets default values for all ext4fs_indir* pointers/variables.
Signed-off-by Lukasz Majewski <[email protected]>--- fs/ext4/ext4_common.c | 23 ++++++++++++++--------- fs/ext4/ext4_write.c | 1 + include/ext4fs.h | 1 + 3 files changed, 16 insertions(+), 9 deletions(-)fs/ext4/ext4_common.c +1
-9@@ -1841,16 +1841,8 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) return blknr; } -void ext4fs_close (void ) +void ext4fs_reinit_global (void ) { -if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { -ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); - ext4fs_file =NULL ; - } -if (ext4fs_root !=NULL ) { -free (ext4fs_root); - ext4fs_root =NULL ; - }if (ext4fs_indir1_block !=NULL ) {free (ext4fs_indir1_block);ext4fs_indir1_block = NULL;fs/ext4/ext4_common.c +13
-0@@ -1870,6 +1862,19 @@ void ext4fs_close(void) ext4fs_indir3_blkno =-1 ; } } +void ext4fs_close (void ) +{ +if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { +ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); + ext4fs_file =NULL ; + } +if (ext4fs_root !=NULL ) { +free (ext4fs_root); + ext4fs_root =NULL ; + } + +ext4fs_reinit_global (); +} int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,struct
ext2fs_node**fnode, int
*ftype) diff --gita/fs/ext4/ext4_write.cb/fs/ext4/ext4_write.cindex 46c573b..4a5f652 100644fs/ext4/ext4_write.c +1
-0@@ -562,6 +562,7 @@ static int ext4fs_delete_file(int inodeno)ext4fs_update ();ext4fs_deinit (); +ext4fs_reinit_global ();
Quoted 13 lines
include/ext4fs.h int ext4fs_open(const char *filename); · line 136
Quoted 11 lines
fs/ext4/ext4_write.c +0
-0if (ext4fs_init () !=0 ) {printf ("error in File System init\n" );include/ext4fs.h +1
-0@@ -133,6 +133,7 @@ int ext4fs_open(const char *filename);int ext4fs_read (char *buf,unsigned len);int ext4fs_mount (unsigned part_length);void ext4fs_close (void ); +void ext4fs_reinit_global (void );Can we have a comment as to what this function does?
I can add comment to the source code. No problem.
Quoted 10 lines
Quoted 7 lines
include/ext4fs.h +0
-0int ext4fs_ls (const char *dirname);int ext4fs_exists (const char *filename); void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node*currroot); --
1.7.10.4Regards,
Simon
Signature · 5 lines
Best regards, Lukasz Majewski Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
v2 cover fs:ext4: Fixes and code cleanup
In reply to Lukasz MajewskiThis code fixes problem with storing file with the same name multiple times on the same ext4 fs (with different sizes).
Code reorganization and cleanup is also included.
Lukasz Majewski (2):
fs:ext4:cleanup: Remove superfluous code fs:ext4:write:fix: Reinitialize global variables after updating a
file
fs/ext4/ext4_common.c | 41 ++++++++++++++++++++++++----------- fs/ext4/ext4_write.c | 57 +++++++++++++++++-------------------------------- include/ext4fs.h | 1 + 3 files changed, 49 insertions(+), 50 deletions(-)
Signature · 1 line
1.7.10.4
PATCH v2 1/2 fs:ext4:cleanup: Remove superfluous code
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
---
Changes for v2:
- Remove () parenthesis around pointers
--- fs/ext4/ext4_common.c | 6 ++---- fs/ext4/ext4_write.c | 56 +++++++++++++++++-------------------------------- 2 files changed, 21 insertions(+), 41 deletions(-)
fs/ext4/ext4_common.c +2 -4
@@ -904,10 +904,8 @@ long int ext4fs_get_new_blk_no(void) restart: fs->curr_blkno++;/* get the blockbitmap index respective to blockno */ -if (fs->blksz !=1024 ) { - bg_idx = fs->curr_blkno / blk_per_grp; - }else { - bg_idx = fs->curr_blkno / blk_per_grp; + bg_idx = fs->curr_blkno / blk_per_grp; +if (fs->blksz ==1024 ) { remainder = fs->curr_blkno % blk_per_grp;if (!remainder) bg_idx--;
fs/ext4/ext4_write.c +19 -37
104 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH v2 1/2 fs:ext4:cleanup: Remove superfluous code
Quoted 6 lines · ?ukasz Majewski
Code responsible for handling situation when ext4 has block size of 1024B can be ordered to take less space.
This patch does that for ext4 common and write files.
Signed-off-by Lukasz Majewski <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140512/43945f1a/attachment.pgp>
PATCH v2 2/2 fs:ext4:write:fix: Reinitialize global variables after updating a file
In reply to Lukasz MajewskiThis bug shows up when file stored on the ext4 file system is updated.
The ext4fs_delete_file() is responsible for deleting file's (e.g. uImage) data.
However some global data (especially ext4fs_indir2_block), which is used during file deletion are left unchanged.
The ext4fs_indir2_block pointer stores reference to old ext4 double indirect allocated blocks. When it is unchanged, after file deletion, ext4fs_write_file() uses the same pointer (since it is already initialized
- i.e. not NULL) to return number of blocks to write. This trunks larger file when previous one was smaller.
Lets consider following scenario:
1. Flash target with ext4 formatted boot.img (which has uImage [*] on itself)
2. Developer wants to upload their custom uImage [**]
- When new uImage [**] is smaller than the [*] - everything works correctly - we are able to store the whole smaller file with corrupted ext4fs_indir2_block pointer
- When new uImage [**] is larger than the [*] - theCRC is corrupted, since truncation on data stored at eMMC was done.
3. When uImage CRC error appears, then reboot and LTHOR/DFU reflashing causes proper setting of ext4fs_indir2_block() and after that uImage[**] is successfully stored (correct uImage [*] metadata is stored at an eMMC on the first flashing).
Due to above the bug was very difficult to reproduce.
This patch sets default values for all ext4fs_indir* pointers/variables.
---
Changes for v2:
- Add comment describing the purpose of ext4fs_reinit_global() function
--- fs/ext4/ext4_common.c | 35 ++++++++++++++++++++++++++--------- fs/ext4/ext4_write.c | 1 + include/ext4fs.h | 1 + 3 files changed, 28 insertions(+), 9 deletions(-)
fs/ext4/ext4_common.c +26 -9
@@ -1841,16 +1841,20 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock)return blknr; } -void ext4fs_close (void ) +/** +* ext4fs_reinit_global() - Reinitialize values of ext4 write implementation's +* global pointers +* +* This function assures that for a file with the same name but different size +* the sequential store on the ext4 filesystem will be correct. +* +* In this function the global data, responsible for internal representation +* of the ext4 data are initialized to the reset state. Without this, during +* replacement of the smaller file with the bigger truncation of new file was +* performed. +*/ +void ext4fs_reinit_global (void ) { -if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { -ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); - ext4fs_file =NULL ; - } -if (ext4fs_root !=NULL ) { -free (ext4fs_root); - ext4fs_root =NULL ; - }if (ext4fs_indir1_block !=NULL ) {free (ext4fs_indir1_block); ext4fs_indir1_block =NULL ;
@@ -1870,6 +1874,19 @@ void ext4fs_close(void) ext4fs_indir3_blkno =-1 ; } } +void ext4fs_close (void ) +{ +if ((ext4fs_file !=NULL ) && (ext4fs_root !=NULL )) { +ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen); + ext4fs_file =NULL ; + } +if (ext4fs_root !=NULL ) { +free (ext4fs_root); + ext4fs_root =NULL ; + } + +ext4fs_reinit_global (); +}int ext4fs_iterate_dir (struct ext2fs_node *dir,char *name,struct ext2fs_node **fnode,int *ftype)
fs/ext4/ext4_write.c +1 -0
@@ -562,6 +562,7 @@ static int ext4fs_delete_file(int inodeno)ext4fs_update ();ext4fs_deinit (); +ext4fs_reinit_global ();if (ext4fs_init () !=0 ) {printf ("error in File System init\n" );
include/ext4fs.h +1 -0
@@ -133,6 +133,7 @@ int ext4fs_open(const char *filename);int ext4fs_read (char *buf,unsigned len);int ext4fs_mount (unsigned part_length);void ext4fs_close (void ); +void ext4fs_reinit_global (void );int ext4fs_ls (const char *dirname);int ext4fs_exists (const char *filename);void ext4fs_free_node (struct ext2fs_node *node,struct ext2fs_node *currroot);
Signature · 1 line
1.7.10.4
PATCH v2 2/2 fs:ext4:write:fix: Reinitialize global variables after updating a file
Quoted 27 lines · ?ukasz Majewski
This bug shows up when file stored on the ext4 file system is updated.
The
ext4fs_delete_file()is responsible for deleting file's (e.g. uImage) data.
However some global data (especiallyext4fs_indir2_block), which is used during file deletion are left unchanged.The
ext4fs_indir2_blockpointer stores reference to old ext4 double indirect allocated blocks. When it is unchanged, after file deletion,ext4fs_write_file()uses the same pointer (since it is already initialized
- i.e. not NULL) to return number of blocks to write. This trunks larger file when previous one was smaller.Lets consider following scenario:
1. Flash target with ext4 formatted boot.img (which has uImage [*] on itself)
2. Developer wants to upload their custom uImage [**]
- When new uImage [**] is smaller than the [*] - everything works correctly - we are able to store the whole smaller file with corruptedext4fs_indir2_blockpointer
- When new uImage [**] is larger than the [*] - theCRC is corrupted, since truncation on data stored at eMMC was done.
3. When uImage CRC error appears, then reboot and LTHOR/DFU reflashing causes proper setting ofext4fs_indir2_block()and after that uImage[**] is successfully stored (correct uImage [*] metadata is stored at an eMMC on the first flashing).
Quoted 4 lines
Due to above the bug was very difficult to reproduce.
This patch sets default values for all ext4fs_indir* pointers/variables.Signed-off-by Lukasz Majewski <[email protected]>
Applied to u-boot/master, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140512/83b32b6e/attachment.pgp>