Changeset d0d7afb in mainline for uspace/lib/ext4/libext4_directory.c


Ignore:
Timestamp:
2012-03-01T19:56:31Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c30a015
Parents:
d8269dc
Message:

Code refactorization (entry insertion)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ext4/libext4_directory.c

    rd8269dc rd0d7afb  
    314314
    315315int ext4_directory_add_entry(ext4_filesystem_t *fs, ext4_inode_ref_t * parent,
    316                 const char *entry_name, ext4_inode_ref_t *child)
     316                const char *name, ext4_inode_ref_t *child)
    317317{
    318318        int rc;
    319319
    320         EXT4FS_DBG("adding entry to directory \%u [ino = \%u, name = \%s]", parent->index, child->index, entry_name);
    321 
    322         uint16_t name_len = strlen(entry_name);
     320        EXT4FS_DBG("adding entry to directory \%u [ino = \%u, name = \%s]", parent->index, child->index, name);
    323321
    324322        // Index adding (if allowed)
     
    326324                        ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) {
    327325
    328                 rc = ext4_directory_dx_add_entry(fs, parent, child, name_len, entry_name);
     326                rc = ext4_directory_dx_add_entry(fs, parent, child, name);
    329327
    330328                // Check if index is not corrupted
     
    347345        // Linear algorithm
    348346
    349         ext4_directory_iterator_t it;
    350         rc = ext4_directory_iterator_init(&it, fs, parent, 0);
    351         if (rc != EOK) {
    352                 return rc;
    353         }
    354 
     347        EXT4FS_DBG("Linear algorithm");
     348
     349        uint32_t iblock, fblock;
    355350        uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
    356         uint16_t required_len = 8 + name_len + (4 - name_len % 4);
    357 
    358         while (it.current != NULL) {
    359                 uint32_t entry_inode = ext4_directory_entry_ll_get_inode(it.current);
    360                 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(it.current);
    361 
    362                 if ((entry_inode == 0) && (rec_len >= required_len)) {
    363 
    364                         ext4_directory_write_entry(fs->superblock, it.current, rec_len,
    365                                         child, entry_name, name_len);
    366                         it.current_block->dirty = true;
    367                         return ext4_directory_iterator_fini(&it);
    368                 }
    369 
    370                 if (entry_inode != 0) {
    371                         uint16_t used_name_len = ext4_directory_entry_ll_get_name_length(
    372                                         fs->superblock, it.current);
    373 
    374                         uint16_t used_space = 8 + used_name_len;
    375                         if ((used_name_len % 4) != 0) {
    376                                 used_space += 4 - (used_name_len % 4);
    377                         }
    378                         uint16_t free_space = rec_len - used_space;
    379 
    380                         EXT4FS_DBG("rec_len = \%u, used_space = \%u, free space = \%u", rec_len, used_space, free_space);
    381 
    382                         if (free_space >= required_len) {
    383 
    384                                 // Cut tail of current entry
    385                                 ext4_directory_entry_ll_set_entry_length(it.current, used_space);
    386 
    387                                 // SEEK manually
    388                                 uint32_t local_offset = (it.current_offset % block_size);
    389                                 local_offset += used_space;
    390                                 ext4_directory_entry_ll_t *new_entry = it.current_block->data + local_offset;
    391 
    392                                 // We are sure, that both entries are in the same data block
    393                                 // dirtyness will be set now
    394 
    395                                 ext4_directory_write_entry(fs->superblock, new_entry,
    396                                                 free_space, child, entry_name, name_len);
    397                                 it.current_block->dirty = true;
    398                                 return ext4_directory_iterator_fini(&it);
    399                         }
    400 
    401                 }
    402 
    403                 rc = ext4_directory_iterator_next(&it);
    404                 if (rc != EOK) {
    405                         return rc;
    406                 }
    407         }
    408 
    409         // Destroy iterator
    410         ext4_directory_iterator_fini(&it);
     351        uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode);
     352        uint32_t total_blocks = inode_size / block_size;
     353
     354        uint32_t name_len = strlen(name);
     355
     356        bool success = false;
     357        for (iblock = 0; iblock < total_blocks; ++iblock) {
     358
     359                rc = ext4_filesystem_get_inode_data_block_index(fs, parent->inode, iblock, &fblock);
     360                if (rc != EOK) {
     361                        return rc;
     362                }
     363
     364                block_t *block;
     365                rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
     366                if (rc != EOK) {
     367                        return rc;
     368                }
     369
     370                rc = ext4_directory_try_insert_entry(fs->superblock, block, child, name, name_len);
     371                if (rc == EOK) {
     372                        success = true;
     373                }
     374
     375                rc = block_put(block);
     376                if (rc != EOK) {
     377                        return rc;
     378                }
     379
     380                if (success) {
     381                        return EOK;
     382                }
     383        }
     384
    411385
    412386        EXT4FS_DBG("NO FREE SPACE - needed to allocate block");
    413387
    414         uint32_t fblock;
    415         uint32_t iblock;
    416388        rc = ext4_directory_append_block(fs, parent, &fblock, &iblock);
    417389        if (rc != EOK) {
     
    428400        // Fill block with zeroes
    429401        memset(new_block->data, 0, block_size);
    430 
    431402        ext4_directory_entry_ll_t *block_entry = new_block->data;
    432 
    433         ext4_directory_write_entry(fs->superblock, block_entry, block_size,
    434         child, entry_name, name_len);
     403        ext4_directory_write_entry(fs->superblock, block_entry, block_size, child, name, name_len);
    435404
    436405        new_block->dirty = true;
     
    556525}
    557526
     527int ext4_directory_try_insert_entry(ext4_superblock_t *sb,
     528                block_t *target_block, ext4_inode_ref_t *child,
     529                const char *name, uint32_t name_len)
     530{
     531        uint32_t block_size = ext4_superblock_get_block_size(sb);
     532        uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len;
     533        if ((required_len % 4) != 0) {
     534                required_len += 4 - (required_len % 4);
     535        }
     536
     537        ext4_directory_entry_ll_t *dentry = target_block->data;
     538        ext4_directory_entry_ll_t *stop = target_block->data + block_size;
     539
     540        while (dentry < stop) {
     541
     542                uint32_t inode = ext4_directory_entry_ll_get_inode(dentry);
     543                uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry);
     544
     545                if ((inode == 0) && (rec_len >= required_len)) {
     546                        ext4_directory_write_entry(sb, dentry, rec_len, child, name, name_len);
     547                        target_block->dirty = true;
     548                        return EOK;
     549                }
     550
     551                if (inode != 0) {
     552                        uint16_t used_name_len =
     553                                        ext4_directory_entry_ll_get_name_length(sb, dentry);
     554
     555                        uint16_t used_space =
     556                                        sizeof(ext4_fake_directory_entry_t) + used_name_len;
     557                        if ((used_name_len % 4) != 0) {
     558                                used_space += 4 - (used_name_len % 4);
     559                        }
     560                        uint16_t free_space = rec_len - used_space;
     561
     562                        if (free_space >= required_len) {
     563
     564                                // Cut tail of current entry
     565                                ext4_directory_entry_ll_set_entry_length(dentry, used_space);
     566                                ext4_directory_entry_ll_t *new_entry =
     567                                                (void *)dentry + used_space;
     568                                ext4_directory_write_entry(sb, new_entry,
     569                                                free_space, child, name, name_len);
     570
     571                                target_block->dirty = true;
     572                                return EOK;
     573                        }
     574                }
     575
     576                dentry = (void *)dentry + rec_len;
     577        }
     578
     579        return ENOSPC;
     580}
     581
    558582
    559583/**
Note: See TracChangeset for help on using the changeset viewer.