Changeset 3d35386 in mainline for uspace/lib/block/block.c


Ignore:
Timestamp:
2014-07-28T20:10:01Z (10 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c1f26834
Parents:
7eb6c96
Message:

libblock: limit the number of retries if we fail to write a block to disk.

The original behaviour is to continously retry to write a block until the
operation succeeds, this will cause the system to enter an infinite loop
if the underlying device is unable to satisfy the request.

This patch introduces an upper limit to the number of retries and discards
the block if the limit is reached.
It also fixes a bug in the block_get() function that allows the user to
try to read a block beyond the end of the device.

File:
1 edited

Legend:

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

    r7eb6c96 r3d35386  
    5555#include "block.h"
    5656
     57#define MAX_WRITE_RETRIES 10
     58
    5759/** Lock protecting the device connection list */
    5860static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
     
    7981        void *bb_buf;
    8082        aoff64_t bb_addr;
     83        aoff64_t pblocks;    /**< Number of physical blocks */
    8184        size_t pblock_size;  /**< Physical block size. */
    8285        cache_t *cache;
     
    103106
    104107static int devcon_add(service_id_t service_id, async_sess_t *sess,
    105     size_t bsize, bd_t *bd)
     108    size_t bsize, aoff64_t dev_size, bd_t *bd)
    106109{
    107110        devcon_t *devcon;
     
    118121        devcon->bb_addr = 0;
    119122        devcon->pblock_size = bsize;
     123        devcon->pblocks = dev_size;
    120124        devcon->cache = NULL;
    121125       
     
    164168                return rc;
    165169        }
    166        
    167         rc = devcon_add(service_id, sess, bsize, bd);
     170
     171        aoff64_t dev_size;
     172        rc = bd_get_num_blocks(bd, &dev_size);
     173        if (rc != EOK) {
     174                bd_close(bd);
     175                async_hangup(sess);
     176                return rc;
     177        }
     178       
     179        rc = devcon_add(service_id, sess, bsize, dev_size, bd);
    168180        if (rc != EOK) {
    169181                bd_close(bd);
     
    349361        fibril_mutex_initialize(&b->lock);
    350362        b->refcnt = 1;
     363        b->write_failures = 0;
    351364        b->dirty = false;
    352365        b->toxic = false;
     
    373386        block_t *b;
    374387        link_t *link;
    375 
     388        aoff64_t p_ba;
    376389        int rc;
    377390       
     
    382395       
    383396        cache = devcon->cache;
     397
     398        /* Check whether the logical block (or part of it) is beyond
     399         * the end of the device or not.
     400         */
     401        p_ba = ba_ltop(devcon, ba);
     402        p_ba += cache->blocks_cluster;
     403        if (p_ba >= devcon->pblocks) {
     404                /* This request cannot be satisfied */
     405                return EIO;
     406        }
     407
    384408
    385409retry:
     
    458482                                         * another block next time.
    459483                                         */
    460                                         fibril_mutex_unlock(&b->lock);
    461                                         goto retry;
    462                                 }
     484                                        if (b->write_failures < MAX_WRITE_RETRIES) {
     485                                                b->write_failures++;
     486                                                fibril_mutex_unlock(&b->lock);
     487                                                goto retry;
     488                                        } else {
     489                                                printf("Too many errors writing block %"
     490                                                    PRIuOFF64 "from device handle %" PRIun "\n"
     491                                                    "SEVERE DATA LOSS POSSIBLE\n",
     492                                                    b->lba, devcon->service_id);
     493                                        }
     494                                } else
     495                                        b->write_failures = 0;
     496
    463497                                b->dirty = false;
    464498                                if (!fibril_mutex_trylock(&cache->lock)) {
     
    577611                rc = write_blocks(devcon, block->pba, cache->blocks_cluster,
    578612                    block->data, block->size);
     613                if (rc == EOK)
     614                        block->write_failures = 0;
    579615                block->dirty = false;
    580616        }
     
    602638                                 */
    603639                                block->refcnt++;
    604                                 fibril_mutex_unlock(&block->lock);
    605640                                fibril_mutex_unlock(&cache->lock);
    606                                 goto retry;
     641
     642                                if (block->write_failures < MAX_WRITE_RETRIES) {
     643                                        block->write_failures++;
     644                                        fibril_mutex_unlock(&block->lock);
     645                                        goto retry;
     646                                } else {
     647                                        printf("Too many errors writing block %"
     648                                            PRIuOFF64 "from device handle %" PRIun "\n"
     649                                            "SEVERE DATA LOSS POSSIBLE\n",
     650                                            block->lba, devcon->service_id);
     651                                }
    607652                        }
    608653                        /*
     
    770815        devcon_t *devcon = devcon_search(service_id);
    771816        assert(devcon);
    772        
     817
    773818        return bd_get_num_blocks(devcon->bd, nblocks);
    774819}
Note: See TracChangeset for help on using the changeset viewer.