Changeset 1787e527 in mainline for uspace/srv/fs/fat/fat_ops.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_ops.c
rfcbd1be r1787e527 65 65 static LIST_INITIALIZE(ffn_head); 66 66 67 /* 68 * Forward declarations of FAT libfs operations. 69 */ 70 static int fat_root_get(fs_node_t **, dev_handle_t); 71 static int fat_match(fs_node_t **, fs_node_t *, const char *); 72 static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t); 73 static int fat_node_put(fs_node_t *); 74 static int fat_create_node(fs_node_t **, dev_handle_t, int); 75 static int fat_destroy_node(fs_node_t *); 76 static int fat_link(fs_node_t *, fs_node_t *, const char *); 77 static int fat_unlink(fs_node_t *, fs_node_t *, const char *); 78 static int fat_has_children(bool *, fs_node_t *); 79 static fs_index_t fat_index_get(fs_node_t *); 80 static size_t fat_size_get(fs_node_t *); 81 static unsigned fat_lnkcnt_get(fs_node_t *); 82 static char fat_plb_get_char(unsigned); 83 static bool fat_is_directory(fs_node_t *); 84 static bool fat_is_file(fs_node_t *node); 85 86 /* 87 * Helper functions. 88 */ 67 89 static void fat_node_initialize(fat_node_t *node) 68 90 { … … 78 100 } 79 101 80 static voidfat_node_sync(fat_node_t *node)102 static int fat_node_sync(fat_node_t *node) 81 103 { 82 104 block_t *b; … … 85 107 uint16_t bps; 86 108 unsigned dps; 109 int rc; 87 110 88 111 assert(node->dirty); … … 93 116 94 117 /* Read the block that contains the dentry of interest. */ 95 b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc,118 rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc, 96 119 (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 120 if (rc != EOK) 121 return rc; 97 122 98 123 d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps); … … 108 133 109 134 b->dirty = true; /* need to sync block */ 110 block_put(b); 111 } 112 113 static fat_node_t *fat_node_get_new(void) 135 rc = block_put(b); 136 return rc; 137 } 138 139 static int fat_node_get_new(fat_node_t **nodepp) 114 140 { 115 141 fs_node_t *fn; 116 142 fat_node_t *nodep; 143 int rc; 117 144 118 145 fibril_mutex_lock(&ffn_mutex); … … 130 157 list_remove(&nodep->ffn_link); 131 158 fibril_mutex_unlock(&ffn_mutex); 132 if (nodep->dirty) 133 fat_node_sync(nodep); 159 if (nodep->dirty) { 160 rc = fat_node_sync(nodep); 161 if (rc != EOK) { 162 idxp_tmp->nodep = NULL; 163 fibril_mutex_unlock(&nodep->lock); 164 fibril_mutex_unlock(&idxp_tmp->lock); 165 free(nodep->bp); 166 free(nodep); 167 return rc; 168 } 169 } 134 170 idxp_tmp->nodep = NULL; 135 171 fibril_mutex_unlock(&nodep->lock); … … 142 178 fn = (fs_node_t *)malloc(sizeof(fs_node_t)); 143 179 if (!fn) 144 return NULL;180 return ENOMEM; 145 181 nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); 146 182 if (!nodep) { 147 183 free(fn); 148 return NULL;184 return ENOMEM; 149 185 } 150 186 } … … 154 190 nodep->bp = fn; 155 191 156 return nodep; 192 *nodepp = nodep; 193 return EOK; 157 194 } 158 195 … … 161 198 * @param idxp Locked index structure. 162 199 */ 163 static fat_node_t *fat_node_get_core(fat_idx_t *idxp)200 static int fat_node_get_core(fat_node_t **nodepp, fat_idx_t *idxp) 164 201 { 165 202 block_t *b; … … 170 207 unsigned spc; 171 208 unsigned dps; 209 int rc; 172 210 173 211 if (idxp->nodep) { … … 177 215 */ 178 216 fibril_mutex_lock(&idxp->nodep->lock); 179 if (!idxp->nodep->refcnt++) 217 if (!idxp->nodep->refcnt++) { 218 fibril_mutex_lock(&ffn_mutex); 180 219 list_remove(&idxp->nodep->ffn_link); 220 fibril_mutex_unlock(&ffn_mutex); 221 } 181 222 fibril_mutex_unlock(&idxp->nodep->lock); 182 return idxp->nodep; 223 *nodepp = idxp->nodep; 224 return EOK; 183 225 } 184 226 … … 189 231 assert(idxp->pfc); 190 232 191 nodep = fat_node_get_new();192 if ( !nodep)193 return NULL;233 rc = fat_node_get_new(&nodep); 234 if (rc != EOK) 235 return rc; 194 236 195 237 bs = block_bb_get(idxp->dev_handle); … … 199 241 200 242 /* Read the block that contains the dentry of interest. */ 201 b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc,243 rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc, 202 244 (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 203 assert(b); 245 if (rc != EOK) { 246 (void) fat_node_put(FS_NODE(nodep)); 247 return rc; 248 } 204 249 205 250 d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps); … … 216 261 * size of the directory by walking the FAT. 217 262 */ 218 nodep->size = bps * spc * fat_clusters_get(bs, idxp->dev_handle, 263 uint16_t clusters; 264 rc = fat_clusters_get(&clusters, bs, idxp->dev_handle, 219 265 uint16_t_le2host(d->firstc)); 266 if (rc != EOK) { 267 (void) fat_node_put(FS_NODE(nodep)); 268 return rc; 269 } 270 nodep->size = bps * spc * clusters; 220 271 } else { 221 272 nodep->type = FAT_FILE; … … 226 277 nodep->refcnt = 1; 227 278 228 block_put(b); 279 rc = block_put(b); 280 if (rc != EOK) { 281 (void) fat_node_put(FS_NODE(nodep)); 282 return rc; 283 } 229 284 230 285 /* Link the idx structure with the node structure. */ … … 232 287 idxp->nodep = nodep; 233 288 234 return nodep; 235 } 236 237 /* 238 * Forward declarations of FAT libfs operations. 239 */ 240 static fs_node_t *fat_node_get(dev_handle_t, fs_index_t); 241 static void fat_node_put(fs_node_t *); 242 static fs_node_t *fat_create_node(dev_handle_t, int); 243 static int fat_destroy_node(fs_node_t *); 244 static int fat_link(fs_node_t *, fs_node_t *, const char *); 245 static int fat_unlink(fs_node_t *, fs_node_t *, const char *); 246 static fs_node_t *fat_match(fs_node_t *, const char *); 247 static fs_index_t fat_index_get(fs_node_t *); 248 static size_t fat_size_get(fs_node_t *); 249 static unsigned fat_lnkcnt_get(fs_node_t *); 250 static bool fat_has_children(fs_node_t *); 251 static fs_node_t *fat_root_get(dev_handle_t); 252 static char fat_plb_get_char(unsigned); 253 static bool fat_is_directory(fs_node_t *); 254 static bool fat_is_file(fs_node_t *node); 289 *nodepp = nodep; 290 return EOK; 291 } 255 292 256 293 /* … … 258 295 */ 259 296 260 /** Instantiate a FAT in-core node. */ 261 fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index) 262 { 263 fat_node_t *nodep; 264 fat_idx_t *idxp; 265 266 idxp = fat_idx_get_by_index(dev_handle, index); 267 if (!idxp) 268 return NULL; 269 /* idxp->lock held */ 270 nodep = fat_node_get_core(idxp); 271 fibril_mutex_unlock(&idxp->lock); 272 return FS_NODE(nodep); 273 } 274 275 void fat_node_put(fs_node_t *fn) 276 { 277 fat_node_t *nodep = FAT_NODE(fn); 278 bool destroy = false; 279 280 fibril_mutex_lock(&nodep->lock); 281 if (!--nodep->refcnt) { 282 if (nodep->idx) { 283 fibril_mutex_lock(&ffn_mutex); 284 list_append(&nodep->ffn_link, &ffn_head); 285 fibril_mutex_unlock(&ffn_mutex); 286 } else { 287 /* 288 * The node does not have any index structure associated 289 * with itself. This can only mean that we are releasing 290 * the node after a failed attempt to allocate the index 291 * structure for it. 292 */ 293 destroy = true; 294 } 295 } 296 fibril_mutex_unlock(&nodep->lock); 297 if (destroy) { 298 free(nodep->bp); 299 free(nodep); 300 } 301 } 302 303 fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags) 304 { 305 fat_idx_t *idxp; 306 fat_node_t *nodep; 307 fat_bs_t *bs; 308 fat_cluster_t mcl, lcl; 309 uint16_t bps; 310 int rc; 311 312 bs = block_bb_get(dev_handle); 313 bps = uint16_t_le2host(bs->bps); 314 if (flags & L_DIRECTORY) { 315 /* allocate a cluster */ 316 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 317 if (rc != EOK) 318 return NULL; 319 } 320 321 nodep = fat_node_get_new(); 322 if (!nodep) { 323 fat_free_clusters(bs, dev_handle, mcl); 324 return NULL; 325 } 326 idxp = fat_idx_get_new(dev_handle); 327 if (!idxp) { 328 fat_free_clusters(bs, dev_handle, mcl); 329 fat_node_put(FS_NODE(nodep)); 330 return NULL; 331 } 332 /* idxp->lock held */ 333 if (flags & L_DIRECTORY) { 334 /* Populate the new cluster with unused dentries. */ 335 fat_zero_cluster(bs, dev_handle, mcl); 336 nodep->type = FAT_DIRECTORY; 337 nodep->firstc = mcl; 338 nodep->size = bps * bs->spc; 339 } else { 340 nodep->type = FAT_FILE; 341 nodep->firstc = FAT_CLST_RES0; 342 nodep->size = 0; 343 } 344 nodep->lnkcnt = 0; /* not linked anywhere */ 345 nodep->refcnt = 1; 346 nodep->dirty = true; 347 348 nodep->idx = idxp; 349 idxp->nodep = nodep; 350 351 fibril_mutex_unlock(&idxp->lock); 352 return FS_NODE(nodep); 353 } 354 355 int fat_destroy_node(fs_node_t *fn) 356 { 357 fat_node_t *nodep = FAT_NODE(fn); 358 fat_bs_t *bs; 359 360 /* 361 * The node is not reachable from the file system. This means that the 362 * link count should be zero and that the index structure cannot be 363 * found in the position hash. Obviously, we don't need to lock the node 364 * nor its index structure. 365 */ 366 assert(nodep->lnkcnt == 0); 367 368 /* 369 * The node may not have any children. 370 */ 371 assert(fat_has_children(fn) == false); 372 373 bs = block_bb_get(nodep->idx->dev_handle); 374 if (nodep->firstc != FAT_CLST_RES0) { 375 assert(nodep->size); 376 /* Free all clusters allocated to the node. */ 377 fat_free_clusters(bs, nodep->idx->dev_handle, nodep->firstc); 378 } 379 380 fat_idx_destroy(nodep->idx); 381 free(nodep->bp); 382 free(nodep); 383 return EOK; 384 } 385 386 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 387 { 388 fat_node_t *parentp = FAT_NODE(pfn); 389 fat_node_t *childp = FAT_NODE(cfn); 390 fat_dentry_t *d; 391 fat_bs_t *bs; 392 block_t *b; 393 unsigned i, j; 394 uint16_t bps; 395 unsigned dps; 396 unsigned blocks; 397 fat_cluster_t mcl, lcl; 398 int rc; 399 400 fibril_mutex_lock(&childp->lock); 401 if (childp->lnkcnt == 1) { 402 /* 403 * On FAT, we don't support multiple hard links. 404 */ 405 fibril_mutex_unlock(&childp->lock); 406 return EMLINK; 407 } 408 assert(childp->lnkcnt == 0); 409 fibril_mutex_unlock(&childp->lock); 410 411 if (!fat_dentry_name_verify(name)) { 412 /* 413 * Attempt to create unsupported name. 414 */ 415 return ENOTSUP; 416 } 417 418 /* 419 * Get us an unused parent node's dentry or grow the parent and allocate 420 * a new one. 421 */ 422 423 fibril_mutex_lock(&parentp->idx->lock); 424 bs = block_bb_get(parentp->idx->dev_handle); 425 bps = uint16_t_le2host(bs->bps); 426 dps = bps / sizeof(fat_dentry_t); 427 428 blocks = parentp->size / bps; 429 430 for (i = 0; i < blocks; i++) { 431 b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); 432 for (j = 0; j < dps; j++) { 433 d = ((fat_dentry_t *)b->data) + j; 434 switch (fat_classify_dentry(d)) { 435 case FAT_DENTRY_SKIP: 436 case FAT_DENTRY_VALID: 437 /* skipping used and meta entries */ 438 continue; 439 case FAT_DENTRY_FREE: 440 case FAT_DENTRY_LAST: 441 /* found an empty slot */ 442 goto hit; 443 } 444 } 445 block_put(b); 446 } 447 j = 0; 448 449 /* 450 * We need to grow the parent in order to create a new unused dentry. 451 */ 452 if (parentp->firstc == FAT_CLST_ROOT) { 453 /* Can't grow the root directory. */ 454 fibril_mutex_unlock(&parentp->idx->lock); 455 return ENOSPC; 456 } 457 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 458 if (rc != EOK) { 459 fibril_mutex_unlock(&parentp->idx->lock); 460 return rc; 461 } 462 fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 463 fat_append_clusters(bs, parentp, mcl); 464 parentp->size += bps * bs->spc; 465 parentp->dirty = true; /* need to sync node */ 466 b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); 467 d = (fat_dentry_t *)b->data; 468 469 hit: 470 /* 471 * At this point we only establish the link between the parent and the 472 * child. The dentry, except of the name and the extension, will remain 473 * uninitialized until the corresponding node is synced. Thus the valid 474 * dentry data is kept in the child node structure. 475 */ 476 memset(d, 0, sizeof(fat_dentry_t)); 477 fat_dentry_name_set(d, name); 478 b->dirty = true; /* need to sync block */ 479 block_put(b); 480 fibril_mutex_unlock(&parentp->idx->lock); 481 482 fibril_mutex_lock(&childp->idx->lock); 483 484 /* 485 * If possible, create the Sub-directory Identifier Entry and the 486 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 487 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 488 * not use them anyway, so this is rather a sign of our good will. 489 */ 490 b = fat_block_get(bs, childp, 0, BLOCK_FLAGS_NONE); 491 d = (fat_dentry_t *)b->data; 492 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 493 str_cmp(d->name, FAT_NAME_DOT) == 0) { 494 memset(d, 0, sizeof(fat_dentry_t)); 495 str_cpy(d->name, 8, FAT_NAME_DOT); 496 str_cpy(d->ext, 3, FAT_EXT_PAD); 497 d->attr = FAT_ATTR_SUBDIR; 498 d->firstc = host2uint16_t_le(childp->firstc); 499 /* TODO: initialize also the date/time members. */ 500 } 501 d++; 502 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 503 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 504 memset(d, 0, sizeof(fat_dentry_t)); 505 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 506 str_cpy(d->ext, 3, FAT_EXT_PAD); 507 d->attr = FAT_ATTR_SUBDIR; 508 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 509 host2uint16_t_le(FAT_CLST_RES0) : 510 host2uint16_t_le(parentp->firstc); 511 /* TODO: initialize also the date/time members. */ 512 } 513 b->dirty = true; /* need to sync block */ 514 block_put(b); 515 516 childp->idx->pfc = parentp->firstc; 517 childp->idx->pdi = i * dps + j; 518 fibril_mutex_unlock(&childp->idx->lock); 519 520 fibril_mutex_lock(&childp->lock); 521 childp->lnkcnt = 1; 522 childp->dirty = true; /* need to sync node */ 523 fibril_mutex_unlock(&childp->lock); 524 525 /* 526 * Hash in the index structure into the position hash. 527 */ 528 fat_idx_hashin(childp->idx); 529 530 return EOK; 531 } 532 533 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 534 { 535 fat_node_t *parentp = FAT_NODE(pfn); 536 fat_node_t *childp = FAT_NODE(cfn); 537 fat_bs_t *bs; 538 fat_dentry_t *d; 539 uint16_t bps; 540 block_t *b; 541 542 if (!parentp) 543 return EBUSY; 544 545 if (fat_has_children(cfn)) 546 return ENOTEMPTY; 547 548 fibril_mutex_lock(&parentp->lock); 549 fibril_mutex_lock(&childp->lock); 550 assert(childp->lnkcnt == 1); 551 fibril_mutex_lock(&childp->idx->lock); 552 bs = block_bb_get(childp->idx->dev_handle); 553 bps = uint16_t_le2host(bs->bps); 554 555 b = _fat_block_get(bs, childp->idx->dev_handle, childp->idx->pfc, 556 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 557 BLOCK_FLAGS_NONE); 558 d = (fat_dentry_t *)b->data + 559 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 560 /* mark the dentry as not-currently-used */ 561 d->name[0] = FAT_DENTRY_ERASED; 562 b->dirty = true; /* need to sync block */ 563 block_put(b); 564 565 /* remove the index structure from the position hash */ 566 fat_idx_hashout(childp->idx); 567 /* clear position information */ 568 childp->idx->pfc = FAT_CLST_RES0; 569 childp->idx->pdi = 0; 570 fibril_mutex_unlock(&childp->idx->lock); 571 childp->lnkcnt = 0; 572 childp->dirty = true; 573 fibril_mutex_unlock(&childp->lock); 574 fibril_mutex_unlock(&parentp->lock); 575 576 return EOK; 577 } 578 579 fs_node_t *fat_match(fs_node_t *pfn, const char *component) 297 int fat_root_get(fs_node_t **rfn, dev_handle_t dev_handle) 298 { 299 return fat_node_get(rfn, dev_handle, 0); 300 } 301 302 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 580 303 { 581 304 fat_bs_t *bs; … … 588 311 fat_dentry_t *d; 589 312 block_t *b; 313 int rc; 590 314 591 315 fibril_mutex_lock(&parentp->idx->lock); … … 595 319 blocks = parentp->size / bps; 596 320 for (i = 0; i < blocks; i++) { 597 b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); 321 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 322 if (rc != EOK) { 323 fibril_mutex_unlock(&parentp->idx->lock); 324 return rc; 325 } 598 326 for (j = 0; j < dps; j++) { 599 327 d = ((fat_dentry_t *)b->data) + j; … … 603 331 continue; 604 332 case FAT_DENTRY_LAST: 605 block_put(b); 333 /* miss */ 334 rc = block_put(b); 606 335 fibril_mutex_unlock(&parentp->idx->lock); 607 return NULL; 336 *rfn = NULL; 337 return rc; 608 338 default: 609 339 case FAT_DENTRY_VALID: … … 629 359 * run out of 32-bit indices. 630 360 */ 631 block_put(b);632 return NULL;361 rc = block_put(b); 362 return (rc == EOK) ? ENOMEM : rc; 633 363 } 634 nodep = fat_node_get_core(idx);364 rc = fat_node_get_core(&nodep, idx); 635 365 fibril_mutex_unlock(&idx->lock); 636 block_put(b); 637 return FS_NODE(nodep); 366 if (rc != EOK) { 367 (void) block_put(b); 368 return rc; 369 } 370 *rfn = FS_NODE(nodep); 371 rc = block_put(b); 372 if (rc != EOK) 373 (void) fat_node_put(*rfn); 374 return rc; 638 375 } 639 376 } 640 block_put(b); 377 rc = block_put(b); 378 if (rc != EOK) { 379 fibril_mutex_unlock(&parentp->idx->lock); 380 return rc; 381 } 641 382 } 642 383 643 384 fibril_mutex_unlock(&parentp->idx->lock); 644 return NULL; 645 } 646 647 fs_index_t fat_index_get(fs_node_t *fn) 648 { 649 return FAT_NODE(fn)->idx->index; 650 } 651 652 size_t fat_size_get(fs_node_t *fn) 653 { 654 return FAT_NODE(fn)->size; 655 } 656 657 unsigned fat_lnkcnt_get(fs_node_t *fn) 658 { 659 return FAT_NODE(fn)->lnkcnt; 660 } 661 662 bool fat_has_children(fs_node_t *fn) 385 *rfn = NULL; 386 return EOK; 387 } 388 389 /** Instantiate a FAT in-core node. */ 390 int fat_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index) 391 { 392 fat_node_t *nodep; 393 fat_idx_t *idxp; 394 int rc; 395 396 idxp = fat_idx_get_by_index(dev_handle, index); 397 if (!idxp) { 398 *rfn = NULL; 399 return EOK; 400 } 401 /* idxp->lock held */ 402 rc = fat_node_get_core(&nodep, idxp); 403 fibril_mutex_unlock(&idxp->lock); 404 if (rc == EOK) 405 *rfn = FS_NODE(nodep); 406 return rc; 407 } 408 409 int fat_node_put(fs_node_t *fn) 410 { 411 fat_node_t *nodep = FAT_NODE(fn); 412 bool destroy = false; 413 414 fibril_mutex_lock(&nodep->lock); 415 if (!--nodep->refcnt) { 416 if (nodep->idx) { 417 fibril_mutex_lock(&ffn_mutex); 418 list_append(&nodep->ffn_link, &ffn_head); 419 fibril_mutex_unlock(&ffn_mutex); 420 } else { 421 /* 422 * The node does not have any index structure associated 423 * with itself. This can only mean that we are releasing 424 * the node after a failed attempt to allocate the index 425 * structure for it. 426 */ 427 destroy = true; 428 } 429 } 430 fibril_mutex_unlock(&nodep->lock); 431 if (destroy) { 432 free(nodep->bp); 433 free(nodep); 434 } 435 return EOK; 436 } 437 438 int fat_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int flags) 439 { 440 fat_idx_t *idxp; 441 fat_node_t *nodep; 442 fat_bs_t *bs; 443 fat_cluster_t mcl, lcl; 444 uint16_t bps; 445 int rc; 446 447 bs = block_bb_get(dev_handle); 448 bps = uint16_t_le2host(bs->bps); 449 if (flags & L_DIRECTORY) { 450 /* allocate a cluster */ 451 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 452 if (rc != EOK) 453 return rc; 454 /* populate the new cluster with unused dentries */ 455 rc = fat_zero_cluster(bs, dev_handle, mcl); 456 if (rc != EOK) { 457 (void) fat_free_clusters(bs, dev_handle, mcl); 458 return rc; 459 } 460 } 461 462 rc = fat_node_get_new(&nodep); 463 if (rc != EOK) { 464 (void) fat_free_clusters(bs, dev_handle, mcl); 465 return rc; 466 } 467 rc = fat_idx_get_new(&idxp, dev_handle); 468 if (rc != EOK) { 469 (void) fat_free_clusters(bs, dev_handle, mcl); 470 (void) fat_node_put(FS_NODE(nodep)); 471 return rc; 472 } 473 /* idxp->lock held */ 474 if (flags & L_DIRECTORY) { 475 nodep->type = FAT_DIRECTORY; 476 nodep->firstc = mcl; 477 nodep->size = bps * bs->spc; 478 } else { 479 nodep->type = FAT_FILE; 480 nodep->firstc = FAT_CLST_RES0; 481 nodep->size = 0; 482 } 483 nodep->lnkcnt = 0; /* not linked anywhere */ 484 nodep->refcnt = 1; 485 nodep->dirty = true; 486 487 nodep->idx = idxp; 488 idxp->nodep = nodep; 489 490 fibril_mutex_unlock(&idxp->lock); 491 *rfn = FS_NODE(nodep); 492 return EOK; 493 } 494 495 int fat_destroy_node(fs_node_t *fn) 496 { 497 fat_node_t *nodep = FAT_NODE(fn); 498 fat_bs_t *bs; 499 bool has_children; 500 int rc; 501 502 /* 503 * The node is not reachable from the file system. This means that the 504 * link count should be zero and that the index structure cannot be 505 * found in the position hash. Obviously, we don't need to lock the node 506 * nor its index structure. 507 */ 508 assert(nodep->lnkcnt == 0); 509 510 /* 511 * The node may not have any children. 512 */ 513 rc = fat_has_children(&has_children, fn); 514 if (rc != EOK) 515 return rc; 516 assert(!has_children); 517 518 bs = block_bb_get(nodep->idx->dev_handle); 519 if (nodep->firstc != FAT_CLST_RES0) { 520 assert(nodep->size); 521 /* Free all clusters allocated to the node. */ 522 rc = fat_free_clusters(bs, nodep->idx->dev_handle, 523 nodep->firstc); 524 } 525 526 fat_idx_destroy(nodep->idx); 527 free(nodep->bp); 528 free(nodep); 529 return rc; 530 } 531 532 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 533 { 534 fat_node_t *parentp = FAT_NODE(pfn); 535 fat_node_t *childp = FAT_NODE(cfn); 536 fat_dentry_t *d; 537 fat_bs_t *bs; 538 block_t *b; 539 unsigned i, j; 540 uint16_t bps; 541 unsigned dps; 542 unsigned blocks; 543 fat_cluster_t mcl, lcl; 544 int rc; 545 546 fibril_mutex_lock(&childp->lock); 547 if (childp->lnkcnt == 1) { 548 /* 549 * On FAT, we don't support multiple hard links. 550 */ 551 fibril_mutex_unlock(&childp->lock); 552 return EMLINK; 553 } 554 assert(childp->lnkcnt == 0); 555 fibril_mutex_unlock(&childp->lock); 556 557 if (!fat_dentry_name_verify(name)) { 558 /* 559 * Attempt to create unsupported name. 560 */ 561 return ENOTSUP; 562 } 563 564 /* 565 * Get us an unused parent node's dentry or grow the parent and allocate 566 * a new one. 567 */ 568 569 fibril_mutex_lock(&parentp->idx->lock); 570 bs = block_bb_get(parentp->idx->dev_handle); 571 bps = uint16_t_le2host(bs->bps); 572 dps = bps / sizeof(fat_dentry_t); 573 574 blocks = parentp->size / bps; 575 576 for (i = 0; i < blocks; i++) { 577 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 578 if (rc != EOK) { 579 fibril_mutex_unlock(&parentp->idx->lock); 580 return rc; 581 } 582 for (j = 0; j < dps; j++) { 583 d = ((fat_dentry_t *)b->data) + j; 584 switch (fat_classify_dentry(d)) { 585 case FAT_DENTRY_SKIP: 586 case FAT_DENTRY_VALID: 587 /* skipping used and meta entries */ 588 continue; 589 case FAT_DENTRY_FREE: 590 case FAT_DENTRY_LAST: 591 /* found an empty slot */ 592 goto hit; 593 } 594 } 595 rc = block_put(b); 596 if (rc != EOK) { 597 fibril_mutex_unlock(&parentp->idx->lock); 598 return rc; 599 } 600 } 601 j = 0; 602 603 /* 604 * We need to grow the parent in order to create a new unused dentry. 605 */ 606 if (parentp->firstc == FAT_CLST_ROOT) { 607 /* Can't grow the root directory. */ 608 fibril_mutex_unlock(&parentp->idx->lock); 609 return ENOSPC; 610 } 611 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 612 if (rc != EOK) { 613 fibril_mutex_unlock(&parentp->idx->lock); 614 return rc; 615 } 616 rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 617 if (rc != EOK) { 618 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 619 fibril_mutex_unlock(&parentp->idx->lock); 620 return rc; 621 } 622 rc = fat_append_clusters(bs, parentp, mcl); 623 if (rc != EOK) { 624 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 625 fibril_mutex_unlock(&parentp->idx->lock); 626 return rc; 627 } 628 parentp->size += bps * bs->spc; 629 parentp->dirty = true; /* need to sync node */ 630 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 631 if (rc != EOK) { 632 fibril_mutex_unlock(&parentp->idx->lock); 633 return rc; 634 } 635 d = (fat_dentry_t *)b->data; 636 637 hit: 638 /* 639 * At this point we only establish the link between the parent and the 640 * child. The dentry, except of the name and the extension, will remain 641 * uninitialized until the corresponding node is synced. Thus the valid 642 * dentry data is kept in the child node structure. 643 */ 644 memset(d, 0, sizeof(fat_dentry_t)); 645 fat_dentry_name_set(d, name); 646 b->dirty = true; /* need to sync block */ 647 rc = block_put(b); 648 fibril_mutex_unlock(&parentp->idx->lock); 649 if (rc != EOK) 650 return rc; 651 652 fibril_mutex_lock(&childp->idx->lock); 653 654 /* 655 * If possible, create the Sub-directory Identifier Entry and the 656 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 657 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 658 * not use them anyway, so this is rather a sign of our good will. 659 */ 660 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 661 if (rc != EOK) { 662 /* 663 * Rather than returning an error, simply skip the creation of 664 * these two entries. 665 */ 666 goto skip_dots; 667 } 668 d = (fat_dentry_t *)b->data; 669 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 670 str_cmp(d->name, FAT_NAME_DOT) == 0) { 671 memset(d, 0, sizeof(fat_dentry_t)); 672 str_cpy(d->name, 8, FAT_NAME_DOT); 673 str_cpy(d->ext, 3, FAT_EXT_PAD); 674 d->attr = FAT_ATTR_SUBDIR; 675 d->firstc = host2uint16_t_le(childp->firstc); 676 /* TODO: initialize also the date/time members. */ 677 } 678 d++; 679 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 680 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 681 memset(d, 0, sizeof(fat_dentry_t)); 682 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 683 str_cpy(d->ext, 3, FAT_EXT_PAD); 684 d->attr = FAT_ATTR_SUBDIR; 685 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 686 host2uint16_t_le(FAT_CLST_RES0) : 687 host2uint16_t_le(parentp->firstc); 688 /* TODO: initialize also the date/time members. */ 689 } 690 b->dirty = true; /* need to sync block */ 691 /* 692 * Ignore the return value as we would have fallen through on error 693 * anyway. 694 */ 695 (void) block_put(b); 696 skip_dots: 697 698 childp->idx->pfc = parentp->firstc; 699 childp->idx->pdi = i * dps + j; 700 fibril_mutex_unlock(&childp->idx->lock); 701 702 fibril_mutex_lock(&childp->lock); 703 childp->lnkcnt = 1; 704 childp->dirty = true; /* need to sync node */ 705 fibril_mutex_unlock(&childp->lock); 706 707 /* 708 * Hash in the index structure into the position hash. 709 */ 710 fat_idx_hashin(childp->idx); 711 712 return EOK; 713 } 714 715 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 716 { 717 fat_node_t *parentp = FAT_NODE(pfn); 718 fat_node_t *childp = FAT_NODE(cfn); 719 fat_bs_t *bs; 720 fat_dentry_t *d; 721 uint16_t bps; 722 block_t *b; 723 bool has_children; 724 int rc; 725 726 if (!parentp) 727 return EBUSY; 728 729 rc = fat_has_children(&has_children, cfn); 730 if (rc != EOK) 731 return rc; 732 if (has_children) 733 return ENOTEMPTY; 734 735 fibril_mutex_lock(&parentp->lock); 736 fibril_mutex_lock(&childp->lock); 737 assert(childp->lnkcnt == 1); 738 fibril_mutex_lock(&childp->idx->lock); 739 bs = block_bb_get(childp->idx->dev_handle); 740 bps = uint16_t_le2host(bs->bps); 741 742 rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc, 743 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 744 BLOCK_FLAGS_NONE); 745 if (rc != EOK) 746 goto error; 747 d = (fat_dentry_t *)b->data + 748 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 749 /* mark the dentry as not-currently-used */ 750 d->name[0] = FAT_DENTRY_ERASED; 751 b->dirty = true; /* need to sync block */ 752 rc = block_put(b); 753 if (rc != EOK) 754 goto error; 755 756 /* remove the index structure from the position hash */ 757 fat_idx_hashout(childp->idx); 758 /* clear position information */ 759 childp->idx->pfc = FAT_CLST_RES0; 760 childp->idx->pdi = 0; 761 fibril_mutex_unlock(&childp->idx->lock); 762 childp->lnkcnt = 0; 763 childp->dirty = true; 764 fibril_mutex_unlock(&childp->lock); 765 fibril_mutex_unlock(&parentp->lock); 766 767 return EOK; 768 769 error: 770 fibril_mutex_unlock(&parentp->idx->lock); 771 fibril_mutex_unlock(&childp->lock); 772 fibril_mutex_unlock(&childp->idx->lock); 773 return rc; 774 } 775 776 int fat_has_children(bool *has_children, fs_node_t *fn) 663 777 { 664 778 fat_bs_t *bs; … … 669 783 block_t *b; 670 784 unsigned i, j; 671 672 if (nodep->type != FAT_DIRECTORY) 673 return false; 785 int rc; 786 787 if (nodep->type != FAT_DIRECTORY) { 788 *has_children = false; 789 return EOK; 790 } 674 791 675 792 fibril_mutex_lock(&nodep->idx->lock); … … 683 800 fat_dentry_t *d; 684 801 685 b = fat_block_get(bs, nodep, i, BLOCK_FLAGS_NONE); 802 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 803 if (rc != EOK) { 804 fibril_mutex_unlock(&nodep->idx->lock); 805 return rc; 806 } 686 807 for (j = 0; j < dps; j++) { 687 808 d = ((fat_dentry_t *)b->data) + j; … … 691 812 continue; 692 813 case FAT_DENTRY_LAST: 693 block_put(b);814 rc = block_put(b); 694 815 fibril_mutex_unlock(&nodep->idx->lock); 695 return false; 816 *has_children = false; 817 return rc; 696 818 default: 697 819 case FAT_DENTRY_VALID: 698 block_put(b);820 rc = block_put(b); 699 821 fibril_mutex_unlock(&nodep->idx->lock); 700 return true; 822 *has_children = true; 823 return rc; 701 824 } 702 block_put(b); 825 } 826 rc = block_put(b); 827 if (rc != EOK) { 703 828 fibril_mutex_unlock(&nodep->idx->lock); 704 return true; 705 } 706 block_put(b); 829 return rc; 830 } 707 831 } 708 832 709 833 fibril_mutex_unlock(&nodep->idx->lock); 710 return false; 711 } 712 713 fs_node_t *fat_root_get(dev_handle_t dev_handle) 714 { 715 return fat_node_get(dev_handle, 0); 834 *has_children = false; 835 return EOK; 836 } 837 838 839 fs_index_t fat_index_get(fs_node_t *fn) 840 { 841 return FAT_NODE(fn)->idx->index; 842 } 843 844 size_t fat_size_get(fs_node_t *fn) 845 { 846 return FAT_NODE(fn)->size; 847 } 848 849 unsigned fat_lnkcnt_get(fs_node_t *fn) 850 { 851 return FAT_NODE(fn)->lnkcnt; 716 852 } 717 853 … … 733 869 /** libfs operations */ 734 870 libfs_ops_t fat_libfs_ops = { 871 .root_get = fat_root_get, 735 872 .match = fat_match, 736 873 .node_get = fat_node_get, … … 740 877 .link = fat_link, 741 878 .unlink = fat_unlink, 879 .has_children = fat_has_children, 742 880 .index_get = fat_index_get, 743 881 .size_get = fat_size_get, 744 882 .lnkcnt_get = fat_lnkcnt_get, 745 .has_children = fat_has_children,746 .root_get = fat_root_get,747 883 .plb_get_char = fat_plb_get_char, 748 884 .is_directory = fat_is_directory, … … 766 902 ipc_callid_t callid; 767 903 size_t size; 768 if (! ipc_data_write_receive(&callid, &size)) {904 if (!async_data_write_receive(&callid, &size)) { 769 905 ipc_answer_0(callid, EINVAL); 770 906 ipc_answer_0(rid, EINVAL); … … 777 913 return; 778 914 } 779 ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);915 ipcarg_t retval = async_data_write_finalize(callid, opts, size); 780 916 if (retval != EOK) { 781 917 ipc_answer_0(rid, retval); … … 799 935 800 936 /* prepare the boot block */ 801 rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE);937 rc = block_bb_read(dev_handle, BS_BLOCK); 802 938 if (rc != EOK) { 803 939 block_fini(dev_handle); … … 895 1031 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 896 1032 off_t pos = (off_t)IPC_GET_ARG3(*request); 897 fs_node_t *fn = fat_node_get(dev_handle, index);1033 fs_node_t *fn; 898 1034 fat_node_t *nodep; 899 1035 fat_bs_t *bs; … … 901 1037 size_t bytes; 902 1038 block_t *b; 903 1039 int rc; 1040 1041 rc = fat_node_get(&fn, dev_handle, index); 1042 if (rc != EOK) { 1043 ipc_answer_0(rid, rc); 1044 return; 1045 } 904 1046 if (!fn) { 905 1047 ipc_answer_0(rid, ENOENT); … … 910 1052 ipc_callid_t callid; 911 1053 size_t len; 912 if (! ipc_data_read_receive(&callid, &len)) {1054 if (!async_data_read_receive(&callid, &len)) { 913 1055 fat_node_put(fn); 914 1056 ipc_answer_0(callid, EINVAL); … … 929 1071 /* reading beyond the EOF */ 930 1072 bytes = 0; 931 (void) ipc_data_read_finalize(callid, NULL, 0);1073 (void) async_data_read_finalize(callid, NULL, 0); 932 1074 } else { 933 1075 bytes = min(len, bps - pos % bps); 934 1076 bytes = min(bytes, nodep->size - pos); 935 b = fat_block_get(bs, nodep, pos / bps,1077 rc = fat_block_get(&b, bs, nodep, pos / bps, 936 1078 BLOCK_FLAGS_NONE); 937 (void) ipc_data_read_finalize(callid, b->data + pos % bps, 1079 if (rc != EOK) { 1080 fat_node_put(fn); 1081 ipc_answer_0(callid, rc); 1082 ipc_answer_0(rid, rc); 1083 return; 1084 } 1085 (void) async_data_read_finalize(callid, b->data + pos % bps, 938 1086 bytes); 939 block_put(b); 1087 rc = block_put(b); 1088 if (rc != EOK) { 1089 fat_node_put(fn); 1090 ipc_answer_0(rid, rc); 1091 return; 1092 } 940 1093 } 941 1094 } else { … … 959 1112 off_t o; 960 1113 961 b = fat_block_get(bs, nodep, bnum, BLOCK_FLAGS_NONE); 1114 rc = fat_block_get(&b, bs, nodep, bnum, 1115 BLOCK_FLAGS_NONE); 1116 if (rc != EOK) 1117 goto err; 962 1118 for (o = pos % (bps / sizeof(fat_dentry_t)); 963 1119 o < bps / sizeof(fat_dentry_t); … … 969 1125 continue; 970 1126 case FAT_DENTRY_LAST: 971 block_put(b); 1127 rc = block_put(b); 1128 if (rc != EOK) 1129 goto err; 972 1130 goto miss; 973 1131 default: 974 1132 case FAT_DENTRY_VALID: 975 1133 fat_dentry_name_get(d, name); 976 block_put(b); 1134 rc = block_put(b); 1135 if (rc != EOK) 1136 goto err; 977 1137 goto hit; 978 1138 } 979 1139 } 980 block_put(b); 1140 rc = block_put(b); 1141 if (rc != EOK) 1142 goto err; 981 1143 bnum++; 982 1144 } 983 1145 miss: 984 fat_node_put(fn); 985 ipc_answer_0(callid, ENOENT); 986 ipc_answer_1(rid, ENOENT, 0); 987 return; 1146 rc = fat_node_put(fn); 1147 ipc_answer_0(callid, rc != EOK ? rc : ENOENT); 1148 ipc_answer_1(rid, rc != EOK ? rc : ENOENT, 0); 1149 return; 1150 1151 err: 1152 (void) fat_node_put(fn); 1153 ipc_answer_0(callid, rc); 1154 ipc_answer_0(rid, rc); 1155 return; 1156 988 1157 hit: 989 (void) ipc_data_read_finalize(callid, name, str_size(name) + 1);1158 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 990 1159 bytes = (pos - spos) + 1; 991 1160 } 992 1161 993 fat_node_put(fn);994 ipc_answer_1(rid, EOK, (ipcarg_t)bytes);1162 rc = fat_node_put(fn); 1163 ipc_answer_1(rid, rc, (ipcarg_t)bytes); 995 1164 } 996 1165 … … 1000 1169 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1001 1170 off_t pos = (off_t)IPC_GET_ARG3(*request); 1002 fs_node_t *fn = fat_node_get(dev_handle, index);1171 fs_node_t *fn; 1003 1172 fat_node_t *nodep; 1004 1173 fat_bs_t *bs; 1005 size_t bytes ;1174 size_t bytes, size; 1006 1175 block_t *b; 1007 1176 uint16_t bps; … … 1010 1179 off_t boundary; 1011 1180 int flags = BLOCK_FLAGS_NONE; 1012 1181 int rc; 1182 1183 rc = fat_node_get(&fn, dev_handle, index); 1184 if (rc != EOK) { 1185 ipc_answer_0(rid, rc); 1186 return; 1187 } 1013 1188 if (!fn) { 1014 1189 ipc_answer_0(rid, ENOENT); … … 1019 1194 ipc_callid_t callid; 1020 1195 size_t len; 1021 if (! ipc_data_write_receive(&callid, &len)) {1022 fat_node_put(fn);1196 if (!async_data_write_receive(&callid, &len)) { 1197 (void) fat_node_put(fn); 1023 1198 ipc_answer_0(callid, EINVAL); 1024 1199 ipc_answer_0(rid, EINVAL); … … 1050 1225 * next block size boundary. 1051 1226 */ 1052 fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); 1053 b = fat_block_get(bs, nodep, pos / bps, flags); 1054 (void) ipc_data_write_finalize(callid, b->data + pos % bps, 1227 rc = fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); 1228 if (rc != EOK) { 1229 (void) fat_node_put(fn); 1230 ipc_answer_0(callid, rc); 1231 ipc_answer_0(rid, rc); 1232 return; 1233 } 1234 rc = fat_block_get(&b, bs, nodep, pos / bps, flags); 1235 if (rc != EOK) { 1236 (void) fat_node_put(fn); 1237 ipc_answer_0(callid, rc); 1238 ipc_answer_0(rid, rc); 1239 return; 1240 } 1241 (void) async_data_write_finalize(callid, b->data + pos % bps, 1055 1242 bytes); 1056 1243 b->dirty = true; /* need to sync block */ 1057 block_put(b); 1244 rc = block_put(b); 1245 if (rc != EOK) { 1246 (void) fat_node_put(fn); 1247 ipc_answer_0(rid, rc); 1248 return; 1249 } 1058 1250 if (pos + bytes > nodep->size) { 1059 1251 nodep->size = pos + bytes; 1060 1252 nodep->dirty = true; /* need to sync node */ 1061 1253 } 1062 ipc_answer_2(rid, EOK, bytes, nodep->size); 1063 fat_node_put(fn); 1254 size = nodep->size; 1255 rc = fat_node_put(fn); 1256 ipc_answer_2(rid, rc, bytes, nodep->size); 1064 1257 return; 1065 1258 } else { … … 1068 1261 * clusters for the node and zero them out. 1069 1262 */ 1070 int status;1071 1263 unsigned nclsts; 1072 1264 fat_cluster_t mcl, lcl; … … 1074 1266 nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc; 1075 1267 /* create an independent chain of nclsts clusters in all FATs */ 1076 status= fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);1077 if ( status!= EOK) {1268 rc = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); 1269 if (rc != EOK) { 1078 1270 /* could not allocate a chain of nclsts clusters */ 1079 fat_node_put(fn);1080 ipc_answer_0(callid, status);1081 ipc_answer_0(rid, status);1271 (void) fat_node_put(fn); 1272 ipc_answer_0(callid, rc); 1273 ipc_answer_0(rid, rc); 1082 1274 return; 1083 1275 } 1084 1276 /* zero fill any gaps */ 1085 fat_fill_gap(bs, nodep, mcl, pos); 1086 b = _fat_block_get(bs, dev_handle, lcl, (pos / bps) % spc, 1277 rc = fat_fill_gap(bs, nodep, mcl, pos); 1278 if (rc != EOK) { 1279 (void) fat_free_clusters(bs, dev_handle, mcl); 1280 (void) fat_node_put(fn); 1281 ipc_answer_0(callid, rc); 1282 ipc_answer_0(rid, rc); 1283 return; 1284 } 1285 rc = _fat_block_get(&b, bs, dev_handle, lcl, (pos / bps) % spc, 1087 1286 flags); 1088 (void) ipc_data_write_finalize(callid, b->data + pos % bps, 1287 if (rc != EOK) { 1288 (void) fat_free_clusters(bs, dev_handle, mcl); 1289 (void) fat_node_put(fn); 1290 ipc_answer_0(callid, rc); 1291 ipc_answer_0(rid, rc); 1292 return; 1293 } 1294 (void) async_data_write_finalize(callid, b->data + pos % bps, 1089 1295 bytes); 1090 1296 b->dirty = true; /* need to sync block */ 1091 block_put(b); 1297 rc = block_put(b); 1298 if (rc != EOK) { 1299 (void) fat_free_clusters(bs, dev_handle, mcl); 1300 (void) fat_node_put(fn); 1301 ipc_answer_0(rid, rc); 1302 return; 1303 } 1092 1304 /* 1093 1305 * Append the cluster chain starting in mcl to the end of the 1094 1306 * node's cluster chain. 1095 1307 */ 1096 fat_append_clusters(bs, nodep, mcl); 1097 nodep->size = pos + bytes; 1308 rc = fat_append_clusters(bs, nodep, mcl); 1309 if (rc != EOK) { 1310 (void) fat_free_clusters(bs, dev_handle, mcl); 1311 (void) fat_node_put(fn); 1312 ipc_answer_0(rid, rc); 1313 return; 1314 } 1315 nodep->size = size = pos + bytes; 1098 1316 nodep->dirty = true; /* need to sync node */ 1099 ipc_answer_2(rid, EOK, bytes, nodep->size);1100 fat_node_put(fn);1317 rc = fat_node_put(fn); 1318 ipc_answer_2(rid, rc, bytes, size); 1101 1319 return; 1102 1320 } … … 1108 1326 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1109 1327 size_t size = (off_t)IPC_GET_ARG3(*request); 1110 fs_node_t *fn = fat_node_get(dev_handle, index);1328 fs_node_t *fn; 1111 1329 fat_node_t *nodep; 1112 1330 fat_bs_t *bs; … … 1116 1334 int rc; 1117 1335 1336 rc = fat_node_get(&fn, dev_handle, index); 1337 if (rc != EOK) { 1338 ipc_answer_0(rid, rc); 1339 return; 1340 } 1118 1341 if (!fn) { 1119 1342 ipc_answer_0(rid, ENOENT); … … 1147 1370 */ 1148 1371 if (size == 0) { 1149 fat_chop_clusters(bs, nodep, FAT_CLST_RES0); 1372 rc = fat_chop_clusters(bs, nodep, FAT_CLST_RES0); 1373 if (rc != EOK) 1374 goto out; 1150 1375 } else { 1151 1376 fat_cluster_t lastc; 1152 (void) fat_cluster_walk(bs, dev_handle, nodep->firstc, 1153 &lastc, (size - 1) / bpc); 1154 fat_chop_clusters(bs, nodep, lastc); 1377 rc = fat_cluster_walk(bs, dev_handle, nodep->firstc, 1378 &lastc, NULL, (size - 1) / bpc); 1379 if (rc != EOK) 1380 goto out; 1381 rc = fat_chop_clusters(bs, nodep, lastc); 1382 if (rc != EOK) 1383 goto out; 1155 1384 } 1156 1385 nodep->size = size; … … 1158 1387 rc = EOK; 1159 1388 } 1389 out: 1160 1390 fat_node_put(fn); 1161 1391 ipc_answer_0(rid, rc); … … 1172 1402 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1173 1403 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1404 fs_node_t *fn; 1174 1405 int rc; 1175 1406 1176 fs_node_t *fn = fat_node_get(dev_handle, index); 1407 rc = fat_node_get(&fn, dev_handle, index); 1408 if (rc != EOK) { 1409 ipc_answer_0(rid, rc); 1410 return; 1411 } 1177 1412 if (!fn) { 1178 1413 ipc_answer_0(rid, ENOENT);
Note:
See TracChangeset
for help on using the changeset viewer.