Changeset 5a324099 in mainline


Ignore:
Timestamp:
2008-05-04T16:17:01Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0c1ad7ac
Parents:
f520905
Message:

Code for de/allocation of VFS indices for FAT.

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

Legend:

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

    rf520905 r5a324099  
    215215extern void fat_lookup(ipc_callid_t, ipc_call_t *);
    216216
    217 extern fat_idx_t *fat_idx_map(fat_cluster_t, unsigned);
     217extern fat_idx_t *fat_idx_map(dev_handle_t, fat_cluster_t, unsigned);
    218218
    219219#endif
  • uspace/srv/fs/fat/fat_idx.c

    rf520905 r5a324099  
    3737
    3838#include "fat.h"
     39#include "../../vfs/vfs.h"
    3940#include <errno.h>
    4041#include <string.h>
     
    4445#include <futex.h>
    4546
    46 fat_idx_t *fat_idx_map(fat_cluster_t pfc, unsigned pdi)
     47/** Each instance of this type describes one interval of freed VFS indices. */
     48typedef struct {
     49        link_t          link;
     50        fs_index_t      first;
     51        fs_index_t      last;
     52} freed_t;
     53
     54/**
     55 * Each instance of this type describes state of all VFS indices that
     56 * are currently unused.
     57 */
     58typedef struct {
     59        link_t          link;
     60        dev_handle_t    dev_handle;
     61
     62        /** Next unassigned index. */
     63        fs_index_t      next;
     64        /** Number of remaining unassigned indices. */
     65        uint64_t        remaining;
     66
     67        /** Sorted list of intervals of freed indices. */
     68        link_t          freed_head;
     69} unused_t;
     70
     71static LIST_INITIALIZE(unused_head);
     72
     73/** Allocate a VFS index which is not currently in use. */
     74static bool fat_idx_alloc(dev_handle_t dev_handle, fs_index_t *index)
     75{
     76        link_t *l;
     77        unused_t *u;
     78       
     79        assert(index);
     80        for (l = unused_head.next; l != &unused_head; l = l->next) {
     81                u = list_get_instance(l, unused_t, link);
     82                if (u->dev_handle == dev_handle)
     83                        goto hit;
     84        }
     85
     86        /* dev_handle not found */
     87        return false;   
     88
     89hit:
     90        if (list_empty(&u->freed_head)) {
     91                if (u->remaining) {
     92                        /*
     93                         * There are no freed indices, allocate one directly
     94                         * from the counter.
     95                         */
     96                        *index = u->next++;
     97                        --u->remaining;
     98                        return true;
     99                }
     100        } else {
     101                /* There are some freed indices which we can reuse. */
     102                freed_t *f = list_get_instance(u->freed_head.next, freed_t,
     103                    link);
     104                *index = f->first;
     105                if (f->first++ == f->last) {
     106                        /* Destroy the interval. */
     107                        list_remove(&f->link);
     108                        free(f);
     109                }
     110                return true;
     111        }
     112        /*
     113         * We ran out of indices, which is extremely unlikely with FAT16, but
     114         * theoretically still possible (e.g. too many open unlinked nodes or
     115         * too many zero-sized nodes).
     116         */
     117        return false;
     118}
     119
     120/** If possible, merge two intervals of freed indices. */
     121static void try_merge_intervals(link_t *l, link_t *r, link_t *cur)
     122{
     123        freed_t *fl = list_get_instance(l, freed_t, link);
     124        freed_t *fr = list_get_instance(r, freed_t, link);
     125
     126        if (fl->last + 1 == fr->first) {
     127                if (cur == l) {
     128                        fl->last = fr->last;
     129                        list_remove(r);
     130                        free(r);
     131                } else {
     132                        fr->first = fl->first;
     133                        list_remove(l);
     134                        free(l);
     135                }
     136        }
     137}
     138
     139/** Free a VFS index, which is no longer in use. */
     140static void fat_idx_free(dev_handle_t dev_handle, fs_index_t index)
     141{
     142        link_t *l;
     143        unused_t *u;
     144
     145        for (l = unused_head.next; l != &unused_head; l = l->next) {
     146                u = list_get_instance(l, unused_t, link);
     147                if (u->dev_handle == dev_handle)
     148                        goto hit;
     149        }
     150
     151        /* should not happen */
     152        assert(0);
     153
     154hit:
     155        if (u->next == index + 1) {
     156                /* The index can be returned directly to the counter. */
     157                u->next--;
     158                u->remaining++;
     159                return;
     160        } else {
     161                /*
     162                 * The index must be returned either to an existing freed
     163                 * interval or a new interval must be created.
     164                 */
     165                link_t *lnk;
     166                freed_t *n;
     167                for (lnk = u->freed_head.next; lnk != &u->freed_head;
     168                    lnk = lnk->next) {
     169                        freed_t *f = list_get_instance(lnk, freed_t, link);
     170                        if (f->first == index + 1) {
     171                                f->first--;
     172                                if (lnk->prev != &u->freed_head)
     173                                        try_merge_intervals(lnk->prev, lnk,
     174                                            lnk);
     175                                return;
     176                        }
     177                        if (f->last == index - 1) {
     178                                f->last++;
     179                                if (lnk->next != &u->freed_head)
     180                                        try_merge_intervals(lnk, lnk->next,
     181                                            lnk);
     182                                return;
     183                        }
     184                        if (index > f->first) {
     185                                n = malloc(sizeof(freed_t));
     186                                /* TODO: sleep until allocation succeeds */
     187                                assert(n);
     188                                link_initialize(&n->link);
     189                                n->first = index;
     190                                n->last = index;
     191                                list_insert_before(&n->link, lnk);
     192                                return;
     193                        }
     194
     195                }
     196                /* The index will form the last interval. */
     197                n = malloc(sizeof(freed_t));
     198                /* TODO: sleep until allocation succeeds */
     199                assert(n);
     200                link_initialize(&n->link);
     201                n->first = index;
     202                n->last = index;
     203                list_append(&n->link, &u->freed_head);
     204        }
     205}
     206
     207fat_idx_t *fat_idx_map(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi)
    47208{
    48209        return NULL;    /* TODO */
  • uspace/srv/fs/fat/fat_ops.c

    rf520905 r5a324099  
    309309                        if (strcmp(name, component) == 0) {
    310310                                /* hit */
    311                                 fat_idx_t *idx = fat_idx_map(parentp->firstc,
     311                                fat_idx_t *idx = fat_idx_map(
     312                                    parentp->idx->dev_handle, parentp->firstc,
    312313                                    i * dps + j);
    313314                                void *node = fat_node_get(idx->dev_handle,
Note: See TracChangeset for help on using the changeset viewer.