Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d0d7afb in mainline


Ignore:
Timestamp:
2012-03-01T19:56:31Z (10 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master
Children:
c30a015
Parents:
d8269dc
Message:

Code refactorization (entry insertion)

Location:
uspace/lib/ext4
Files:
4 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/**
  • uspace/lib/ext4/libext4_directory.h

    rd8269dc rd0d7afb  
    106106                ext4_inode_ref_t *, const char *);
    107107
     108extern int ext4_directory_try_insert_entry(ext4_superblock_t *,
     109                block_t *, ext4_inode_ref_t *, const char *, uint32_t);
    108110#endif
    109111
  • uspace/lib/ext4/libext4_directory_index.c

    rd8269dc rd0d7afb  
    503503                block_t *old_data_block, ext4_directory_dx_block_t *index_block, block_t **new_data_block)
    504504{
    505         int rc;
     505        int rc = EOK;
    506506
    507507        uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
     
    652652
    653653int ext4_directory_dx_add_entry(ext4_filesystem_t *fs,
    654                 ext4_inode_ref_t *parent, ext4_inode_ref_t *child,
    655                 size_t name_size, const char *name)
    656 {
    657         int rc;
     654                ext4_inode_ref_t *parent, ext4_inode_ref_t *child, const char *name)
     655{
     656        int rc = EOK;
     657        int rc2;
    658658
    659659        // get direct block 0 (index root)
     
    670670        }
    671671
     672        uint32_t name_len = strlen(name);
    672673        ext4_hash_info_t hinfo;
    673         rc = ext4_directory_hinfo_init(&hinfo, root_block, fs->superblock, name_size, name);
     674        rc = ext4_directory_hinfo_init(&hinfo, root_block, fs->superblock, name_len, name);
    674675        if (rc != EOK) {
    675676                block_put(root_block);
     
    702703        }
    703704
    704         uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
    705         uint16_t required_len = 8 + name_size + (4 - name_size % 4);
    706 
    707         ext4_directory_entry_ll_t *de = target_block->data;
    708         ext4_directory_entry_ll_t *stop = target_block->data + block_size;
    709 
    710         while (de < stop) {
    711 
    712                 uint32_t de_inode = ext4_directory_entry_ll_get_inode(de);
    713                 uint16_t de_rec_len = ext4_directory_entry_ll_get_entry_length(de);
    714 
    715                 if ((de_inode == 0) && (de_rec_len >= required_len)) {
    716                         ext4_directory_write_entry(fs->superblock, de, de_rec_len,
    717                                 child, name, name_size);
    718 
    719                                 // TODO cleanup
    720                                 target_block->dirty = true;
    721                                 rc = block_put(target_block);
    722                                 if (rc != EOK) {
    723                                         return EXT4_ERR_BAD_DX_DIR;
    724                                 }
    725                                 return EOK;
    726                 }
    727 
    728                 if (de_inode != 0) {
    729                         uint16_t used_name_len = ext4_directory_entry_ll_get_name_length(
    730                                         fs->superblock, de);
    731 
    732                         uint16_t used_space = 8 + used_name_len;
    733                         if ((used_name_len % 4) != 0) {
    734                                 used_space += 4 - (used_name_len % 4);
    735                         }
    736                         uint16_t free_space = de_rec_len - used_space;
    737 
    738                         if (free_space >= required_len) {
    739 
    740                                 // Cut tail of current entry
    741                                 ext4_directory_entry_ll_set_entry_length(de, used_space);
    742                                 ext4_directory_entry_ll_t *new_entry = (void *)de + used_space;
    743                                 ext4_directory_write_entry(fs->superblock, new_entry,
    744                                         free_space, child, name, name_size);
    745 
    746                                 // TODO cleanup
    747                                 target_block->dirty = true;
    748                                 rc = block_put(target_block);
    749                                 if (rc != EOK) {
    750                                         return EXT4_ERR_BAD_DX_DIR;
    751                                 }
    752                                 return EOK;
    753 
    754                         }
    755 
    756                 }
    757 
    758                 de = (void *)de + de_rec_len;
     705        rc = ext4_directory_try_insert_entry(fs->superblock, target_block, child, name, name_len);
     706        if (rc == EOK) {
     707                goto cleanup;
     708
    759709        }
    760710
    761711    EXT4FS_DBG("no free space found");
     712
     713    uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
    762714
    763715        ext4_directory_dx_entry_t *entries = ((ext4_directory_dx_node_t *) dx_block->block->data)->entries;
     
    786738                rc =  ext4_directory_append_block(fs, parent, &new_fblock, &new_iblock);
    787739                if (rc != EOK) {
    788                         // TODO error
     740                        goto cleanup;
    789741                }
    790742
     
    793745                rc = block_get(&new_block, fs->device, new_fblock, BLOCK_FLAGS_NOREAD);
    794746                if (rc != EOK) {
    795                         // TODO error
     747                        goto cleanup;
    796748                }
    797749
     
    873825        }
    874826
    875         // TODO Where to save new entry
     827        // Where to save new entry
    876828        uint32_t new_block_hash = ext4_directory_dx_entry_get_hash(dx_block->position + 1);
    877829        if (hinfo.hash >= new_block_hash) {
    878                 de = new_block->data;
    879                 stop = new_block->data + block_size;
     830                rc = ext4_directory_try_insert_entry(fs->superblock, new_block, child, name, name_len);
    880831        } else {
    881                 de = target_block->data;
    882                 stop = target_block->data + block_size;
    883         }
    884 
    885         while (de < stop) {
    886 
    887                 uint32_t de_inode = ext4_directory_entry_ll_get_inode(de);
    888                 uint16_t de_rec_len = ext4_directory_entry_ll_get_entry_length(de);
    889 
    890                 if ((de_inode == 0) && (de_rec_len >= required_len)) {
    891                         ext4_directory_write_entry(fs->superblock, de, de_rec_len,
    892                                 child, name, name_size);
    893                                 goto success;
    894                 }
    895 
    896                 if (de_inode != 0) {
    897                         uint16_t used_name_len = ext4_directory_entry_ll_get_name_length(
    898                                         fs->superblock, de);
    899 
    900                         uint16_t used_space = 8 + used_name_len;
    901                         if ((used_name_len % 4) != 0) {
    902                                 used_space += 4 - (used_name_len % 4);
    903                         }
    904                         uint16_t free_space = de_rec_len - used_space;
    905 
    906                         if (free_space >= required_len) {
    907 
    908                                 // Cut tail of current entry
    909                                 ext4_directory_entry_ll_set_entry_length(de, used_space);
    910                                 ext4_directory_entry_ll_t *new_entry = (void *)de + used_space;
    911                                 ext4_directory_write_entry(fs->superblock, new_entry,
    912                                         free_space, child, name, name_size);
    913 
    914                                 goto success;
    915                         }
    916 
    917                 }
    918 
    919                 de = (void *)de + de_rec_len;
    920         }
    921 
    922 success:
     832                rc = ext4_directory_try_insert_entry(fs->superblock, target_block, child, name, name_len);
     833        }
     834
     835        if (rc != EOK) {
     836                goto terminate;
     837        }
     838
     839
     840terminate:
     841        rc = block_put(new_block);
     842        if (rc != EOK) {
     843                EXT4FS_DBG("error writing new block");
     844        }
     845
     846
     847cleanup:
     848
     849        rc2 = rc;
    923850
    924851        rc = block_put(target_block);
    925852        if (rc != EOK) {
    926                 EXT4FS_DBG("error writing target block");
    927         }
    928         rc = block_put(new_block);
    929         if (rc != EOK) {
    930                 EXT4FS_DBG("error writing new block");
     853                return rc;
    931854        }
    932855
     
    936859                rc = block_put(dx_it->block);
    937860                if (rc != EOK) {
    938                         EXT4FS_DBG("error writing index block \%u", (uint32_t)dx_it->block->pba);
     861                        return rc;
    939862                }
    940863                dx_it++;
    941864        }
    942865
    943         return EOK;
     866        return rc2;
    944867}
    945868
  • uspace/lib/ext4/libext4_directory_index.h

    rd8269dc rd0d7afb  
    126126                ext4_filesystem_t *, ext4_inode_ref_t *, size_t, const char *);
    127127extern int ext4_directory_dx_add_entry(ext4_filesystem_t *,
    128                 ext4_inode_ref_t *, ext4_inode_ref_t *, size_t, const char *);
     128                ext4_inode_ref_t *, ext4_inode_ref_t *, const char *);
    129129
    130130#endif
Note: See TracChangeset for help on using the changeset viewer.