Changeset 7bc4508 in mainline for uspace/lib/ext4/libext4_directory.c


Ignore:
Timestamp:
2011-10-18T19:58:36Z (14 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7bd2c19
Parents:
12f55220
Message:

First part of reading htree directory index - the most important functionality (computing hashes) still missing

File:
1 edited

Legend:

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

    r12f55220 r7bc4508  
    6666}
    6767
     68uint8_t ext4_directory_dx_root_info_get_hash_version(ext4_directory_dx_root_info_t *root_info)
     69{
     70        return root_info->hash_version;
     71}
     72
     73uint8_t ext4_directory_dx_root_info_get_info_length(ext4_directory_dx_root_info_t *root_info)
     74{
     75        return root_info->info_length;
     76}
     77
     78uint8_t ext4_directory_dx_root_info_get_indirect_levels(ext4_directory_dx_root_info_t *root_info)
     79{
     80        return root_info->indirect_levels;
     81}
     82
     83uint16_t ext4_directory_dx_countlimit_get_limit(ext4_directory_dx_countlimit_t *countlimit)
     84{
     85        return uint16_t_le2host(countlimit->limit);
     86}
     87uint16_t ext4_directory_dx_countlimit_get_count(ext4_directory_dx_countlimit_t *countlimit)
     88{
     89        return uint16_t_le2host(countlimit->count);
     90}
     91
     92uint32_t ext4_directory_dx_entry_get_hash(ext4_directory_dx_entry_t *entry)
     93{
     94        return uint32_t_le2host(entry->hash);
     95}
     96
     97uint32_t ext4_directory_dx_entry_get_block(ext4_directory_dx_entry_t *entry)
     98{
     99        return uint32_t_le2host(entry->block);
     100}
     101
     102
     103
    68104int ext4_directory_iterator_init(ext4_directory_iterator_t *it,
    69105    ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, aoff64_t pos)
     
    209245}
    210246
     247int ext4_directory_dx_find_entry(ext4_directory_iterator_t *it,
     248                ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, const char *name)
     249{
     250        int rc;
     251        uint32_t fblock;
     252        block_t *phys_block;
     253        ext4_directory_dx_root_t *root;
     254        uint32_t hash;
     255        ext4_directory_dx_hash_info_t hinfo;
     256
     257        // get direct block 0 (index root)
     258        rc = ext4_filesystem_get_inode_data_block_index(fs, inode_ref->inode, 0, &fblock);
     259        if (rc != EOK) {
     260                return rc;
     261        }
     262
     263        rc = block_get(&phys_block, fs->device, fblock, BLOCK_FLAGS_NONE);
     264        if (rc != EOK) {
     265                it->current_block = NULL;
     266                        return rc;
     267        }
     268
     269        // Now having index root
     270        root = (ext4_directory_dx_root_t *)phys_block->data;
     271
     272        // Check hash version - only if supported
     273        EXT4FS_DBG("hash_version = \%u", root->info.hash_version);
     274
     275        // Check unused flags
     276        if (root->info.unused_flags != 0) {
     277                EXT4FS_DBG("ERR: unused_flags = \%u", root->info.unused_flags);
     278                block_put(phys_block);
     279                return EXT4_ERR_BAD_DX_DIR;
     280        }
     281
     282        // Check indirect levels
     283        if (root->info.indirect_levels > 1) {
     284                EXT4FS_DBG("ERR: indirect_levels = \%u", root->info.indirect_levels);
     285                block_put(phys_block);
     286                return EXT4_ERR_BAD_DX_DIR;
     287        }
     288
     289        uint32_t bs = ext4_superblock_get_block_size(fs->superblock);
     290
     291        uint32_t entry_space = bs - 2* sizeof(ext4_directory_dx_dot_entry_t) - sizeof(ext4_directory_dx_root_info_t);
     292    entry_space = entry_space / sizeof(ext4_directory_dx_entry_t);
     293
     294
     295    uint32_t limit = ext4_directory_dx_countlimit_get_limit((ext4_directory_dx_countlimit_t *)&root->entries);
     296    uint32_t count = ext4_directory_dx_countlimit_get_count((ext4_directory_dx_countlimit_t *)&root->entries);
     297
     298    if (limit != entry_space) {
     299                block_put(phys_block);
     300        return EXT4_ERR_BAD_DX_DIR;
     301        }
     302
     303        if ((count == 0) || (count > limit)) {
     304                block_put(phys_block);
     305                return EXT4_ERR_BAD_DX_DIR;
     306        }
     307
     308        /* DEBUG list
     309    for (uint16_t i = 0; i < count; ++i) {
     310        uint32_t hash = ext4_directory_dx_entry_get_hash(&root->entries[i]);
     311        uint32_t block = ext4_directory_dx_entry_get_block(&root->entries[i]);
     312        EXT4FS_DBG("hash = \%u, block = \%u", hash, block);
     313    }
     314    */
     315
     316        hinfo.hash_version = ext4_directory_dx_root_info_get_hash_version(&root->info);
     317        if ((hinfo.hash_version <= EXT4_DIRECTORY_DX_HASH_TEA)
     318                        && (ext4_superblock_has_flag(fs->superblock, EXT4_SUPERBLOCK_FLAGS_UNSIGNED_HASH))) {
     319                // 3 is magic from ext4 linux implementation
     320                hinfo.hash_version += 3;
     321        }
     322
     323        hinfo.seed = ext4_superblock_get_hash_seed(fs->superblock);
     324        hinfo.hash = 0;
     325        if (name) {
     326                ext4_directory_hash(&hinfo, name);
     327        }
     328
     329        hash = hinfo.hash;
     330
     331        ext4_directory_dx_entry_t *p, *q, *m;
     332
     333        // TODO cycle
     334        // while (true)
     335
     336                p = &root->entries[1];
     337                q = &root->entries[count - 1];
     338
     339                while (p <= q) {
     340                        m = p + (q - p) / 2;
     341                        if (ext4_directory_dx_entry_get_hash(m) > hash) {
     342                                q = m - 1;
     343                        } else {
     344                                p = m + 1;
     345                        }
     346                }
     347
     348                /* TODO move to leaf or next node
     349                at = p - 1;
     350                dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
     351        frame->bh = bh;
     352        frame->entries = entries;
     353        frame->at = at;
     354
     355        if (indirect == 0) {
     356                        // TODO write return values !!!
     357                return EOK;
     358        }
     359
     360        indirect--;
     361
     362                // TODO read next block
     363                if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
     364                        goto fail2;
     365                at = entries = ((struct dx_node *) bh->b_data)->entries;
     366                if (dx_get_limit(entries) != dx_node_limit (dir)) {
     367                ext4_warning(dir->i_sb, "dx entry: limit != node limit");
     368                        brelse(bh);
     369            *err = ERR_BAD_DX_DIR;
     370                        goto fail2;
     371                }
     372                frame++;
     373                frame->bh = NULL;
     374                 */
     375
     376        // } END WHILE
     377
     378
     379        // TODO delete it !!!
     380        return EXT4_ERR_BAD_DX_DIR;
     381
     382        if ((it->current == NULL) || (it->current->inode == 0)) {
     383                        return ENOENT;
     384        }
     385
     386        return EOK;
     387}
     388
     389void ext4_directory_hash(ext4_directory_dx_hash_info_t *hinfo, const char* name)
     390{
     391        // TODO
     392}
    211393
    212394/**
Note: See TracChangeset for help on using the changeset viewer.