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

Changeset 2e07f62c in mainline


Ignore:
Timestamp:
2010-01-31T18:11:24Z (10 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
1735f3e, 7d6f7d2b
Parents:
ab4bace (diff), 430de97 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge progress from the file system branch allowing FAT to be unmounted.

Location:
uspace
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libblock/libblock.c

    rab4bace r2e07f62c  
    198198        assert(devcon);
    199199       
     200        if (devcon->cache)
     201                (void) block_cache_fini(dev_handle);
     202
    200203        devcon_remove(devcon);
    201204
    202205        if (devcon->bb_buf)
    203206                free(devcon->bb_buf);
    204 
    205         if (devcon->cache) {
    206                 hash_table_destroy(&devcon->cache->block_hash);
    207                 free(devcon->cache);
    208         }
    209207
    210208        munmap(devcon->comm_area, devcon->comm_size);
     
    302300
    303301        devcon->cache = cache;
     302        return EOK;
     303}
     304
     305int block_cache_fini(dev_handle_t dev_handle)
     306{
     307        devcon_t *devcon = devcon_search(dev_handle);
     308        cache_t *cache;
     309        int rc;
     310
     311        if (!devcon)
     312                return ENOENT;
     313        if (!devcon->cache)
     314                return EOK;
     315        cache = devcon->cache;
     316       
     317        /*
     318         * We are expecting to find all blocks for this device handle on the
     319         * free list, i.e. the block reference count should be zero. Do not
     320         * bother with the cache and block locks because we are single-threaded.
     321         */
     322        while (!list_empty(&cache->free_head)) {
     323                block_t *b = list_get_instance(cache->free_head.next,
     324                    block_t, free_link);
     325
     326                list_remove(&b->free_link);
     327                if (b->dirty) {
     328                        memcpy(devcon->comm_area, b->data, b->size);
     329                        rc = write_blocks(devcon, b->boff, 1);
     330                        if (rc != EOK)
     331                                return rc;
     332                }
     333
     334                long key = b->boff;
     335                hash_table_remove(&cache->block_hash, &key, 1);
     336               
     337                free(b->data);
     338                free(b);
     339        }
     340
     341        hash_table_destroy(&cache->block_hash);
     342        devcon->cache = NULL;
     343        free(cache);
     344
    304345        return EOK;
    305346}
  • uspace/lib/libblock/libblock.h

    rab4bace r2e07f62c  
    100100
    101101extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode);
     102extern int block_cache_fini(dev_handle_t);
    102103
    103104extern int block_get(block_t **, dev_handle_t, bn_t, int);
  • uspace/srv/fs/fat/fat_idx.c

    rab4bace r2e07f62c  
    149149{
    150150        dev_handle_t dev_handle = (dev_handle_t)key[UPH_DH_KEY];
    151         fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
    152         unsigned pdi = (unsigned)key[UPH_PDI_KEY];
     151        fat_cluster_t pfc;
     152        unsigned pdi;
    153153        fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uph_link);
    154154
    155         return (dev_handle == fidx->dev_handle) && (pfc == fidx->pfc) &&
    156             (pdi == fidx->pdi);
     155        switch (keys) {
     156        case 1:
     157                return (dev_handle == fidx->dev_handle);
     158        case 3:
     159                pfc = (fat_cluster_t) key[UPH_PFC_KEY];
     160                pdi = (unsigned) key[UPH_PDI_KEY];
     161                return (dev_handle == fidx->dev_handle) && (pfc == fidx->pfc) &&
     162                    (pdi == fidx->pdi);
     163        default:
     164                assert((keys == 1) || (keys == 3));
     165        }
    157166}
    158167
     
    197206{
    198207        dev_handle_t dev_handle = (dev_handle_t)key[UIH_DH_KEY];
    199         fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
     208        fs_index_t index;
    200209        fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
    201210
    202         return (dev_handle == fidx->dev_handle) && (index == fidx->index);
     211        switch (keys) {
     212        case 1:
     213                return (dev_handle == fidx->dev_handle);
     214        case 2:
     215                index = (fs_index_t) key[UIH_INDEX_KEY];
     216                return (dev_handle == fidx->dev_handle) &&
     217                    (index == fidx->index);
     218        default:
     219                assert((keys == 1) || (keys == 2));
     220        }
    203221}
    204222
    205223static void idx_remove_callback(link_t *item)
    206224{
    207         /* nothing to do */
     225        fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
     226
     227        free(fidx);
    208228}
    209229
     
    486506                [UIH_INDEX_KEY] = idx->index,
    487507        };
     508        dev_handle_t dev_handle = idx->dev_handle;
     509        fs_index_t index = idx->index;
    488510
    489511        assert(idx->pfc == FAT_CLST_RES0);
     
    498520        fibril_mutex_unlock(&used_lock);
    499521        /* Release the VFS index. */
    500         fat_index_free(idx->dev_handle, idx->index);
    501         /* Deallocate the structure. */
    502         free(idx);
     522        fat_index_free(dev_handle, index);
     523        /* The index structure itself is freed in idx_remove_callback(). */
    503524}
    504525
     
    543564void fat_idx_fini_by_dev_handle(dev_handle_t dev_handle)
    544565{
    545         unused_t *u;
    546 
    547         u = unused_find(dev_handle, true);
     566        unsigned long ikey[] = {
     567                [UIH_DH_KEY] = dev_handle
     568        };
     569        unsigned long pkey[] = {
     570                [UPH_DH_KEY] = dev_handle
     571        };
     572
     573        /*
     574         * Remove this instance's index structure from up_hash and ui_hash.
     575         * Process up_hash first and ui_hash second because the index structure
     576         * is actually removed in idx_remove_callback().
     577         */
     578        fibril_mutex_lock(&used_lock);
     579        hash_table_remove(&up_hash, pkey, 1);
     580        hash_table_remove(&ui_hash, ikey, 1);
     581        fibril_mutex_unlock(&used_lock);
     582
     583        /*
     584         * Free the unused and freed structures for this instance.
     585         */
     586        unused_t *u = unused_find(dev_handle, true);
    548587        assert(u);
    549588        list_remove(&u->link);
  • uspace/srv/fs/fat/fat_ops.c

    rab4bace r2e07f62c  
    137137        rc = block_put(b);
    138138        return rc;
     139}
     140
     141static int fat_node_fini_by_dev_handle(dev_handle_t dev_handle)
     142{
     143        link_t *lnk;
     144        fat_node_t *nodep;
     145        int rc;
     146
     147        /*
     148         * We are called from fat_unmounted() and assume that there are already
     149         * no nodes belonging to this instance with non-zero refcount. Therefore
     150         * it is sufficient to clean up only the FAT free node list.
     151         */
     152
     153restart:
     154        fibril_mutex_lock(&ffn_mutex);
     155        for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
     156                nodep = list_get_instance(lnk, fat_node_t, ffn_link);
     157                if (!fibril_mutex_trylock(&nodep->lock)) {
     158                        fibril_mutex_unlock(&ffn_mutex);
     159                        goto restart;
     160                }
     161                if (!fibril_mutex_trylock(&nodep->idx->lock)) {
     162                        fibril_mutex_unlock(&nodep->lock);
     163                        fibril_mutex_unlock(&ffn_mutex);
     164                        goto restart;
     165                }
     166                if (nodep->idx->dev_handle != dev_handle) {
     167                        fibril_mutex_unlock(&nodep->idx->lock);
     168                        fibril_mutex_unlock(&nodep->lock);
     169                        continue;
     170                }
     171
     172                list_remove(&nodep->ffn_link);
     173                fibril_mutex_unlock(&ffn_mutex);
     174
     175                /*
     176                 * We can unlock the node and its index structure because we are
     177                 * the last player on this playground and VFS is preventing new
     178                 * players from entering.
     179                 */
     180                fibril_mutex_unlock(&nodep->idx->lock);
     181                fibril_mutex_unlock(&nodep->lock);
     182
     183                if (nodep->dirty) {
     184                        rc = fat_node_sync(nodep);
     185                        if (rc != EOK)
     186                                return rc;
     187                }
     188                nodep->idx->nodep = NULL;
     189                free(nodep->bp);
     190                free(nodep);
     191
     192                /* Need to restart because we changed the ffn_head list. */
     193                goto restart;
     194        }
     195        fibril_mutex_unlock(&ffn_mutex);
     196
     197        return EOK;
    139198}
    140199
     
    9861045        rc = fat_sanity_check(bs, dev_handle);
    9871046        if (rc != EOK) {
     1047                (void) block_cache_fini(dev_handle);
    9881048                block_fini(dev_handle);
    9891049                ipc_answer_0(rid, rc);
     
    9931053        rc = fat_idx_init_by_dev_handle(dev_handle);
    9941054        if (rc != EOK) {
     1055                (void) block_cache_fini(dev_handle);
    9951056                block_fini(dev_handle);
    9961057                ipc_answer_0(rid, rc);
     
    10011062        fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
    10021063        if (!rfn) {
     1064                (void) block_cache_fini(dev_handle);
    10031065                block_fini(dev_handle);
    10041066                fat_idx_fini_by_dev_handle(dev_handle);
     
    10101072        if (!rootp) {
    10111073                free(rfn);
     1074                (void) block_cache_fini(dev_handle);
    10121075                block_fini(dev_handle);
    10131076                fat_idx_fini_by_dev_handle(dev_handle);
     
    10211084                free(rfn);
    10221085                free(rootp);
     1086                (void) block_cache_fini(dev_handle);
    10231087                block_fini(dev_handle);
    10241088                fat_idx_fini_by_dev_handle(dev_handle);
     
    10511115void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
    10521116{
    1053         ipc_answer_0(rid, ENOTSUP);
     1117        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     1118        fs_node_t *fn;
     1119        fat_node_t *nodep;
     1120        int rc;
     1121
     1122        rc = fat_root_get(&fn, dev_handle);
     1123        if (rc != EOK) {
     1124                ipc_answer_0(rid, rc);
     1125                return;
     1126        }
     1127        nodep = FAT_NODE(fn);
     1128
     1129        /*
     1130         * We expect exactly two references on the root node. One for the
     1131         * fat_root_get() above and one created in fat_mounted().
     1132         */
     1133        if (nodep->refcnt != 2) {
     1134                (void) fat_node_put(fn);
     1135                ipc_answer_0(rid, EBUSY);
     1136                return;
     1137        }
     1138       
     1139        /*
     1140         * Put the root node and force it to the FAT free node list.
     1141         */
     1142        (void) fat_node_put(fn);
     1143        (void) fat_node_put(fn);
     1144
     1145        /*
     1146         * Perform cleanup of the node structures, index structures and
     1147         * associated data. Write back this file system's dirty blocks and
     1148         * stop using libblock for this instance.
     1149         */
     1150        (void) fat_node_fini_by_dev_handle(dev_handle);
     1151        fat_idx_fini_by_dev_handle(dev_handle);
     1152        (void) block_cache_fini(dev_handle);
     1153        block_fini(dev_handle);
     1154
     1155        ipc_answer_0(rid, EOK);
    10541156}
    10551157
Note: See TracChangeset for help on using the changeset viewer.