mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-07-04 21:32:09 +00:00
ext4: Scan all directory blocks for space when inserting a new entry
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 <stefan.bruens@rwth-aachen.de> Reviewed-by: Lukasz Majewski <l.majewski@samsung.com>
This commit is contained in:
parent
b96c3c7292
commit
a321abd54f
1 changed files with 30 additions and 44 deletions
|
@ -370,14 +370,10 @@ int ext4fs_update_parent_dentry(char *filename, int file_type)
|
||||||
{
|
{
|
||||||
unsigned int *zero_buffer = NULL;
|
unsigned int *zero_buffer = NULL;
|
||||||
char *root_first_block_buffer = NULL;
|
char *root_first_block_buffer = NULL;
|
||||||
int direct_blk_idx;
|
int blk_idx;
|
||||||
long int root_blknr;
|
|
||||||
long int first_block_no_of_root = 0;
|
long int first_block_no_of_root = 0;
|
||||||
long int previous_blknr = -1;
|
|
||||||
int totalbytes = 0;
|
int totalbytes = 0;
|
||||||
short int padding_factor = 0;
|
|
||||||
unsigned int new_entry_byte_reqd;
|
unsigned int new_entry_byte_reqd;
|
||||||
unsigned int last_entry_dirlen;
|
|
||||||
int sizeof_void_space = 0;
|
int sizeof_void_space = 0;
|
||||||
int templength = 0;
|
int templength = 0;
|
||||||
int inodeno = -1;
|
int inodeno = -1;
|
||||||
|
@ -389,6 +385,7 @@ int ext4fs_update_parent_dentry(char *filename, int file_type)
|
||||||
uint32_t new_blk_no;
|
uint32_t new_blk_no;
|
||||||
uint32_t new_size;
|
uint32_t new_size;
|
||||||
uint32_t new_blockcnt;
|
uint32_t new_blockcnt;
|
||||||
|
uint32_t directory_blocks;
|
||||||
|
|
||||||
zero_buffer = zalloc(fs->blksz);
|
zero_buffer = zalloc(fs->blksz);
|
||||||
if (!zero_buffer) {
|
if (!zero_buffer) {
|
||||||
|
@ -401,19 +398,18 @@ int ext4fs_update_parent_dentry(char *filename, int file_type)
|
||||||
printf("No Memory\n");
|
printf("No Memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
new_entry_byte_reqd = ROUND(strlen(filename) +
|
||||||
|
sizeof(struct ext2_dirent), 4);
|
||||||
restart:
|
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 */
|
/* read the block no allocated to a file */
|
||||||
for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
|
first_block_no_of_root = read_allocated_block(g_parent_inode, blk_idx);
|
||||||
direct_blk_idx++) {
|
if (first_block_no_of_root <= 0)
|
||||||
root_blknr = read_allocated_block(g_parent_inode,
|
goto fail;
|
||||||
direct_blk_idx);
|
|
||||||
if (root_blknr == 0) {
|
|
||||||
first_block_no_of_root = previous_blknr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
previous_blknr = root_blknr;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = ext4fs_devread((lbaint_t)first_block_no_of_root
|
status = ext4fs_devread((lbaint_t)first_block_no_of_root
|
||||||
* fs->sect_perblk,
|
* fs->sect_perblk,
|
||||||
|
@ -425,42 +421,33 @@ restart:
|
||||||
goto fail;
|
goto fail;
|
||||||
dir = (struct ext2_dirent *)root_first_block_buffer;
|
dir = (struct ext2_dirent *)root_first_block_buffer;
|
||||||
totalbytes = 0;
|
totalbytes = 0;
|
||||||
|
|
||||||
while (le16_to_cpu(dir->direntlen) > 0) {
|
while (le16_to_cpu(dir->direntlen) > 0) {
|
||||||
/*
|
unsigned short used_len = ROUND(dir->namelen +
|
||||||
* blocksize-totalbytes because last directory length
|
sizeof(struct ext2_dirent), 4);
|
||||||
* i.e. dir->direntlen is free availble space in the
|
|
||||||
* block that means it is a last entry of directory
|
|
||||||
* entry
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* traversing the each directory entry */
|
/* last entry of block */
|
||||||
if (fs->blksz - totalbytes == le16_to_cpu(dir->direntlen)) {
|
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) +
|
/* check if new entry fits */
|
||||||
sizeof(struct ext2_dirent) + padding_factor;
|
if ((used_len + new_entry_byte_reqd) <=
|
||||||
padding_factor = 0;
|
le16_to_cpu(dir->direntlen)) {
|
||||||
/*
|
dir->direntlen = cpu_to_le16(used_len);
|
||||||
* update last directory entry length to its
|
break;
|
||||||
* length because we are creating new directory
|
} else {
|
||||||
* entry
|
if (blk_idx > 0) {
|
||||||
*/
|
printf("Block full, trying previous\n");
|
||||||
if (dir->namelen % 4 != 0)
|
blk_idx--;
|
||||||
padding_factor = 4 - (dir->namelen % 4);
|
goto restart_read;
|
||||||
|
}
|
||||||
last_entry_dirlen = dir->namelen +
|
printf("All blocks full: Allocate new\n");
|
||||||
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");
|
|
||||||
|
|
||||||
if (le32_to_cpu(g_parent_inode->flags) &
|
if (le32_to_cpu(g_parent_inode->flags) &
|
||||||
EXT4_EXTENTS_FL) {
|
EXT4_EXTENTS_FL) {
|
||||||
printf("Directory uses extents\n");
|
printf("Directory uses extents\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (direct_blk_idx == INDIRECT_BLOCKS - 1) {
|
if (directory_blocks >= INDIRECT_BLOCKS) {
|
||||||
printf("Directory exceeds limit\n");
|
printf("Directory exceeds limit\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -470,7 +457,8 @@ restart:
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
put_ext4((uint64_t)new_blk_no * fs->blksz, zero_buffer, fs->blksz);
|
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);
|
cpu_to_le32(new_blk_no);
|
||||||
|
|
||||||
new_size = le32_to_cpu(g_parent_inode->size);
|
new_size = le32_to_cpu(g_parent_inode->size);
|
||||||
|
@ -487,8 +475,6 @@ restart:
|
||||||
goto fail;
|
goto fail;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
dir->direntlen = cpu_to_le16(last_entry_dirlen);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templength = le16_to_cpu(dir->direntlen);
|
templength = le16_to_cpu(dir->direntlen);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue