Changeset fc35e98 in mainline
- Timestamp:
- 2011-04-07T19:14:33Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 97bc3ee
- Parents:
- ccca251
- Location:
- uspace/srv/fs/fat
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
rccca251 rfc35e98 84 84 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) 85 85 { 86 block_t *b;87 86 uint16_t clusters = 0; 88 87 fat_cluster_t clst = firstc; 89 88 int rc; 89 uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 : FAT12_CLST_LAST1; 90 uint16_t clst_bad = FATTYPE(bs) == 16 ? FAT16_CLST_BAD : FAT12_CLST_BAD; 90 91 91 92 if (firstc == FAT_CLST_RES0) { … … 98 99 } 99 100 100 while (clst < FAT_CLST_LAST1 && clusters < max_clusters) { 101 aoff64_t fsec; /* sector offset relative to FAT1 */ 102 unsigned fidx; /* FAT1 entry index */ 103 101 while (clst < clst_last1 && clusters < max_clusters) { 104 102 assert(clst >= FAT_CLST_FIRST); 105 103 if (lastc) 106 104 *lastc = clst; /* remember the last cluster number */ 107 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 108 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 109 /* read FAT1 */ 110 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec, 111 BLOCK_FLAGS_NONE); 112 if (rc != EOK) 113 return rc; 114 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 115 assert(clst != FAT_CLST_BAD); 116 rc = block_put(b); 117 if (rc != EOK) 118 return rc; 119 clusters++; 120 } 121 122 if (lastc && clst < FAT_CLST_LAST1) 105 106 /* read FAT1 */ 107 /* We should use fat_get_cluster instead */ 108 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst); 109 if (rc != EOK) 110 return rc; 111 112 assert(clst != clst_bad); 113 114 clusters++; 115 } 116 117 if (lastc && clst < clst_last1) 123 118 *lastc = clst; 124 119 if (numc) … … 309 304 block_t *b; 310 305 fat_cluster_t *cp; 311 int rc; 312 313 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 314 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 315 if (rc != EOK) 316 return rc; 317 cp = (fat_cluster_t *)b->data + 318 clst % (BPS(bs) / sizeof(fat_cluster_t)); 319 *value = uint16_t_le2host(*cp); 306 aoff64_t fsec; /* sector offset relative to FAT */ 307 unsigned fidx; /* entry index */ 308 int rc; 309 310 assert(fatno < FATCNT(bs)); 311 312 313 if (FATTYPE(bs) == 16) 314 { 315 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 316 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 317 } 318 else 319 { 320 fsec = (clst + clst/2) / BPS(bs); 321 fidx = clst % (2 * BPS(bs) / 3 ); 322 } 323 324 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 325 fsec, BLOCK_FLAGS_NONE); 326 if (rc != EOK) 327 return rc; 328 329 if (FATTYPE(bs) == 16) 330 cp = &((fat_cluster_t *)b->data)[fidx]; 331 else 332 cp = (fat_cluster_t *)(b->data + fidx); 333 334 *value = *cp; 335 336 if (FATTYPE(bs) == 12) 337 { 338 if (clst & 0x0001) 339 *value = (*value) >> 4; 340 else 341 *value = (*value) & 0x0fff; 342 } 343 344 *value = uint16_t_le2host(*value); 320 345 rc = block_put(b); 321 346 … … 340 365 fat_cluster_t *cp; 341 366 int rc; 342 343 assert(fatno < FATCNT(bs)); 344 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 345 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 367 aoff64_t fsec; /* sector offset relative to FAT */ 368 unsigned fidx; /* entry index */ 369 370 assert(fatno < FATCNT(bs)); 371 372 if (FATTYPE(bs) == 16) 373 { 374 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 375 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 376 } 377 else 378 { 379 fsec = (clst + clst/2) / BPS(bs); 380 fidx = clst % (2 * BPS(bs) / 3 ); 381 } 382 383 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 384 fsec, BLOCK_FLAGS_NONE); 346 385 if (rc != EOK) 347 386 return rc; 348 cp = (fat_cluster_t *)b->data + 349 clst % (BPS(bs) / sizeof(fat_cluster_t)); 350 *cp = host2uint16_t_le(value); 351 b->dirty = true; /* need to sync block */ 387 388 if (FATTYPE(bs) == 12) 389 { 390 cp = (fat_cluster_t *)(b->data + fidx); 391 if (clst & 0x0001) 392 { 393 *cp &= 0x000f; 394 *cp |= host2uint16_t_le(value) << 4; 395 } 396 else 397 { 398 *cp &= 0xf000; 399 *cp |= host2uint16_t_le(value) & 0x0fff; 400 } 401 } 402 else 403 { 404 cp = &((fat_cluster_t *)b->data)[fidx]; 405 *cp = host2uint16_t_le(value); 406 } 407 408 b->dirty = true; /* need to sync block */ 352 409 rc = block_put(b); 353 410 return rc; … … 369 426 unsigned c; 370 427 int rc; 428 uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 : 429 FAT12_CLST_LAST1; 371 430 372 431 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 373 432 for (c = 0; c < nclsts; c++) { 374 433 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c], 375 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);434 c == 0 ? clst_last1 : lifo[c - 1]); 376 435 if (rc != EOK) 377 436 return rc; … … 403 462 fat_cluster_t *mcl, fat_cluster_t *lcl) 404 463 { 405 block_t *blk; 406 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 407 unsigned found = 0; /* top of the free cluster number stack */ 408 unsigned b, c, cl; 409 int rc; 410 411 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 412 if (!lifo) 413 return ENOMEM; 414 415 /* 416 * Search FAT1 for unused clusters. 417 */ 418 fibril_mutex_lock(&fat_alloc_lock); 419 for (b = 0, cl = 0; b < SF(bs); b++) { 420 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b, 421 BLOCK_FLAGS_NONE); 422 if (rc != EOK) 423 goto error; 424 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) { 425 /* 426 * Check if the entire cluster is physically there. 427 * This check becomes necessary when the file system is 428 * created with fewer total sectors than how many is 429 * inferred from the size of the file allocation table 430 * or when the last cluster ends beyond the end of the 431 * device. 432 */ 433 if ((cl >= FAT_CLST_FIRST) && 434 CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) { 435 rc = block_put(blk); 436 if (rc != EOK) 437 goto error; 438 goto out; 439 } 440 441 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 442 if (uint16_t_le2host(*clst) == FAT_CLST_RES0) { 443 /* 444 * The cluster is free. Put it into our stack 445 * of found clusters and mark it as non-free. 446 */ 447 lifo[found] = cl; 448 *clst = (found == 0) ? 449 host2uint16_t_le(FAT_CLST_LAST1) : 450 host2uint16_t_le(lifo[found - 1]); 451 blk->dirty = true; /* need to sync block */ 452 if (++found == nclsts) { 453 /* we are almost done */ 454 rc = block_put(blk); 455 if (rc != EOK) 456 goto error; 457 /* update the shadow copies of FAT */ 458 rc = fat_alloc_shadow_clusters(bs, 459 devmap_handle, lifo, nclsts); 460 if (rc != EOK) 461 goto error; 462 *mcl = lifo[found - 1]; 463 *lcl = lifo[0]; 464 free(lifo); 465 fibril_mutex_unlock(&fat_alloc_lock); 466 return EOK; 467 } 468 } 469 } 470 rc = block_put(blk); 471 if (rc != EOK) { 472 error: 473 fibril_mutex_unlock(&fat_alloc_lock); 474 free(lifo); 475 return rc; 476 } 477 } 478 out: 479 fibril_mutex_unlock(&fat_alloc_lock); 480 481 /* 482 * We could not find enough clusters. Now we need to free the clusters 483 * we have allocated so far. 484 */ 485 while (found--) { 486 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], 487 FAT_CLST_RES0); 488 if (rc != EOK) { 489 free(lifo); 490 return rc; 491 } 492 } 493 494 free(lifo); 495 return ENOSPC; 464 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 465 unsigned found = 0; /* top of the free cluster number stack */ 466 fat_cluster_t clst, max_clst, value; 467 int rc = EOK; 468 uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 : 469 FAT12_CLST_LAST1; 470 471 472 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 473 if (!lifo) 474 return ENOMEM; 475 476 /* 477 * Search FAT1 for unused clusters. 478 */ 479 480 if (FATTYPE(bs) == 16) 481 max_clst = SF(bs) * BPS(bs) / sizeof(fat_cluster_t); 482 else 483 max_clst = 2 *SF(bs) * BPS(bs) / 3; 484 485 fibril_mutex_lock(&fat_alloc_lock); 486 for (clst=0; clst < max_clst && found < nclsts; clst++) 487 { 488 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value); 489 if (rc != EOK) 490 break; 491 /* 492 * Check if the entire cluster is physically there. 493 * This check becomes necessary when the file system is 494 * created with fewer total sectors than how many is 495 * inferred from the size of the file allocation table 496 * or when the last cluster ends beyond the end of the 497 * device. 498 */ 499 if ((clst >= FAT_CLST_FIRST) && 500 CLBN2PBN(bs, clst, SPC(bs) - 1) >= TS(bs)) { 501 rc = EIO; 502 break; 503 } 504 if (value == FAT_CLST_RES0) { 505 /* 506 * The cluster is free. Put it into our stack 507 * of found clusters and mark it as non-free. 508 */ 509 lifo[found] = clst; 510 rc = fat_set_cluster(bs, devmap_handle, FAT1, clst, 511 (found == 0) ? clst_last1 : 512 lifo[found - 1]); 513 if (rc != EOK) 514 break; 515 516 found++; 517 } 518 } 519 520 if (rc == EOK && found == nclsts) 521 { 522 rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts); 523 if (rc == EOK) 524 { 525 *mcl = lifo[found - 1]; 526 *lcl = lifo[0]; 527 free(lifo); 528 fibril_mutex_unlock(&fat_alloc_lock); 529 return EOK; 530 } 531 } 532 533 /* If something wrong - free the clusters */ 534 if (found > 0) 535 { 536 while (found--) { 537 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], 538 FAT_CLST_RES0); 539 } 540 } 541 542 free(lifo); 543 fibril_mutex_unlock(&fat_alloc_lock); 544 return ENOSPC; 496 545 } 497 546 … … 510 559 fat_cluster_t nextc; 511 560 int rc; 561 uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 : 562 FAT12_CLST_LAST1; 563 uint16_t clst_bad = FATTYPE(bs) == 16 ? FAT16_CLST_BAD : 564 FAT12_CLST_BAD; 512 565 513 566 /* Mark all clusters in the chain as free in all copies of FAT. */ 514 while (firstc < FAT_CLST_LAST1) {515 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);567 while (firstc < clst_last1) { 568 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad); 516 569 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc); 517 570 if (rc != EOK) … … 591 644 int rc; 592 645 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; 646 uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 : 647 FAT12_CLST_LAST1; 593 648 594 649 /* … … 617 672 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 618 673 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl, 619 FAT_CLST_LAST1);674 clst_last1); 620 675 if (rc != EOK) 621 676 return rc; … … 676 731 677 732 /* Check total number of sectors. */ 678 679 733 if (bs->totsec16 == 0 && bs->totsec32 == 0) 680 734 return ENOTSUP; … … 704 758 705 759 /* Check signature of each FAT. */ 706 707 760 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 708 761 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); … … 722 775 * set to one. 723 776 */ 724 if ((e0 >> 8) != 0xff || e1 != 0xffff) 777 /* Disabled for testing FAT12 778 if ((e0 >> 8) != 0xff || e1 != 0xffff) 725 779 return ENOTSUP; 780 */ 726 781 } 727 782 -
uspace/srv/fs/fat/fat_fat.h
rccca251 rfc35e98 40 40 #define FAT1 0 41 41 42 #define FAT_CLST_RES0 0x0000 43 #define FAT_CLST_RES1 0x0001 44 #define FAT_CLST_FIRST 0x0002 45 #define FAT_CLST_BAD 0xfff7 46 #define FAT_CLST_LAST1 0xfff8 47 #define FAT_CLST_LAST8 0xffff 42 #define FAT_CLST_RES0 0x0000 43 #define FAT_CLST_RES1 0x0001 44 #define FAT_CLST_FIRST 0x0002 45 46 #define FAT12_CLST_BAD 0x0ff7 47 #define FAT12_CLST_LAST1 0x0ff8 48 #define FAT12_CLST_LAST8 0x0fff 49 #define FAT16_CLST_BAD 0xfff7 50 #define FAT16_CLST_LAST1 0xfff8 51 #define FAT16_CLST_LAST8 0xffff 48 52 49 53 /* internally used to mark root directory's parent */ … … 51 55 /* internally used to mark root directory */ 52 56 #define FAT_CLST_ROOT FAT_CLST_RES1 57 58 #define FATTYPE(bs) (bs)->reserved 53 59 54 60 /* forward declarations */ -
uspace/srv/fs/fat/fat_ops.c
rccca251 rfc35e98 104 104 node->dirty = false; 105 105 node->lastc_cached_valid = false; 106 node->lastc_cached_value = FAT _CLST_LAST1;106 node->lastc_cached_value = FAT16_CLST_LAST1; 107 107 node->currc_cached_valid = false; 108 108 node->currc_cached_bn = 0; 109 node->currc_cached_value = FAT _CLST_LAST1;109 node->currc_cached_value = FAT16_CLST_LAST1; 110 110 } 111 111 … … 945 945 */ 946 946 947 948 #define RootDirSectors(bs) (((RDE(bs)*32) + (BPS(bs)-1)) / BPS(bs)) 949 #define FATSz(bs) SF(bs) != 0 ? SF(bs) : uint32_t_le2host((bs)->fat32.sectors_per_fat) 950 #define DataSec(bs) (TS(bs) - (RSCNT(bs) + (FATCNT(bs) * FATSz(bs)) + RootDirSectors(bs))) 951 #define CountOfClusters(bs) (DataSec(bs) / SPC(bs)) 952 947 953 void fat_mounted(ipc_callid_t rid, ipc_call_t *request) 948 954 { … … 1000 1006 } 1001 1007 1008 /* Storing FAT type (12, 16, 32) in reserved field (bs->reserved) */ 1009 if (CountOfClusters(bs) < 4085) { 1010 /* Volume is FAT12 */ 1011 printf("Found FAT12 filesystem\n"); 1012 (bs)->reserved = 12; 1013 } else if (CountOfClusters(bs) < 65525) { 1014 /* Volume is FAT16 */ 1015 printf("Found FAT16 filesystem\n"); 1016 (bs)->reserved = 16; 1017 } else { 1018 /* Volume is FAT32 */ 1019 printf("FAT32 is not supported by FAT driver. Sorry\n"); 1020 block_fini(devmap_handle); 1021 async_answer_0(rid, ENOTSUP); 1022 return; 1023 1024 } 1025 1002 1026 /* Do some simple sanity checks on the file system. */ 1003 1027 rc = fat_sanity_check(bs, devmap_handle); 1004 1028 if (rc != EOK) { 1029 printf("Sanity check failed\n"); 1005 1030 (void) block_cache_fini(devmap_handle); 1006 1031 block_fini(devmap_handle);
Note:
See TracChangeset
for help on using the changeset viewer.