Changeset add5835 in mainline


Ignore:
Timestamp:
2008-05-17T20:10:54Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e811bde
Parents:
78a1b7b
Message:

Add locks to FAT index structures, FAT in-core node structures. Add futex to
protect the list of free cached FAT in-core nodes. Make fat_node_get() and
fat_node_put() and some other functions aware of these new locks.

Location:
uspace/srv/fs/fat
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/fat/fat.h

    r78a1b7b radd5835  
    181181        link_t          uih_link;
    182182
     183        futex_t         lock;
    183184        dev_handle_t    dev_handle;
    184185        fs_index_t      index;
     
    198199/** FAT in-core node. */
    199200typedef struct fat_node {
     201        futex_t                 lock;
    200202        fat_node_type_t         type;
    201203        fat_idx_t               *idx;
  • uspace/srv/fs/fat/fat_idx.c

    r78a1b7b radd5835  
    7575static LIST_INITIALIZE(unused_head);
    7676
    77 /** Futex protecting the up_hash and ui_hash.
    78  *
    79  * The locking strategy assumes that there will be at most one fibril for each
    80  * dev_handle.  Therefore it will be sufficient to hold the futex for shorter
    81  * times (i.e. only during hash table operations as opposed to holding it the
    82  * whole time between an unsuccessful find and the following insert). Should the
    83  * assumption break, the locking strategy for this futex will have to be
    84  * reconsidered.
    85  */
     77/** Futex protecting the up_hash and ui_hash. */
    8678static futex_t used_futex = FUTEX_INITIALIZER;
    8779
     
    353345        futex_down(&used_futex);
    354346        l = hash_table_find(&up_hash, pkey);
    355         futex_up(&used_futex);
    356347        if (l) {
    357348                fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
     
    359350                fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
    360351                if (!fidx) {
     352                        futex_up(&used_futex);
    361353                        return NULL;
    362354                }
    363355                if (!fat_idx_alloc(dev_handle, &fidx->index)) {
    364356                        free(fidx);
     357                        futex_up(&used_futex);
    365358                        return NULL;
    366359                }
     
    373366                link_initialize(&fidx->uph_link);
    374367                link_initialize(&fidx->uih_link);
     368                futex_initialize(&fidx->lock, 1);
    375369                fidx->dev_handle = dev_handle;
    376370                fidx->pfc = pfc;
     
    378372                fidx->nodep = NULL;
    379373
    380                 futex_down(&used_futex);
    381374                hash_table_insert(&up_hash, pkey, &fidx->uph_link);
    382375                hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
    383                 futex_up(&used_futex);
    384         }
     376        }
     377        futex_down(&fidx->lock);
     378        futex_up(&used_futex);
    385379
    386380        return fidx;
     
    399393        futex_down(&used_futex);
    400394        l = hash_table_find(&ui_hash, ikey);
    401         futex_up(&used_futex);
    402395        if (l) {
    403396                fidx = hash_table_get_instance(l, fat_idx_t, uih_link);
    404         }
     397                futex_down(&fidx->lock);
     398        }
     399        futex_up(&used_futex);
    405400
    406401        return fidx;
  • uspace/srv/fs/fat/fat_ops.c

    r78a1b7b radd5835  
    5151#define BS_BLOCK                0
    5252
    53 /** List of free FAT nodes that still contain valid data. */
    54 LIST_INITIALIZE(ffn_head);
     53/** Futex protecting the list of cached free FAT nodes. */
     54static futex_t ffn_futex = FUTEX_INITIALIZER;
     55
     56/** List of cached free FAT nodes. */
     57static LIST_INITIALIZE(ffn_head);
    5558
    5659#define FAT_NAME_LEN            8
     
    180183static void fat_node_initialize(fat_node_t *node)
    181184{
     185        futex_initialize(&node->lock, 1);
    182186        node->idx = NULL;
    183187        node->type = 0;
     
    237241}
    238242
    239 /** Instantiate a FAT in-core node. */
    240 static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
    241 {
    242         fat_idx_t *idx;
     243/** Internal version of fat_node_get().
     244 *
     245 * @param idxp          Locked index structure.
     246 */
     247static void *fat_node_get_core(fat_idx_t *idxp)
     248{
    243249        block_t *b;
    244250        fat_dentry_t *d;
     
    247253        unsigned dps;
    248254
    249         idx = fat_idx_get_by_index(dev_handle, index);
    250         if (!idx)
    251                 return NULL;
    252 
    253         if (idx->nodep) {
     255        if (idxp->nodep) {
    254256                /*
    255257                 * We are lucky.
    256258                 * The node is already instantiated in memory.
    257259                 */
    258                 if (!idx->nodep->refcnt++)
     260                futex_down(&idxp->nodep->lock);
     261                if (!idxp->nodep->refcnt++)
    259262                        list_remove(&nodep->ffn_link);
    260                 return idx->nodep;
     263                futex_up(&idxp->nodep->lock);
     264                return idxp->nodep;
    261265        }
    262266
     
    265269         */
    266270       
    267         assert(idx->pfc);
    268 
     271        assert(idxp->pfc);
     272
     273        futex_down(&ffn_futex);
    269274        if (!list_empty(&ffn_head)) {
    270                 /* Try to use a cached unused node structure. */
     275                /* Try to use a cached free node structure. */
     276                fat_idx_t *idxp_tmp;
    271277                nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
     278                if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
     279                        goto skip_cache;
     280                idxp_tmp = nodep->idx;
     281                if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
     282                        futex_up(&nodep->lock);
     283                        goto skip_cache;
     284                }
     285                list_remove(&nodep->ffn_link);
     286                futex_up(&ffn_futex);
    272287                if (nodep->dirty)
    273288                        fat_node_sync(nodep);
    274                 list_remove(&nodep->ffn_link);
    275                 nodep->idx->nodep = NULL;
     289                idxp_tmp->nodep = NULL;
     290                futex_up(&nodep->lock);
     291                futex_up(&idxp_tmp->lock);
    276292        } else {
     293skip_cache:
    277294                /* Try to allocate a new node structure. */
     295                futex_up(&ffn_futex);
    278296                nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
    279297                if (!nodep)
     
    282300        fat_node_initialize(nodep);
    283301
    284         bps = fat_bps_get(dev_handle);
     302        bps = fat_bps_get(idxp->dev_handle);
    285303        dps = bps / sizeof(fat_dentry_t);
    286304
    287305        /* Read the block that contains the dentry of interest. */
    288         b = _fat_block_get(dev_handle, idx->pfc,
    289             (idx->pdi * sizeof(fat_dentry_t)) / bps);
     306        b = _fat_block_get(idxp->dev_handle, idxp->pfc,
     307            (idxp->pdi * sizeof(fat_dentry_t)) / bps);
    290308        assert(b);
    291309
    292         d = ((fat_dentry_t *)b->data) + (idx->pdi % dps);
     310        d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
    293311        if (d->attr & FAT_ATTR_SUBDIR) {
    294312                /*
     
    309327
    310328        /* Link the idx structure with the node structure. */
    311         nodep->idx = idx;
    312         idx->nodep = nodep;
     329        nodep->idx = idxp;
     330        idxp->nodep = nodep;
    313331
    314332        return nodep;
    315333}
    316334
     335/** Instantiate a FAT in-core node. */
     336static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
     337{
     338        void *node;
     339        fat_idx_t *idxp;
     340
     341        idxp = fat_idx_get_by_index(dev_handle, index);
     342        if (!idxp)
     343                return NULL;
     344        /* idxp->lock held */
     345        node = fat_node_get_core(idxp);
     346        futex_up(&idxp->lock);
     347        return node;
     348}
     349
    317350static void fat_node_put(void *node)
    318351{
    319352        fat_node_t *nodep = (fat_node_t *)node;
    320353
     354        futex_down(&nodep->lock);
    321355        if (!--nodep->refcnt) {
     356                futex_down(&ffn_futex);
    322357                list_append(&nodep->ffn_link, &ffn_head);
    323         }
     358                futex_up(&ffn_futex);
     359        }
     360        futex_up(&nodep->lock);
    324361}
    325362
     
    380417                        if (strcmp(name, component) == 0) {
    381418                                /* hit */
     419                                void *node;
    382420                                fat_idx_t *idx = fat_idx_get_by_pos(
    383421                                    parentp->idx->dev_handle, parentp->firstc,
     
    391429                                        return NULL;
    392430                                }
    393                                 void *node = fat_node_get(idx->dev_handle,
    394                                     idx->index);
     431                                node = fat_node_get_core(idx);
     432                                futex_up(&idx->lock);
    395433                                block_put(b);
    396434                                return node;
     
    433471                return false;
    434472
     473        futex_down(&nodep->idx->lock);
    435474        bps = fat_bps_get(nodep->idx->dev_handle);
    436475        dps = bps / sizeof(fat_dentry_t);
     
    453492                        case FAT_DENTRY_LAST:
    454493                                block_put(b);
     494                                futex_up(&nodep->idx->lock);
    455495                                return false;
    456496                        default:
    457497                        case FAT_DENTRY_VALID:
    458498                                block_put(b);
     499                                futex_up(&nodep->idx->lock);
    459500                                return true;
    460501                        }
    461502                        block_put(b);
     503                        futex_up(&nodep->idx->lock);
    462504                        return true;
    463505                }
     
    465507        }
    466508
     509        futex_up(&nodep->idx->lock);
    467510        return false;
    468511}
Note: See TracChangeset for help on using the changeset viewer.