From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lukasz Majewski Date: Mon, 29 Aug 2016 15:56:52 +0200 Subject: [U-Boot] [PATCH v3 04/13] ext4: Scan all directory blocks for space when inserting a new entry In-Reply-To: <5f87fb1422db45bb964ff6aa6b4ed557@rwthex-w2-b.rwth-ad.de> References: <20160828204238.10809-1-stefan.bruens@rwth-aachen.de> <5f87fb1422db45bb964ff6aa6b4ed557@rwthex-w2-b.rwth-ad.de> Message-ID: <20160829155652.05af2487@amdc2363> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Stefan, > Previously, only the last directory block was scanned for available > space. Instead, scan all blocks back to front, and if no sufficient > space is found, eventually append a new block. > Blocks are only appended if the directory does not use extents or the > new block would require insertion of indirect blocks, as the old code > does. > > Signed-off-by: Stefan Br?ns > --- > fs/ext4/ext4_common.c | 72 > ++++++++++++++++++++------------------------------- 1 file changed, > 28 insertions(+), 44 deletions(-) > > v3: Patch added to series > > diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c > index 49d6465..96dc371 100644 > --- a/fs/ext4/ext4_common.c > +++ b/fs/ext4/ext4_common.c > @@ -365,14 +365,10 @@ int ext4fs_update_parent_dentry(char *filename, > int file_type) { > unsigned int *zero_buffer = NULL; > char *root_first_block_buffer = NULL; > - int direct_blk_idx; > - long int root_blknr; > + int blk_idx; > long int first_block_no_of_root = 0; > - long int previous_blknr = -1; > int totalbytes = 0; > - short int padding_factor = 0; > unsigned int new_entry_byte_reqd; > - unsigned int last_entry_dirlen; > int sizeof_void_space = 0; > int templength = 0; > int inodeno = -1; > @@ -384,6 +380,7 @@ int ext4fs_update_parent_dentry(char *filename, > int file_type) uint32_t new_blk_no; > uint32_t new_size; > uint32_t new_blockcnt; > + uint32_t directory_blocks; > > zero_buffer = zalloc(fs->blksz); > if (!zero_buffer) { > @@ -396,19 +393,16 @@ int ext4fs_update_parent_dentry(char *filename, > int file_type) printf("No Memory\n"); > return -1; > } > + new_entry_byte_reqd = ROUND(strlen(filename) + > + sizeof(struct ext2_dirent), 4); > restart: > + directory_blocks = le32_to_cpu(g_parent_inode->size) >> > + LOG2_BLOCK_SIZE(ext4fs_root); > + blk_idx = directory_blocks - 1; > > +restart_read: > /* read the block no allocated to a file */ > - for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; > - direct_blk_idx++) { > - root_blknr = read_allocated_block(g_parent_inode, > - direct_blk_idx); > - if (root_blknr == 0) { > - first_block_no_of_root = previous_blknr; > - break; > - } > - previous_blknr = root_blknr; > - } > + first_block_no_of_root = > read_allocated_block(g_parent_inode, blk_idx); > status = ext4fs_devread((lbaint_t)first_block_no_of_root > * fs->sect_perblk, > @@ -420,42 +414,33 @@ restart: > goto fail; > dir = (struct ext2_dirent *)root_first_block_buffer; > totalbytes = 0; > + > while (le16_to_cpu(dir->direntlen) > 0) { > - /* > - * blocksize-totalbytes because last directory length > - * i.e. dir->direntlen is free availble space in the > - * block that means it is a last entry of directory > - * entry > - */ > + unsigned short used_len = ROUND(dir->namelen + > + sizeof(struct ext2_dirent), 4); > > - /* traversing the each directory entry */ > + /* last entry of block */ > if (fs->blksz - totalbytes == > le16_to_cpu(dir->direntlen)) { > - if (strlen(filename) % 4 != 0) > - padding_factor = 4 - > (strlen(filename) % 4); - > - new_entry_byte_reqd = strlen(filename) + > - sizeof(struct ext2_dirent) + > padding_factor; > - padding_factor = 0; > - /* > - * update last directory entry length to its > - * length because we are creating new > directory > - * entry > - */ > - if (dir->namelen % 4 != 0) > - padding_factor = 4 - (dir->namelen % > 4); > - last_entry_dirlen = dir->namelen + > - sizeof(struct ext2_dirent) + > padding_factor; > - if ((fs->blksz - totalbytes - > last_entry_dirlen) < > - new_entry_byte_reqd) { > - printf("Last Block Full:Allocate new > block\n"); > + /* check if new entry fits */ > + if ((used_len + new_entry_byte_reqd) <= > + le16_to_cpu(dir->direntlen)) { > + dir->direntlen = > cpu_to_le16(used_len); > + break; > + } else { > + if (blk_idx > 0) { > + printf("Block full, trying > previous\n"); > + blk_idx--; > + goto restart_read; > + } > + printf("All blocks full: Allocate > new\n"); > if > (le32_to_cpu(g_parent_inode->flags) & EXT4_EXTENTS_FL) { > printf("Directory uses > extents\n"); goto fail; > } > - if (direct_blk_idx == > INDIRECT_BLOCKS - 1) { > + if (directory_blocks >= > INDIRECT_BLOCKS) { printf("Directory exceeds limit\n"); > goto fail; > } > @@ -465,7 +450,8 @@ restart: > goto fail; > } > put_ext4((uint64_t)new_blk_no * > fs->blksz, zero_buffer, fs->blksz); > - > g_parent_inode->b.blocks.dir_blocks[direct_blk_idx] = > + g_parent_inode->b.blocks. > + dir_blocks[directory_blocks] > = cpu_to_le32(new_blk_no); > > new_size = > le32_to_cpu(g_parent_inode->size); @@ -482,8 +468,6 @@ restart: > goto fail; > goto restart; > } > - dir->direntlen = > cpu_to_le16(last_entry_dirlen); > - break; > } > > templength = le16_to_cpu(dir->direntlen); Reviewed-by: Lukasz Majewski -- Best regards, Lukasz Majewski Samsung R&D Institute Poland (SRPOL) | Linux Platform Group