Rev 3022 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3022 | Rev 4055 | ||
---|---|---|---|
Line 72... | Line 72... | ||
72 | static futex_t unused_futex = FUTEX_INITIALIZER; |
72 | static futex_t unused_futex = FUTEX_INITIALIZER; |
73 | 73 | ||
74 | /** List of unused structures. */ |
74 | /** List of unused structures. */ |
75 | static LIST_INITIALIZE(unused_head); |
75 | static LIST_INITIALIZE(unused_head); |
76 | 76 | ||
- | 77 | static void unused_initialize(unused_t *u, dev_handle_t dev_handle) |
|
- | 78 | { |
|
- | 79 | link_initialize(&u->link); |
|
- | 80 | u->dev_handle = dev_handle; |
|
- | 81 | u->next = 0; |
|
- | 82 | u->remaining = ((uint64_t)((fs_index_t)-1)) + 1; |
|
- | 83 | list_initialize(&u->freed_head); |
|
- | 84 | } |
|
- | 85 | ||
- | 86 | static unused_t *unused_find(dev_handle_t dev_handle, bool lock) |
|
- | 87 | { |
|
- | 88 | unused_t *u; |
|
- | 89 | link_t *l; |
|
- | 90 | ||
- | 91 | if (lock) |
|
- | 92 | futex_down(&unused_futex); |
|
- | 93 | for (l = unused_head.next; l != &unused_head; l = l->next) { |
|
- | 94 | u = list_get_instance(l, unused_t, link); |
|
- | 95 | if (u->dev_handle == dev_handle) |
|
- | 96 | return u; |
|
- | 97 | } |
|
- | 98 | if (lock) |
|
- | 99 | futex_up(&unused_futex); |
|
- | 100 | return NULL; |
|
- | 101 | } |
|
- | 102 | ||
77 | /** Futex protecting the up_hash and ui_hash. */ |
103 | /** Futex protecting the up_hash and ui_hash. */ |
78 | static futex_t used_futex = FUTEX_INITIALIZER; |
104 | static futex_t used_futex = FUTEX_INITIALIZER; |
79 | 105 | ||
80 | /** |
106 | /** |
81 | * Global hash table of all used fat_idx_t structures. |
107 | * Global hash table of all used fat_idx_t structures. |
Line 186... | Line 212... | ||
186 | .compare = idx_compare, |
212 | .compare = idx_compare, |
187 | .remove_callback = idx_remove_callback, |
213 | .remove_callback = idx_remove_callback, |
188 | }; |
214 | }; |
189 | 215 | ||
190 | /** Allocate a VFS index which is not currently in use. */ |
216 | /** Allocate a VFS index which is not currently in use. */ |
191 | static bool fat_idx_alloc(dev_handle_t dev_handle, fs_index_t *index) |
217 | static bool fat_index_alloc(dev_handle_t dev_handle, fs_index_t *index) |
192 | { |
218 | { |
193 | link_t *l; |
- | |
194 | unused_t *u; |
219 | unused_t *u; |
195 | 220 | ||
196 | assert(index); |
221 | assert(index); |
197 | futex_down(&unused_futex); |
- | |
198 | for (l = unused_head.next; l != &unused_head; l = l->next) { |
- | |
199 | u = list_get_instance(l, unused_t, link); |
- | |
200 | if (u->dev_handle == dev_handle) |
222 | u = unused_find(dev_handle, true); |
201 | goto hit; |
223 | if (!u) |
202 | } |
- | |
203 | futex_up(&unused_futex); |
- | |
204 | - | ||
205 | /* dev_handle not found */ |
- | |
206 | return false; |
224 | return false; |
207 | 225 | ||
208 | hit: |
- | |
209 | if (list_empty(&u->freed_head)) { |
226 | if (list_empty(&u->freed_head)) { |
210 | if (u->remaining) { |
227 | if (u->remaining) { |
211 | /* |
228 | /* |
212 | * There are no freed indices, allocate one directly |
229 | * There are no freed indices, allocate one directly |
213 | * from the counter. |
230 | * from the counter. |
Line 257... | Line 274... | ||
257 | } |
274 | } |
258 | } |
275 | } |
259 | } |
276 | } |
260 | 277 | ||
261 | /** Free a VFS index, which is no longer in use. */ |
278 | /** Free a VFS index, which is no longer in use. */ |
262 | static void fat_idx_free(dev_handle_t dev_handle, fs_index_t index) |
279 | static void fat_index_free(dev_handle_t dev_handle, fs_index_t index) |
263 | { |
280 | { |
264 | link_t *l; |
- | |
265 | unused_t *u; |
281 | unused_t *u; |
266 | 282 | ||
267 | futex_down(&unused_futex); |
- | |
268 | for (l = unused_head.next; l != &unused_head; l = l->next) { |
- | |
269 | u = list_get_instance(l, unused_t, link); |
- | |
270 | if (u->dev_handle == dev_handle) |
283 | u = unused_find(dev_handle, true); |
271 | goto hit; |
- | |
272 | } |
- | |
273 | futex_up(&unused_futex); |
- | |
274 | - | ||
275 | /* should not happen */ |
- | |
276 | assert(0); |
284 | assert(u); |
277 | 285 | ||
278 | hit: |
- | |
279 | if (u->next == index + 1) { |
286 | if (u->next == index + 1) { |
280 | /* The index can be returned directly to the counter. */ |
287 | /* The index can be returned directly to the counter. */ |
281 | u->next--; |
288 | u->next--; |
282 | u->remaining++; |
289 | u->remaining++; |
283 | } else { |
290 | } else { |
Line 329... | Line 336... | ||
329 | list_append(&n->link, &u->freed_head); |
336 | list_append(&n->link, &u->freed_head); |
330 | } |
337 | } |
331 | futex_up(&unused_futex); |
338 | futex_up(&unused_futex); |
332 | } |
339 | } |
333 | 340 | ||
- | 341 | static fat_idx_t *fat_idx_create(dev_handle_t dev_handle) |
|
- | 342 | { |
|
- | 343 | fat_idx_t *fidx; |
|
- | 344 | ||
- | 345 | fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
|
- | 346 | if (!fidx) |
|
- | 347 | return NULL; |
|
- | 348 | if (!fat_index_alloc(dev_handle, &fidx->index)) { |
|
- | 349 | free(fidx); |
|
- | 350 | return NULL; |
|
- | 351 | } |
|
- | 352 | ||
- | 353 | link_initialize(&fidx->uph_link); |
|
- | 354 | link_initialize(&fidx->uih_link); |
|
- | 355 | futex_initialize(&fidx->lock, 1); |
|
- | 356 | fidx->dev_handle = dev_handle; |
|
- | 357 | fidx->pfc = FAT_CLST_RES0; /* no parent yet */ |
|
- | 358 | fidx->pdi = 0; |
|
- | 359 | fidx->nodep = NULL; |
|
- | 360 | ||
- | 361 | return fidx; |
|
- | 362 | } |
|
- | 363 | ||
- | 364 | fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle) |
|
- | 365 | { |
|
- | 366 | fat_idx_t *fidx; |
|
- | 367 | ||
- | 368 | futex_down(&used_futex); |
|
- | 369 | fidx = fat_idx_create(dev_handle); |
|
- | 370 | if (!fidx) { |
|
- | 371 | futex_up(&used_futex); |
|
- | 372 | return NULL; |
|
- | 373 | } |
|
- | 374 | ||
- | 375 | unsigned long ikey[] = { |
|
- | 376 | [UIH_DH_KEY] = dev_handle, |
|
- | 377 | [UIH_INDEX_KEY] = fidx->index, |
|
- | 378 | }; |
|
- | 379 | ||
- | 380 | hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
|
- | 381 | futex_down(&fidx->lock); |
|
- | 382 | futex_up(&used_futex); |
|
- | 383 | ||
- | 384 | return fidx; |
|
- | 385 | } |
|
- | 386 | ||
334 | fat_idx_t * |
387 | fat_idx_t * |
335 | fat_idx_get_by_pos(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi) |
388 | fat_idx_get_by_pos(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi) |
336 | { |
389 | { |
337 | fat_idx_t *fidx; |
390 | fat_idx_t *fidx; |
338 | link_t *l; |
391 | link_t *l; |
Line 345... | Line 398... | ||
345 | futex_down(&used_futex); |
398 | futex_down(&used_futex); |
346 | l = hash_table_find(&up_hash, pkey); |
399 | l = hash_table_find(&up_hash, pkey); |
347 | if (l) { |
400 | if (l) { |
348 | fidx = hash_table_get_instance(l, fat_idx_t, uph_link); |
401 | fidx = hash_table_get_instance(l, fat_idx_t, uph_link); |
349 | } else { |
402 | } else { |
350 | fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t)); |
403 | fidx = fat_idx_create(dev_handle); |
351 | if (!fidx) { |
404 | if (!fidx) { |
352 | futex_up(&used_futex); |
405 | futex_up(&used_futex); |
353 | return NULL; |
406 | return NULL; |
354 | } |
407 | } |
355 | if (!fat_idx_alloc(dev_handle, &fidx->index)) { |
- | |
356 | free(fidx); |
- | |
357 | futex_up(&used_futex); |
- | |
358 | return NULL; |
- | |
359 | } |
- | |
360 | 408 | ||
361 | unsigned long ikey[] = { |
409 | unsigned long ikey[] = { |
362 | [UIH_DH_KEY] = dev_handle, |
410 | [UIH_DH_KEY] = dev_handle, |
363 | [UIH_INDEX_KEY] = fidx->index, |
411 | [UIH_INDEX_KEY] = fidx->index, |
364 | }; |
412 | }; |
365 | 413 | ||
366 | link_initialize(&fidx->uph_link); |
- | |
367 | link_initialize(&fidx->uih_link); |
- | |
368 | futex_initialize(&fidx->lock, 1); |
- | |
369 | fidx->dev_handle = dev_handle; |
- | |
370 | fidx->pfc = pfc; |
414 | fidx->pfc = pfc; |
371 | fidx->pdi = pdi; |
415 | fidx->pdi = pdi; |
372 | fidx->nodep = NULL; |
- | |
373 | 416 | ||
374 | hash_table_insert(&up_hash, pkey, &fidx->uph_link); |
417 | hash_table_insert(&up_hash, pkey, &fidx->uph_link); |
375 | hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
418 | hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
376 | } |
419 | } |
377 | futex_down(&fidx->lock); |
420 | futex_down(&fidx->lock); |
378 | futex_up(&used_futex); |
421 | futex_up(&used_futex); |
379 | 422 | ||
380 | return fidx; |
423 | return fidx; |
381 | } |
424 | } |
382 | 425 | ||
- | 426 | void fat_idx_hashin(fat_idx_t *idx) |
|
- | 427 | { |
|
- | 428 | unsigned long pkey[] = { |
|
- | 429 | [UPH_DH_KEY] = idx->dev_handle, |
|
- | 430 | [UPH_PFC_KEY] = idx->pfc, |
|
- | 431 | [UPH_PDI_KEY] = idx->pdi, |
|
- | 432 | }; |
|
- | 433 | ||
- | 434 | futex_down(&used_futex); |
|
- | 435 | hash_table_insert(&up_hash, pkey, &idx->uph_link); |
|
- | 436 | futex_up(&used_futex); |
|
- | 437 | } |
|
- | 438 | ||
- | 439 | void fat_idx_hashout(fat_idx_t *idx) |
|
- | 440 | { |
|
- | 441 | unsigned long pkey[] = { |
|
- | 442 | [UPH_DH_KEY] = idx->dev_handle, |
|
- | 443 | [UPH_PFC_KEY] = idx->pfc, |
|
- | 444 | [UPH_PDI_KEY] = idx->pdi, |
|
- | 445 | }; |
|
- | 446 | ||
- | 447 | futex_down(&used_futex); |
|
- | 448 | hash_table_remove(&up_hash, pkey, 3); |
|
- | 449 | futex_up(&used_futex); |
|
- | 450 | } |
|
- | 451 | ||
383 | fat_idx_t * |
452 | fat_idx_t * |
384 | fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index) |
453 | fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index) |
385 | { |
454 | { |
386 | fat_idx_t *fidx = NULL; |
455 | fat_idx_t *fidx = NULL; |
387 | link_t *l; |
456 | link_t *l; |
Line 399... | Line 468... | ||
399 | futex_up(&used_futex); |
468 | futex_up(&used_futex); |
400 | 469 | ||
401 | return fidx; |
470 | return fidx; |
402 | } |
471 | } |
403 | 472 | ||
- | 473 | /** Destroy the index structure. |
|
- | 474 | * |
|
- | 475 | * @param idx The index structure to be destroyed. |
|
- | 476 | */ |
|
- | 477 | void fat_idx_destroy(fat_idx_t *idx) |
|
- | 478 | { |
|
- | 479 | unsigned long ikey[] = { |
|
- | 480 | [UIH_DH_KEY] = idx->dev_handle, |
|
- | 481 | [UIH_INDEX_KEY] = idx->index, |
|
- | 482 | }; |
|
- | 483 | ||
- | 484 | assert(idx->pfc == FAT_CLST_RES0); |
|
- | 485 | ||
- | 486 | futex_down(&used_futex); |
|
- | 487 | /* |
|
- | 488 | * Since we can only free unlinked nodes, the index structure is not |
|
- | 489 | * present in the position hash (uph). We therefore hash it out from |
|
- | 490 | * the index hash only. |
|
- | 491 | */ |
|
- | 492 | hash_table_remove(&ui_hash, ikey, 2); |
|
- | 493 | futex_up(&used_futex); |
|
- | 494 | /* Release the VFS index. */ |
|
- | 495 | fat_index_free(idx->dev_handle, idx->index); |
|
- | 496 | /* Deallocate the structure. */ |
|
- | 497 | free(idx); |
|
- | 498 | } |
|
- | 499 | ||
- | 500 | int fat_idx_init(void) |
|
- | 501 | { |
|
- | 502 | if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops)) |
|
- | 503 | return ENOMEM; |
|
- | 504 | if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) { |
|
- | 505 | hash_table_destroy(&up_hash); |
|
- | 506 | return ENOMEM; |
|
- | 507 | } |
|
- | 508 | return EOK; |
|
- | 509 | } |
|
- | 510 | ||
- | 511 | void fat_idx_fini(void) |
|
- | 512 | { |
|
- | 513 | /* We assume the hash tables are empty. */ |
|
- | 514 | hash_table_destroy(&up_hash); |
|
- | 515 | hash_table_destroy(&ui_hash); |
|
- | 516 | } |
|
- | 517 | ||
- | 518 | int fat_idx_init_by_dev_handle(dev_handle_t dev_handle) |
|
- | 519 | { |
|
- | 520 | unused_t *u; |
|
- | 521 | int rc = EOK; |
|
- | 522 | ||
- | 523 | u = (unused_t *) malloc(sizeof(unused_t)); |
|
- | 524 | if (!u) |
|
- | 525 | return ENOMEM; |
|
- | 526 | unused_initialize(u, dev_handle); |
|
- | 527 | futex_down(&unused_futex); |
|
- | 528 | if (!unused_find(dev_handle, false)) |
|
- | 529 | list_append(&u->link, &unused_head); |
|
- | 530 | else |
|
- | 531 | rc = EEXIST; |
|
- | 532 | futex_up(&unused_futex); |
|
- | 533 | return rc; |
|
- | 534 | } |
|
- | 535 | ||
- | 536 | void fat_idx_fini_by_dev_handle(dev_handle_t dev_handle) |
|
- | 537 | { |
|
- | 538 | unused_t *u; |
|
- | 539 | ||
- | 540 | u = unused_find(dev_handle, true); |
|
- | 541 | assert(u); |
|
- | 542 | list_remove(&u->link); |
|
- | 543 | futex_up(&unused_futex); |
|
- | 544 | ||
- | 545 | while (!list_empty(&u->freed_head)) { |
|
- | 546 | freed_t *f; |
|
- | 547 | f = list_get_instance(u->freed_head.next, freed_t, link); |
|
- | 548 | list_remove(&f->link); |
|
- | 549 | free(f); |
|
- | 550 | } |
|
- | 551 | free(u); |
|
- | 552 | } |
|
- | 553 | ||
- | 554 | /** |
|
- | 555 | * @} |
|
- | 556 | */ |