Changes in uspace/srv/fs/fat/fat_fat.c [c7bbf029:d260a95] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
rc7bbf029 rd260a95 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>50 49 #include <mem.h> 51 50 … … 54 53 * primitive boot sector members. 55 54 */ 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 60 55 #define CLBN2PBN(bs, cl, bn) \ 61 56 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) … … 65 60 * during allocation of clusters. The lock does not have to be held durring 66 61 * deallocation of clusters. 67 */ 62 */ 68 63 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 69 64 … … 77 72 * @param numc If non-NULL, output argument holding the number of 78 73 * clusters seen during the walk. 79 * @param max_clusters Maximum number of clusters to visit. 74 * @param max_clusters Maximum number of clusters to visit. 80 75 * 81 76 * @return EOK on success or a negative error code. 82 77 */ 83 int 78 int 84 79 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc, 85 80 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) 86 81 { 87 block_t *b;88 82 uint16_t clusters = 0; 89 fat_cluster_t clst = firstc; 83 fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs); 84 fat_cluster_t clst_bad = FAT_CLST_BAD(bs); 90 85 int rc; 91 86 … … 99 94 } 100 95 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 96 while (clst < clst_last1 && clusters < max_clusters) { 105 97 assert(clst >= FAT_CLST_FIRST); 106 98 if (lastc) 107 99 *lastc = clst; /* remember the last cluster number */ 108 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 109 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 100 110 101 /* read FAT1 */ 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; 102 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst); 103 if (rc != EOK) 104 return rc; 105 106 assert(clst != clst_bad); 120 107 clusters++; 121 108 } 122 109 123 if (lastc && clst < FAT_CLST_LAST1)110 if (lastc && clst < clst_last1) 124 111 *lastc = clst; 125 112 if (numc) … … 151 138 return ELIMIT; 152 139 153 if (nodep->firstc == FAT_CLST_ROOT) 140 if (nodep->firstc == FAT_CLST_ROOT) 154 141 goto fall_through; 155 142 … … 178 165 if (rc != EOK) 179 166 return rc; 180 167 181 168 /* 182 169 * Update the "current" cluster cache. … … 198 185 * @param clp If not NULL, address where the cluster containing bn 199 186 * will be stored. 200 * stored 187 * stored 201 188 * @param bn Block number. 202 189 * @param flags Flags passed to libblock. … … 275 262 return rc; 276 263 } 277 264 278 265 if (o >= pos) 279 266 return EOK; 280 267 281 268 /* zero out the initial part of the new cluster chain */ 282 269 for (o = boundary; o < pos; o += BPS(bs)) { … … 308 295 fat_cluster_t clst, fat_cluster_t *value) 309 296 { 310 block_t *b; 311 fat_cluster_t *cp; 312 int rc; 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)); 313 307 314 308 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 315 (clst * sizeof(fat_cluster_t))/ BPS(bs), BLOCK_FLAGS_NONE);309 offset / BPS(bs), BLOCK_FLAGS_NONE); 316 310 if (rc != EOK) 317 311 return rc; 318 cp = (fat_cluster_t *)b->data + 319 clst % (BPS(bs) / sizeof(fat_cluster_t)); 320 *value = uint16_t_le2host(*cp); 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); 321 354 rc = block_put(b); 322 355 323 356 return rc; 324 357 } … … 338 371 fat_cluster_t clst, fat_cluster_t value) 339 372 { 340 block_t *b; 341 fat_cluster_t *cp; 342 int rc; 373 block_t *b, *b1; 374 aoff64_t offset; 375 fat_cluster_t *cp, temp; 376 int rc; 377 int spans = 0; 343 378 344 379 assert(fatno < FATCNT(bs)); 380 381 if (FAT_IS_FAT12(bs)) 382 offset = (clst + clst/2); 383 else 384 offset = (clst * sizeof(fat_cluster_t)); 385 345 386 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 346 (clst * sizeof(fat_cluster_t))/ BPS(bs), BLOCK_FLAGS_NONE);387 offset / BPS(bs), BLOCK_FLAGS_NONE); 347 388 if (rc != EOK) 348 389 return rc; 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 */ 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 */ 353 448 rc = block_put(b); 354 449 return rc; … … 369 464 uint8_t fatno; 370 465 unsigned c; 466 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 371 467 int rc; 372 468 … … 374 470 for (c = 0; c < nclsts; c++) { 375 471 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c], 376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);472 c == 0 ? clst_last1 : lifo[c - 1]); 377 473 if (rc != EOK) 378 474 return rc; … … 404 500 fat_cluster_t *mcl, fat_cluster_t *lcl) 405 501 { 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; 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; 411 506 412 507 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 413 508 if (!lifo) 414 509 return ENOMEM; 415 416 510 /* 417 511 * Search FAT1 for unused clusters. 418 512 */ 419 513 fibril_mutex_lock(&fat_alloc_lock); 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 } 470 } 471 rc = block_put(blk); 472 if (rc != EOK) { 473 error: 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++; 531 } 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]; 539 free(lifo); 474 540 fibril_mutex_unlock(&fat_alloc_lock); 475 free(lifo); 476 return rc; 477 } 478 } 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--) { 541 return EOK; 542 } 543 } 544 545 /* If something wrong - free the clusters */ 546 if (found > 0) { 547 while (found--) { 487 548 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], 488 549 FAT_CLST_RES0); 489 if (rc != EOK) { 490 free(lifo); 491 return rc; 492 } 493 } 494 550 } 551 } 552 495 553 free(lifo); 554 fibril_mutex_unlock(&fat_alloc_lock); 496 555 return ENOSPC; 497 556 } … … 509 568 { 510 569 unsigned fatno; 511 fat_cluster_t nextc ;570 fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs); 512 571 int rc; 513 572 514 573 /* Mark all clusters in the chain as free in all copies of FAT. */ 515 while (firstc < FAT_CLST_LAST1 ) {516 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);574 while (firstc < FAT_CLST_LAST1(bs)) { 575 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad); 517 576 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc); 518 577 if (rc != EOK) … … 565 624 566 625 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 567 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,568 lastc, mcl);626 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, 627 fatno, lastc, mcl); 569 628 if (rc != EOK) 570 629 return rc; … … 590 649 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 591 650 { 651 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 592 652 int rc; 593 653 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; … … 618 678 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 619 679 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl, 620 FAT_CLST_LAST1);680 clst_last1); 621 681 if (rc != EOK) 622 682 return rc; … … 677 737 678 738 /* Check total number of sectors. */ 679 680 739 if (bs->totsec16 == 0 && bs->totsec32 == 0) 681 740 return ENOTSUP; 682 741 683 742 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 684 bs->totsec16 != bs->totsec32) 743 bs->totsec16 != bs->totsec32) 685 744 return ENOTSUP; 686 745 … … 705 764 706 765 /* Check signature of each FAT. */ 707 708 766 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 709 767 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); … … 723 781 * set to one. 724 782 */ 725 if ((e0 >> 8) != 0xff || e1 != 0xffff)783 if (!FAT_IS_FAT12(bs) && ((e0 >> 8) != 0xff || e1 != 0xffff)) 726 784 return ENOTSUP; 727 785 } … … 732 790 /** 733 791 * @} 734 */ 792 */
Note:
See TracChangeset
for help on using the changeset viewer.