Subversion Repositories HelenOS

Rev

Rev 2927 | Rev 3153 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2927 Rev 3009
Line 48... Line 48...
48
#include <assert.h>
48
#include <assert.h>
49
#include <futex.h>
49
#include <futex.h>
50
 
50
 
51
#define BS_BLOCK        0
51
#define BS_BLOCK        0
52
 
52
 
53
/** List of free FAT nodes that still contain valid data. */
53
/** Futex protecting the list of cached free FAT nodes. */
-
 
54
static futex_t ffn_futex = FUTEX_INITIALIZER;
-
 
55
 
-
 
56
/** List of cached free FAT nodes. */
54
LIST_INITIALIZE(ffn_head);
57
static LIST_INITIALIZE(ffn_head);
55
 
58
 
56
#define FAT_NAME_LEN        8
59
#define FAT_NAME_LEN        8
57
#define FAT_EXT_LEN     3
60
#define FAT_EXT_LEN     3
58
 
61
 
59
#define FAT_PAD         ' ' 
62
#define FAT_PAD         ' ' 
Line 177... Line 180...
177
    return b;
180
    return b;
178
}
181
}
179
 
182
 
180
static void fat_node_initialize(fat_node_t *node)
183
static void fat_node_initialize(fat_node_t *node)
181
{
184
{
-
 
185
    futex_initialize(&node->lock, 1);
182
    node->idx = NULL;
186
    node->idx = NULL;
183
    node->type = 0;
187
    node->type = 0;
184
    link_initialize(&node->ffn_link);
188
    link_initialize(&node->ffn_link);
185
    node->size = 0;
189
    node->size = 0;
186
    node->lnkcnt = 0;
190
    node->lnkcnt = 0;
Line 234... Line 238...
234
static void fat_node_sync(fat_node_t *node)
238
static void fat_node_sync(fat_node_t *node)
235
{
239
{
236
    /* TODO */
240
    /* TODO */
237
}
241
}
238
 
242
 
239
/** Instantiate a FAT in-core node. */
243
/** Internal version of fat_node_get().
-
 
244
 *
-
 
245
 * @param idxp      Locked index structure.
-
 
246
 */
240
static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
247
static void *fat_node_get_core(fat_idx_t *idxp)
241
{
248
{
242
    fat_idx_t *idx;
-
 
243
    block_t *b;
249
    block_t *b;
244
    fat_dentry_t *d;
250
    fat_dentry_t *d;
245
    fat_node_t *nodep;
251
    fat_node_t *nodep;
246
    unsigned bps;
252
    unsigned bps;
247
    unsigned dps;
253
    unsigned dps;
248
 
254
 
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) {
254
        /*
256
        /*
255
         * We are lucky.
257
         * We are lucky.
256
         * The node is already instantiated in memory.
258
         * The node is already instantiated in memory.
257
         */
259
         */
-
 
260
        futex_down(&idxp->nodep->lock);
258
        if (!idx->nodep->refcnt++)
261
        if (!idxp->nodep->refcnt++)
259
            list_remove(&nodep->ffn_link);
262
            list_remove(&nodep->ffn_link);
-
 
263
        futex_up(&idxp->nodep->lock);
260
        return idx->nodep;
264
        return idxp->nodep;
261
    }
265
    }
262
 
266
 
263
    /*
267
    /*
264
     * We must instantiate the node from the file system.
268
     * We must instantiate the node from the file system.
265
     */
269
     */
266
   
270
   
267
    assert(idx->pfc);
271
    assert(idxp->pfc);
268
 
272
 
-
 
273
    futex_down(&ffn_futex);
269
    if (!list_empty(&ffn_head)) {
274
    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;
271
        nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
277
        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);
272
        if (nodep->dirty)
287
        if (nodep->dirty)
273
            fat_node_sync(nodep);
288
            fat_node_sync(nodep);
-
 
289
        idxp_tmp->nodep = NULL;
274
        list_remove(&nodep->ffn_link);
290
        futex_up(&nodep->lock);
275
        nodep->idx->nodep = NULL;
291
        futex_up(&idxp_tmp->lock);
276
    } else {
292
    } else {
-
 
293
skip_cache:
277
        /* Try to allocate a new node structure. */
294
        /* Try to allocate a new node structure. */
-
 
295
        futex_up(&ffn_futex);
278
        nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
296
        nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
279
        if (!nodep)
297
        if (!nodep)
280
            return NULL;
298
            return NULL;
281
    }
299
    }
282
    fat_node_initialize(nodep);
300
    fat_node_initialize(nodep);
283
 
301
 
284
    bps = fat_bps_get(dev_handle);
302
    bps = fat_bps_get(idxp->dev_handle);
285
    dps = bps / sizeof(fat_dentry_t);
303
    dps = bps / sizeof(fat_dentry_t);
286
 
304
 
287
    /* Read the block that contains the dentry of interest. */
305
    /* Read the block that contains the dentry of interest. */
288
    b = _fat_block_get(dev_handle, idx->pfc,
306
    b = _fat_block_get(idxp->dev_handle, idxp->pfc,
289
        (idx->pdi * sizeof(fat_dentry_t)) / bps);
307
        (idxp->pdi * sizeof(fat_dentry_t)) / bps);
290
    assert(b);
308
    assert(b);
291
 
309
 
292
    d = ((fat_dentry_t *)b->data) + (idx->pdi % dps);
310
    d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
293
    if (d->attr & FAT_ATTR_SUBDIR) {
311
    if (d->attr & FAT_ATTR_SUBDIR) {
294
        /*
312
        /*
295
         * The only directory which does not have this bit set is the
313
         * The only directory which does not have this bit set is the
296
         * root directory itself. The root directory node is handled
314
         * root directory itself. The root directory node is handled
297
         * and initialized elsewhere.
315
         * and initialized elsewhere.
Line 306... Line 324...
306
    nodep->refcnt = 1;
324
    nodep->refcnt = 1;
307
 
325
 
308
    block_put(b);
326
    block_put(b);
309
 
327
 
310
    /* Link the idx structure with the node structure. */
328
    /* Link the idx structure with the node structure. */
311
    nodep->idx = idx;
329
    nodep->idx = idxp;
312
    idx->nodep = nodep;
330
    idxp->nodep = nodep;
313
 
331
 
314
    return nodep;
332
    return nodep;
315
}
333
}
316
 
334
 
-
 
335
/** Instantiate a FAT in-core node. */
-
 
336
static 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
 
317
static void fat_node_put(void *node)
350
static void fat_node_put(void *node)
318
{
351
{
319
    fat_node_t *nodep = (fat_node_t *)node;
352
    fat_node_t *nodep = (fat_node_t *)node;
320
 
353
 
-
 
354
    futex_down(&nodep->lock);
321
    if (!--nodep->refcnt) {
355
    if (!--nodep->refcnt) {
-
 
356
        futex_down(&ffn_futex);
322
        list_append(&nodep->ffn_link, &ffn_head);
357
        list_append(&nodep->ffn_link, &ffn_head);
-
 
358
        futex_up(&ffn_futex);
323
    }
359
    }
-
 
360
    futex_up(&nodep->lock);
324
}
361
}
325
 
362
 
326
static void *fat_create(int flags)
363
static void *fat_create(int flags)
327
{
364
{
328
    return NULL;    /* not supported at the moment */
365
    return NULL;    /* not supported at the moment */
Line 352... Line 389...
352
    unsigned dps;       /* dentries per sector */
389
    unsigned dps;       /* dentries per sector */
353
    unsigned blocks;
390
    unsigned blocks;
354
    fat_dentry_t *d;
391
    fat_dentry_t *d;
355
    block_t *b;
392
    block_t *b;
356
 
393
 
-
 
394
    futex_down(&parentp->idx->lock);
357
    bps = fat_bps_get(parentp->idx->dev_handle);
395
    bps = fat_bps_get(parentp->idx->dev_handle);
358
    dps = bps / sizeof(fat_dentry_t);
396
    dps = bps / sizeof(fat_dentry_t);
359
    blocks = parentp->size / bps + (parentp->size % bps != 0);
397
    blocks = parentp->size / bps + (parentp->size % bps != 0);
360
    for (i = 0; i < blocks; i++) {
398
    for (i = 0; i < blocks; i++) {
361
        unsigned dentries;
399
        unsigned dentries;
Line 369... Line 407...
369
            switch (fat_classify_dentry(d)) {
407
            switch (fat_classify_dentry(d)) {
370
            case FAT_DENTRY_SKIP:
408
            case FAT_DENTRY_SKIP:
371
                continue;
409
                continue;
372
            case FAT_DENTRY_LAST:
410
            case FAT_DENTRY_LAST:
373
                block_put(b);
411
                block_put(b);
-
 
412
                futex_up(&parentp->idx->lock);
374
                return NULL;
413
                return NULL;
375
            default:
414
            default:
376
            case FAT_DENTRY_VALID:
415
            case FAT_DENTRY_VALID:
377
                dentry_name_canonify(d, name);
416
                dentry_name_canonify(d, name);
378
                break;
417
                break;
379
            }
418
            }
380
            if (strcmp(name, component) == 0) {
419
            if (strcmp(name, component) == 0) {
381
                /* hit */
420
                /* hit */
-
 
421
                void *node;
-
 
422
                /*
-
 
423
                 * Assume tree hierarchy for locking.  We
-
 
424
                 * already have the parent and now we are going
-
 
425
                 * to lock the child.  Never lock in the oposite
-
 
426
                 * order.
-
 
427
                 */
382
                fat_idx_t *idx = fat_idx_get_by_pos(
428
                fat_idx_t *idx = fat_idx_get_by_pos(
383
                    parentp->idx->dev_handle, parentp->firstc,
429
                    parentp->idx->dev_handle, parentp->firstc,
384
                    i * dps + j);
430
                    i * dps + j);
-
 
431
                futex_up(&parentp->idx->lock);
385
                if (!idx) {
432
                if (!idx) {
386
                    /*
433
                    /*
387
                     * Can happen if memory is low or if we
434
                     * Can happen if memory is low or if we
388
                     * run out of 32-bit indices.
435
                     * run out of 32-bit indices.
389
                     */
436
                     */
390
                    block_put(b);
437
                    block_put(b);
391
                    return NULL;
438
                    return NULL;
392
                }
439
                }
393
                void *node = fat_node_get(idx->dev_handle,
440
                node = fat_node_get_core(idx);
394
                    idx->index);
441
                futex_up(&idx->lock);
395
                block_put(b);
442
                block_put(b);
396
                return node;
443
                return node;
397
            }
444
            }
398
        }
445
        }
399
        block_put(b);
446
        block_put(b);
400
    }
447
    }
401
 
-
 
-
 
448
    futex_up(&parentp->idx->lock);
402
    return NULL;
449
    return NULL;
403
}
450
}
404
 
451
 
405
static fs_index_t fat_index_get(void *node)
452
static fs_index_t fat_index_get(void *node)
406
{
453
{
Line 430... Line 477...
430
    unsigned i, j;
477
    unsigned i, j;
431
 
478
 
432
    if (nodep->type != FAT_DIRECTORY)
479
    if (nodep->type != FAT_DIRECTORY)
433
        return false;
480
        return false;
434
 
481
 
-
 
482
    futex_down(&nodep->idx->lock);
435
    bps = fat_bps_get(nodep->idx->dev_handle);
483
    bps = fat_bps_get(nodep->idx->dev_handle);
436
    dps = bps / sizeof(fat_dentry_t);
484
    dps = bps / sizeof(fat_dentry_t);
437
 
485
 
438
    blocks = nodep->size / bps + (nodep->size % bps != 0);
486
    blocks = nodep->size / bps + (nodep->size % bps != 0);
439
 
487
 
Line 450... Line 498...
450
            switch (fat_classify_dentry(d)) {
498
            switch (fat_classify_dentry(d)) {
451
            case FAT_DENTRY_SKIP:
499
            case FAT_DENTRY_SKIP:
452
                continue;
500
                continue;
453
            case FAT_DENTRY_LAST:
501
            case FAT_DENTRY_LAST:
454
                block_put(b);
502
                block_put(b);
-
 
503
                futex_up(&nodep->idx->lock);
455
                return false;
504
                return false;
456
            default:
505
            default:
457
            case FAT_DENTRY_VALID:
506
            case FAT_DENTRY_VALID:
458
                block_put(b);
507
                block_put(b);
-
 
508
                futex_up(&nodep->idx->lock);
459
                return true;
509
                return true;
460
            }
510
            }
461
            block_put(b);
511
            block_put(b);
-
 
512
            futex_up(&nodep->idx->lock);
462
            return true;
513
            return true;
463
        }
514
        }
464
        block_put(b);
515
        block_put(b);
465
    }
516
    }
466
 
517
 
-
 
518
    futex_up(&nodep->idx->lock);
467
    return false;
519
    return false;
468
}
520
}
469
 
521
 
470
static void *fat_root_get(dev_handle_t dev_handle)
522
static void *fat_root_get(dev_handle_t dev_handle)
471
{
523
{