Changeset 20235a3 in mainline for uspace/srv/fs/fat/fat_fat.c
- Timestamp:
- 2010-09-02T20:55:28Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0c39b96
- Parents:
- 0c61955 (diff), 3249673 (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
r0c61955 r20235a3 49 49 #include <mem.h> 50 50 51 /* 52 * Convenience macros for computing some frequently used values from the 53 * primitive boot sector members. 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 #define CLBN2PBN(bs, cl, bn) \ 60 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) 61 51 62 /** 52 63 * The fat_alloc_lock mutex protects all copies of the File Allocation Table … … 74 85 { 75 86 block_t *b; 76 unsigned bps;77 unsigned rscnt; /* block address of the first FAT */78 87 uint16_t clusters = 0; 79 88 fat_cluster_t clst = firstc; 80 89 int rc; 81 82 bps = uint16_t_le2host(bs->bps);83 rscnt = uint16_t_le2host(bs->rscnt);84 90 85 91 if (firstc == FAT_CLST_RES0) { … … 99 105 if (lastc) 100 106 *lastc = clst; /* remember the last cluster number */ 101 fsec = (clst * sizeof(fat_cluster_t)) / bps;102 fidx = clst % ( bps/ sizeof(fat_cluster_t));107 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 108 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 103 109 /* read FAT1 */ 104 rc = block_get(&b, dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); 110 rc = block_get(&b, dev_handle, RSCNT(bs) + fsec, 111 BLOCK_FLAGS_NONE); 105 112 if (rc != EOK) 106 113 return rc; … … 125 132 * @param block Pointer to a block pointer for storing result. 126 133 * @param bs Buffer holding the boot sector of the file system. 127 * @param dev_handle Device handle of the file system. 128 * @param firstc First cluster used by the file. Can be zero if the file 129 * is empty. 134 * @param nodep FAT node. 130 135 * @param bn Block number. 131 136 * @param flags Flags passed to libblock. … … 134 139 */ 135 140 int 141 fat_block_get(block_t **block, struct fat_bs *bs, fat_node_t *nodep, 142 aoff64_t bn, int flags) 143 { 144 fat_cluster_t firstc = nodep->firstc; 145 fat_cluster_t currc; 146 aoff64_t relbn = bn; 147 int rc; 148 149 if (!nodep->size) 150 return ELIMIT; 151 152 if (nodep->firstc == FAT_CLST_ROOT) 153 goto fall_through; 154 155 if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) && 156 nodep->lastc_cached_valid) { 157 /* 158 * This is a request to read a block within the last cluster 159 * when fortunately we have the last cluster number cached. 160 */ 161 return block_get(block, nodep->idx->dev_handle, 162 CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags); 163 } 164 165 if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) { 166 /* 167 * We can start with the cluster cached by the previous call to 168 * fat_block_get(). 169 */ 170 firstc = nodep->currc_cached_value; 171 relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs); 172 } 173 174 fall_through: 175 rc = _fat_block_get(block, bs, nodep->idx->dev_handle, firstc, 176 &currc, relbn, flags); 177 if (rc != EOK) 178 return rc; 179 180 /* 181 * Update the "current" cluster cache. 182 */ 183 nodep->currc_cached_valid = true; 184 nodep->currc_cached_bn = bn; 185 nodep->currc_cached_value = currc; 186 187 return rc; 188 } 189 190 /** Read block from file located on a FAT file system. 191 * 192 * @param block Pointer to a block pointer for storing result. 193 * @param bs Buffer holding the boot sector of the file system. 194 * @param dev_handle Device handle of the file system. 195 * @param fcl First cluster used by the file. Can be zero if the file 196 * is empty. 197 * @param clp If not NULL, address where the cluster containing bn 198 * will be stored. 199 * stored 200 * @param bn Block number. 201 * @param flags Flags passed to libblock. 202 * 203 * @return EOK on success or a negative error code. 204 */ 205 int 136 206 _fat_block_get(block_t **block, fat_bs_t *bs, dev_handle_t dev_handle, 137 fat_cluster_t firstc, aoff64_t bn, int flags) 138 { 139 unsigned bps; 140 unsigned rscnt; /* block address of the first FAT */ 141 unsigned rde; 142 unsigned rds; /* root directory size */ 143 unsigned sf; 144 unsigned ssa; /* size of the system area */ 207 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 208 { 145 209 uint16_t clusters; 146 210 unsigned max_clusters; 147 fat_cluster_t lastc;211 fat_cluster_t c; 148 212 int rc; 149 213 … … 151 215 * This function can only operate on non-zero length files. 152 216 */ 153 if (f irstc== FAT_CLST_RES0)217 if (fcl == FAT_CLST_RES0) 154 218 return ELIMIT; 155 219 156 bps = uint16_t_le2host(bs->bps); 157 rscnt = uint16_t_le2host(bs->rscnt); 158 rde = uint16_t_le2host(bs->root_ent_max); 159 sf = uint16_t_le2host(bs->sec_per_fat); 160 161 rds = (sizeof(fat_dentry_t) * rde) / bps; 162 rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); 163 ssa = rscnt + bs->fatcnt * sf + rds; 164 165 if (firstc == FAT_CLST_ROOT) { 220 if (fcl == FAT_CLST_ROOT) { 166 221 /* root directory special case */ 167 assert(bn < rds);168 rc = block_get(block, dev_handle, rscnt + bs->fatcnt * sf + bn,169 flags);222 assert(bn < RDS(bs)); 223 rc = block_get(block, dev_handle, 224 RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags); 170 225 return rc; 171 226 } 172 227 173 max_clusters = bn / bs->spc; 174 rc = fat_cluster_walk(bs, dev_handle, firstc, &lastc, &clusters, 175 max_clusters); 228 max_clusters = bn / SPC(bs); 229 rc = fat_cluster_walk(bs, dev_handle, fcl, &c, &clusters, max_clusters); 176 230 if (rc != EOK) 177 231 return rc; 178 232 assert(clusters == max_clusters); 179 233 180 rc = block_get(block, dev_handle, 181 ssa + (lastc - FAT_CLST_FIRST) * bs->spc + bn % bs->spc, flags); 234 rc = block_get(block, dev_handle, CLBN2PBN(bs, c, bn), flags); 235 236 if (clp) 237 *clp = c; 182 238 183 239 return rc; … … 198 254 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 199 255 { 200 uint16_t bps;201 unsigned spc;202 256 block_t *b; 203 257 aoff64_t o, boundary; 204 258 int rc; 205 259 206 bps = uint16_t_le2host(bs->bps); 207 spc = bs->spc; 208 209 boundary = ROUND_UP(nodep->size, bps * spc); 260 boundary = ROUND_UP(nodep->size, BPS(bs) * SPC(bs)); 210 261 211 262 /* zero out already allocated space */ 212 263 for (o = nodep->size; o < pos && o < boundary; 213 o = ALIGN_DOWN(o + bps, bps)) {214 int flags = (o % bps== 0) ?264 o = ALIGN_DOWN(o + BPS(bs), BPS(bs))) { 265 int flags = (o % BPS(bs) == 0) ? 215 266 BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE; 216 rc = fat_block_get(&b, bs, nodep, o / bps, flags);217 if (rc != EOK) 218 return rc; 219 memset(b->data + o % bps, 0, bps - o % bps);267 rc = fat_block_get(&b, bs, nodep, o / BPS(bs), flags); 268 if (rc != EOK) 269 return rc; 270 memset(b->data + o % BPS(bs), 0, BPS(bs) - o % BPS(bs)); 220 271 b->dirty = true; /* need to sync node */ 221 272 rc = block_put(b); … … 228 279 229 280 /* zero out the initial part of the new cluster chain */ 230 for (o = boundary; o < pos; o += bps) {281 for (o = boundary; o < pos; o += BPS(bs)) { 231 282 rc = _fat_block_get(&b, bs, nodep->idx->dev_handle, mcl, 232 (o - boundary) / bps, BLOCK_FLAGS_NOREAD);233 if (rc != EOK) 234 return rc; 235 memset(b->data, 0, min( bps, pos - o));283 NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD); 284 if (rc != EOK) 285 return rc; 286 memset(b->data, 0, min(BPS(bs), pos - o)); 236 287 b->dirty = true; /* need to sync node */ 237 288 rc = block_put(b); … … 257 308 { 258 309 block_t *b; 259 uint16_t bps;260 uint16_t rscnt;261 uint16_t sf;262 310 fat_cluster_t *cp; 263 311 int rc; 264 312 265 bps = uint16_t_le2host(bs->bps); 266 rscnt = uint16_t_le2host(bs->rscnt); 267 sf = uint16_t_le2host(bs->sec_per_fat); 268 269 rc = block_get(&b, dev_handle, rscnt + sf * fatno + 270 (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); 313 rc = block_get(&b, dev_handle, RSCNT(bs) + SF(bs) * fatno + 314 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 271 315 if (rc != EOK) 272 316 return rc; 273 cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); 317 cp = (fat_cluster_t *)b->data + 318 clst % (BPS(bs) / sizeof(fat_cluster_t)); 274 319 *value = uint16_t_le2host(*cp); 275 320 rc = block_put(b); … … 293 338 { 294 339 block_t *b; 295 uint16_t bps;296 uint16_t rscnt;297 uint16_t sf;298 340 fat_cluster_t *cp; 299 341 int rc; 300 342 301 bps = uint16_t_le2host(bs->bps); 302 rscnt = uint16_t_le2host(bs->rscnt); 303 sf = uint16_t_le2host(bs->sec_per_fat); 304 305 assert(fatno < bs->fatcnt); 306 rc = block_get(&b, dev_handle, rscnt + sf * fatno + 307 (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); 343 assert(fatno < FATCNT(bs)); 344 rc = block_get(&b, dev_handle, RSCNT(bs) + SF(bs) * fatno + 345 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 308 346 if (rc != EOK) 309 347 return rc; 310 cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); 348 cp = (fat_cluster_t *)b->data + 349 clst % (BPS(bs) / sizeof(fat_cluster_t)); 311 350 *cp = host2uint16_t_le(value); 312 351 b->dirty = true; /* need to sync block */ … … 364 403 fat_cluster_t *mcl, fat_cluster_t *lcl) 365 404 { 366 uint16_t bps;367 uint16_t rscnt;368 uint16_t sf;369 uint32_t ts;370 unsigned rde;371 unsigned rds;372 unsigned ssa;373 405 block_t *blk; 374 406 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ … … 380 412 if (!lifo) 381 413 return ENOMEM; 382 383 bps = uint16_t_le2host(bs->bps);384 rscnt = uint16_t_le2host(bs->rscnt);385 sf = uint16_t_le2host(bs->sec_per_fat);386 rde = uint16_t_le2host(bs->root_ent_max);387 ts = (uint32_t) uint16_t_le2host(bs->totsec16);388 if (ts == 0)389 ts = uint32_t_le2host(bs->totsec32);390 391 rds = (sizeof(fat_dentry_t) * rde) / bps;392 rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);393 ssa = rscnt + bs->fatcnt * sf + rds;394 414 395 415 /* … … 397 417 */ 398 418 fibril_mutex_lock(&fat_alloc_lock); 399 for (b = 0, cl = 0; b < sf; b++) { 400 rc = block_get(&blk, dev_handle, rscnt + b, BLOCK_FLAGS_NONE); 419 for (b = 0, cl = 0; b < SF(bs); b++) { 420 rc = block_get(&blk, dev_handle, RSCNT(bs) + b, 421 BLOCK_FLAGS_NONE); 401 422 if (rc != EOK) 402 423 goto error; 403 for (c = 0; c < bps/ sizeof(fat_cluster_t); c++, cl++) {424 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) { 404 425 /* 405 * Check if the cluster is physically there. This check 406 * becomes necessary when the file system is created 407 * with fewer total sectors than how many is inferred 408 * from the size of the file allocation table. 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. 409 432 */ 410 if ((cl >= 2) && ((cl - 2) * bs->spc + ssa >= ts)) { 433 if ((cl >= FAT_CLST_FIRST) && 434 CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) { 411 435 rc = block_put(blk); 412 436 if (rc != EOK) … … 511 535 * @param nodep Node representing the file. 512 536 * @param mcl First cluster of the cluster chain to append. 537 * @param lcl Last cluster of the cluster chain to append. 513 538 * 514 539 * @return EOK on success or a negative error code. 515 540 */ 516 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl) 541 int 542 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 543 fat_cluster_t lcl) 517 544 { 518 545 dev_handle_t dev_handle = nodep->idx->dev_handle; 519 fat_cluster_t l cl;546 fat_cluster_t lastc; 520 547 uint16_t numc; 521 548 uint8_t fatno; 522 549 int rc; 523 550 524 rc = fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, &numc, 525 (uint16_t) -1); 526 if (rc != EOK) 527 return rc; 528 529 if (numc == 0) { 530 /* No clusters allocated to the node yet. */ 531 nodep->firstc = mcl; 532 nodep->dirty = true; /* need to sync node */ 533 return EOK; 551 if (nodep->lastc_cached_valid) { 552 lastc = nodep->lastc_cached_value; 553 nodep->lastc_cached_valid = false; 554 } else { 555 rc = fat_cluster_walk(bs, dev_handle, nodep->firstc, &lastc, 556 &numc, (uint16_t) -1); 557 if (rc != EOK) 558 return rc; 559 560 if (numc == 0) { 561 /* No clusters allocated to the node yet. */ 562 nodep->firstc = mcl; 563 nodep->dirty = true; /* need to sync node */ 564 return EOK; 565 } 534 566 } 535 567 536 568 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 537 rc = fat_set_cluster(bs, nodep->idx->dev_handle, fatno, l cl,569 rc = fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lastc, 538 570 mcl); 539 571 if (rc != EOK) 540 572 return rc; 541 573 } 574 575 nodep->lastc_cached_valid = true; 576 nodep->lastc_cached_value = lcl; 542 577 543 578 return EOK; … … 548 583 * @param bs Buffer holding the boot sector of the file system. 549 584 * @param nodep FAT node where the chopping will take place. 550 * @param l astcLast cluster which will remain in the node. If this585 * @param lcl Last cluster which will remain in the node. If this 551 586 * argument is FAT_CLST_RES0, then all clusters will 552 587 * be chopped off. … … 554 589 * @return EOK on success or a negative return code. 555 590 */ 556 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc) 557 { 558 int rc; 559 591 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 592 { 593 int rc; 560 594 dev_handle_t dev_handle = nodep->idx->dev_handle; 561 if (lastc == FAT_CLST_RES0) { 595 596 /* 597 * Invalidate cached cluster numbers. 598 */ 599 nodep->lastc_cached_valid = false; 600 if (nodep->currc_cached_value != lcl) 601 nodep->currc_cached_valid = false; 602 603 if (lcl == FAT_CLST_RES0) { 562 604 /* The node will have zero size and no clusters allocated. */ 563 605 rc = fat_free_clusters(bs, dev_handle, nodep->firstc); … … 570 612 unsigned fatno; 571 613 572 rc = fat_get_cluster(bs, dev_handle, FAT1, l astc, &nextc);614 rc = fat_get_cluster(bs, dev_handle, FAT1, lcl, &nextc); 573 615 if (rc != EOK) 574 616 return rc; … … 576 618 /* Terminate the cluster chain in all copies of FAT. */ 577 619 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 578 rc = fat_set_cluster(bs, dev_handle, fatno, l astc,620 rc = fat_set_cluster(bs, dev_handle, fatno, lcl, 579 621 FAT_CLST_LAST1); 580 622 if (rc != EOK) … … 588 630 } 589 631 632 /* 633 * Update and re-enable the last cluster cache. 634 */ 635 nodep->lastc_cached_valid = true; 636 nodep->lastc_cached_value = lcl; 637 590 638 return EOK; 591 639 } … … 596 644 int i; 597 645 block_t *b; 598 unsigned bps; 599 int rc; 600 601 bps = uint16_t_le2host(bs->bps); 602 603 for (i = 0; i < bs->spc; i++) { 604 rc = _fat_block_get(&b, bs, dev_handle, c, i, 646 int rc; 647 648 for (i = 0; i < SPC(bs); i++) { 649 rc = _fat_block_get(&b, bs, dev_handle, c, NULL, i, 605 650 BLOCK_FLAGS_NOREAD); 606 651 if (rc != EOK) 607 652 return rc; 608 memset(b->data, 0, bps);653 memset(b->data, 0, BPS(bs)); 609 654 b->dirty = true; 610 655 rc = block_put(b);
Note:
See TracChangeset
for help on using the changeset viewer.