Changeset d1ac0d7 in mainline


Ignore:
Timestamp:
2011-05-03T20:37:06Z (13 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
423f64f
Parents:
daa36d3
Message:

Fixed bugs with mounting

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/ext2fs/ext2fs_ops.c

    rdaa36d3 rd1ac0d7  
    6262#define EXT2FS_NODE(node)       ((node) ? (ext2fs_node_t *) (node)->data : NULL)
    6363#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
     64#define OPEN_NODES_KEYS 2
     65#define OPEN_NODES_DEV_HANDLE_KEY 0
     66#define OPEN_NODES_INODE_KEY 1
     67#define OPEN_NODES_BUCKETS 256
    6468
    6569typedef struct ext2fs_instance {
     
    6771        devmap_handle_t devmap_handle;
    6872        ext2_filesystem_t *filesystem;
     73        unsigned int open_nodes_count;
    6974} ext2fs_instance_t;
    7075
     
    7277        ext2fs_instance_t *instance;
    7378        ext2_inode_ref_t *inode_ref;
     79        fs_node_t *fs_node;
     80        link_t link;
     81        unsigned int references;
    7482} ext2fs_node_t;
    7583
     
    8492static bool ext2fs_is_dots(const uint8_t *, size_t);
    8593static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
     94static int ext2fs_node_put_core(ext2fs_node_t *);
    8695
    8796/*
     
    111120static LIST_INITIALIZE(instance_list);
    112121static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex);
     122static hash_table_t open_nodes;
     123static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
     124
     125/* Hash table interface for open nodes hash table */
     126static hash_index_t open_nodes_hash(unsigned long key[])
     127{
     128        /* TODO: This is very simple and probably can be improved */
     129        return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
     130}
     131
     132static int open_nodes_compare(unsigned long key[], hash_count_t keys,
     133    link_t *item)
     134{
     135        ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
     136        assert(keys > 0);
     137        if (enode->instance->devmap_handle !=
     138            ((devmap_handle_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
     139                return false;
     140        }
     141        if (keys == 1) {
     142                return true;
     143        }
     144        assert(keys == 2);
     145        return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
     146}
     147
     148static void open_nodes_remove_cb(link_t *link)
     149{
     150        /* We don't use remove callback for this hash table */
     151}
     152
     153static hash_table_operations_t open_nodes_ops = {
     154        .hash = open_nodes_hash,
     155        .compare = open_nodes_compare,
     156        .remove_callback = open_nodes_remove_cb,
     157};
    113158
    114159/**
     
    117162int ext2fs_global_init(void)
    118163{
     164        if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
     165            OPEN_NODES_KEYS, &open_nodes_ops)) {
     166                return ENOMEM;
     167        }
    119168        return EOK;
    120169}
     
    122171int ext2fs_global_fini(void)
    123172{
     173        hash_table_destroy(&open_nodes);
    124174        return EOK;
    125175}
    126 
    127176
    128177
     
    262311        ext2_inode_ref_t *inode_ref = NULL;
    263312
     313        fibril_mutex_lock(&open_nodes_lock);
     314       
     315        /* Check if the node is not already open */
     316        unsigned long key[] = {
     317                [OPEN_NODES_DEV_HANDLE_KEY] = inst->devmap_handle,
     318                [OPEN_NODES_INODE_KEY] = index,
     319        };
     320        link_t *already_open = hash_table_find(&open_nodes, key);
     321
     322        if (already_open) {
     323                enode = hash_table_get_instance(already_open, ext2fs_node_t, link);
     324                *rfn = enode->fs_node;
     325                enode->references++;
     326
     327                fibril_mutex_unlock(&open_nodes_lock);
     328                return EOK;
     329        }
     330
    264331        enode = malloc(sizeof(ext2fs_node_t));
    265332        if (enode == NULL) {
     333                fibril_mutex_unlock(&open_nodes_lock);
    266334                return ENOMEM;
    267335        }
     
    270338        if (node == NULL) {
    271339                free(enode);
     340                fibril_mutex_unlock(&open_nodes_lock);
    272341                return ENOMEM;
    273342        }       
     
    278347                free(enode);
    279348                free(node);
     349                fibril_mutex_unlock(&open_nodes_lock);
    280350                return rc;
    281351        }
     
    283353        enode->inode_ref = inode_ref;
    284354        enode->instance = inst;
     355        enode->references = 1;
     356        enode->fs_node = node;
     357        link_initialize(&enode->link);
     358       
    285359        node->data = enode;
    286360        *rfn = node;
    287361       
     362        hash_table_insert(&open_nodes, key, &enode->link);
     363        inst->open_nodes_count++;
     364       
    288365        EXT2FS_DBG("inode: %u", inode_ref->index);
    289366       
    290367        EXT2FS_DBG("EOK");
    291368
     369        fibril_mutex_unlock(&open_nodes_lock);
    292370        return EOK;
    293371}
     
    308386        int rc;
    309387        ext2fs_node_t *enode = EXT2FS_NODE(fn);
     388       
     389        fibril_mutex_lock(&open_nodes_lock);
     390
     391        assert(enode->references > 0);
     392        enode->references--;
     393        if (enode->references == 0) {
     394                rc = ext2fs_node_put_core(enode);
     395                if (rc != EOK) {
     396                        fibril_mutex_unlock(&open_nodes_lock);
     397                        return rc;
     398                }
     399        }
     400
     401        fibril_mutex_unlock(&open_nodes_lock);
     402       
     403        return EOK;
     404}
     405
     406int ext2fs_node_put_core(ext2fs_node_t *enode)
     407{
     408        int rc;
     409
     410        unsigned long key[] = {
     411                [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->devmap_handle,
     412                [OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
     413        };
     414        hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
     415        assert(enode->instance->open_nodes_count > 0);
     416        enode->instance->open_nodes_count--;
     417
    310418        rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
    311419        if (rc != EOK) {
    312420                EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
    313         }
    314         return rc;
     421                return rc;
     422        }
     423
     424        free(enode->fs_node);
     425        free(enode);
     426        return EOK;
    315427}
    316428
     
    544656        }
    545657       
    546         /* Initialize instance and add to the list */
     658        /* Initialize instance */
    547659        link_initialize(&inst->link);
    548660        inst->devmap_handle = devmap_handle;
    549661        inst->filesystem = fs;
    550        
     662        inst->open_nodes_count = 0;
     663       
     664        /* Read root node */
     665        fs_node_t *root_node;
     666        rc = ext2fs_node_get_core(&root_node, inst, EXT2_INODE_ROOT_INDEX);
     667        if (rc != EOK) {
     668                ext2_filesystem_fini(fs);
     669                free(fs);
     670                free(inst);
     671                async_answer_0(rid, rc);
     672                return;
     673        }
     674        ext2fs_node_t *enode = EXT2FS_NODE(root_node);
     675               
     676        /* Add instance to the list */
    551677        fibril_mutex_lock(&instance_list_mutex);
    552678        list_append(&inst->link, &instance_list);
    553679        fibril_mutex_unlock(&instance_list_mutex);
    554680       
    555         async_answer_0(rid, EOK);
     681        async_answer_3(rid, EOK,
     682            EXT2_INODE_ROOT_INDEX,
     683            0,
     684            ext2_inode_get_usage_count(enode->inode_ref->inode));
     685       
     686        ext2fs_node_put(root_node);
    556687}
    557688
     
    576707        }
    577708       
    578         // TODO: check if the fs is busy
     709        fibril_mutex_lock(&open_nodes_lock);
     710
     711        EXT2FS_DBG("open_nodes_count = %d", inst->open_nodes_count)
     712        if (inst->open_nodes_count != 0) {
     713                fibril_mutex_unlock(&open_nodes_lock);
     714                async_answer_0(rid, EBUSY);
     715                return;
     716        }
    579717       
    580718        // Remove the instance from list
     
    582720        list_remove(&inst->link);
    583721        fibril_mutex_unlock(&instance_list_mutex);
     722
     723        fibril_mutex_unlock(&open_nodes_lock);
    584724       
    585725        ext2_filesystem_fini(inst->filesystem);
Note: See TracChangeset for help on using the changeset viewer.