Subversion Repositories HelenOS

Rev

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

Rev 2910 Rev 2951
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 377... Line 414...
377
                dentry_name_canonify(d, name);
414
                dentry_name_canonify(d, name);
378
                break;
415
                break;
379
            }
416
            }
380
            if (strcmp(name, component) == 0) {
417
            if (strcmp(name, component) == 0) {
381
                /* hit */
418
                /* hit */
-
 
419
                void *node;
382
                fat_idx_t *idx = fat_idx_get_by_pos(
420
                fat_idx_t *idx = fat_idx_get_by_pos(
383
                    parentp->idx->dev_handle, parentp->firstc,
421
                    parentp->idx->dev_handle, parentp->firstc,
384
                    i * dps + j);
422
                    i * dps + j);
385
                if (!idx) {
423
                if (!idx) {
386
                    /*
424
                    /*
Line 388... Line 426...
388
                     * run out of 32-bit indices.
426
                     * run out of 32-bit indices.
389
                     */
427
                     */
390
                    block_put(b);
428
                    block_put(b);
391
                    return NULL;
429
                    return NULL;
392
                }
430
                }
393
                void *node = fat_node_get(idx->dev_handle,
431
                node = fat_node_get_core(idx);
394
                    idx->index);
432
                futex_up(&idx->lock);
395
                block_put(b);
433
                block_put(b);
396
                return node;
434
                return node;
397
            }
435
            }
398
        }
436
        }
399
        block_put(b);
437
        block_put(b);
Line 430... Line 468...
430
    unsigned i, j;
468
    unsigned i, j;
431
 
469
 
432
    if (nodep->type != FAT_DIRECTORY)
470
    if (nodep->type != FAT_DIRECTORY)
433
        return false;
471
        return false;
434
 
472
 
-
 
473
    futex_down(&nodep->idx->lock);
435
    bps = fat_bps_get(nodep->idx->dev_handle);
474
    bps = fat_bps_get(nodep->idx->dev_handle);
436
    dps = bps / sizeof(fat_dentry_t);
475
    dps = bps / sizeof(fat_dentry_t);
437
 
476
 
438
    blocks = nodep->size / bps + (nodep->size % bps != 0);
477
    blocks = nodep->size / bps + (nodep->size % bps != 0);
439
 
478
 
Line 450... Line 489...
450
            switch (fat_classify_dentry(d)) {
489
            switch (fat_classify_dentry(d)) {
451
            case FAT_DENTRY_SKIP:
490
            case FAT_DENTRY_SKIP:
452
                continue;
491
                continue;
453
            case FAT_DENTRY_LAST:
492
            case FAT_DENTRY_LAST:
454
                block_put(b);
493
                block_put(b);
-
 
494
                futex_up(&nodep->idx->lock);
455
                return false;
495
                return false;
456
            default:
496
            default:
457
            case FAT_DENTRY_VALID:
497
            case FAT_DENTRY_VALID:
458
                block_put(b);
498
                block_put(b);
-
 
499
                futex_up(&nodep->idx->lock);
459
                return true;
500
                return true;
460
            }
501
            }
461
            block_put(b);
502
            block_put(b);
-
 
503
            futex_up(&nodep->idx->lock);
462
            return true;
504
            return true;
463
        }
505
        }
464
        block_put(b);
506
        block_put(b);
465
    }
507
    }
466
 
508
 
-
 
509
    futex_up(&nodep->idx->lock);
467
    return false;
510
    return false;
468
}
511
}
469
 
512
 
470
static void *fat_root_get(dev_handle_t dev_handle)
513
static void *fat_root_get(dev_handle_t dev_handle)
471
{
514
{