Changes in uspace/srv/fs/fat/fat_fat.c [c7bbf029:dc6b148] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
rc7bbf029 rdc6b148 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 50 51 #include <mem.h> 51 52 52 /* 53 * Convenience macros for computing some frequently used values from the 54 * primitive boot sector members. 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 60 #define CLBN2PBN(bs, cl, bn) \ 61 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) 53 #define IS_ODD(number) (number & 0x1) 62 54 63 55 /** … … 65 57 * during allocation of clusters. The lock does not have to be held durring 66 58 * deallocation of clusters. 67 */ 59 */ 68 60 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 69 61 … … 71 63 * 72 64 * @param bs Buffer holding the boot sector for the file. 73 * @param devmap_handle Device handleof the device with the file.65 * @param service_id Service ID of the device with the file. 74 66 * @param firstc First cluster to start the walk with. 75 67 * @param lastc If non-NULL, output argument hodling the last cluster … … 77 69 * @param numc If non-NULL, output argument holding the number of 78 70 * clusters seen during the walk. 79 * @param max_clusters Maximum number of clusters to visit. 71 * @param max_clusters Maximum number of clusters to visit. 80 72 * 81 73 * @return EOK on success or a negative error code. 82 74 */ 83 int 84 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,85 fat_cluster_t *lastc, uint 16_t *numc, uint16_t max_clusters)86 { 87 block_t *b;88 uint16_t clusters = 0;89 fat_cluster_t clst = firstc;75 int 76 fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc, 77 fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters) 78 { 79 uint32_t clusters = 0; 80 fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs); 81 fat_cluster_t clst_bad = FAT_CLST_BAD(bs); 90 82 int rc; 91 83 … … 99 91 } 100 92 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 93 while (clst < clst_last1 && clusters < max_clusters) { 105 94 assert(clst >= FAT_CLST_FIRST); 106 95 if (lastc) 107 96 *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)); 97 110 98 /* 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; 99 rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst); 100 if (rc != EOK) 101 return rc; 102 103 assert(clst != clst_bad); 120 104 clusters++; 121 105 } 122 106 123 if (lastc && clst < FAT_CLST_LAST1)107 if (lastc && clst < clst_last1) 124 108 *lastc = clst; 125 109 if (numc) … … 151 135 return ELIMIT; 152 136 153 if ( nodep->firstc == FAT_CLST_ROOT)137 if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT) 154 138 goto fall_through; 155 139 … … 160 144 * when fortunately we have the last cluster number cached. 161 145 */ 162 return block_get(block, nodep->idx-> devmap_handle,146 return block_get(block, nodep->idx->service_id, 163 147 CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags); 164 148 } … … 174 158 175 159 fall_through: 176 rc = _fat_block_get(block, bs, nodep->idx-> devmap_handle, firstc,160 rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc, 177 161 &currc, relbn, flags); 178 162 if (rc != EOK) 179 163 return rc; 180 164 181 165 /* 182 166 * Update the "current" cluster cache. … … 193 177 * @param block Pointer to a block pointer for storing result. 194 178 * @param bs Buffer holding the boot sector of the file system. 195 * @param devmap_handle Devicehandle of the file system.179 * @param service_id Service ID handle of the file system. 196 180 * @param fcl First cluster used by the file. Can be zero if the file 197 181 * is empty. 198 182 * @param clp If not NULL, address where the cluster containing bn 199 183 * will be stored. 200 * stored 184 * stored 201 185 * @param bn Block number. 202 186 * @param flags Flags passed to libblock. … … 205 189 */ 206 190 int 207 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,191 _fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id, 208 192 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 209 193 { 210 uint 16_t clusters;211 u nsignedmax_clusters;194 uint32_t clusters; 195 uint32_t max_clusters; 212 196 fat_cluster_t c; 213 197 int rc; … … 219 203 return ELIMIT; 220 204 221 if ( fcl == FAT_CLST_ROOT) {205 if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) { 222 206 /* root directory special case */ 223 207 assert(bn < RDS(bs)); 224 rc = block_get(block, devmap_handle,208 rc = block_get(block, service_id, 225 209 RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags); 226 210 return rc; … … 228 212 229 213 max_clusters = bn / SPC(bs); 230 rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);214 rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters); 231 215 if (rc != EOK) 232 216 return rc; 233 217 assert(clusters == max_clusters); 234 218 235 rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);219 rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags); 236 220 237 221 if (clp) … … 253 237 * @return EOK on success or a negative error code. 254 238 */ 255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 239 int 240 fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 256 241 { 257 242 block_t *b; … … 275 260 return rc; 276 261 } 277 262 278 263 if (o >= pos) 279 264 return EOK; 280 265 281 266 /* zero out the initial part of the new cluster chain */ 282 267 for (o = boundary; o < pos; o += BPS(bs)) { 283 rc = _fat_block_get(&b, bs, nodep->idx-> devmap_handle, mcl,268 rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl, 284 269 NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD); 285 270 if (rc != EOK) … … 298 283 * 299 284 * @param bs Buffer holding the boot sector for the file system. 300 * @param devmap_handle Device handlefor the file system.285 * @param service_id Service ID for the file system. 301 286 * @param clst Cluster which to get. 302 287 * @param value Output argument holding the value of the cluster. … … 304 289 * @return EOK or a negative error code. 305 290 */ 306 int307 fat_get_cluster (fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,291 static int 292 fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 308 293 fat_cluster_t clst, fat_cluster_t *value) 309 294 { 310 block_t *b; 311 fat_cluster_t *cp; 312 int rc; 313 314 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 315 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 295 block_t *b, *b1; 296 uint16_t byte1, byte2; 297 aoff64_t offset; 298 int rc; 299 300 offset = (clst + clst / 2); 301 if (offset / BPS(bs) >= SF(bs)) 302 return ERANGE; 303 304 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 305 offset / BPS(bs), BLOCK_FLAGS_NONE); 316 306 if (rc != EOK) 317 307 return rc; 318 cp = (fat_cluster_t *)b->data + 319 clst % (BPS(bs) / sizeof(fat_cluster_t)); 320 *value = uint16_t_le2host(*cp); 308 309 byte1 = ((uint8_t *) b->data)[offset % BPS(bs)]; 310 /* This cluster access spans a sector boundary. Check only for FAT12 */ 311 if ((offset % BPS(bs)) + 1 == BPS(bs)) { 312 /* Is this the last sector of FAT? */ 313 if (offset / BPS(bs) < SF(bs)) { 314 /* No, read the next sector */ 315 rc = block_get(&b1, service_id, 1 + RSCNT(bs) + 316 SF(bs) * fatno + offset / BPS(bs), 317 BLOCK_FLAGS_NONE); 318 if (rc != EOK) { 319 block_put(b); 320 return rc; 321 } 322 /* 323 * Combining value with last byte of current sector and 324 * first byte of next sector 325 */ 326 byte2 = ((uint8_t*) b1->data)[0]; 327 328 rc = block_put(b1); 329 if (rc != EOK) { 330 block_put(b); 331 return rc; 332 } 333 } else { 334 /* Yes. This is the last sector of FAT */ 335 block_put(b); 336 return ERANGE; 337 } 338 } else 339 byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1]; 340 341 *value = uint16_t_le2host(byte1 | (byte2 << 8)); 342 if (IS_ODD(clst)) 343 *value = (*value) >> 4; 344 else 345 *value = (*value) & FAT12_MASK; 346 321 347 rc = block_put(b); 322 348 323 349 return rc; 324 350 } 325 351 352 /** Get cluster from the first FAT. 353 * 354 * @param bs Buffer holding the boot sector for the file system. 355 * @param service_id Service ID for the file system. 356 * @param clst Cluster which to get. 357 * @param value Output argument holding the value of the cluster. 358 * 359 * @return EOK or a negative error code. 360 */ 361 static int 362 fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 363 fat_cluster_t clst, fat_cluster_t *value) 364 { 365 block_t *b; 366 aoff64_t offset; 367 int rc; 368 369 offset = (clst * FAT16_CLST_SIZE); 370 371 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 372 offset / BPS(bs), BLOCK_FLAGS_NONE); 373 if (rc != EOK) 374 return rc; 375 376 *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs))); 377 378 rc = block_put(b); 379 380 return rc; 381 } 382 383 /** Get cluster from the first FAT. 384 * 385 * @param bs Buffer holding the boot sector for the file system. 386 * @param service_id Service ID for the file system. 387 * @param clst Cluster which to get. 388 * @param value Output argument holding the value of the cluster. 389 * 390 * @return EOK or a negative error code. 391 */ 392 static int 393 fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 394 fat_cluster_t clst, fat_cluster_t *value) 395 { 396 block_t *b; 397 aoff64_t offset; 398 int rc; 399 400 offset = (clst * FAT32_CLST_SIZE); 401 402 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 403 offset / BPS(bs), BLOCK_FLAGS_NONE); 404 if (rc != EOK) 405 return rc; 406 407 *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) & 408 FAT32_MASK; 409 410 rc = block_put(b); 411 412 return rc; 413 } 414 415 416 /** Get cluster from the first FAT. 417 * 418 * @param bs Buffer holding the boot sector for the file system. 419 * @param service_id Service ID for the file system. 420 * @param clst Cluster which to get. 421 * @param value Output argument holding the value of the cluster. 422 * 423 * @return EOK or a negative error code. 424 */ 425 int 426 fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 427 fat_cluster_t clst, fat_cluster_t *value) 428 { 429 int rc; 430 431 assert(fatno < FATCNT(bs)); 432 433 if (FAT_IS_FAT12(bs)) 434 rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value); 435 else if (FAT_IS_FAT16(bs)) 436 rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value); 437 else 438 rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value); 439 440 return rc; 441 } 442 326 443 /** Set cluster in one instance of FAT. 327 444 * 328 445 * @param bs Buffer holding the boot sector for the file system. 329 * @param devmap_handle Device handlefor the file system.446 * @param service_id Service ID for the file system. 330 447 * @param fatno Number of the FAT instance where to make the change. 331 448 * @param clst Cluster which is to be set. … … 334 451 * @return EOK on success or a negative error code. 335 452 */ 336 int337 fat_set_cluster (fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,453 static int 454 fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 338 455 fat_cluster_t clst, fat_cluster_t value) 339 456 { 340 block_t *b; 341 fat_cluster_t *cp; 342 int rc; 343 344 assert(fatno < FATCNT(bs)); 345 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 346 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 457 block_t *b, *b1 = NULL; 458 aoff64_t offset; 459 uint16_t byte1, byte2; 460 int rc; 461 462 offset = (clst + clst / 2); 463 if (offset / BPS(bs) >= SF(bs)) 464 return ERANGE; 465 466 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 467 offset / BPS(bs), BLOCK_FLAGS_NONE); 347 468 if (rc != EOK) 348 469 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 */ 470 471 byte1 = ((uint8_t*) b->data)[offset % BPS(bs)]; 472 bool border = false; 473 /* This cluster access spans a sector boundary. */ 474 if ((offset % BPS(bs)) + 1 == BPS(bs)) { 475 /* Is it the last sector of FAT? */ 476 if (offset / BPS(bs) < SF(bs)) { 477 /* No, read the next sector */ 478 rc = block_get(&b1, service_id, 1 + RSCNT(bs) + 479 SF(bs) * fatno + offset / BPS(bs), 480 BLOCK_FLAGS_NONE); 481 if (rc != EOK) { 482 block_put(b); 483 return rc; 484 } 485 /* 486 * Combining value with last byte of current sector and 487 * first byte of next sector 488 */ 489 byte2 = ((uint8_t *) b1->data)[0]; 490 border = true; 491 } else { 492 /* Yes. This is the last sector of FAT */ 493 block_put(b); 494 return ERANGE; 495 } 496 } else 497 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1]; 498 499 if (IS_ODD(clst)) { 500 byte1 &= 0x0f; 501 byte2 = 0; 502 value = (value << 4); 503 } else { 504 byte1 = 0; 505 byte2 &= 0xf0; 506 value &= FAT12_MASK; 507 } 508 509 byte1 = byte1 | (value & 0xff); 510 byte2 = byte2 | (value >> 8); 511 512 ((uint8_t *) b->data)[(offset % BPS(bs))] = byte1; 513 if (border) { 514 ((uint8_t *) b1->data)[0] = byte2; 515 516 b1->dirty = true; 517 rc = block_put(b1); 518 if (rc != EOK) { 519 block_put(b); 520 return rc; 521 } 522 } else 523 ((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2; 524 525 b->dirty = true; /* need to sync block */ 353 526 rc = block_put(b); 527 354 528 return rc; 355 529 } 356 530 531 /** Set cluster in one instance of FAT. 532 * 533 * @param bs Buffer holding the boot sector for the file system. 534 * @param service_id Service ID for the file system. 535 * @param fatno Number of the FAT instance where to make the change. 536 * @param clst Cluster which is to be set. 537 * @param value Value to set the cluster with. 538 * 539 * @return EOK on success or a negative error code. 540 */ 541 static int 542 fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 543 fat_cluster_t clst, fat_cluster_t value) 544 { 545 block_t *b; 546 aoff64_t offset; 547 int rc; 548 549 offset = (clst * FAT16_CLST_SIZE); 550 551 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 552 offset / BPS(bs), BLOCK_FLAGS_NONE); 553 if (rc != EOK) 554 return rc; 555 556 *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value); 557 558 b->dirty = true; /* need to sync block */ 559 rc = block_put(b); 560 561 return rc; 562 } 563 564 /** Set cluster in one instance of FAT. 565 * 566 * @param bs Buffer holding the boot sector for the file system. 567 * @param service_id Service ID for the file system. 568 * @param fatno Number of the FAT instance where to make the change. 569 * @param clst Cluster which is to be set. 570 * @param value Value to set the cluster with. 571 * 572 * @return EOK on success or a negative error code. 573 */ 574 static int 575 fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 576 fat_cluster_t clst, fat_cluster_t value) 577 { 578 block_t *b; 579 aoff64_t offset; 580 int rc; 581 fat_cluster_t temp; 582 583 offset = (clst * FAT32_CLST_SIZE); 584 585 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 586 offset / BPS(bs), BLOCK_FLAGS_NONE); 587 if (rc != EOK) 588 return rc; 589 590 temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))); 591 temp &= 0xf0000000; 592 temp |= (value & FAT32_MASK); 593 *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp); 594 595 b->dirty = true; /* need to sync block */ 596 rc = block_put(b); 597 598 return rc; 599 } 600 601 /** Set cluster in one instance of FAT. 602 * 603 * @param bs Buffer holding the boot sector for the file system. 604 * @param service_id Device service ID for the file system. 605 * @param fatno Number of the FAT instance where to make the change. 606 * @param clst Cluster which is to be set. 607 * @param value Value to set the cluster with. 608 * 609 * @return EOK on success or a negative error code. 610 */ 611 int 612 fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 613 fat_cluster_t clst, fat_cluster_t value) 614 { 615 int rc; 616 617 assert(fatno < FATCNT(bs)); 618 619 if (FAT_IS_FAT12(bs)) 620 rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value); 621 else if (FAT_IS_FAT16(bs)) 622 rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value); 623 else 624 rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value); 625 626 return rc; 627 } 628 357 629 /** Replay the allocatoin of clusters in all shadow instances of FAT. 358 630 * 359 631 * @param bs Buffer holding the boot sector of the file system. 360 * @param devmap_handle Device handleof the file system.632 * @param service_id Service ID of the file system. 361 633 * @param lifo Chain of allocated clusters. 362 634 * @param nclsts Number of clusters in the lifo chain. … … 364 636 * @return EOK on success or a negative error code. 365 637 */ 366 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,638 int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id, 367 639 fat_cluster_t *lifo, unsigned nclsts) 368 640 { 369 641 uint8_t fatno; 370 642 unsigned c; 371 int rc; 372 373 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 643 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 644 int rc; 645 646 for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) { 374 647 for (c = 0; c < nclsts; c++) { 375 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);648 rc = fat_set_cluster(bs, service_id, fatno, lifo[c], 649 c == 0 ? clst_last1 : lifo[c - 1]); 377 650 if (rc != EOK) 378 651 return rc; … … 391 664 * 392 665 * @param bs Buffer holding the boot sector of the file system. 393 * @param devmap_handle Device handleof the file system.666 * @param service_id Device service ID of the file system. 394 667 * @param nclsts Number of clusters to allocate. 395 668 * @param mcl Output parameter where the first cluster in the chain … … 401 674 */ 402 675 int 403 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,676 fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts, 404 677 fat_cluster_t *mcl, fat_cluster_t *lcl) 405 678 { 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; 679 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 680 unsigned found = 0; /* top of the free cluster number stack */ 681 fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs); 682 int rc = EOK; 411 683 412 684 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); … … 418 690 */ 419 691 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++) { 692 for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts; 693 clst++) { 694 rc = fat_get_cluster(bs, service_id, FAT1, clst, &value); 695 if (rc != EOK) 696 break; 697 698 if (value == FAT_CLST_RES0) { 426 699 /* 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. 700 * The cluster is free. Put it into our stack 701 * of found clusters and mark it as non-free. 433 702 */ 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 } 703 lifo[found] = clst; 704 rc = fat_set_cluster(bs, service_id, FAT1, clst, 705 (found == 0) ? clst_last1 : lifo[found - 1]); 706 if (rc != EOK) 707 break; 708 709 found++; 470 710 } 471 rc = block_put(blk); 472 if (rc != EOK) { 473 error: 711 } 712 713 if (rc == EOK && found == nclsts) { 714 rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts); 715 if (rc == EOK) { 716 *mcl = lifo[found - 1]; 717 *lcl = lifo[0]; 718 free(lifo); 474 719 fibril_mutex_unlock(&fat_alloc_lock); 475 free(lifo); 476 return rc; 720 return EOK; 477 721 } 478 722 } 479 out: 723 724 /* If something wrong - free the clusters */ 725 while (found--) { 726 (void) fat_set_cluster(bs, service_id, FAT1, lifo[found], 727 FAT_CLST_RES0); 728 } 729 730 free(lifo); 480 731 fibril_mutex_unlock(&fat_alloc_lock); 481 732 482 /*483 * We could not find enough clusters. Now we need to free the clusters484 * we have allocated so far.485 */486 while (found--) {487 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],488 FAT_CLST_RES0);489 if (rc != EOK) {490 free(lifo);491 return rc;492 }493 }494 495 free(lifo);496 733 return ENOSPC; 497 734 } … … 500 737 * 501 738 * @param bs Buffer hodling the boot sector of the file system. 502 * @param devmap_handle Device handleof the file system.739 * @param service_id Device service ID of the file system. 503 740 * @param firstc First cluster in the chain which is to be freed. 504 741 * … … 506 743 */ 507 744 int 508 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)745 fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc) 509 746 { 510 747 unsigned fatno; 511 fat_cluster_t nextc ;748 fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs); 512 749 int rc; 513 750 514 751 /* 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); 517 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc); 518 if (rc != EOK) 519 return rc; 520 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 521 rc = fat_set_cluster(bs, devmap_handle, fatno, firstc, 752 while (firstc < FAT_CLST_LAST1(bs)) { 753 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad); 754 755 rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc); 756 if (rc != EOK) 757 return rc; 758 759 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 760 rc = fat_set_cluster(bs, service_id, fatno, firstc, 522 761 FAT_CLST_RES0); 523 762 if (rc != EOK) … … 540 779 * @return EOK on success or a negative error code. 541 780 */ 542 int 543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 781 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 544 782 fat_cluster_t lcl) 545 783 { 546 devmap_handle_t devmap_handle = nodep->idx->devmap_handle;784 service_id_t service_id = nodep->idx->service_id; 547 785 fat_cluster_t lastc; 548 786 uint8_t fatno; … … 558 796 nodep->lastc_cached_valid = false; 559 797 } else { 560 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,561 &lastc, NULL, (uint 16_t) -1);798 rc = fat_cluster_walk(bs, service_id, nodep->firstc, 799 &lastc, NULL, (uint32_t) -1); 562 800 if (rc != EOK) 563 801 return rc; 564 802 } 565 803 566 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {567 rc = fat_set_cluster(bs, nodep->idx-> devmap_handle, fatno,568 lastc, mcl);804 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 805 rc = fat_set_cluster(bs, nodep->idx->service_id, 806 fatno, lastc, mcl); 569 807 if (rc != EOK) 570 808 return rc; … … 590 828 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 591 829 { 592 int rc; 593 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; 830 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 831 int rc; 832 service_id_t service_id = nodep->idx->service_id; 594 833 595 834 /* … … 602 841 if (lcl == FAT_CLST_RES0) { 603 842 /* The node will have zero size and no clusters allocated. */ 604 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);843 rc = fat_free_clusters(bs, service_id, nodep->firstc); 605 844 if (rc != EOK) 606 845 return rc; … … 611 850 unsigned fatno; 612 851 613 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);852 rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc); 614 853 if (rc != EOK) 615 854 return rc; 616 855 617 856 /* Terminate the cluster chain in all copies of FAT. */ 618 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {619 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,620 FAT_CLST_LAST1);857 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 858 rc = fat_set_cluster(bs, service_id, fatno, lcl, 859 clst_last1); 621 860 if (rc != EOK) 622 861 return rc; … … 624 863 625 864 /* Free all following clusters. */ 626 rc = fat_free_clusters(bs, devmap_handle, nextc);865 rc = fat_free_clusters(bs, service_id, nextc); 627 866 if (rc != EOK) 628 867 return rc; … … 639 878 640 879 int 641 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)880 fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c) 642 881 { 643 882 int i; … … 646 885 647 886 for (i = 0; i < SPC(bs); i++) { 648 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,887 rc = _fat_block_get(&b, bs, service_id, c, NULL, i, 649 888 BLOCK_FLAGS_NOREAD); 650 889 if (rc != EOK) … … 666 905 * does not contain a fat file system. 667 906 */ 668 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)907 int fat_sanity_check(fat_bs_t *bs, service_id_t service_id) 669 908 { 670 909 fat_cluster_t e0, e1; … … 673 912 674 913 /* Check number of FATs. */ 675 if ( bs->fatcnt== 0)914 if (FATCNT(bs) == 0) 676 915 return ENOTSUP; 677 916 678 917 /* Check total number of sectors. */ 679 680 if (bs->totsec16 == 0 && bs->totsec32 == 0) 918 if (TS(bs) == 0) 681 919 return ENOTSUP; 682 920 683 921 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 684 bs->totsec16 != bs->totsec32) 922 bs->totsec16 != bs->totsec32) 685 923 return ENOTSUP; 686 924 … … 690 928 691 929 /* Check number of sectors per FAT. */ 692 if ( bs->sec_per_fat== 0)930 if (SF(bs) == 0) 693 931 return ENOTSUP; 694 932 … … 700 938 * sanitized to support file systems with this property. 701 939 */ 702 if ( (uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %703 uint16_t_le2host(bs->bps) != 0)940 if (!FAT_IS_FAT32(bs) && 941 (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0) 704 942 return ENOTSUP; 705 943 706 944 /* Check signature of each FAT. */ 707 708 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 709 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); 945 for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) { 946 rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0); 710 947 if (rc != EOK) 711 948 return EIO; 712 949 713 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);950 rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1); 714 951 if (rc != EOK) 715 952 return EIO; 716 953 717 /* Check that first byte of FAT contains the media descriptor. */ 954 /* 955 * Check that first byte of FAT contains the media descriptor. 956 */ 718 957 if ((e0 & 0xff) != bs->mdesc) 719 958 return ENOTSUP; … … 723 962 * set to one. 724 963 */ 725 if ((e0 >> 8) != 0xff || e1 != 0xffff) 964 if (!FAT_IS_FAT12(bs) && 965 ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs))) 726 966 return ENOTSUP; 727 967 } … … 732 972 /** 733 973 * @} 734 */ 974 */
Note:
See TracChangeset
for help on using the changeset viewer.