Changes in uspace/srv/fs/fat/fat_fat.c [d260a95:c7bbf029] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
rd260a95 rc7bbf029 29 29 /** @addtogroup fs 30 30 * @{ 31 */ 31 */ 32 32 33 33 /** … … 47 47 #include <assert.h> 48 48 #include <fibril_synch.h> 49 #include <malloc.h> 49 50 #include <mem.h> 50 51 … … 53 54 * primitive boot sector members. 54 55 */ 56 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \ 57 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0) 58 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs)) 59 55 60 #define CLBN2PBN(bs, cl, bn) \ 56 61 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) … … 60 65 * during allocation of clusters. The lock does not have to be held durring 61 66 * deallocation of clusters. 62 */ 67 */ 63 68 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 64 69 … … 72 77 * @param numc If non-NULL, output argument holding the number of 73 78 * clusters seen during the walk. 74 * @param max_clusters Maximum number of clusters to visit. 79 * @param max_clusters Maximum number of clusters to visit. 75 80 * 76 81 * @return EOK on success or a negative error code. 77 82 */ 78 int 83 int 79 84 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc, 80 85 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) 81 86 { 87 block_t *b; 82 88 uint16_t clusters = 0; 83 fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs); 84 fat_cluster_t clst_bad = FAT_CLST_BAD(bs); 89 fat_cluster_t clst = firstc; 85 90 int rc; 86 91 … … 94 99 } 95 100 96 while (clst < clst_last1 && clusters < max_clusters) { 101 while (clst < FAT_CLST_LAST1 && clusters < max_clusters) { 102 aoff64_t fsec; /* sector offset relative to FAT1 */ 103 unsigned fidx; /* FAT1 entry index */ 104 97 105 assert(clst >= FAT_CLST_FIRST); 98 106 if (lastc) 99 107 *lastc = clst; /* remember the last cluster number */ 100 108 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 109 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 101 110 /* read FAT1 */ 102 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst); 103 if (rc != EOK) 104 return rc; 105 106 assert(clst != clst_bad); 111 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec, 112 BLOCK_FLAGS_NONE); 113 if (rc != EOK) 114 return rc; 115 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 116 assert(clst != FAT_CLST_BAD); 117 rc = block_put(b); 118 if (rc != EOK) 119 return rc; 107 120 clusters++; 108 121 } 109 122 110 if (lastc && clst < clst_last1)123 if (lastc && clst < FAT_CLST_LAST1) 111 124 *lastc = clst; 112 125 if (numc) … … 138 151 return ELIMIT; 139 152 140 if (nodep->firstc == FAT_CLST_ROOT) 153 if (nodep->firstc == FAT_CLST_ROOT) 141 154 goto fall_through; 142 155 … … 165 178 if (rc != EOK) 166 179 return rc; 167 180 168 181 /* 169 182 * Update the "current" cluster cache. … … 185 198 * @param clp If not NULL, address where the cluster containing bn 186 199 * will be stored. 187 * stored 200 * stored 188 201 * @param bn Block number. 189 202 * @param flags Flags passed to libblock. … … 262 275 return rc; 263 276 } 264 277 265 278 if (o >= pos) 266 279 return EOK; 267 280 268 281 /* zero out the initial part of the new cluster chain */ 269 282 for (o = boundary; o < pos; o += BPS(bs)) { … … 295 308 fat_cluster_t clst, fat_cluster_t *value) 296 309 { 297 block_t *b, *b1; 298 aoff64_t offset; 299 int rc; 300 301 assert(fatno < FATCNT(bs)); 302 303 if (FAT_IS_FAT12(bs)) 304 offset = (clst + clst/2); 305 else 306 offset = (clst * sizeof(fat_cluster_t)); 310 block_t *b; 311 fat_cluster_t *cp; 312 int rc; 307 313 308 314 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 309 offset/ BPS(bs), BLOCK_FLAGS_NONE);315 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 310 316 if (rc != EOK) 311 317 return rc; 312 313 /* This cluster access spans a sector boundary. Check only for FAT12 */ 314 if (FAT_IS_FAT12(bs) && (offset % BPS(bs)+1 == BPS(bs))) { 315 /* Is it last sector of FAT? */ 316 if (offset / BPS(bs) < SF(bs)) { 317 /* No. Reading next sector */ 318 rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) + 319 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE); 320 if (rc != EOK) { 321 block_put(b); 322 return rc; 323 } 324 /* 325 * Combining value with last byte of current sector and 326 * first byte of next sector 327 */ 328 *value = *(uint8_t *)(b->data + BPS(bs) - 1); 329 *value |= *(uint8_t *)(b1->data); 330 331 rc = block_put(b1); 332 if (rc != EOK) { 333 block_put(b); 334 return rc; 335 } 336 } 337 else { 338 /* Yes. It is last sector of FAT */ 339 block_put(b); 340 return ERANGE; 341 } 342 } 343 else 344 *value = *(fat_cluster_t *)(b->data + offset % BPS(bs)); 345 346 if (FAT_IS_FAT12(bs)) { 347 if (clst & 0x0001) 348 *value = (*value) >> 4; 349 else 350 *value = (*value) & 0x0fff; 351 } 352 353 *value = uint16_t_le2host(*value); 318 cp = (fat_cluster_t *)b->data + 319 clst % (BPS(bs) / sizeof(fat_cluster_t)); 320 *value = uint16_t_le2host(*cp); 354 321 rc = block_put(b); 355 322 356 323 return rc; 357 324 } … … 371 338 fat_cluster_t clst, fat_cluster_t value) 372 339 { 373 block_t *b, *b1; 374 aoff64_t offset; 375 fat_cluster_t *cp, temp; 376 int rc; 377 int spans = 0; 340 block_t *b; 341 fat_cluster_t *cp; 342 int rc; 378 343 379 344 assert(fatno < FATCNT(bs)); 380 381 if (FAT_IS_FAT12(bs))382 offset = (clst + clst/2);383 else384 offset = (clst * sizeof(fat_cluster_t));385 386 345 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 387 offset/ BPS(bs), BLOCK_FLAGS_NONE);346 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 388 347 if (rc != EOK) 389 348 return rc; 390 391 /* This cluster access spans a sector boundary. Check only for FAT12 */ 392 if (FAT_IS_FAT12(bs) && (offset % BPS(bs)+1 == BPS(bs))) { 393 /* Is it last sector of FAT? */ 394 if (offset / BPS(bs) < SF(bs)) { 395 /* No. Reading next sector */ 396 rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) + 397 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE); 398 if (rc != EOK) { 399 block_put(b); 400 return rc; 401 } 402 /* 403 * Combining value with last byte of current sector and 404 * first byte of next sector 405 */ 406 spans=1; 407 cp = &temp; 408 *cp = *(uint8_t *)(b->data + BPS(bs) - 1); 409 *cp |= *(uint8_t *)(b1->data); 410 } 411 else { 412 /* Yes. It is last sector of fat */ 413 block_put(b); 414 return ERANGE; 415 } 416 } 417 else 418 cp = (fat_cluster_t *)(b->data + offset % BPS(bs)); 419 420 value = host2uint16_t_le(value); 421 if (FAT_IS_FAT12(bs)) { 422 if (clst & 0x0001) { 423 *cp &= 0x000f; 424 *cp |= value << 4; 425 } 426 else { 427 *cp &= 0xf000; 428 *cp |= value & 0x0fff; 429 } 430 431 if (spans) 432 { 433 *(uint8_t *)(b->data + BPS(bs) - 1) = cp[0]; 434 *(uint8_t *)(b1->data) = cp[1]; 435 436 b1->dirty = true; 437 rc = block_put(b1); 438 if (rc != EOK) { 439 block_put(b); 440 return rc; 441 } 442 } 443 } 444 else 445 *cp = value; 446 447 b->dirty = true; /* need to sync block */ 349 cp = (fat_cluster_t *)b->data + 350 clst % (BPS(bs) / sizeof(fat_cluster_t)); 351 *cp = host2uint16_t_le(value); 352 b->dirty = true; /* need to sync block */ 448 353 rc = block_put(b); 449 354 return rc; … … 464 369 uint8_t fatno; 465 370 unsigned c; 466 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);467 371 int rc; 468 372 … … 470 374 for (c = 0; c < nclsts; c++) { 471 375 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c], 472 c == 0 ? clst_last1 : lifo[c - 1]);376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]); 473 377 if (rc != EOK) 474 378 return rc; … … 500 404 fat_cluster_t *mcl, fat_cluster_t *lcl) 501 405 { 502 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 503 unsigned found = 0; /* top of the free cluster number stack */ 504 fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs); 505 int rc = EOK; 406 block_t *blk; 407 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 408 unsigned found = 0; /* top of the free cluster number stack */ 409 unsigned b, c, cl; 410 int rc; 506 411 507 412 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 508 413 if (!lifo) 509 414 return ENOMEM; 415 510 416 /* 511 417 * Search FAT1 for unused clusters. 512 418 */ 513 419 fibril_mutex_lock(&fat_alloc_lock); 514 for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) { 515 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value); 516 if (rc != EOK) 517 break; 518 519 if (value == FAT_CLST_RES0) { 520 /* 521 * The cluster is free. Put it into our stack 522 * of found clusters and mark it as non-free. 523 */ 524 lifo[found] = clst; 525 rc = fat_set_cluster(bs, devmap_handle, FAT1, clst, 526 (found == 0) ? clst_last1 : lifo[found - 1]); 527 if (rc != EOK) 528 break; 529 530 found++; 420 for (b = 0, cl = 0; b < SF(bs); b++) { 421 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b, 422 BLOCK_FLAGS_NONE); 423 if (rc != EOK) 424 goto error; 425 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) { 426 /* 427 * Check if the entire cluster is physically there. 428 * This check becomes necessary when the file system is 429 * created with fewer total sectors than how many is 430 * inferred from the size of the file allocation table 431 * or when the last cluster ends beyond the end of the 432 * device. 433 */ 434 if ((cl >= FAT_CLST_FIRST) && 435 CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) { 436 rc = block_put(blk); 437 if (rc != EOK) 438 goto error; 439 goto out; 440 } 441 442 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 443 if (uint16_t_le2host(*clst) == FAT_CLST_RES0) { 444 /* 445 * The cluster is free. Put it into our stack 446 * of found clusters and mark it as non-free. 447 */ 448 lifo[found] = cl; 449 *clst = (found == 0) ? 450 host2uint16_t_le(FAT_CLST_LAST1) : 451 host2uint16_t_le(lifo[found - 1]); 452 blk->dirty = true; /* need to sync block */ 453 if (++found == nclsts) { 454 /* we are almost done */ 455 rc = block_put(blk); 456 if (rc != EOK) 457 goto error; 458 /* update the shadow copies of FAT */ 459 rc = fat_alloc_shadow_clusters(bs, 460 devmap_handle, lifo, nclsts); 461 if (rc != EOK) 462 goto error; 463 *mcl = lifo[found - 1]; 464 *lcl = lifo[0]; 465 free(lifo); 466 fibril_mutex_unlock(&fat_alloc_lock); 467 return EOK; 468 } 469 } 531 470 } 532 } 533 534 if (rc == EOK && found == nclsts) { 535 rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts); 536 if (rc == EOK) { 537 *mcl = lifo[found - 1]; 538 *lcl = lifo[0]; 471 rc = block_put(blk); 472 if (rc != EOK) { 473 error: 474 fibril_mutex_unlock(&fat_alloc_lock); 539 475 free(lifo); 540 fibril_mutex_unlock(&fat_alloc_lock); 541 return EOK; 476 return rc; 542 477 } 543 478 } 544 545 /* If something wrong - free the clusters */ 546 if (found > 0) { 547 while (found--) { 479 out: 480 fibril_mutex_unlock(&fat_alloc_lock); 481 482 /* 483 * We could not find enough clusters. Now we need to free the clusters 484 * we have allocated so far. 485 */ 486 while (found--) { 548 487 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], 549 488 FAT_CLST_RES0); 489 if (rc != EOK) { 490 free(lifo); 491 return rc; 550 492 } 551 493 } 552 494 553 495 free(lifo); 554 fibril_mutex_unlock(&fat_alloc_lock);555 496 return ENOSPC; 556 497 } … … 568 509 { 569 510 unsigned fatno; 570 fat_cluster_t nextc , clst_bad = FAT_CLST_BAD(bs);511 fat_cluster_t nextc; 571 512 int rc; 572 513 573 514 /* Mark all clusters in the chain as free in all copies of FAT. */ 574 while (firstc < FAT_CLST_LAST1 (bs)) {575 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);515 while (firstc < FAT_CLST_LAST1) { 516 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD); 576 517 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc); 577 518 if (rc != EOK) … … 624 565 625 566 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 626 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, 627 fatno,lastc, mcl);567 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno, 568 lastc, mcl); 628 569 if (rc != EOK) 629 570 return rc; … … 649 590 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 650 591 { 651 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);652 592 int rc; 653 593 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; … … 678 618 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 679 619 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl, 680 clst_last1);620 FAT_CLST_LAST1); 681 621 if (rc != EOK) 682 622 return rc; … … 737 677 738 678 /* Check total number of sectors. */ 679 739 680 if (bs->totsec16 == 0 && bs->totsec32 == 0) 740 681 return ENOTSUP; 741 682 742 683 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 743 bs->totsec16 != bs->totsec32) 684 bs->totsec16 != bs->totsec32) 744 685 return ENOTSUP; 745 686 … … 764 705 765 706 /* Check signature of each FAT. */ 707 766 708 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 767 709 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); … … 781 723 * set to one. 782 724 */ 783 if (!FAT_IS_FAT12(bs) && ((e0 >> 8) != 0xff || e1 != 0xffff))725 if ((e0 >> 8) != 0xff || e1 != 0xffff) 784 726 return ENOTSUP; 785 727 } … … 790 732 /** 791 733 * @} 792 */ 734 */
Note:
See TracChangeset
for help on using the changeset viewer.