Changeset 97bc3ee in mainline
- Timestamp:
- 2011-04-09T19:23:12Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d260a95
- Parents:
- fc35e98
- Location:
- uspace/srv/fs/fat
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
rfc35e98 r97bc3ee 29 29 /** @addtogroup fs 30 30 * @{ 31 */ 31 */ 32 32 33 33 /** … … 53 53 * primitive boot sector members. 54 54 */ 55 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \56 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)57 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))58 59 55 #define CLBN2PBN(bs, cl, bn) \ 60 56 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) … … 64 60 * during allocation of clusters. The lock does not have to be held durring 65 61 * deallocation of clusters. 66 */ 62 */ 67 63 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 68 64 … … 76 72 * @param numc If non-NULL, output argument holding the number of 77 73 * clusters seen during the walk. 78 * @param max_clusters Maximum number of clusters to visit. 74 * @param max_clusters Maximum number of clusters to visit. 79 75 * 80 76 * @return EOK on success or a negative error code. 81 77 */ 82 int 78 int 83 79 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc, 84 80 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) … … 105 101 106 102 /* read FAT1 */ 107 /* We should use fat_get_cluster instead */108 103 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst); 109 104 if (rc != EOK) … … 145 140 return ELIMIT; 146 141 147 if (nodep->firstc == FAT_CLST_ROOT) 142 if (nodep->firstc == FAT_CLST_ROOT) 148 143 goto fall_through; 149 144 … … 172 167 if (rc != EOK) 173 168 return rc; 174 169 175 170 /* 176 171 * Update the "current" cluster cache. … … 192 187 * @param clp If not NULL, address where the cluster containing bn 193 188 * will be stored. 194 * stored 189 * stored 195 190 * @param bn Block number. 196 191 * @param flags Flags passed to libblock. … … 269 264 return rc; 270 265 } 271 266 272 267 if (o >= pos) 273 268 return EOK; 274 269 275 270 /* zero out the initial part of the new cluster chain */ 276 271 for (o = boundary; o < pos; o += BPS(bs)) { … … 302 297 fat_cluster_t clst, fat_cluster_t *value) 303 298 { 304 block_t *b; 305 fat_cluster_t *cp; 306 aoff64_t fsec; /* sector offset relative to FAT */ 307 unsigned fidx; /* entry index */ 299 block_t *b, *b1; 300 aoff64_t offset; 308 301 int rc; 309 302 310 303 assert(fatno < FATCNT(bs)); 311 304 312 313 305 if (FATTYPE(bs) == 16) 314 { 315 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 316 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 306 offset = (clst * 2); 307 else 308 offset = (clst + clst/2); 309 310 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 311 offset / BPS(bs), BLOCK_FLAGS_NONE); 312 if (rc != EOK) 313 return rc; 314 315 /* This cluster access spans a sector boundary. Check only for FAT12 */ 316 if (FATTYPE(bs) == 12 && (offset % BPS(bs)+1 == BPS(bs))) { 317 /* Is it last sector of FAT? */ 318 if (offset / BPS(bs) < SF(bs)) { /* NO */ 319 /* Reading next sector */ 320 rc = block_get(&b1, devmap_handle, 1+RSCNT(bs)+SF(bs)*fatno + 321 offset / BPS(bs), BLOCK_FLAGS_NONE); 322 if (rc != EOK) { 323 block_put(b); 324 return rc; 325 } 326 /* 327 * Combining value with last byte of current sector and 328 * first byte of next sector 329 */ 330 *value = *(uint8_t *)(b->data + BPS(bs) - 1); 331 *value |= *(uint8_t *)(b1->data); 332 333 rc = block_put(b1); 334 if (rc != EOK) { 335 block_put(b); 336 return rc; 337 } 338 } 339 else { /* YES */ 340 block_put(b); 341 return ERANGE; 342 } 317 343 } 318 344 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 { 345 *value = *(fat_cluster_t *)(b->data + offset % BPS(bs)); 346 347 if (FATTYPE(bs) == 12) { 338 348 if (clst & 0x0001) 339 349 *value = (*value) >> 4; … … 344 354 *value = uint16_t_le2host(*value); 345 355 rc = block_put(b); 346 356 347 357 return rc; 348 358 } … … 362 372 fat_cluster_t clst, fat_cluster_t value) 363 373 { 364 block_t *b ;365 fat_cluster_t *cp;366 int rc;367 aoff64_t fsec; /* sector offset relative to FAT */ 368 unsigned fidx; /* entry index */374 block_t *b, *b1; 375 aoff64_t offset; 376 fat_cluster_t *cp, temp; 377 int rc; 378 int spans = 0; 369 379 370 380 assert(fatno < FATCNT(bs)); 371 381 372 382 if (FATTYPE(bs) == 16) 373 { 374 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 375 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 383 offset = (clst * sizeof(fat_cluster_t)); 384 else 385 offset = (clst + clst/2); 386 387 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 388 offset / BPS(bs), BLOCK_FLAGS_NONE); 389 if (rc != EOK) 390 return rc; 391 392 /* This cluster access spans a sector boundary. Check only for FAT12 */ 393 if (FATTYPE(bs) == 12 && (offset % BPS(bs)+1 == BPS(bs))) { 394 /* Is it last sector of FAT? */ 395 if (offset / BPS(bs) < SF(bs)) { /* NO */ 396 /* Reading next sector */ 397 rc = block_get(&b1, devmap_handle, 1+RSCNT(bs)+SF(bs)*fatno + 398 offset / BPS(bs), BLOCK_FLAGS_NONE); 399 if (rc != EOK) { 400 block_put(b); 401 return rc; 402 } 403 /* 404 * Combining value with last byte of current sector and 405 * first byte of next sector 406 */ 407 spans=1; 408 cp = &temp; 409 *cp = *(uint8_t *)(b->data + BPS(bs) - 1); 410 *cp |= *(uint8_t *)(b1->data); 411 } 412 else { /* YES */ 413 block_put(b); 414 return ERANGE; 415 } 376 416 } 377 417 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);385 if (rc != EOK) 386 return rc; 387 388 if (FATTYPE(bs) == 12)389 {390 cp = (fat_cluster_t *)(b->data + fidx); 391 if ( clst & 0x0001)418 cp = (fat_cluster_t *)(b->data + offset % BPS(bs)); 419 420 value = host2uint16_t_le(value); 421 if (FATTYPE(bs) == 12) { 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) 392 432 { 393 *cp &= 0x000f; 394 *cp |= host2uint16_t_le(value) << 4; 395 } 396 else 397 { 398 *cp &= 0xf000; 399 *cp |= host2uint16_t_le(value) & 0x0fff; 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 } 400 442 } 401 443 } 402 444 else 403 { 404 cp = &((fat_cluster_t *)b->data)[fidx]; 405 *cp = host2uint16_t_le(value); 406 } 445 *cp = value; 407 446 408 447 b->dirty = true; /* need to sync block */ … … 464 503 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 465 504 unsigned found = 0; /* top of the free cluster number stack */ 466 fat_cluster_t clst, max_clst,value;505 fat_cluster_t clst, value; 467 506 int rc = EOK; 468 507 uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 : 469 508 FAT12_CLST_LAST1; 470 509 471 472 510 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 473 511 if (!lifo) 474 512 return ENOMEM; 475 476 513 /* 477 514 * Search FAT1 for unused clusters. 478 515 */ 479 480 if (FATTYPE(bs) == 16)481 max_clst = SF(bs) * BPS(bs) / sizeof(fat_cluster_t);482 else483 max_clst = 2 *SF(bs) * BPS(bs) / 3;484 485 516 fibril_mutex_lock(&fat_alloc_lock); 486 for (clst=0; clst < max_clst && found < nclsts; clst++) 487 { 517 for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) { 488 518 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value); 489 519 if (rc != EOK) 490 520 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 } 521 504 522 if (value == FAT_CLST_RES0) { 505 523 /* … … 518 536 } 519 537 520 if (rc == EOK && found == nclsts) 521 { 538 if (rc == EOK && found == nclsts) { 522 539 rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts); 523 if (rc == EOK) 524 { 540 if (rc == EOK) { 525 541 *mcl = lifo[found - 1]; 526 542 *lcl = lifo[0]; … … 532 548 533 549 /* If something wrong - free the clusters */ 534 if (found > 0) 535 { 550 if (found > 0) { 536 551 while (found--) { 537 552 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], … … 735 750 736 751 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 737 bs->totsec16 != bs->totsec32) 752 bs->totsec16 != bs->totsec32) 738 753 return ENOTSUP; 739 754 … … 775 790 * set to one. 776 791 */ 777 /* Disabled for testing FAT12 778 if ((e0 >> 8) != 0xff || e1 != 0xffff) 792 if (FATTYPE(bs)!=12 && ((e0 >> 8) != 0xff || e1 != 0xffff)) 779 793 return ENOTSUP; 780 */781 794 } 782 795 … … 786 799 /** 787 800 * @} 788 */ 801 */ -
uspace/srv/fs/fat/fat_fat.h
rfc35e98 r97bc3ee 29 29 /** @addtogroup fs 30 30 * @{ 31 */ 31 */ 32 32 33 33 #ifndef FAT_FAT_FAT_H_ … … 56 56 #define FAT_CLST_ROOT FAT_CLST_RES1 57 57 58 #define FATTYPE(bs) (bs)->reserved 58 /* 59 * Convenience macros for computing some frequently used values from the 60 * primitive boot sector members. 61 */ 62 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \ 63 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0) 64 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs)) 65 #define DS(bs) (TS(bs) - SSA(bs)) 66 #define CC(bs) (DS(bs) / SPC(bs)) 67 #define FATTYPE(bs) (bs)->reserved 59 68 60 69 /* forward declarations */ -
uspace/srv/fs/fat/fat_ops.c
rfc35e98 r97bc3ee 29 29 /** @addtogroup fs 30 30 * @{ 31 */ 31 */ 32 32 33 33 /** … … 116 116 fat_dentry_t *d; 117 117 int rc; 118 118 119 119 assert(node->dirty); 120 120 121 121 bs = block_bb_get(node->idx->devmap_handle); 122 122 123 123 /* Read the block that contains the dentry of interest. */ 124 124 rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc, … … 136 136 d->attr = FAT_ATTR_SUBDIR; 137 137 } 138 138 139 139 /* TODO: update other fields? (e.g time fields) */ 140 140 141 141 b->dirty = true; /* need to sync block */ 142 142 rc = block_put(b); … … 255 255 fn->data = nodep; 256 256 nodep->bp = fn; 257 257 258 258 *nodepp = nodep; 259 259 return EOK; … … 291 291 * We must instantiate the node from the file system. 292 292 */ 293 293 294 294 assert(idxp->pfc); 295 295 … … 310 310 d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs)); 311 311 if (d->attr & FAT_ATTR_SUBDIR) { 312 /* 312 /* 313 313 * The only directory which does not have this bit set is the 314 314 * root directory itself. The root directory node is handled … … 316 316 */ 317 317 nodep->type = FAT_DIRECTORY; 318 /* 318 319 /* 319 320 * Unfortunately, the 'size' field of the FAT dentry is not 320 321 * defined for the directory entry type. We must determine the … … 334 335 nodep->size = uint32_t_le2host(d->size); 335 336 } 336 nodep->firstc = uint16_t_le2host(d->firstc); 337 338 nodep->firstc = uint16_t_le2host(d->firstc); 337 339 nodep->lnkcnt = 1; 338 340 nodep->refcnt = 1; … … 383 385 if (rc != EOK) 384 386 return rc; 385 for (j = 0; j < DPS(bs); j++) { 387 for (j = 0; j < DPS(bs); j++) { 386 388 d = ((fat_dentry_t *)b->data) + j; 387 389 switch (fat_classify_dentry(d)) { … … 521 523 rc = fat_idx_get_new(&idxp, devmap_handle); 522 524 if (rc != EOK) { 523 (void) fat_free_clusters(bs, devmap_handle, mcl); 525 (void) fat_free_clusters(bs, devmap_handle, mcl); 524 526 (void) fat_node_put(FS_NODE(nodep)); 525 527 return rc; … … 618 620 * a new one. 619 621 */ 620 622 621 623 fibril_mutex_lock(&parentp->idx->lock); 622 624 bs = block_bb_get(parentp->idx->devmap_handle); … … 650 652 } 651 653 j = 0; 652 654 653 655 /* 654 656 * We need to grow the parent in order to create a new unused dentry. … … 697 699 rc = block_put(b); 698 700 fibril_mutex_unlock(&parentp->idx->lock); 699 if (rc != EOK) 701 if (rc != EOK) 700 702 return rc; 701 703 702 704 fibril_mutex_lock(&childp->idx->lock); 703 705 704 706 if (childp->type == FAT_DIRECTORY) { 705 707 /* … … 778 780 if (!parentp) 779 781 return EBUSY; 780 782 781 783 rc = fat_has_children(&has_children, cfn); 782 784 if (rc != EOK) … … 794 796 NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 795 797 BLOCK_FLAGS_NONE); 796 if (rc != EOK) 798 if (rc != EOK) 797 799 goto error; 798 800 d = (fat_dentry_t *)b->data + … … 839 841 return EOK; 840 842 } 841 843 842 844 fibril_mutex_lock(&nodep->idx->lock); 843 845 bs = block_bb_get(nodep->idx->devmap_handle); … … 847 849 for (i = 0; i < blocks; i++) { 848 850 fat_dentry_t *d; 849 851 850 852 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 851 853 if (rc != EOK) { … … 875 877 if (rc != EOK) { 876 878 fibril_mutex_unlock(&nodep->idx->lock); 877 return rc; 879 return rc; 878 880 } 879 881 } … … 945 947 */ 946 948 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 953 949 void fat_mounted(ipc_callid_t rid, ipc_call_t *request) 954 950 { … … 956 952 enum cache_mode cmode; 957 953 fat_bs_t *bs; 958 954 959 955 /* Accept the mount options */ 960 956 char *opts; 961 957 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL); 962 958 963 959 if (rc != EOK) { 964 960 async_answer_0(rid, rc); … … 991 987 /* get the buffer with the boot sector */ 992 988 bs = block_bb_get(devmap_handle); 993 989 994 990 if (BPS(bs) != BS_SIZE) { 995 991 block_fini(devmap_handle); … … 1007 1003 1008 1004 /* Storing FAT type (12, 16, 32) in reserved field (bs->reserved) */ 1009 if (C ountOfClusters(bs) < 4085) {1005 if (CC(bs) < 4085) { 1010 1006 /* Volume is FAT12 */ 1011 1007 printf("Found FAT12 filesystem\n"); 1012 1008 (bs)->reserved = 12; 1013 } else if (C ountOfClusters(bs) < 65525) {1009 } else if (CC(bs) < 65525) { 1014 1010 /* Volume is FAT16 */ 1015 1011 printf("Found FAT16 filesystem\n"); … … 1017 1013 } else { 1018 1014 /* Volume is FAT32 */ 1019 printf("FAT32 is not supported by FAT driver. Sorry\n");1015 printf("FAT32 filesystem is not supported by FAT server. Sorry.\n"); 1020 1016 block_fini(devmap_handle); 1021 1017 async_answer_0(rid, ENOTSUP); … … 1085 1081 rootp->bp = rfn; 1086 1082 rfn->data = rootp; 1087 1083 1088 1084 fibril_mutex_unlock(&ridxp->lock); 1089 1085 … … 1119 1115 return; 1120 1116 } 1121 1117 1122 1118 /* 1123 1119 * Put the root node and force it to the FAT free node list. … … 1300 1296 int flags = BLOCK_FLAGS_NONE; 1301 1297 int rc; 1302 1298 1303 1299 rc = fat_node_get(&fn, devmap_handle, index); 1304 1300 if (rc != EOK) { … … 1311 1307 } 1312 1308 nodep = FAT_NODE(fn); 1313 1309 1314 1310 ipc_callid_t callid; 1315 1311 size_t len; … … 1328 1324 * but this one greatly simplifies fat_write(). Note that we can afford 1329 1325 * to do this because the client must be ready to handle the return 1330 * value signalizing a smaller number of bytes written. 1331 */ 1326 * value signalizing a smaller number of bytes written. 1327 */ 1332 1328 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1333 1329 if (bytes == BPS(bs)) 1334 1330 flags |= BLOCK_FLAGS_NOREAD; 1335 1331 1336 1332 boundary = ROUND_UP(nodep->size, BPC(bs)); 1337 1333 if (pos < boundary) { … … 1379 1375 */ 1380 1376 unsigned nclsts; 1381 fat_cluster_t mcl, lcl; 1382 1377 fat_cluster_t mcl, lcl; 1378 1383 1379 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1384 1380 /* create an independent chain of nclsts clusters in all FATs */ … … 1476 1472 nodep->size = size; 1477 1473 nodep->dirty = true; /* need to sync node */ 1478 rc = EOK; 1474 rc = EOK; 1479 1475 } else { 1480 1476 /* … … 1497 1493 nodep->size = size; 1498 1494 nodep->dirty = true; /* need to sync node */ 1499 rc = EOK; 1495 rc = EOK; 1500 1496 } 1501 1497 out: … … 1553 1549 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1554 1550 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1555 1551 1556 1552 fs_node_t *fn; 1557 1553 int rc = fat_node_get(&fn, devmap_handle, index); … … 1564 1560 return; 1565 1561 } 1566 1562 1567 1563 fat_node_t *nodep = FAT_NODE(fn); 1568 1564 1569 1565 nodep->dirty = true; 1570 1566 rc = fat_node_sync(nodep); 1571 1567 1572 1568 fat_node_put(fn); 1573 1569 async_answer_0(rid, rc);
Note:
See TracChangeset
for help on using the changeset viewer.