OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [fs/] [fat/] [current/] [src/] [fatfs_ncache.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      fatfs_ncache.c
4
//
5
//      FAT file system node cache functions
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):           Savin Zlobec <savin@elatec.si> 
43
// Date:                2003-06-26
44
//
45
//####DESCRIPTIONEND####
46
//
47
//==========================================================================
48
 
49
#include <pkgconf/fs_fat.h>
50
#include <pkgconf/infra.h>
51
#include <cyg/infra/cyg_type.h>
52
#include <cyg/infra/cyg_ass.h>
53
#include <cyg/infra/cyg_trac.h>
54
#include <cyg/infra/diag.h>
55
#include <sys/types.h>
56
#include <ctype.h>
57
 
58
#include "fatfs.h"
59
 
60
//==========================================================================
61
// Defines & macros 
62
 
63
#ifdef CYGDBG_USE_ASSERTS
64
# define USE_ASSERTS 1
65
#endif
66
 
67
#ifdef FATFS_NODE_CACHE_EXTRA_CHECKS
68
# define USE_XCHECKS 1
69
#endif
70
 
71
#ifdef FATFS_TRACE_NODE_CACHE
72
# define TNC 1
73
#else
74
# define TNC 0
75
#endif
76
 
77
// This defines how many nodes should always be kept in dead list - 
78
// it should be >= 2 or the file finding code may not work correctly!
79
#define DLIST_KEEP_NUM 2 
80
 
81
//==========================================================================
82
// Node list functions 
83
 
84
static void
85
node_list_init(fatfs_node_list_t *list)
86
{
87
    list->size  = 0;
88
    list->first = list->last = NULL;
89
}
90
 
91
static __inline__ int
92
node_list_get_size(fatfs_node_list_t *list)
93
{
94
    return (list->size);
95
}
96
 
97
static __inline__ fatfs_node_t*
98
node_list_get_head(fatfs_node_list_t *list)
99
{
100
    return (list->first);
101
}
102
 
103
static __inline__ fatfs_node_t*
104
node_list_get_tail(fatfs_node_list_t *list)
105
{
106
    return (list->last);
107
}
108
 
109
static __inline__ fatfs_node_t*
110
node_list_get_next(fatfs_node_t *node)
111
{
112
    return (node->list_next);
113
}
114
 
115
static __inline__ fatfs_node_t*
116
node_list_get_prev(fatfs_node_t *node)
117
{
118
    return (node->list_prev);
119
}
120
 
121
static __inline__ bool
122
node_list_is_last(fatfs_node_t *node)
123
{
124
    return (NULL == node->list_next);
125
}
126
 
127
static __inline__ bool
128
node_list_is_first(fatfs_node_t *node)
129
{
130
    return (NULL == node->list_prev);
131
}
132
 
133
static void
134
node_list_head_add(fatfs_node_list_t *list, fatfs_node_t *node)
135
{
136
    node->list_prev = NULL;
137
    node->list_next = list->first;
138
 
139
    if (NULL == list->first)
140
    {
141
        CYG_ASSERTC(list->size == 0);
142
        list->last = node;
143
    }
144
    else
145
    {
146
        list->first->list_prev = node;
147
    }
148
 
149
    list->first = node;
150
    list->size++;
151
}
152
 
153
#if 0
154
static __inline__ fatfs_node_t*
155
node_list_head_get(fatfs_node_list_t *list)
156
{
157
    return list->first;
158
}
159
 
160
static void
161
node_list_tail_add(fatfs_node_list_t *list, fatfs_node_t *node)
162
{
163
    node->list_prev = list->last;
164
    node->list_next = NULL;
165
 
166
    if (NULL == list->last)
167
    {
168
        CYG_ASSERTC(list->size == 0);
169
        list->first = node;
170
    }
171
    else
172
    {
173
        list->last->list_next = node;
174
    }
175
 
176
    list->last = node;
177
    list->size++;
178
}
179
#endif
180
 
181
static __inline__ fatfs_node_t*
182
node_list_tail_get(fatfs_node_list_t *list)
183
{
184
    return list->last;
185
}
186
 
187
static void
188
node_list_remove(fatfs_node_list_t *list, fatfs_node_t *node)
189
{
190
    if (list->first == list->last)
191
    {
192
        if (list->first == node)
193
        {
194
            CYG_ASSERTC(list->size == 1);
195
            list->first = list->last = NULL;
196
        }
197
        else
198
        {
199
            CYG_ASSERT(false, "chain node not in list!");
200
        }
201
    }
202
    else if (list->first == node)
203
    {
204
        CYG_ASSERTC(node->list_prev == NULL);
205
        list->first = node->list_next;
206
        list->first->list_prev = NULL;
207
    }
208
    else if (list->last == node)
209
    {
210
        CYG_ASSERTC(node->list_next == NULL);
211
        list->last = node->list_prev;
212
        list->last->list_next = NULL;
213
    }
214
    else
215
    {
216
        CYG_ASSERTC(node->list_prev != NULL && node->list_next != NULL);
217
        node->list_prev->list_next = node->list_next;
218
        node->list_next->list_prev = node->list_prev;
219
    }
220
    list->size--;
221
}
222
 
223
#ifdef USE_XCHECKS
224
static void
225
node_list_check(fatfs_node_list_t *list, int min_ref, int max_ref)
226
{
227
    int i;
228
    fatfs_node_t *node, *pnode;
229
 
230
    CYG_ASSERT((list->last == NULL && list->first == NULL) ||
231
               (list->last != NULL && list->first != NULL),
232
               "list->first and list->last broken!");
233
 
234
    if (list->first == NULL)
235
    {
236
        CYG_ASSERTC(list->size == 0);
237
        return;
238
    }
239
 
240
    CYG_ASSERTC(list->first->list_prev == NULL);
241
    CYG_ASSERTC(list->last->list_next == NULL);
242
 
243
    CYG_ASSERTC(list->first->refcnt >= min_ref &&
244
                list->first->refcnt <= max_ref);
245
    CYG_ASSERTC(list->last->refcnt >= min_ref &&
246
                list->last->refcnt <= max_ref);
247
 
248
    i = 1;
249
    node = list->first;
250
    pnode = NULL;
251
    while (node->list_next != NULL)
252
    {
253
        i++;
254
        CYG_ASSERTC(node->list_prev == pnode);
255
        CYG_ASSERTC(node->refcnt >= min_ref && node->refcnt <= max_ref);
256
        pnode = node;
257
        node = node->list_next;
258
    }
259
    CYG_ASSERTC(node->list_prev == pnode);
260
    CYG_ASSERTC(list->size == i);
261
    CYG_ASSERTC(node == list->last);
262
}
263
 
264
static void
265
node_lists_check(fatfs_disk_t* disk)
266
{
267
    node_list_check(&disk->live_nlist, 1, 99999);
268
    node_list_check(&disk->dead_nlist, 0, 0);
269
}
270
#endif // USE_XCHECKS
271
 
272
//==========================================================================
273
// Node hash functions 
274
 
275
static unsigned int
276
hash_fn(const char *str, unsigned int strlen)
277
{
278
    unsigned int i = 0, val = 0;
279
 
280
    while (i++ < strlen)
281
        val = (val ^ (int)toupper(*str++)) << 1;
282
    return(val);
283
}
284
 
285
static void
286
node_hash_init(fatfs_hash_table_t *tbl)
287
{
288
    int i;
289
 
290
    // Set size and clear all slots
291
    tbl->size = FATFS_HASH_TABLE_SIZE;
292
    for (i = 0; i < tbl->size; i++)
293
        tbl->nodes[i] = NULL;
294
    tbl->n = 0;
295
}
296
 
297
static bool
298
node_hash_add(fatfs_hash_table_t *tbl, fatfs_node_t *node)
299
{
300
    unsigned int hval;
301
 
302
    // Calculate hash of given node filename
303
    hval = hash_fn(node->dentry.filename,
304
                   strlen(node->dentry.filename)) % tbl->size;
305
 
306
    CYG_TRACE2(TNC, "name='%s' hval=%d", node->dentry.filename, hval);
307
 
308
    if (tbl->nodes[hval] == NULL)
309
    {
310
        // First node in this slot
311
        node->hash_next  = NULL;
312
        tbl->nodes[hval] = node;
313
        tbl->n++;
314
        return true;
315
    }
316
    else
317
    {
318
        // More nodes in this slot
319
        fatfs_node_t *lnode, *pnode;
320
 
321
        pnode = NULL;
322
        lnode = tbl->nodes[hval];
323
 
324
        // Insert node into list so that it is sorted by filename        
325
        while (lnode != NULL)
326
        {
327
            if (lnode == node)
328
                return false;
329
 
330
            if (strcasecmp(lnode->dentry.filename, node->dentry.filename) > 0)
331
            {
332
                if (pnode != NULL)
333
                    pnode->hash_next = node; // Insert in the middle
334
                else
335
                    tbl->nodes[hval] = node; // Insert at the beginning
336
                node->hash_next = lnode;
337
                tbl->n++;
338
                return true;
339
            }
340
 
341
            pnode = lnode;
342
            lnode = lnode->hash_next;
343
        }
344
        // Insert at the end
345
        pnode->hash_next = node;
346
        node->hash_next  = NULL;
347
        tbl->n++;
348
        return true;
349
    }
350
}
351
 
352
static fatfs_node_t*
353
node_hash_find(fatfs_hash_table_t *tbl,
354
               const char         *name,
355
               unsigned int        namelen,
356
               unsigned int        parent_cluster)
357
{
358
    unsigned int  hval;
359
    fatfs_node_t *node;
360
 
361
    // Calculate hash of name and get the first node in slot
362
    hval = hash_fn(name, namelen) % tbl->size;
363
    node = tbl->nodes[hval];
364
 
365
    CYG_TRACE2(TNC, "name='%s' hval=%d\n", name, hval);
366
 
367
    // Find the node in list wich matches the 
368
    // given name and parent_cluster
369
    while (node != NULL)
370
    {
371
        // First compare the parent cluster number and 
372
        // check filename length since it is faster than 
373
        // comparing filenames
374
        if (parent_cluster == node->dentry.parent_cluster &&
375
            '\0' == node->dentry.filename[namelen])
376
        {
377
            int i = strncasecmp(node->dentry.filename, name, namelen);
378
 
379
            if (i == 0)
380
                return node;
381
            else if (i > 0)
382
                return NULL; // Stop searching - we have a 
383
                             // sorted list so there can't be
384
                             // any matching filename further on
385
                             // if i > 0 - look at node_hash_add
386
        }
387
        node = node->hash_next;
388
    }
389
 
390
    // No such node found
391
    return NULL;
392
}
393
 
394
static bool
395
node_hash_remove_keyless(fatfs_hash_table_t *tbl, fatfs_node_t *node)
396
{
397
    int i;
398
    fatfs_node_t *lnode, *pnode;
399
 
400
    // Look in all slots, since we have no key
401
    for (i = 0; i < tbl->size; i++)
402
    {
403
        // Look in list and remove it if there
404
        lnode = tbl->nodes[i];
405
        pnode = NULL;
406
        while (lnode != NULL)
407
        {
408
            if (lnode == node)
409
            {
410
                if (pnode == NULL)
411
                    tbl->nodes[i]    = lnode->hash_next;
412
                else
413
                    pnode->hash_next = lnode->hash_next;
414
                node->hash_next = NULL;
415
                tbl->n--;
416
 
417
                // All done
418
                return true;
419
            }
420
            pnode = lnode;
421
            lnode = lnode->hash_next;
422
        }
423
    }
424
    return false;
425
}
426
 
427
static bool
428
node_hash_remove(fatfs_hash_table_t *tbl, fatfs_node_t *node)
429
{
430
    unsigned int hval;
431
    fatfs_node_t *lnode, *pnode;
432
 
433
    // Calculate hash of name and get the first node in slot
434
    hval = hash_fn(node->dentry.filename,
435
                   strlen(node->dentry.filename)) % tbl->size;
436
    lnode = tbl->nodes[hval];
437
 
438
    // Now find the node in list and remove it
439
    pnode = NULL;
440
    while (lnode != NULL)
441
    {
442
        if (lnode == node)
443
        {
444
            if (pnode == NULL)
445
                tbl->nodes[hval] = lnode->hash_next;
446
            else
447
                pnode->hash_next = lnode->hash_next;
448
            node->hash_next = NULL;
449
            tbl->n--;
450
 
451
            // All done
452
            return true;
453
        }
454
        pnode = lnode;
455
        lnode = lnode->hash_next;
456
    }
457
 
458
    // Node not in list 
459
    return false;
460
}
461
 
462
#ifdef USE_XCHECKS
463
static void
464
node_hash_check(fatfs_hash_table_t *tbl)
465
{
466
    int i, n;
467
 
468
    n = 0;
469
    for (i = 0; i < tbl->size; i++)
470
    {
471
        fatfs_node_t *lnode, *pnode;
472
 
473
        pnode = NULL;
474
        lnode = tbl->nodes[i];
475
 
476
        while (lnode != NULL)
477
        {
478
            if (pnode != NULL)
479
            {
480
                int c = strcasecmp(pnode->dentry.filename, lnode->dentry.filename);
481
                CYG_ASSERT(c <= 0, "hash table not sorted");
482
                CYG_ASSERT(pnode->dentry.parent_cluster != lnode->dentry.parent_cluster ||
483
 
484
            }
485
            n++;
486
            pnode = lnode;
487
            lnode = lnode->hash_next;
488
        }
489
    }
490
    CYG_ASSERTC(tbl->n == n);
491
}
492
 
493
static void
494
node_hash_not_found_check(fatfs_disk_t *disk,
495
                          const char   *name,
496
                          unsigned int  namelen,
497
                          unsigned int  parent_cluster)
498
{
499
    fatfs_node_t* node;
500
 
501
    node = node_list_get_head(&disk->live_nlist);
502
    while (NULL != node)
503
    {
504
        if (node->dentry.parent_cluster == parent_cluster          &&
505
            namelen == strlen(node->dentry.filename)               &&
506
 
507
            CYG_ASSERT(false, "node not found in hash, "
508
                              "but exists in live list");
509
        node = node_list_get_next(node);
510
    }
511
 
512
    node = node_list_get_head(&disk->dead_nlist);
513
    while (NULL != node)
514
    {
515
        if (node->dentry.parent_cluster == parent_cluster          &&
516
            namelen == strlen(node->dentry.filename)               &&
517
 
518
            CYG_ASSERT(false, "node not found in hash, "
519
                              "but exists in dead list");
520
        node = node_list_get_next(node);
521
    }
522
}
523
 
524
static void
525
node_hash_found_check(fatfs_disk_t *disk,
526
                      const char   *name,
527
                      unsigned int  namelen,
528
                      unsigned int  parent_cluster,
529
                      fatfs_node_t* node)
530
{
531
    fatfs_node_t *n;
532
 
533
    n = node_list_get_head(&disk->live_nlist);
534
    while (NULL != n)
535
    {
536
        if (n == node)
537
        {
538
            if (node->dentry.parent_cluster != parent_cluster ||
539
                namelen != strlen(node->dentry.filename)      ||
540
 
541
                CYG_ASSERT(false, "node_hash_find returned wrong node");
542
            return;
543
        }
544
        n = node_list_get_next(n);
545
    }
546
 
547
    n = node_list_get_head(&disk->dead_nlist);
548
    while (NULL != n)
549
    {
550
        if (n == node)
551
        {
552
            if (node->dentry.parent_cluster != parent_cluster ||
553
                namelen != strlen(node->dentry.filename)      ||
554
 
555
                CYG_ASSERT(false, "node_hash_find returned wrong node");
556
            return;
557
        }
558
        n = node_list_get_next(n);
559
    }
560
 
561
    CYG_ASSERT(false, "node not found in dead or live lists, "
562
                      "but exists in hash.");
563
}
564
#endif // USE_XCHECKS
565
 
566
//--------------------------------------------------------------------------
567
 
568
#ifdef USE_XCHECKS
569
 
570
# define SANITY_CHECK()                                                     \
571
    CYG_MACRO_START                                                         \
572
        node_lists_check(disk);                                             \
573
        node_hash_check(&disk->node_hash);                                  \
574
        CYG_ASSERTC((disk->live_nlist.size + disk->dead_nlist.size) ==      \
575
                    disk->node_hash.n);                                     \
576
    CYG_MACRO_END
577
 
578
# define NODE_FIND_CHECK()                                                    \
579
    CYG_MACRO_START                                                           \
580
        if (NULL == node)                                                     \
581
            node_hash_not_found_check(disk, name, namelen, parent_cluster);   \
582
        else                                                                  \
583
            node_hash_found_check(disk, name, namelen, parent_cluster, node); \
584
    CYG_MACRO_END
585
 
586
#else // USE_XCHECKS
587
# define SANITY_CHECK()    CYG_EMPTY_STATEMENT
588
# define NODE_FIND_CHECK() CYG_EMPTY_STATEMENT
589
#endif // not USE_XCHECKS
590
 
591
//==========================================================================
592
// Node pool allocation functions
593
 
594
static void
595
node_pool_init(fatfs_disk_t *disk)
596
{
597
    int i;
598
 
599
    for (i = 0; i < FATFS_NODE_POOL_SIZE; i++)
600
        disk->node_pool[i] = &disk->node_pool_base[i];
601
 
602
    disk->node_pool_free_cnt = i;
603
}
604
 
605
static fatfs_node_t *
606
node_pool_alloc(fatfs_disk_t *disk)
607
{
608
    fatfs_node_t *node = NULL;
609
 
610
    if (disk->node_pool_free_cnt > 0)
611
        node = disk->node_pool[--disk->node_pool_free_cnt];
612
 
613
    return node;
614
}
615
 
616
static void
617
node_pool_free(fatfs_disk_t *disk, fatfs_node_t *node)
618
{
619
    disk->node_pool[disk->node_pool_free_cnt++] = node;
620
}
621
 
622
//==========================================================================
623
//==========================================================================
624
// Exported functions 
625
 
626
//--------------------------------------------------------------------------
627
// fatfs_node_cache_init()
628
// Initializes node cache of given disk.
629
 
630
void
631
fatfs_node_cache_init(fatfs_disk_t *disk)
632
{
633
    CYG_CHECK_DATA_PTRC(disk);
634
 
635
    node_list_init(&disk->live_nlist);
636
    node_list_init(&disk->dead_nlist);
637
    node_hash_init(&disk->node_hash);
638
    node_pool_init(disk);
639
 
640
    SANITY_CHECK();
641
}
642
 
643
//--------------------------------------------------------------------------
644
// fatfs_node_cache_flush()
645
// Frees all node cache of given disk.
646
 
647
void
648
fatfs_node_cache_flush(fatfs_disk_t *disk)
649
{
650
    fatfs_node_t *node, *next_node;
651
 
652
    node = node_list_get_head(&disk->live_nlist);
653
 
654
    while (NULL != node)
655
    {
656
        next_node = node_list_get_next(node);
657
        node_list_remove(&disk->live_nlist, node);
658
        if (!node_hash_remove(&disk->node_hash, node))
659
            CYG_ASSERT(false, "Node not in hash");
660
        node_pool_free(disk, node);
661
        node = next_node;
662
    }
663
 
664
    node = node_list_get_head(&disk->dead_nlist);
665
 
666
    while (NULL != node)
667
    {
668
        next_node = node_list_get_next(node);
669
        node_list_remove(&disk->dead_nlist, node);
670
        if (!node_hash_remove(&disk->node_hash, node))
671
            CYG_ASSERT(false, "Node not in hash");
672
        node_pool_free(disk, node);
673
        node = next_node;
674
    }
675
 
676
    SANITY_CHECK();
677
}
678
 
679
//--------------------------------------------------------------------------
680
// fatfs_node_alloc()
681
// Allocates a new node.  
682
 
683
fatfs_node_t*
684
fatfs_node_alloc(fatfs_disk_t *disk, fatfs_dir_entry_t *dentry)
685
{
686
    fatfs_node_t *node;
687
 
688
    CYG_CHECK_DATA_PTRC(disk);
689
    CYG_CHECK_DATA_PTRC(dentry);
690
 
691
    node = node_pool_alloc(disk);
692
 
693
    if (NULL == node)
694
    {
695
        CYG_TRACE2(TNC, "getting node from dead list (size=%d keep=%d)",
696
                        node_list_get_size(&disk->dead_nlist), DLIST_KEEP_NUM);
697
 
698
        if (node_list_get_size(&disk->dead_nlist) <= DLIST_KEEP_NUM)
699
            return NULL;
700
 
701
        node = node_list_tail_get(&disk->dead_nlist);
702
        if (NULL == node)
703
            return NULL;
704
 
705
        CYG_TRACE1(TNC, "recycling node='%s'", node->dentry.filename);
706
 
707
        node_list_remove(&disk->dead_nlist, node);
708
        if (!node_hash_remove(&disk->node_hash, node))
709
            CYG_ASSERT(false, "node not in hash");
710
    }
711
 
712
    // Init new node    
713
    node->dentry = *dentry;
714
    node->refcnt = 0;
715
 
716
    node_list_head_add(&disk->dead_nlist, node);
717
    if (!node_hash_add(&disk->node_hash, node))
718
        CYG_ASSERT(false, "node already in hash");
719
 
720
    SANITY_CHECK();
721
 
722
    return node;
723
}
724
 
725
//--------------------------------------------------------------------------
726
// fatfs_node_touch()
727
// Moves given node to top of its list.
728
// (When reusing dead node it is always taken from the bottom of list) 
729
 
730
void
731
fatfs_node_touch(fatfs_disk_t *disk, fatfs_node_t *node)
732
{
733
    CYG_CHECK_DATA_PTRC(disk);
734
    CYG_CHECK_DATA_PTRC(node);
735
    CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt);
736
 
737
    if (node->refcnt == 0)
738
    {
739
        node_list_remove(&disk->dead_nlist, node);
740
        node_list_head_add(&disk->dead_nlist, node);
741
    }
742
    else
743
    {
744
        node_list_remove(&disk->live_nlist, node);
745
        node_list_head_add(&disk->live_nlist, node);
746
    }
747
 
748
    SANITY_CHECK();
749
}
750
 
751
//--------------------------------------------------------------------------
752
// fatfs_node_ref()
753
// Increases the given node reference count.
754
// If the reference goes from 0 to 1, than the node
755
// is moved from dead list to live list.
756
 
757
void
758
fatfs_node_ref(fatfs_disk_t *disk, fatfs_node_t *node)
759
{
760
    CYG_CHECK_DATA_PTRC(disk);
761
    CYG_CHECK_DATA_PTRC(node);
762
    CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt);
763
 
764
    node->refcnt++;
765
    if (1 == node->refcnt)
766
    {
767
        // First reference - move node from dead to live list
768
 
769
        CYG_TRACE1(TNC, "node='%s' to live list", node->dentry.filename);
770
 
771
        node_list_remove(&disk->dead_nlist, node);
772
        node_list_head_add(&disk->live_nlist, node);
773
    }
774
 
775
    SANITY_CHECK();
776
}
777
 
778
//--------------------------------------------------------------------------
779
// fatfs_node_unref()
780
// Decreases the given node reference count.
781
// If the reference goes from 1 to 0, than the node
782
// is moved from live list to top of dead list.
783
// (When reusing dead node it is always taken from the bottom of list)
784
 
785
void
786
fatfs_node_unref(fatfs_disk_t *disk, fatfs_node_t *node)
787
{
788
    CYG_CHECK_DATA_PTRC(disk);
789
    CYG_CHECK_DATA_PTRC(node);
790
    CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt);
791
    CYG_ASSERT(node->refcnt > 0, "node->refcnt <= 0");
792
 
793
    node->refcnt--;
794
    if (0 == node->refcnt)
795
    {
796
        // No more references - move node from live to dead list
797
 
798
        CYG_TRACE1(TNC, "node='%s' to dead list", node->dentry.filename);
799
 
800
        node_list_remove(&disk->live_nlist, node);
801
        node_list_head_add(&disk->dead_nlist, node);
802
    }
803
 
804
    SANITY_CHECK();
805
}
806
 
807
//--------------------------------------------------------------------------
808
// fatfs_node_free()
809
// Frees node memory and removes it from its list and hash. 
810
// This function must not be called on a referenced node.
811
 
812
void
813
fatfs_node_free(fatfs_disk_t *disk, fatfs_node_t *node)
814
{
815
    CYG_CHECK_DATA_PTRC(disk);
816
    CYG_CHECK_DATA_PTRC(node);
817
    CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt);
818
    CYG_ASSERTC(node->refcnt == 0);
819
    CYG_ASSERTC(node != disk->root);
820
 
821
    // Remove from dead list, from hash and free ptr
822
 
823
    node_list_remove(&disk->dead_nlist, node);
824
    if (!node_hash_remove(&disk->node_hash, node))
825
        CYG_ASSERT(false, "node not in hash");
826
 
827
    node_pool_free(disk, node);
828
 
829
    SANITY_CHECK();
830
}
831
 
832
//--------------------------------------------------------------------------
833
// fatfs_node_rehash()
834
// Recalculates given node hash key. 
835
 
836
void
837
fatfs_node_rehash(fatfs_disk_t *disk, fatfs_node_t *node)
838
{
839
    CYG_CHECK_DATA_PTRC(disk);
840
    CYG_CHECK_DATA_PTRC(node);
841
 
842
    if (!node_hash_remove_keyless(&disk->node_hash, node))
843
        CYG_ASSERT(false, "node not in hash");
844
 
845
    if (!node_hash_add(&disk->node_hash, node))
846
        CYG_ASSERT(false, "node already in hash");
847
 
848
    SANITY_CHECK();
849
}
850
 
851
//--------------------------------------------------------------------------
852
// fatfs_node_find()
853
// Finds node in hash by its name and parent cluster. 
854
// If no node found NULL is returned.
855
 
856
fatfs_node_t*
857
fatfs_node_find(fatfs_disk_t *disk,
858
                const char   *name,
859
                unsigned int  namelen,
860
                unsigned int  parent_cluster)
861
{
862
    fatfs_node_t *node;
863
 
864
    CYG_CHECK_DATA_PTRC(disk);
865
    CYG_CHECK_DATA_PTRC(name);
866
 
867
    node = node_hash_find(&disk->node_hash, name, namelen, parent_cluster);
868
 
869
    NODE_FIND_CHECK();
870
 
871
    CYG_TRACE3(TNC, "node name=%s pcluster=%d %s found in cache\n",
872
        name, parent_cluster, ((node != NULL) ? "" : "not"));
873
 
874
    return node;
875
}
876
 
877
//--------------------------------------------------------------------------
878
// fatfs_get_live_node_count()
879
// Gets the number of live nodes.
880
 
881
int
882
fatfs_get_live_node_count(fatfs_disk_t *disk)
883
{
884
    return node_list_get_size(&disk->live_nlist);
885
}
886
 
887
//--------------------------------------------------------------------------
888
// fatfs_get_dead_node_count()
889
// Gets the number of dead nodes.
890
 
891
int
892
fatfs_get_dead_node_count(fatfs_disk_t *disk)
893
{
894
    return node_list_get_size(&disk->dead_nlist);
895
}
896
 
897
// -------------------------------------------------------------------------
898
// EOF fatfs_ncache.c

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.