Changeset 5a324099 in mainline
- Timestamp:
- 2008-05-04T16:17:01Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0c1ad7ac
- Parents:
- f520905
- Location:
- uspace/srv/fs/fat
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat.h
rf520905 r5a324099 215 215 extern void fat_lookup(ipc_callid_t, ipc_call_t *); 216 216 217 extern fat_idx_t *fat_idx_map( fat_cluster_t, unsigned);217 extern fat_idx_t *fat_idx_map(dev_handle_t, fat_cluster_t, unsigned); 218 218 219 219 #endif -
uspace/srv/fs/fat/fat_idx.c
rf520905 r5a324099 37 37 38 38 #include "fat.h" 39 #include "../../vfs/vfs.h" 39 40 #include <errno.h> 40 41 #include <string.h> … … 44 45 #include <futex.h> 45 46 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. */ 48 typedef 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 */ 58 typedef 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 71 static LIST_INITIALIZE(unused_head); 72 73 /** Allocate a VFS index which is not currently in use. */ 74 static 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 89 hit: 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. */ 121 static 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. */ 140 static 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 154 hit: 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 207 fat_idx_t *fat_idx_map(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi) 47 208 { 48 209 return NULL; /* TODO */ -
uspace/srv/fs/fat/fat_ops.c
rf520905 r5a324099 309 309 if (strcmp(name, component) == 0) { 310 310 /* 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, 312 313 i * dps + j); 313 314 void *node = fat_node_get(idx->dev_handle,
Note:
See TracChangeset
for help on using the changeset viewer.