Changeset 1787e527 in mainline for uspace/srv/fs/fat/fat_fat.c
- Timestamp:
- 2009-11-16T21:22:54Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5ebdf94
- Parents:
- fcbd1be (diff), 9c70ed6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
rfcbd1be r1787e527 61 61 * @param dev_handle Device handle of the device with the file. 62 62 * @param firstc First cluster to start the walk with. 63 * @param lastc If non-NULL, output argument hodling the last cluster number visited. 63 * @param lastc If non-NULL, output argument hodling the last cluster 64 * number visited. 65 * @param numc If non-NULL, output argument holding the number of 66 * clusters seen during the walk. 64 67 * @param max_clusters Maximum number of clusters to visit. 65 68 * 66 * @return Number of clusters seen during the walk.67 */ 68 uint16_t69 * @return EOK on success or a negative error code. 70 */ 71 int 69 72 fat_cluster_walk(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc, 70 fat_cluster_t *lastc, uint16_t max_clusters)73 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) 71 74 { 72 75 block_t *b; … … 75 78 uint16_t clusters = 0; 76 79 fat_cluster_t clst = firstc; 80 int rc; 77 81 78 82 bps = uint16_t_le2host(bs->bps); … … 83 87 if (lastc) 84 88 *lastc = firstc; 85 return 0; 89 if (numc) 90 *numc = 0; 91 return EOK; 86 92 } 87 93 … … 96 102 fidx = clst % (bps / sizeof(fat_cluster_t)); 97 103 /* read FAT1 */ 98 b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); 104 rc = block_get(&b, dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); 105 if (rc != EOK) 106 return rc; 99 107 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 100 108 assert(clst != FAT_CLST_BAD); 101 block_put(b); 109 rc = block_put(b); 110 if (rc != EOK) 111 return rc; 102 112 clusters++; 103 113 } … … 105 115 if (lastc && clst < FAT_CLST_LAST1) 106 116 *lastc = clst; 107 108 return clusters; 117 if (numc) 118 *numc = clusters; 119 120 return EOK; 109 121 } 110 122 111 123 /** Read block from file located on a FAT file system. 112 124 * 125 * @param block Pointer to a block pointer for storing result. 113 126 * @param bs Buffer holding the boot sector of the file system. 114 127 * @param dev_handle Device handle of the file system. … … 118 131 * @param flags Flags passed to libblock. 119 132 * 120 * @return Block structure holding the requested block. 121 */ 122 block_t * 123 _fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc, 124 bn_t bn, int flags) 125 { 126 block_t *b; 133 * @return EOK on success or a negative error code. 134 */ 135 int 136 _fat_block_get(block_t **block, fat_bs_t *bs, dev_handle_t dev_handle, 137 fat_cluster_t firstc, bn_t bn, int flags) 138 { 127 139 unsigned bps; 128 140 unsigned rscnt; /* block address of the first FAT */ … … 131 143 unsigned sf; 132 144 unsigned ssa; /* size of the system area */ 133 unsigned clusters, max_clusters; 145 uint16_t clusters; 146 unsigned max_clusters; 134 147 fat_cluster_t lastc; 148 int rc; 135 149 136 150 bps = uint16_t_le2host(bs->bps); … … 146 160 /* root directory special case */ 147 161 assert(bn < rds); 148 b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags); 149 return b; 162 rc = block_get(block, dev_handle, rscnt + bs->fatcnt * sf + bn, 163 flags); 164 return rc; 150 165 } 151 166 152 167 max_clusters = bn / bs->spc; 153 clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc,168 rc = fat_cluster_walk(bs, dev_handle, firstc, &lastc, &clusters, 154 169 max_clusters); 170 if (rc != EOK) 171 return rc; 155 172 assert(clusters == max_clusters); 156 173 157 b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc +158 bn % bs->spc, flags);159 160 return b;174 rc = block_get(block, dev_handle, 175 ssa + (lastc - FAT_CLST_FIRST) * bs->spc + bn % bs->spc, flags); 176 177 return rc; 161 178 } 162 179 … … 170 187 * this argument is ignored. 171 188 * @param pos Position in the last node block. 172 */ 173 void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos) 189 * 190 * @return EOK on success or a negative error code. 191 */ 192 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos) 174 193 { 175 194 uint16_t bps; … … 177 196 block_t *b; 178 197 off_t o, boundary; 198 int rc; 179 199 180 200 bps = uint16_t_le2host(bs->bps); … … 188 208 int flags = (o % bps == 0) ? 189 209 BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE; 190 b = fat_block_get(bs, nodep, o / bps, flags); 210 rc = fat_block_get(&b, bs, nodep, o / bps, flags); 211 if (rc != EOK) 212 return rc; 191 213 memset(b->data + o % bps, 0, bps - o % bps); 192 214 b->dirty = true; /* need to sync node */ 193 block_put(b); 215 rc = block_put(b); 216 if (rc != EOK) 217 return rc; 194 218 } 195 219 196 220 if (o >= pos) 197 return ;221 return EOK; 198 222 199 223 /* zero out the initial part of the new cluster chain */ 200 224 for (o = boundary; o < pos; o += bps) { 201 b = _fat_block_get(bs, nodep->idx->dev_handle, mcl,225 rc = _fat_block_get(&b, bs, nodep->idx->dev_handle, mcl, 202 226 (o - boundary) / bps, BLOCK_FLAGS_NOREAD); 227 if (rc != EOK) 228 return rc; 203 229 memset(b->data, 0, min(bps, pos - o)); 204 230 b->dirty = true; /* need to sync node */ 205 block_put(b); 206 } 231 rc = block_put(b); 232 if (rc != EOK) 233 return rc; 234 } 235 236 return EOK; 207 237 } 208 238 … … 212 242 * @param dev_handle Device handle for the file system. 213 243 * @param clst Cluster which to get. 214 * 215 * @return Value found in the cluster. 216 */ 217 fat_cluster_t 218 fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst) 244 * @param value Output argument holding the value of the cluster. 245 * 246 * @return EOK or a negative error code. 247 */ 248 int 249 fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst, 250 fat_cluster_t *value) 219 251 { 220 252 block_t *b; 221 253 uint16_t bps; 222 254 uint16_t rscnt; 223 fat_cluster_t *cp, value; 255 fat_cluster_t *cp; 256 int rc; 224 257 225 258 bps = uint16_t_le2host(bs->bps); 226 259 rscnt = uint16_t_le2host(bs->rscnt); 227 260 228 b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps, 229 BLOCK_FLAGS_NONE); 261 rc = block_get(&b, dev_handle, rscnt + 262 (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); 263 if (rc != EOK) 264 return rc; 230 265 cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); 231 value = uint16_t_le2host(*cp);232 block_put(b);233 234 return value;266 *value = uint16_t_le2host(*cp); 267 rc = block_put(b); 268 269 return rc; 235 270 } 236 271 … … 242 277 * @param clst Cluster which is to be set. 243 278 * @param value Value to set the cluster with. 244 */ 245 void 279 * 280 * @return EOK on success or a negative error code. 281 */ 282 int 246 283 fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno, 247 284 fat_cluster_t clst, fat_cluster_t value) … … 252 289 uint16_t sf; 253 290 fat_cluster_t *cp; 291 int rc; 254 292 255 293 bps = uint16_t_le2host(bs->bps); … … 258 296 259 297 assert(fatno < bs->fatcnt); 260 b = block_get(dev_handle, rscnt + sf * fatno +298 rc = block_get(&b, dev_handle, rscnt + sf * fatno + 261 299 (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); 300 if (rc != EOK) 301 return rc; 262 302 cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); 263 303 *cp = host2uint16_t_le(value); 264 304 b->dirty = true; /* need to sync block */ 265 block_put(b); 305 rc = block_put(b); 306 return rc; 266 307 } 267 308 … … 272 313 * @param lifo Chain of allocated clusters. 273 314 * @param nclsts Number of clusters in the lifo chain. 274 */ 275 void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle, 315 * 316 * @return EOK on success or a negative error code. 317 */ 318 int fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle, 276 319 fat_cluster_t *lifo, unsigned nclsts) 277 320 { 278 321 uint8_t fatno; 279 322 unsigned c; 323 int rc; 280 324 281 325 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 282 326 for (c = 0; c < nclsts; c++) { 283 fat_set_cluster(bs, dev_handle, fatno, lifo[c],327 rc = fat_set_cluster(bs, dev_handle, fatno, lifo[c], 284 328 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]); 329 if (rc != EOK) 330 return rc; 285 331 } 286 332 } 333 334 return EOK; 287 335 } 288 336 … … 311 359 uint16_t rscnt; 312 360 uint16_t sf; 361 uint16_t ts; 362 unsigned rde; 363 unsigned rds; 364 unsigned ssa; 313 365 block_t *blk; 314 366 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 315 367 unsigned found = 0; /* top of the free cluster number stack */ 316 368 unsigned b, c, cl; 369 int rc; 317 370 318 371 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); … … 323 376 rscnt = uint16_t_le2host(bs->rscnt); 324 377 sf = uint16_t_le2host(bs->sec_per_fat); 378 rde = uint16_t_le2host(bs->root_ent_max); 379 ts = uint16_t_le2host(bs->totsec16); 380 381 rds = (sizeof(fat_dentry_t) * rde) / bps; 382 rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); 383 ssa = rscnt + bs->fatcnt * sf + rds; 325 384 326 385 /* … … 329 388 fibril_mutex_lock(&fat_alloc_lock); 330 389 for (b = 0, cl = 0; b < sf; b++) { 331 blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE); 390 rc = block_get(&blk, dev_handle, rscnt + b, BLOCK_FLAGS_NONE); 391 if (rc != EOK) 392 goto error; 332 393 for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) { 394 /* 395 * Check if the cluster is physically there. This check 396 * becomes necessary when the file system is created 397 * with fewer total sectors than how many is inferred 398 * from the size of the file allocation table. 399 */ 400 if ((cl - 2) * bs->spc + ssa >= ts) { 401 rc = block_put(blk); 402 if (rc != EOK) 403 goto error; 404 goto out; 405 } 406 333 407 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 334 408 if (uint16_t_le2host(*clst) == FAT_CLST_RES0) { … … 344 418 if (++found == nclsts) { 345 419 /* we are almost done */ 346 block_put(blk); 420 rc = block_put(blk); 421 if (rc != EOK) 422 goto error; 347 423 /* update the shadow copies of FAT */ 348 fat_alloc_shadow_clusters(bs,424 rc = fat_alloc_shadow_clusters(bs, 349 425 dev_handle, lifo, nclsts); 426 if (rc != EOK) 427 goto error; 350 428 *mcl = lifo[found - 1]; 351 429 *lcl = lifo[0]; … … 356 434 } 357 435 } 358 block_put(blk); 359 } 436 rc = block_put(blk); 437 if (rc != EOK) { 438 error: 439 fibril_mutex_unlock(&fat_alloc_lock); 440 free(lifo); 441 return rc; 442 } 443 } 444 out: 360 445 fibril_mutex_unlock(&fat_alloc_lock); 361 446 … … 365 450 */ 366 451 while (found--) { 367 fat_set_cluster(bs, dev_handle, FAT1, lifo[found],452 rc = fat_set_cluster(bs, dev_handle, FAT1, lifo[found], 368 453 FAT_CLST_RES0); 454 if (rc != EOK) { 455 free(lifo); 456 return rc; 457 } 369 458 } 370 459 … … 378 467 * @param dev_handle Device handle of the file system. 379 468 * @param firstc First cluster in the chain which is to be freed. 380 */ 381 void 469 * 470 * @return EOK on success or a negative return code. 471 */ 472 int 382 473 fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc) 383 474 { 384 475 unsigned fatno; 385 476 fat_cluster_t nextc; 477 int rc; 386 478 387 479 /* Mark all clusters in the chain as free in all copies of FAT. */ 388 480 while (firstc < FAT_CLST_LAST1) { 389 481 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD); 390 nextc = fat_get_cluster(bs, dev_handle, firstc); 391 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) 392 fat_set_cluster(bs, dev_handle, fatno, firstc, 482 rc = fat_get_cluster(bs, dev_handle, firstc, &nextc); 483 if (rc != EOK) 484 return rc; 485 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 486 rc = fat_set_cluster(bs, dev_handle, fatno, firstc, 393 487 FAT_CLST_RES0); 488 if (rc != EOK) 489 return rc; 490 } 491 394 492 firstc = nextc; 395 493 } 494 495 return EOK; 396 496 } 397 497 … … 401 501 * @param nodep Node representing the file. 402 502 * @param mcl First cluster of the cluster chain to append. 403 */ 404 void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl) 503 * 504 * @return EOK on success or a negative error code. 505 */ 506 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl) 405 507 { 406 508 dev_handle_t dev_handle = nodep->idx->dev_handle; 407 509 fat_cluster_t lcl; 510 uint16_t numc; 408 511 uint8_t fatno; 409 410 if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, 411 (uint16_t) -1) == 0) { 512 int rc; 513 514 rc = fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, &numc, 515 (uint16_t) -1); 516 if (rc != EOK) 517 return rc; 518 519 if (numc == 0) { 412 520 /* No clusters allocated to the node yet. */ 413 521 nodep->firstc = mcl; 414 522 nodep->dirty = true; /* need to sync node */ 415 return; 416 } 417 418 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) 419 fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl); 523 return EOK; 524 } 525 526 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 527 rc = fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, 528 mcl); 529 if (rc != EOK) 530 return rc; 531 } 532 533 return EOK; 420 534 } 421 535 … … 427 541 * argument is FAT_CLST_RES0, then all clusters will 428 542 * be chopped off. 429 */ 430 void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc) 431 { 543 * 544 * @return EOK on success or a negative return code. 545 */ 546 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc) 547 { 548 int rc; 549 432 550 dev_handle_t dev_handle = nodep->idx->dev_handle; 433 551 if (lastc == FAT_CLST_RES0) { 434 552 /* The node will have zero size and no clusters allocated. */ 435 fat_free_clusters(bs, dev_handle, nodep->firstc); 553 rc = fat_free_clusters(bs, dev_handle, nodep->firstc); 554 if (rc != EOK) 555 return rc; 436 556 nodep->firstc = FAT_CLST_RES0; 437 557 nodep->dirty = true; /* need to sync node */ … … 440 560 unsigned fatno; 441 561 442 nextc = fat_get_cluster(bs, dev_handle, lastc); 562 rc = fat_get_cluster(bs, dev_handle, lastc, &nextc); 563 if (rc != EOK) 564 return rc; 443 565 444 566 /* Terminate the cluster chain in all copies of FAT. */ 445 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) 446 fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1); 567 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 568 rc = fat_set_cluster(bs, dev_handle, fatno, lastc, 569 FAT_CLST_LAST1); 570 if (rc != EOK) 571 return rc; 572 } 447 573 448 574 /* Free all following clusters. */ 449 fat_free_clusters(bs, dev_handle, nextc); 450 } 451 } 452 453 void 575 rc = fat_free_clusters(bs, dev_handle, nextc); 576 if (rc != EOK) 577 return rc; 578 } 579 580 return EOK; 581 } 582 583 int 454 584 fat_zero_cluster(struct fat_bs *bs, dev_handle_t dev_handle, fat_cluster_t c) 455 585 { … … 457 587 block_t *b; 458 588 unsigned bps; 589 int rc; 459 590 460 591 bps = uint16_t_le2host(bs->bps); 461 592 462 593 for (i = 0; i < bs->spc; i++) { 463 b = _fat_block_get(bs, dev_handle, c, i, BLOCK_FLAGS_NOREAD); 594 rc = _fat_block_get(&b, bs, dev_handle, c, i, 595 BLOCK_FLAGS_NOREAD); 596 if (rc != EOK) 597 return rc; 464 598 memset(b->data, 0, bps); 465 599 b->dirty = true; 466 block_put(b); 467 } 600 rc = block_put(b); 601 if (rc != EOK) 602 return rc; 603 } 604 605 return EOK; 468 606 } 469 607
Note:
See TracChangeset
for help on using the changeset viewer.