Changes in uspace/srv/fs/fat/fat_fat.c [dc6b148:c7bbf029] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
rdc6b148 rc7bbf029 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 30 29 /** @addtogroup fs 31 30 * @{ 32 */ 31 */ 33 32 34 33 /** … … 51 50 #include <mem.h> 52 51 53 #define IS_ODD(number) (number & 0x1) 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))) 54 62 55 63 /** … … 57 65 * during allocation of clusters. The lock does not have to be held durring 58 66 * deallocation of clusters. 59 */ 67 */ 60 68 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 61 69 … … 63 71 * 64 72 * @param bs Buffer holding the boot sector for the file. 65 * @param service_id Service IDof the device with the file.73 * @param devmap_handle Device handle of the device with the file. 66 74 * @param firstc First cluster to start the walk with. 67 75 * @param lastc If non-NULL, output argument hodling the last cluster … … 69 77 * @param numc If non-NULL, output argument holding the number of 70 78 * clusters seen during the walk. 71 * @param max_clusters Maximum number of clusters to visit. 79 * @param max_clusters Maximum number of clusters to visit. 72 80 * 73 81 * @return EOK on success or a negative error code. 74 82 */ 75 int 76 fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,77 fat_cluster_t *lastc, uint 32_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);83 int 84 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc, 85 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) 86 { 87 block_t *b; 88 uint16_t clusters = 0; 89 fat_cluster_t clst = firstc; 82 90 int rc; 83 91 … … 91 99 } 92 100 93 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 94 105 assert(clst >= FAT_CLST_FIRST); 95 106 if (lastc) 96 107 *lastc = clst; /* remember the last cluster number */ 97 108 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 109 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 98 110 /* read FAT1 */ 99 rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst); 100 if (rc != EOK) 101 return rc; 102 103 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; 104 120 clusters++; 105 121 } 106 122 107 if (lastc && clst < clst_last1)123 if (lastc && clst < FAT_CLST_LAST1) 108 124 *lastc = clst; 109 125 if (numc) … … 135 151 return ELIMIT; 136 152 137 if ( !FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)153 if (nodep->firstc == FAT_CLST_ROOT) 138 154 goto fall_through; 139 155 … … 144 160 * when fortunately we have the last cluster number cached. 145 161 */ 146 return block_get(block, nodep->idx-> service_id,162 return block_get(block, nodep->idx->devmap_handle, 147 163 CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags); 148 164 } … … 158 174 159 175 fall_through: 160 rc = _fat_block_get(block, bs, nodep->idx-> service_id, firstc,176 rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc, 161 177 &currc, relbn, flags); 162 178 if (rc != EOK) 163 179 return rc; 164 180 165 181 /* 166 182 * Update the "current" cluster cache. … … 177 193 * @param block Pointer to a block pointer for storing result. 178 194 * @param bs Buffer holding the boot sector of the file system. 179 * @param service_id Service IDhandle of the file system.195 * @param devmap_handle Device handle of the file system. 180 196 * @param fcl First cluster used by the file. Can be zero if the file 181 197 * is empty. 182 198 * @param clp If not NULL, address where the cluster containing bn 183 199 * will be stored. 184 * stored 200 * stored 185 201 * @param bn Block number. 186 202 * @param flags Flags passed to libblock. … … 189 205 */ 190 206 int 191 _fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,207 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle, 192 208 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 193 209 { 194 uint 32_t clusters;195 u int32_tmax_clusters;210 uint16_t clusters; 211 unsigned max_clusters; 196 212 fat_cluster_t c; 197 213 int rc; … … 203 219 return ELIMIT; 204 220 205 if ( !FAT_IS_FAT32(bs) &&fcl == FAT_CLST_ROOT) {221 if (fcl == FAT_CLST_ROOT) { 206 222 /* root directory special case */ 207 223 assert(bn < RDS(bs)); 208 rc = block_get(block, service_id,224 rc = block_get(block, devmap_handle, 209 225 RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags); 210 226 return rc; … … 212 228 213 229 max_clusters = bn / SPC(bs); 214 rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);230 rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters); 215 231 if (rc != EOK) 216 232 return rc; 217 233 assert(clusters == max_clusters); 218 234 219 rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);235 rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags); 220 236 221 237 if (clp) … … 237 253 * @return EOK on success or a negative error code. 238 254 */ 239 int 240 fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 241 256 { 242 257 block_t *b; … … 260 275 return rc; 261 276 } 262 277 263 278 if (o >= pos) 264 279 return EOK; 265 280 266 281 /* zero out the initial part of the new cluster chain */ 267 282 for (o = boundary; o < pos; o += BPS(bs)) { 268 rc = _fat_block_get(&b, bs, nodep->idx-> service_id, mcl,283 rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl, 269 284 NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD); 270 285 if (rc != EOK) … … 283 298 * 284 299 * @param bs Buffer holding the boot sector for the file system. 285 * @param service_id Service IDfor the file system.300 * @param devmap_handle Device handle for the file system. 286 301 * @param clst Cluster which to get. 287 302 * @param value Output argument holding the value of the cluster. … … 289 304 * @return EOK or a negative error code. 290 305 */ 291 staticint292 fat_get_cluster _fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,306 int 307 fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno, 293 308 fat_cluster_t clst, fat_cluster_t *value) 294 309 { 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); 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); 306 316 if (rc != EOK) 307 317 return rc; 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; 318 cp = (fat_cluster_t *)b->data + 319 clst % (BPS(bs) / sizeof(fat_cluster_t)); 320 *value = uint16_t_le2host(*cp); 321 rc = block_put(b); 346 322 347 rc = block_put(b);348 349 323 return rc; 350 324 } 351 325 352 /** Get cluster from the firstFAT.326 /** Set cluster in one instance of FAT. 353 327 * 354 328 * @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 443 /** Set cluster in one instance of FAT. 444 * 445 * @param bs Buffer holding the boot sector for the file system. 446 * @param service_id Service ID for the file system. 329 * @param devmap_handle Device handle for the file system. 447 330 * @param fatno Number of the FAT instance where to make the change. 448 331 * @param clst Cluster which is to be set. … … 451 334 * @return EOK on success or a negative error code. 452 335 */ 453 staticint454 fat_set_cluster _fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,336 int 337 fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno, 455 338 fat_cluster_t clst, fat_cluster_t value) 456 339 { 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); 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); 468 347 if (rc != EOK) 469 348 return rc; 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 */ 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 */ 526 353 rc = block_put(b); 527 528 354 return rc; 529 355 } 530 356 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 int542 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 int575 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 int612 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 else624 rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);625 626 return rc;627 }628 629 357 /** Replay the allocatoin of clusters in all shadow instances of FAT. 630 358 * 631 359 * @param bs Buffer holding the boot sector of the file system. 632 * @param service_id Service IDof the file system.360 * @param devmap_handle Device handle of the file system. 633 361 * @param lifo Chain of allocated clusters. 634 362 * @param nclsts Number of clusters in the lifo chain. … … 636 364 * @return EOK on success or a negative error code. 637 365 */ 638 int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,366 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, 639 367 fat_cluster_t *lifo, unsigned nclsts) 640 368 { 641 369 uint8_t fatno; 642 370 unsigned c; 643 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 644 int rc; 645 646 for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) { 371 int rc; 372 373 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 647 374 for (c = 0; c < nclsts; c++) { 648 rc = fat_set_cluster(bs, service_id, fatno, lifo[c],649 c == 0 ? clst_last1 : lifo[c - 1]);375 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c], 376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]); 650 377 if (rc != EOK) 651 378 return rc; … … 664 391 * 665 392 * @param bs Buffer holding the boot sector of the file system. 666 * @param service_id Device service IDof the file system.393 * @param devmap_handle Device handle of the file system. 667 394 * @param nclsts Number of clusters to allocate. 668 395 * @param mcl Output parameter where the first cluster in the chain … … 674 401 */ 675 402 int 676 fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,403 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts, 677 404 fat_cluster_t *mcl, fat_cluster_t *lcl) 678 405 { 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; 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; 683 411 684 412 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); … … 690 418 */ 691 419 fibril_mutex_lock(&fat_alloc_lock); 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) { 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++) { 699 426 /* 700 * The cluster is free. Put it into our stack 701 * of found clusters and mark it as non-free. 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. 702 433 */ 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++; 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 } 710 470 } 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]; 471 rc = block_put(blk); 472 if (rc != EOK) { 473 error: 474 fibril_mutex_unlock(&fat_alloc_lock); 718 475 free(lifo); 719 fibril_mutex_unlock(&fat_alloc_lock); 720 return EOK; 476 return rc; 721 477 } 722 478 } 723 724 /* If something wrong - free the clusters */ 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 */ 725 486 while (found--) { 726 (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],487 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], 727 488 FAT_CLST_RES0); 728 } 729 489 if (rc != EOK) { 490 free(lifo); 491 return rc; 492 } 493 } 494 730 495 free(lifo); 731 fibril_mutex_unlock(&fat_alloc_lock);732 733 496 return ENOSPC; 734 497 } … … 737 500 * 738 501 * @param bs Buffer hodling the boot sector of the file system. 739 * @param service_id Device service IDof the file system.502 * @param devmap_handle Device handle of the file system. 740 503 * @param firstc First cluster in the chain which is to be freed. 741 504 * … … 743 506 */ 744 507 int 745 fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)508 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc) 746 509 { 747 510 unsigned fatno; 748 fat_cluster_t nextc , clst_bad = FAT_CLST_BAD(bs);511 fat_cluster_t nextc; 749 512 int rc; 750 513 751 514 /* Mark all clusters in the chain as free in all copies of FAT. */ 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, 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, 761 522 FAT_CLST_RES0); 762 523 if (rc != EOK) … … 779 540 * @return EOK on success or a negative error code. 780 541 */ 781 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 542 int 543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 782 544 fat_cluster_t lcl) 783 545 { 784 service_id_t service_id = nodep->idx->service_id;546 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; 785 547 fat_cluster_t lastc; 786 548 uint8_t fatno; … … 796 558 nodep->lastc_cached_valid = false; 797 559 } else { 798 rc = fat_cluster_walk(bs, service_id, nodep->firstc,799 &lastc, NULL, (uint 32_t) -1);560 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc, 561 &lastc, NULL, (uint16_t) -1); 800 562 if (rc != EOK) 801 563 return rc; 802 564 } 803 565 804 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {805 rc = fat_set_cluster(bs, nodep->idx-> service_id,806 fatno,lastc, mcl);566 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 567 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno, 568 lastc, mcl); 807 569 if (rc != EOK) 808 570 return rc; … … 828 590 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 829 591 { 830 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 831 int rc; 832 service_id_t service_id = nodep->idx->service_id; 592 int rc; 593 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; 833 594 834 595 /* … … 841 602 if (lcl == FAT_CLST_RES0) { 842 603 /* The node will have zero size and no clusters allocated. */ 843 rc = fat_free_clusters(bs, service_id, nodep->firstc);604 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc); 844 605 if (rc != EOK) 845 606 return rc; … … 850 611 unsigned fatno; 851 612 852 rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);613 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc); 853 614 if (rc != EOK) 854 615 return rc; 855 616 856 617 /* Terminate the cluster chain in all copies of FAT. */ 857 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {858 rc = fat_set_cluster(bs, service_id, fatno, lcl,859 clst_last1);618 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 619 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl, 620 FAT_CLST_LAST1); 860 621 if (rc != EOK) 861 622 return rc; … … 863 624 864 625 /* Free all following clusters. */ 865 rc = fat_free_clusters(bs, service_id, nextc);626 rc = fat_free_clusters(bs, devmap_handle, nextc); 866 627 if (rc != EOK) 867 628 return rc; … … 878 639 879 640 int 880 fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)641 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c) 881 642 { 882 643 int i; … … 885 646 886 647 for (i = 0; i < SPC(bs); i++) { 887 rc = _fat_block_get(&b, bs, service_id, c, NULL, i,648 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i, 888 649 BLOCK_FLAGS_NOREAD); 889 650 if (rc != EOK) … … 905 666 * does not contain a fat file system. 906 667 */ 907 int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)668 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle) 908 669 { 909 670 fat_cluster_t e0, e1; … … 912 673 913 674 /* Check number of FATs. */ 914 if ( FATCNT(bs)== 0)675 if (bs->fatcnt == 0) 915 676 return ENOTSUP; 916 677 917 678 /* Check total number of sectors. */ 918 if (TS(bs) == 0) 679 680 if (bs->totsec16 == 0 && bs->totsec32 == 0) 919 681 return ENOTSUP; 920 682 921 683 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 922 bs->totsec16 != bs->totsec32) 684 bs->totsec16 != bs->totsec32) 923 685 return ENOTSUP; 924 686 … … 928 690 929 691 /* Check number of sectors per FAT. */ 930 if ( SF(bs)== 0)692 if (bs->sec_per_fat == 0) 931 693 return ENOTSUP; 932 694 … … 938 700 * sanitized to support file systems with this property. 939 701 */ 940 if ( !FAT_IS_FAT32(bs) &&941 (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)702 if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) % 703 uint16_t_le2host(bs->bps) != 0) 942 704 return ENOTSUP; 943 705 944 706 /* Check signature of each FAT. */ 945 for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) { 946 rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0); 707 708 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 709 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); 947 710 if (rc != EOK) 948 711 return EIO; 949 712 950 rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);713 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1); 951 714 if (rc != EOK) 952 715 return EIO; 953 716 954 /* 955 * Check that first byte of FAT contains the media descriptor. 956 */ 717 /* Check that first byte of FAT contains the media descriptor. */ 957 718 if ((e0 & 0xff) != bs->mdesc) 958 719 return ENOTSUP; … … 962 723 * set to one. 963 724 */ 964 if (!FAT_IS_FAT12(bs) && 965 ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs))) 725 if ((e0 >> 8) != 0xff || e1 != 0xffff) 966 726 return ENOTSUP; 967 727 } … … 972 732 /** 973 733 * @} 974 */ 734 */
Note:
See TracChangeset
for help on using the changeset viewer.