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

Changeset ff62c6d in mainline


Ignore:
Timestamp:
2009-08-27T20:00:17Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
1ee00b7, b7b3fda, cfa8738
Parents:
f2f89315 (diff), 402a18f (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 libblock improvements.

Location:
uspace
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/cmds/modules/bdd/bdd.c

    rf2f89315 rff62c6d  
    4040#include <devmap.h>
    4141#include <errno.h>
     42#include <assert.h>
    4243
    4344#define BLOCK_SIZE      512
     
    110111
    111112        while (size > 0) {
    112                 block = block_get(handle, boff, 0);
     113                rc = block_get(&block, handle, boff, 0);
     114                assert(rc == EOK);
    113115                blk = (uint8_t *) block->data;
    114116
     
    139141                }
    140142
    141                 block_put(block);
     143                rc = block_put(block);
     144                assert(rc == EOK);
    142145
    143146                if (size > rows * BPR)
  • uspace/lib/libblock/libblock.c

    rf2f89315 rff62c6d  
    306306        b->refcnt = 1;
    307307        b->dirty = false;
     308        b->toxic = false;
    308309        fibril_rwlock_initialize(&b->contents_lock);
    309310        link_initialize(&b->free_link);
     
    313314/** Instantiate a block in memory and get a reference to it.
    314315 *
     316 * @param block                 Pointer to where the function will store the
     317 *                              block pointer on success.
    315318 * @param dev_handle            Device handle of the block device.
    316319 * @param boff                  Block offset.
     
    319322 *                              device.
    320323 *
    321  * @return                      Block structure.
    322  */
    323 block_t *block_get(dev_handle_t dev_handle, bn_t boff, int flags)
     324 * @return                      EOK on success or a negative error code.
     325 */
     326int block_get(block_t **block, dev_handle_t dev_handle, bn_t boff, int flags)
    324327{
    325328        devcon_t *devcon;
     
    328331        link_t *l;
    329332        unsigned long key = boff;
    330         bn_t oboff;
     333        int rc = EOK;
    331334       
    332335        devcon = devcon_search(dev_handle);
     
    336339       
    337340        cache = devcon->cache;
     341
     342retry:
    338343        fibril_mutex_lock(&cache->lock);
    339344        l = hash_table_find(&cache->block_hash, &key);
     
    346351                if (b->refcnt++ == 0)
    347352                        list_remove(&b->free_link);
     353                if (b->toxic)
     354                        rc = EIO;
    348355                fibril_mutex_unlock(&b->lock);
    349356                fibril_mutex_unlock(&cache->lock);
     
    352359                 * The block was not found in the cache.
    353360                 */
    354                 int rc;
    355                 bool sync = false;
    356 
    357361                if (cache_can_grow(cache)) {
    358362                        /*
     
    378382                        assert(!list_empty(&cache->free_head));
    379383                        l = cache->free_head.next;
    380                         list_remove(l);
    381384                        b = list_get_instance(l, block_t, free_link);
    382                         sync = b->dirty;
    383                         oboff = b->boff;
     385
     386                        fibril_mutex_lock(&b->lock);
     387                        if (b->dirty) {
     388                                /*
     389                                 * The block needs to be written back to the
     390                                 * device before it changes identity. Do this
     391                                 * while not holding the cache lock so that
     392                                 * concurrency is not impeded. Also move the
     393                                 * block to the end of the free list so that we
     394                                 * do not slow down other instances of
     395                                 * block_get() draining the free list.
     396                                 */
     397                                list_remove(&b->free_link);
     398                                list_append(&b->free_link, &cache->free_head);
     399                                fibril_mutex_unlock(&cache->lock);
     400                                fibril_mutex_lock(&devcon->com_area_lock);
     401                                memcpy(devcon->com_area, b->data, b->size);
     402                                rc = write_block(devcon, b->boff,
     403                                    cache->block_size);
     404                                fibril_mutex_unlock(&devcon->com_area_lock);
     405                                if (rc != EOK) {
     406                                        /*
     407                                         * We did not manage to write the block
     408                                         * to the device. Keep it around for
     409                                         * another try. Hopefully, we will grab
     410                                         * another block next time.
     411                                         */
     412                                        fibril_mutex_unlock(&b->lock);
     413                                        goto retry;
     414                                }
     415                                b->dirty = false;
     416                                if (!fibril_mutex_trylock(&cache->lock)) {
     417                                        /*
     418                                         * Somebody is probably racing with us.
     419                                         * Unlock the block and retry.
     420                                         */
     421                                        fibril_mutex_unlock(&b->lock);
     422                                        goto retry;
     423                                }
     424
     425                        }
     426                        fibril_mutex_unlock(&b->lock);
     427
     428                        /*
     429                         * Unlink the block from the free list and the hash
     430                         * table.
     431                         */
     432                        list_remove(&b->free_link);
    384433                        temp_key = b->boff;
    385434                        hash_table_remove(&cache->block_hash, &temp_key, 1);
     
    394443                /*
    395444                 * Lock the block before releasing the cache lock. Thus we don't
    396                  * kill concurent operations on the cache while doing I/O on the
    397                  * block.
     445                 * kill concurrent operations on the cache while doing I/O on
     446                 * the block.
    398447                 */
    399448                fibril_mutex_lock(&b->lock);
    400449                fibril_mutex_unlock(&cache->lock);
    401450
    402                 if (sync) {
    403                         /*
    404                          * The block is dirty and needs to be written back to
    405                          * the device before we can read in the new contents.
    406                          */
    407                         fibril_mutex_lock(&devcon->com_area_lock);
    408                         memcpy(devcon->com_area, b->data, b->size);
    409                         rc = write_block(devcon, oboff, cache->block_size);
    410                         assert(rc == EOK);
    411                         fibril_mutex_unlock(&devcon->com_area_lock);
    412                 }
    413451                if (!(flags & BLOCK_FLAGS_NOREAD)) {
    414452                        /*
     
    418456                        fibril_mutex_lock(&devcon->com_area_lock);
    419457                        rc = read_block(devcon, b->boff, cache->block_size);
    420                         assert(rc == EOK);
    421458                        memcpy(b->data, devcon->com_area, cache->block_size);
    422459                        fibril_mutex_unlock(&devcon->com_area_lock);
    423                 }
     460                        if (rc != EOK)
     461                                b->toxic = true;
     462                } else
     463                        rc = EOK;
    424464
    425465                fibril_mutex_unlock(&b->lock);
    426466        }
    427         return b;
     467        *block = b;
     468        return rc;
    428469}
    429470
     
    433474 *
    434475 * @param block         Block of which a reference is to be released.
    435  */
    436 void block_put(block_t *block)
     476 *
     477 * @return              EOK on success or a negative error code.
     478 */
     479int block_put(block_t *block)
    437480{
    438481        devcon_t *devcon = devcon_search(block->dev_handle);
    439482        cache_t *cache;
    440         int rc;
     483        unsigned blocks_cached;
     484        enum cache_mode mode;
     485        int rc = EOK;
    441486
    442487        assert(devcon);
     
    444489
    445490        cache = devcon->cache;
     491
     492retry:
     493        fibril_mutex_lock(&cache->lock);
     494        blocks_cached = cache->blocks_cached;
     495        mode = cache->mode;
     496        fibril_mutex_unlock(&cache->lock);
     497
     498        /*
     499         * Determine whether to sync the block. Syncing the block is best done
     500         * when not holding the cache lock as it does not impede concurrency.
     501         * Since the situation may have changed when we unlocked the cache, the
     502         * blocks_cached and mode variables are mere hints. We will recheck the
     503         * conditions later when the cache lock is held again.
     504         */
     505        fibril_mutex_lock(&block->lock);
     506        if (block->toxic)
     507                block->dirty = false;   /* will not write back toxic block */
     508        if (block->dirty && (block->refcnt == 1) &&
     509            (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
     510                fibril_mutex_lock(&devcon->com_area_lock);
     511                memcpy(devcon->com_area, block->data, block->size);
     512                rc = write_block(devcon, block->boff, block->size);
     513                fibril_mutex_unlock(&devcon->com_area_lock);
     514                block->dirty = false;
     515        }
     516        fibril_mutex_unlock(&block->lock);
     517
    446518        fibril_mutex_lock(&cache->lock);
    447519        fibril_mutex_lock(&block->lock);
     
    449521                /*
    450522                 * Last reference to the block was dropped. Either free the
    451                  * block or put it on the free list.
     523                 * block or put it on the free list. In case of an I/O error,
     524                 * free the block.
    452525                 */
    453                 if (cache->blocks_cached > CACHE_HI_WATERMARK) {
    454                         /*
    455                          * Currently there are too many cached blocks.
     526                if ((cache->blocks_cached > CACHE_HI_WATERMARK) ||
     527                    (rc != EOK)) {
     528                        /*
     529                         * Currently there are too many cached blocks or there
     530                         * was an I/O error when writing the block back to the
     531                         * device.
    456532                         */
    457533                        if (block->dirty) {
    458                                 fibril_mutex_lock(&devcon->com_area_lock);
    459                                 memcpy(devcon->com_area, block->data,
    460                                     block->size);
    461                                 rc = write_block(devcon, block->boff,
    462                                     block->size);
    463                                 assert(rc == EOK);
    464                                 fibril_mutex_unlock(&devcon->com_area_lock);
     534                                /*
     535                                 * We cannot sync the block while holding the
     536                                 * cache lock. Release everything and retry.
     537                                 */
     538                                block->refcnt++;
     539                                fibril_mutex_unlock(&block->lock);
     540                                fibril_mutex_unlock(&cache->lock);
     541                                goto retry;
    465542                        }
    466543                        /*
     
    473550                        cache->blocks_cached--;
    474551                        fibril_mutex_unlock(&cache->lock);
    475                         return;
     552                        return rc;
    476553                }
    477554                /*
    478555                 * Put the block on the free list.
    479556                 */
     557                if (cache->mode != CACHE_MODE_WB && block->dirty) {
     558                        /*
     559                         * We cannot sync the block while holding the cache
     560                         * lock. Release everything and retry.
     561                         */
     562                        block->refcnt++;
     563                        fibril_mutex_unlock(&block->lock);
     564                        fibril_mutex_unlock(&cache->lock);
     565                        goto retry;
     566                }
    480567                list_append(&block->free_link, &cache->free_head);
    481                 if (cache->mode != CACHE_MODE_WB && block->dirty) {
    482                         fibril_mutex_lock(&devcon->com_area_lock);
    483                         memcpy(devcon->com_area, block->data, block->size);
    484                         rc = write_block(devcon, block->boff, block->size);
    485                         assert(rc == EOK);
    486                         fibril_mutex_unlock(&devcon->com_area_lock);
    487 
    488                         block->dirty = false;
    489                 }
    490568        }
    491569        fibril_mutex_unlock(&block->lock);
    492570        fibril_mutex_unlock(&cache->lock);
     571
     572        return rc;
    493573}
    494574
  • uspace/lib/libblock/libblock.h

    rf2f89315 rff62c6d  
    6969        /** If true, the block needs to be written back to the block device. */
    7070        bool dirty;
     71        /** If true, the blcok does not contain valid data. */
     72        bool toxic;
    7173        /** Readers / Writer lock protecting the contents of the block. */
    7274        fibril_rwlock_t contents_lock;
     
    101103extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode);
    102104
    103 extern block_t *block_get(dev_handle_t, bn_t, int);
    104 extern void block_put(block_t *);
     105extern int block_get(block_t **, dev_handle_t, bn_t, int);
     106extern int block_put(block_t *);
    105107
    106108extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *,
  • uspace/srv/fs/fat/fat_fat.c

    rf2f89315 rff62c6d  
    7575        uint16_t clusters = 0;
    7676        fat_cluster_t clst = firstc;
     77        int rc;
    7778
    7879        bps = uint16_t_le2host(bs->bps);
     
    9697                fidx = clst % (bps / sizeof(fat_cluster_t));
    9798                /* read FAT1 */
    98                 b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
     99                rc = block_get(&b, dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
     100                assert(rc == EOK);
    99101                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    100102                assert(clst != FAT_CLST_BAD);
    101                 block_put(b);
     103                rc = block_put(b);
     104                assert(rc == EOK);
    102105                clusters++;
    103106        }
     
    133136        unsigned clusters, max_clusters;
    134137        fat_cluster_t lastc;
     138        int rc;
    135139
    136140        bps = uint16_t_le2host(bs->bps);
     
    146150                /* root directory special case */
    147151                assert(bn < rds);
    148                 b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags);
     152                rc = block_get(&b, dev_handle, rscnt + bs->fatcnt * sf + bn,
     153                    flags);
     154                assert(rc == EOK);
    149155                return b;
    150156        }
     
    155161        assert(clusters == max_clusters);
    156162
    157         b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc +
    158             bn % bs->spc, flags);
     163        rc = block_get(&b, dev_handle, ssa +
     164            (lastc - FAT_CLST_FIRST) * bs->spc + bn % bs->spc, flags);
     165        assert(rc == EOK);
    159166
    160167        return b;
     
    177184        block_t *b;
    178185        off_t o, boundary;
     186        int rc;
    179187
    180188        bps = uint16_t_le2host(bs->bps);
     
    191199                memset(b->data + o % bps, 0, bps - o % bps);
    192200                b->dirty = true;                /* need to sync node */
    193                 block_put(b);
     201                rc = block_put(b);
     202                assert(rc == EOK);
    194203        }
    195204       
     
    203212                memset(b->data, 0, min(bps, pos - o));
    204213                b->dirty = true;                /* need to sync node */
    205                 block_put(b);
     214                rc = block_put(b);
     215                assert(rc == EOK);
    206216        }
    207217}
     
    222232        uint16_t rscnt;
    223233        fat_cluster_t *cp, value;
     234        int rc;
    224235
    225236        bps = uint16_t_le2host(bs->bps);
    226237        rscnt = uint16_t_le2host(bs->rscnt);
    227238
    228         b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps,
    229             BLOCK_FLAGS_NONE);
     239        rc = block_get(&b, dev_handle, rscnt +
     240            (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
     241        assert(rc == EOK);
    230242        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
    231243        value = uint16_t_le2host(*cp);
    232         block_put(b);
     244        rc = block_put(b);
     245        assert(rc == EOK);
    233246       
    234247        return value;
     
    252265        uint16_t sf;
    253266        fat_cluster_t *cp;
     267        int rc;
    254268
    255269        bps = uint16_t_le2host(bs->bps);
     
    258272
    259273        assert(fatno < bs->fatcnt);
    260         b = block_get(dev_handle, rscnt + sf * fatno +
     274        rc = block_get(&b, dev_handle, rscnt + sf * fatno +
    261275            (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
     276        assert(rc == EOK);
    262277        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
    263278        *cp = host2uint16_t_le(value);
    264279        b->dirty = true;                /* need to sync block */
    265         block_put(b);
     280        rc = block_put(b);
     281        assert(rc == EOK);
    266282}
    267283
     
    315331        unsigned found = 0;     /* top of the free cluster number stack */
    316332        unsigned b, c, cl;
     333        int rc;
    317334
    318335        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    329346        fibril_mutex_lock(&fat_alloc_lock);
    330347        for (b = 0, cl = 0; b < sf; b++) {
    331                 blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
     348                rc = block_get(&blk, dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
    332349                for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
    333350                        fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
     
    344361                                if (++found == nclsts) {
    345362                                        /* we are almost done */
    346                                         block_put(blk);
     363                                        rc = block_put(blk);
     364                                        assert(rc == EOK);
    347365                                        /* update the shadow copies of FAT */
    348366                                        fat_alloc_shadow_clusters(bs,
     
    356374                        }
    357375                }
    358                 block_put(blk);
     376                rc = block_put(blk);
     377                assert(rc == EOK);
    359378        }
    360379        fibril_mutex_unlock(&fat_alloc_lock);
     
    457476        block_t *b;
    458477        unsigned bps;
     478        int rc;
    459479
    460480        bps = uint16_t_le2host(bs->bps);
     
    464484                memset(b->data, 0, bps);
    465485                b->dirty = true;
    466                 block_put(b);
     486                rc = block_put(b);
     487                assert(rc == EOK);
    467488        }
    468489}
  • uspace/srv/fs/fat/fat_ops.c

    rf2f89315 rff62c6d  
    8585        uint16_t bps;
    8686        unsigned dps;
     87        int rc;
    8788       
    8889        assert(node->dirty);
     
    108109       
    109110        b->dirty = true;                /* need to sync block */
    110         block_put(b);
     111        rc = block_put(b);
     112        assert(rc == EOK);
    111113}
    112114
     
    170172        unsigned spc;
    171173        unsigned dps;
     174        int rc;
    172175
    173176        if (idxp->nodep) {
     
    226229        nodep->refcnt = 1;
    227230
    228         block_put(b);
     231        rc = block_put(b);
     232        assert(rc == EOK);
    229233
    230234        /* Link the idx structure with the node structure. */
     
    443447                        }
    444448                }
    445                 block_put(b);
     449                rc = block_put(b);
     450                assert(rc == EOK);
    446451        }
    447452        j = 0;
     
    477482        fat_dentry_name_set(d, name);
    478483        b->dirty = true;                /* need to sync block */
    479         block_put(b);
     484        rc = block_put(b);
     485        assert(rc == EOK);
    480486        fibril_mutex_unlock(&parentp->idx->lock);
    481487
     
    512518        }
    513519        b->dirty = true;                /* need to sync block */
    514         block_put(b);
     520        rc = block_put(b);
     521        assert(rc == EOK);
    515522
    516523        childp->idx->pfc = parentp->firstc;
     
    539546        uint16_t bps;
    540547        block_t *b;
     548        int rc;
    541549
    542550        if (!parentp)
     
    561569        d->name[0] = FAT_DENTRY_ERASED;
    562570        b->dirty = true;                /* need to sync block */
    563         block_put(b);
     571        rc = block_put(b);
     572        assert(rc == EOK);
    564573
    565574        /* remove the index structure from the position hash */
     
    588597        fat_dentry_t *d;
    589598        block_t *b;
     599        int rc;
    590600
    591601        fibril_mutex_lock(&parentp->idx->lock);
     
    603613                                continue;
    604614                        case FAT_DENTRY_LAST:
    605                                 block_put(b);
     615                                rc = block_put(b);
     616                                assert(rc == EOK);
    606617                                fibril_mutex_unlock(&parentp->idx->lock);
    607618                                return NULL;
     
    629640                                         * run out of 32-bit indices.
    630641                                         */
    631                                         block_put(b);
     642                                        rc = block_put(b);
     643                                        assert(rc == EOK);
    632644                                        return NULL;
    633645                                }
    634646                                nodep = fat_node_get_core(idx);
    635647                                fibril_mutex_unlock(&idx->lock);
    636                                 block_put(b);
     648                                rc = block_put(b);
     649                                assert(rc == EOK);
    637650                                return FS_NODE(nodep);
    638651                        }
    639652                }
    640                 block_put(b);
     653                rc = block_put(b);
     654                assert(rc == EOK);
    641655        }
    642656
     
    669683        block_t *b;
    670684        unsigned i, j;
     685        int rc;
    671686
    672687        if (nodep->type != FAT_DIRECTORY)
     
    691706                                continue;
    692707                        case FAT_DENTRY_LAST:
    693                                 block_put(b);
     708                                rc = block_put(b);
     709                                assert(rc == EOK);
    694710                                fibril_mutex_unlock(&nodep->idx->lock);
    695711                                return false;
    696712                        default:
    697713                        case FAT_DENTRY_VALID:
    698                                 block_put(b);
     714                                rc = block_put(b);
     715                                assert(rc == EOK);
    699716                                fibril_mutex_unlock(&nodep->idx->lock);
    700717                                return true;
    701718                        }
    702                         block_put(b);
     719                        rc = block_put(b);
     720                        assert(rc == EOK);
    703721                        fibril_mutex_unlock(&nodep->idx->lock);
    704722                        return true;
    705723                }
    706                 block_put(b);
     724                rc = block_put(b);
     725                assert(rc == EOK);
    707726        }
    708727
     
    901920        size_t bytes;
    902921        block_t *b;
     922        int rc;
    903923
    904924        if (!fn) {
     
    937957                        (void) ipc_data_read_finalize(callid, b->data + pos % bps,
    938958                            bytes);
    939                         block_put(b);
     959                        rc = block_put(b);
     960                        assert(rc == EOK);
    940961                }
    941962        } else {
     
    969990                                        continue;
    970991                                case FAT_DENTRY_LAST:
    971                                         block_put(b);
     992                                        rc = block_put(b);
     993                                        assert(rc == EOK);
    972994                                        goto miss;
    973995                                default:
    974996                                case FAT_DENTRY_VALID:
    975997                                        fat_dentry_name_get(d, name);
    976                                         block_put(b);
     998                                        rc == block_put(b);
     999                                        assert(rc == EOK);
    9771000                                        goto hit;
    9781001                                }
    9791002                        }
    980                         block_put(b);
     1003                        rc = block_put(b);
     1004                        assert(rc == EOK);
    9811005                        bnum++;
    9821006                }
     
    10101034        off_t boundary;
    10111035        int flags = BLOCK_FLAGS_NONE;
     1036        int rc;
    10121037       
    10131038        if (!fn) {
     
    10551080                    bytes);
    10561081                b->dirty = true;                /* need to sync block */
    1057                 block_put(b);
     1082                rc = block_put(b);
     1083                assert(rc == EOK);
    10581084                if (pos + bytes > nodep->size) {
    10591085                        nodep->size = pos + bytes;
     
    10891115                    bytes);
    10901116                b->dirty = true;                /* need to sync block */
    1091                 block_put(b);
     1117                rc = block_put(b);
     1118                assert(rc == EOK);
    10921119                /*
    10931120                 * Append the cluster chain starting in mcl to the end of the
Note: See TracChangeset for help on using the changeset viewer.