Changes in uspace/srv/fs/fat/fat_ops.c [cca29e3c:1313ee9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
rcca29e3c r1313ee9 52 52 #include <adt/list.h> 53 53 #include <assert.h> 54 #include <fibril_sync .h>54 #include <fibril_synch.h> 55 55 #include <sys/mman.h> 56 56 #include <align.h> … … 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_open(fs_node_t *); 74 static int fat_node_put(fs_node_t *); 75 static int fat_create_node(fs_node_t **, dev_handle_t, int); 76 static int fat_destroy_node(fs_node_t *); 77 static int fat_link(fs_node_t *, fs_node_t *, const char *); 78 static int fat_unlink(fs_node_t *, fs_node_t *, const char *); 79 static int fat_has_children(bool *, fs_node_t *); 80 static fs_index_t fat_index_get(fs_node_t *); 81 static size_t fat_size_get(fs_node_t *); 82 static unsigned fat_lnkcnt_get(fs_node_t *); 83 static char fat_plb_get_char(unsigned); 84 static bool fat_is_directory(fs_node_t *); 85 static bool fat_is_file(fs_node_t *node); 86 static dev_handle_t fat_device_get(fs_node_t *node); 87 88 /* 89 * Helper functions. 90 */ 67 91 static void fat_node_initialize(fat_node_t *node) 68 92 { … … 78 102 } 79 103 80 static voidfat_node_sync(fat_node_t *node)104 static int fat_node_sync(fat_node_t *node) 81 105 { 82 106 block_t *b; … … 96 120 rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc, 97 121 (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 98 assert(rc == EOK); 122 if (rc != EOK) 123 return rc; 99 124 100 125 d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps); … … 111 136 b->dirty = true; /* need to sync block */ 112 137 rc = block_put(b); 113 assert(rc == EOK);114 } 115 116 static fat_node_t *fat_node_get_new(void)138 return rc; 139 } 140 141 static int fat_node_get_new(fat_node_t **nodepp) 117 142 { 118 143 fs_node_t *fn; 119 144 fat_node_t *nodep; 145 int rc; 120 146 121 147 fibril_mutex_lock(&ffn_mutex); … … 133 159 list_remove(&nodep->ffn_link); 134 160 fibril_mutex_unlock(&ffn_mutex); 135 if (nodep->dirty) 136 fat_node_sync(nodep); 161 if (nodep->dirty) { 162 rc = fat_node_sync(nodep); 163 if (rc != EOK) { 164 idxp_tmp->nodep = NULL; 165 fibril_mutex_unlock(&nodep->lock); 166 fibril_mutex_unlock(&idxp_tmp->lock); 167 free(nodep->bp); 168 free(nodep); 169 return rc; 170 } 171 } 137 172 idxp_tmp->nodep = NULL; 138 173 fibril_mutex_unlock(&nodep->lock); … … 145 180 fn = (fs_node_t *)malloc(sizeof(fs_node_t)); 146 181 if (!fn) 147 return NULL;182 return ENOMEM; 148 183 nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); 149 184 if (!nodep) { 150 185 free(fn); 151 return NULL;186 return ENOMEM; 152 187 } 153 188 } … … 157 192 nodep->bp = fn; 158 193 159 return nodep; 194 *nodepp = nodep; 195 return EOK; 160 196 } 161 197 … … 164 200 * @param idxp Locked index structure. 165 201 */ 166 static fat_node_t *fat_node_get_core(fat_idx_t *idxp)202 static int fat_node_get_core(fat_node_t **nodepp, fat_idx_t *idxp) 167 203 { 168 204 block_t *b; … … 181 217 */ 182 218 fibril_mutex_lock(&idxp->nodep->lock); 183 if (!idxp->nodep->refcnt++) 219 if (!idxp->nodep->refcnt++) { 220 fibril_mutex_lock(&ffn_mutex); 184 221 list_remove(&idxp->nodep->ffn_link); 222 fibril_mutex_unlock(&ffn_mutex); 223 } 185 224 fibril_mutex_unlock(&idxp->nodep->lock); 186 return idxp->nodep; 225 *nodepp = idxp->nodep; 226 return EOK; 187 227 } 188 228 … … 193 233 assert(idxp->pfc); 194 234 195 nodep = fat_node_get_new();196 if ( !nodep)197 return NULL;235 rc = fat_node_get_new(&nodep); 236 if (rc != EOK) 237 return rc; 198 238 199 239 bs = block_bb_get(idxp->dev_handle); … … 205 245 rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc, 206 246 (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 207 assert(rc == EOK); 247 if (rc != EOK) { 248 (void) fat_node_put(FS_NODE(nodep)); 249 return rc; 250 } 208 251 209 252 d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps); … … 223 266 rc = fat_clusters_get(&clusters, bs, idxp->dev_handle, 224 267 uint16_t_le2host(d->firstc)); 225 assert(rc == EOK); 268 if (rc != EOK) { 269 (void) fat_node_put(FS_NODE(nodep)); 270 return rc; 271 } 226 272 nodep->size = bps * spc * clusters; 227 273 } else { … … 234 280 235 281 rc = block_put(b); 236 assert(rc == EOK); 282 if (rc != EOK) { 283 (void) fat_node_put(FS_NODE(nodep)); 284 return rc; 285 } 237 286 238 287 /* Link the idx structure with the node structure. */ … … 240 289 idxp->nodep = nodep; 241 290 242 return nodep; 243 } 244 245 /* 246 * Forward declarations of FAT libfs operations. 247 */ 248 static fs_node_t *fat_node_get(dev_handle_t, fs_index_t); 249 static void fat_node_put(fs_node_t *); 250 static fs_node_t *fat_create_node(dev_handle_t, int); 251 static int fat_destroy_node(fs_node_t *); 252 static int fat_link(fs_node_t *, fs_node_t *, const char *); 253 static int fat_unlink(fs_node_t *, fs_node_t *, const char *); 254 static fs_node_t *fat_match(fs_node_t *, const char *); 255 static fs_index_t fat_index_get(fs_node_t *); 256 static size_t fat_size_get(fs_node_t *); 257 static unsigned fat_lnkcnt_get(fs_node_t *); 258 static bool fat_has_children(fs_node_t *); 259 static fs_node_t *fat_root_get(dev_handle_t); 260 static char fat_plb_get_char(unsigned); 261 static bool fat_is_directory(fs_node_t *); 262 static bool fat_is_file(fs_node_t *node); 291 *nodepp = nodep; 292 return EOK; 293 } 263 294 264 295 /* … … 266 297 */ 267 298 268 /** Instantiate a FAT in-core node. */ 269 fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index) 270 { 271 fat_node_t *nodep; 272 fat_idx_t *idxp; 273 274 idxp = fat_idx_get_by_index(dev_handle, index); 275 if (!idxp) 276 return NULL; 277 /* idxp->lock held */ 278 nodep = fat_node_get_core(idxp); 279 fibril_mutex_unlock(&idxp->lock); 280 return FS_NODE(nodep); 281 } 282 283 void fat_node_put(fs_node_t *fn) 284 { 285 fat_node_t *nodep = FAT_NODE(fn); 286 bool destroy = false; 287 288 fibril_mutex_lock(&nodep->lock); 289 if (!--nodep->refcnt) { 290 if (nodep->idx) { 291 fibril_mutex_lock(&ffn_mutex); 292 list_append(&nodep->ffn_link, &ffn_head); 293 fibril_mutex_unlock(&ffn_mutex); 294 } else { 295 /* 296 * The node does not have any index structure associated 297 * with itself. This can only mean that we are releasing 298 * the node after a failed attempt to allocate the index 299 * structure for it. 300 */ 301 destroy = true; 302 } 303 } 304 fibril_mutex_unlock(&nodep->lock); 305 if (destroy) { 306 free(nodep->bp); 307 free(nodep); 308 } 309 } 310 311 fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags) 312 { 313 fat_idx_t *idxp; 314 fat_node_t *nodep; 315 fat_bs_t *bs; 316 fat_cluster_t mcl, lcl; 317 uint16_t bps; 318 int rc; 319 320 bs = block_bb_get(dev_handle); 321 bps = uint16_t_le2host(bs->bps); 322 if (flags & L_DIRECTORY) { 323 /* allocate a cluster */ 324 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 325 if (rc != EOK) 326 return NULL; 327 } 328 329 nodep = fat_node_get_new(); 330 if (!nodep) { 331 (void) fat_free_clusters(bs, dev_handle, mcl); 332 return NULL; 333 } 334 idxp = fat_idx_get_new(dev_handle); 335 if (!idxp) { 336 (void) fat_free_clusters(bs, dev_handle, mcl); 337 fat_node_put(FS_NODE(nodep)); 338 return NULL; 339 } 340 /* idxp->lock held */ 341 if (flags & L_DIRECTORY) { 342 /* Populate the new cluster with unused dentries. */ 343 rc = fat_zero_cluster(bs, dev_handle, mcl); 344 assert(rc == EOK); 345 nodep->type = FAT_DIRECTORY; 346 nodep->firstc = mcl; 347 nodep->size = bps * bs->spc; 348 } else { 349 nodep->type = FAT_FILE; 350 nodep->firstc = FAT_CLST_RES0; 351 nodep->size = 0; 352 } 353 nodep->lnkcnt = 0; /* not linked anywhere */ 354 nodep->refcnt = 1; 355 nodep->dirty = true; 356 357 nodep->idx = idxp; 358 idxp->nodep = nodep; 359 360 fibril_mutex_unlock(&idxp->lock); 361 return FS_NODE(nodep); 362 } 363 364 int fat_destroy_node(fs_node_t *fn) 365 { 366 fat_node_t *nodep = FAT_NODE(fn); 367 fat_bs_t *bs; 368 int rc = EOK; 369 370 /* 371 * The node is not reachable from the file system. This means that the 372 * link count should be zero and that the index structure cannot be 373 * found in the position hash. Obviously, we don't need to lock the node 374 * nor its index structure. 375 */ 376 assert(nodep->lnkcnt == 0); 377 378 /* 379 * The node may not have any children. 380 */ 381 assert(fat_has_children(fn) == false); 382 383 bs = block_bb_get(nodep->idx->dev_handle); 384 if (nodep->firstc != FAT_CLST_RES0) { 385 assert(nodep->size); 386 /* Free all clusters allocated to the node. */ 387 rc = fat_free_clusters(bs, nodep->idx->dev_handle, 388 nodep->firstc); 389 } 390 391 fat_idx_destroy(nodep->idx); 392 free(nodep->bp); 393 free(nodep); 394 return rc; 395 } 396 397 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 398 { 399 fat_node_t *parentp = FAT_NODE(pfn); 400 fat_node_t *childp = FAT_NODE(cfn); 401 fat_dentry_t *d; 402 fat_bs_t *bs; 403 block_t *b; 404 unsigned i, j; 405 uint16_t bps; 406 unsigned dps; 407 unsigned blocks; 408 fat_cluster_t mcl, lcl; 409 int rc; 410 411 fibril_mutex_lock(&childp->lock); 412 if (childp->lnkcnt == 1) { 413 /* 414 * On FAT, we don't support multiple hard links. 415 */ 416 fibril_mutex_unlock(&childp->lock); 417 return EMLINK; 418 } 419 assert(childp->lnkcnt == 0); 420 fibril_mutex_unlock(&childp->lock); 421 422 if (!fat_dentry_name_verify(name)) { 423 /* 424 * Attempt to create unsupported name. 425 */ 426 return ENOTSUP; 427 } 428 429 /* 430 * Get us an unused parent node's dentry or grow the parent and allocate 431 * a new one. 432 */ 433 434 fibril_mutex_lock(&parentp->idx->lock); 435 bs = block_bb_get(parentp->idx->dev_handle); 436 bps = uint16_t_le2host(bs->bps); 437 dps = bps / sizeof(fat_dentry_t); 438 439 blocks = parentp->size / bps; 440 441 for (i = 0; i < blocks; i++) { 442 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 443 assert(rc == EOK); 444 for (j = 0; j < dps; j++) { 445 d = ((fat_dentry_t *)b->data) + j; 446 switch (fat_classify_dentry(d)) { 447 case FAT_DENTRY_SKIP: 448 case FAT_DENTRY_VALID: 449 /* skipping used and meta entries */ 450 continue; 451 case FAT_DENTRY_FREE: 452 case FAT_DENTRY_LAST: 453 /* found an empty slot */ 454 goto hit; 455 } 456 } 457 rc = block_put(b); 458 assert(rc == EOK); 459 } 460 j = 0; 461 462 /* 463 * We need to grow the parent in order to create a new unused dentry. 464 */ 465 if (parentp->firstc == FAT_CLST_ROOT) { 466 /* Can't grow the root directory. */ 467 fibril_mutex_unlock(&parentp->idx->lock); 468 return ENOSPC; 469 } 470 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 471 if (rc != EOK) { 472 fibril_mutex_unlock(&parentp->idx->lock); 473 return rc; 474 } 475 rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 476 assert(rc == EOK); 477 rc = fat_append_clusters(bs, parentp, mcl); 478 assert(rc == EOK); 479 parentp->size += bps * bs->spc; 480 parentp->dirty = true; /* need to sync node */ 481 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 482 assert(rc == EOK); 483 d = (fat_dentry_t *)b->data; 484 485 hit: 486 /* 487 * At this point we only establish the link between the parent and the 488 * child. The dentry, except of the name and the extension, will remain 489 * uninitialized until the corresponding node is synced. Thus the valid 490 * dentry data is kept in the child node structure. 491 */ 492 memset(d, 0, sizeof(fat_dentry_t)); 493 fat_dentry_name_set(d, name); 494 b->dirty = true; /* need to sync block */ 495 rc = block_put(b); 496 assert(rc == EOK); 497 fibril_mutex_unlock(&parentp->idx->lock); 498 499 fibril_mutex_lock(&childp->idx->lock); 500 501 /* 502 * If possible, create the Sub-directory Identifier Entry and the 503 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 504 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 505 * not use them anyway, so this is rather a sign of our good will. 506 */ 507 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 508 assert(rc == EOK); 509 d = (fat_dentry_t *)b->data; 510 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 511 str_cmp(d->name, FAT_NAME_DOT) == 0) { 512 memset(d, 0, sizeof(fat_dentry_t)); 513 str_cpy(d->name, 8, FAT_NAME_DOT); 514 str_cpy(d->ext, 3, FAT_EXT_PAD); 515 d->attr = FAT_ATTR_SUBDIR; 516 d->firstc = host2uint16_t_le(childp->firstc); 517 /* TODO: initialize also the date/time members. */ 518 } 519 d++; 520 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 521 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 522 memset(d, 0, sizeof(fat_dentry_t)); 523 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 524 str_cpy(d->ext, 3, FAT_EXT_PAD); 525 d->attr = FAT_ATTR_SUBDIR; 526 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 527 host2uint16_t_le(FAT_CLST_RES0) : 528 host2uint16_t_le(parentp->firstc); 529 /* TODO: initialize also the date/time members. */ 530 } 531 b->dirty = true; /* need to sync block */ 532 rc = block_put(b); 533 assert(rc == EOK); 534 535 childp->idx->pfc = parentp->firstc; 536 childp->idx->pdi = i * dps + j; 537 fibril_mutex_unlock(&childp->idx->lock); 538 539 fibril_mutex_lock(&childp->lock); 540 childp->lnkcnt = 1; 541 childp->dirty = true; /* need to sync node */ 542 fibril_mutex_unlock(&childp->lock); 543 544 /* 545 * Hash in the index structure into the position hash. 546 */ 547 fat_idx_hashin(childp->idx); 548 549 return EOK; 550 } 551 552 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 553 { 554 fat_node_t *parentp = FAT_NODE(pfn); 555 fat_node_t *childp = FAT_NODE(cfn); 556 fat_bs_t *bs; 557 fat_dentry_t *d; 558 uint16_t bps; 559 block_t *b; 560 int rc; 561 562 if (!parentp) 563 return EBUSY; 564 565 if (fat_has_children(cfn)) 566 return ENOTEMPTY; 567 568 fibril_mutex_lock(&parentp->lock); 569 fibril_mutex_lock(&childp->lock); 570 assert(childp->lnkcnt == 1); 571 fibril_mutex_lock(&childp->idx->lock); 572 bs = block_bb_get(childp->idx->dev_handle); 573 bps = uint16_t_le2host(bs->bps); 574 575 rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc, 576 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 577 BLOCK_FLAGS_NONE); 578 assert(rc == EOK); 579 d = (fat_dentry_t *)b->data + 580 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 581 /* mark the dentry as not-currently-used */ 582 d->name[0] = FAT_DENTRY_ERASED; 583 b->dirty = true; /* need to sync block */ 584 rc = block_put(b); 585 assert(rc == EOK); 586 587 /* remove the index structure from the position hash */ 588 fat_idx_hashout(childp->idx); 589 /* clear position information */ 590 childp->idx->pfc = FAT_CLST_RES0; 591 childp->idx->pdi = 0; 592 fibril_mutex_unlock(&childp->idx->lock); 593 childp->lnkcnt = 0; 594 childp->dirty = true; 595 fibril_mutex_unlock(&childp->lock); 596 fibril_mutex_unlock(&parentp->lock); 597 598 return EOK; 599 } 600 601 fs_node_t *fat_match(fs_node_t *pfn, const char *component) 299 int fat_root_get(fs_node_t **rfn, dev_handle_t dev_handle) 300 { 301 return fat_node_get(rfn, dev_handle, 0); 302 } 303 304 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 602 305 { 603 306 fat_bs_t *bs; … … 619 322 for (i = 0; i < blocks; i++) { 620 323 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 621 assert(rc == EOK); 324 if (rc != EOK) { 325 fibril_mutex_unlock(&parentp->idx->lock); 326 return rc; 327 } 622 328 for (j = 0; j < dps; j++) { 623 329 d = ((fat_dentry_t *)b->data) + j; … … 627 333 continue; 628 334 case FAT_DENTRY_LAST: 335 /* miss */ 629 336 rc = block_put(b); 630 assert(rc == EOK);631 337 fibril_mutex_unlock(&parentp->idx->lock); 632 return NULL; 338 *rfn = NULL; 339 return rc; 633 340 default: 634 341 case FAT_DENTRY_VALID: … … 655 362 */ 656 363 rc = block_put(b); 657 assert(rc == EOK); 658 return NULL; 364 return (rc == EOK) ? ENOMEM : rc; 659 365 } 660 nodep = fat_node_get_core(idx);366 rc = fat_node_get_core(&nodep, idx); 661 367 fibril_mutex_unlock(&idx->lock); 368 if (rc != EOK) { 369 (void) block_put(b); 370 return rc; 371 } 372 *rfn = FS_NODE(nodep); 662 373 rc = block_put(b); 663 assert(rc == EOK); 664 return FS_NODE(nodep); 374 if (rc != EOK) 375 (void) fat_node_put(*rfn); 376 return rc; 665 377 } 666 378 } 667 379 rc = block_put(b); 668 assert(rc == EOK); 380 if (rc != EOK) { 381 fibril_mutex_unlock(&parentp->idx->lock); 382 return rc; 383 } 669 384 } 670 385 671 386 fibril_mutex_unlock(&parentp->idx->lock); 672 return NULL; 673 } 674 675 fs_index_t fat_index_get(fs_node_t *fn) 676 { 677 return FAT_NODE(fn)->idx->index; 678 } 679 680 size_t fat_size_get(fs_node_t *fn) 681 { 682 return FAT_NODE(fn)->size; 683 } 684 685 unsigned fat_lnkcnt_get(fs_node_t *fn) 686 { 687 return FAT_NODE(fn)->lnkcnt; 688 } 689 690 bool fat_has_children(fs_node_t *fn) 387 *rfn = NULL; 388 return EOK; 389 } 390 391 /** Instantiate a FAT in-core node. */ 392 int fat_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index) 393 { 394 fat_node_t *nodep; 395 fat_idx_t *idxp; 396 int rc; 397 398 idxp = fat_idx_get_by_index(dev_handle, index); 399 if (!idxp) { 400 *rfn = NULL; 401 return EOK; 402 } 403 /* idxp->lock held */ 404 rc = fat_node_get_core(&nodep, idxp); 405 fibril_mutex_unlock(&idxp->lock); 406 if (rc == EOK) 407 *rfn = FS_NODE(nodep); 408 return rc; 409 } 410 411 int fat_node_open(fs_node_t *fn) 412 { 413 /* 414 * Opening a file is stateless, nothing 415 * to be done here. 416 */ 417 return EOK; 418 } 419 420 int fat_node_put(fs_node_t *fn) 421 { 422 fat_node_t *nodep = FAT_NODE(fn); 423 bool destroy = false; 424 425 fibril_mutex_lock(&nodep->lock); 426 if (!--nodep->refcnt) { 427 if (nodep->idx) { 428 fibril_mutex_lock(&ffn_mutex); 429 list_append(&nodep->ffn_link, &ffn_head); 430 fibril_mutex_unlock(&ffn_mutex); 431 } else { 432 /* 433 * The node does not have any index structure associated 434 * with itself. This can only mean that we are releasing 435 * the node after a failed attempt to allocate the index 436 * structure for it. 437 */ 438 destroy = true; 439 } 440 } 441 fibril_mutex_unlock(&nodep->lock); 442 if (destroy) { 443 free(nodep->bp); 444 free(nodep); 445 } 446 return EOK; 447 } 448 449 int fat_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int flags) 450 { 451 fat_idx_t *idxp; 452 fat_node_t *nodep; 453 fat_bs_t *bs; 454 fat_cluster_t mcl, lcl; 455 uint16_t bps; 456 int rc; 457 458 bs = block_bb_get(dev_handle); 459 bps = uint16_t_le2host(bs->bps); 460 if (flags & L_DIRECTORY) { 461 /* allocate a cluster */ 462 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 463 if (rc != EOK) 464 return rc; 465 /* populate the new cluster with unused dentries */ 466 rc = fat_zero_cluster(bs, dev_handle, mcl); 467 if (rc != EOK) { 468 (void) fat_free_clusters(bs, dev_handle, mcl); 469 return rc; 470 } 471 } 472 473 rc = fat_node_get_new(&nodep); 474 if (rc != EOK) { 475 (void) fat_free_clusters(bs, dev_handle, mcl); 476 return rc; 477 } 478 rc = fat_idx_get_new(&idxp, dev_handle); 479 if (rc != EOK) { 480 (void) fat_free_clusters(bs, dev_handle, mcl); 481 (void) fat_node_put(FS_NODE(nodep)); 482 return rc; 483 } 484 /* idxp->lock held */ 485 if (flags & L_DIRECTORY) { 486 nodep->type = FAT_DIRECTORY; 487 nodep->firstc = mcl; 488 nodep->size = bps * bs->spc; 489 } else { 490 nodep->type = FAT_FILE; 491 nodep->firstc = FAT_CLST_RES0; 492 nodep->size = 0; 493 } 494 nodep->lnkcnt = 0; /* not linked anywhere */ 495 nodep->refcnt = 1; 496 nodep->dirty = true; 497 498 nodep->idx = idxp; 499 idxp->nodep = nodep; 500 501 fibril_mutex_unlock(&idxp->lock); 502 *rfn = FS_NODE(nodep); 503 return EOK; 504 } 505 506 int fat_destroy_node(fs_node_t *fn) 507 { 508 fat_node_t *nodep = FAT_NODE(fn); 509 fat_bs_t *bs; 510 bool has_children; 511 int rc; 512 513 /* 514 * The node is not reachable from the file system. This means that the 515 * link count should be zero and that the index structure cannot be 516 * found in the position hash. Obviously, we don't need to lock the node 517 * nor its index structure. 518 */ 519 assert(nodep->lnkcnt == 0); 520 521 /* 522 * The node may not have any children. 523 */ 524 rc = fat_has_children(&has_children, fn); 525 if (rc != EOK) 526 return rc; 527 assert(!has_children); 528 529 bs = block_bb_get(nodep->idx->dev_handle); 530 if (nodep->firstc != FAT_CLST_RES0) { 531 assert(nodep->size); 532 /* Free all clusters allocated to the node. */ 533 rc = fat_free_clusters(bs, nodep->idx->dev_handle, 534 nodep->firstc); 535 } 536 537 fat_idx_destroy(nodep->idx); 538 free(nodep->bp); 539 free(nodep); 540 return rc; 541 } 542 543 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 544 { 545 fat_node_t *parentp = FAT_NODE(pfn); 546 fat_node_t *childp = FAT_NODE(cfn); 547 fat_dentry_t *d; 548 fat_bs_t *bs; 549 block_t *b; 550 unsigned i, j; 551 uint16_t bps; 552 unsigned dps; 553 unsigned blocks; 554 fat_cluster_t mcl, lcl; 555 int rc; 556 557 fibril_mutex_lock(&childp->lock); 558 if (childp->lnkcnt == 1) { 559 /* 560 * On FAT, we don't support multiple hard links. 561 */ 562 fibril_mutex_unlock(&childp->lock); 563 return EMLINK; 564 } 565 assert(childp->lnkcnt == 0); 566 fibril_mutex_unlock(&childp->lock); 567 568 if (!fat_dentry_name_verify(name)) { 569 /* 570 * Attempt to create unsupported name. 571 */ 572 return ENOTSUP; 573 } 574 575 /* 576 * Get us an unused parent node's dentry or grow the parent and allocate 577 * a new one. 578 */ 579 580 fibril_mutex_lock(&parentp->idx->lock); 581 bs = block_bb_get(parentp->idx->dev_handle); 582 bps = uint16_t_le2host(bs->bps); 583 dps = bps / sizeof(fat_dentry_t); 584 585 blocks = parentp->size / bps; 586 587 for (i = 0; i < blocks; i++) { 588 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 589 if (rc != EOK) { 590 fibril_mutex_unlock(&parentp->idx->lock); 591 return rc; 592 } 593 for (j = 0; j < dps; j++) { 594 d = ((fat_dentry_t *)b->data) + j; 595 switch (fat_classify_dentry(d)) { 596 case FAT_DENTRY_SKIP: 597 case FAT_DENTRY_VALID: 598 /* skipping used and meta entries */ 599 continue; 600 case FAT_DENTRY_FREE: 601 case FAT_DENTRY_LAST: 602 /* found an empty slot */ 603 goto hit; 604 } 605 } 606 rc = block_put(b); 607 if (rc != EOK) { 608 fibril_mutex_unlock(&parentp->idx->lock); 609 return rc; 610 } 611 } 612 j = 0; 613 614 /* 615 * We need to grow the parent in order to create a new unused dentry. 616 */ 617 if (parentp->firstc == FAT_CLST_ROOT) { 618 /* Can't grow the root directory. */ 619 fibril_mutex_unlock(&parentp->idx->lock); 620 return ENOSPC; 621 } 622 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 623 if (rc != EOK) { 624 fibril_mutex_unlock(&parentp->idx->lock); 625 return rc; 626 } 627 rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 628 if (rc != EOK) { 629 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 630 fibril_mutex_unlock(&parentp->idx->lock); 631 return rc; 632 } 633 rc = fat_append_clusters(bs, parentp, mcl); 634 if (rc != EOK) { 635 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 636 fibril_mutex_unlock(&parentp->idx->lock); 637 return rc; 638 } 639 parentp->size += bps * bs->spc; 640 parentp->dirty = true; /* need to sync node */ 641 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 642 if (rc != EOK) { 643 fibril_mutex_unlock(&parentp->idx->lock); 644 return rc; 645 } 646 d = (fat_dentry_t *)b->data; 647 648 hit: 649 /* 650 * At this point we only establish the link between the parent and the 651 * child. The dentry, except of the name and the extension, will remain 652 * uninitialized until the corresponding node is synced. Thus the valid 653 * dentry data is kept in the child node structure. 654 */ 655 memset(d, 0, sizeof(fat_dentry_t)); 656 fat_dentry_name_set(d, name); 657 b->dirty = true; /* need to sync block */ 658 rc = block_put(b); 659 fibril_mutex_unlock(&parentp->idx->lock); 660 if (rc != EOK) 661 return rc; 662 663 fibril_mutex_lock(&childp->idx->lock); 664 665 /* 666 * If possible, create the Sub-directory Identifier Entry and the 667 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 668 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 669 * not use them anyway, so this is rather a sign of our good will. 670 */ 671 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 672 if (rc != EOK) { 673 /* 674 * Rather than returning an error, simply skip the creation of 675 * these two entries. 676 */ 677 goto skip_dots; 678 } 679 d = (fat_dentry_t *)b->data; 680 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 681 str_cmp(d->name, FAT_NAME_DOT) == 0) { 682 memset(d, 0, sizeof(fat_dentry_t)); 683 str_cpy(d->name, 8, FAT_NAME_DOT); 684 str_cpy(d->ext, 3, FAT_EXT_PAD); 685 d->attr = FAT_ATTR_SUBDIR; 686 d->firstc = host2uint16_t_le(childp->firstc); 687 /* TODO: initialize also the date/time members. */ 688 } 689 d++; 690 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 691 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 692 memset(d, 0, sizeof(fat_dentry_t)); 693 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 694 str_cpy(d->ext, 3, FAT_EXT_PAD); 695 d->attr = FAT_ATTR_SUBDIR; 696 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 697 host2uint16_t_le(FAT_CLST_RES0) : 698 host2uint16_t_le(parentp->firstc); 699 /* TODO: initialize also the date/time members. */ 700 } 701 b->dirty = true; /* need to sync block */ 702 /* 703 * Ignore the return value as we would have fallen through on error 704 * anyway. 705 */ 706 (void) block_put(b); 707 skip_dots: 708 709 childp->idx->pfc = parentp->firstc; 710 childp->idx->pdi = i * dps + j; 711 fibril_mutex_unlock(&childp->idx->lock); 712 713 fibril_mutex_lock(&childp->lock); 714 childp->lnkcnt = 1; 715 childp->dirty = true; /* need to sync node */ 716 fibril_mutex_unlock(&childp->lock); 717 718 /* 719 * Hash in the index structure into the position hash. 720 */ 721 fat_idx_hashin(childp->idx); 722 723 return EOK; 724 } 725 726 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 727 { 728 fat_node_t *parentp = FAT_NODE(pfn); 729 fat_node_t *childp = FAT_NODE(cfn); 730 fat_bs_t *bs; 731 fat_dentry_t *d; 732 uint16_t bps; 733 block_t *b; 734 bool has_children; 735 int rc; 736 737 if (!parentp) 738 return EBUSY; 739 740 rc = fat_has_children(&has_children, cfn); 741 if (rc != EOK) 742 return rc; 743 if (has_children) 744 return ENOTEMPTY; 745 746 fibril_mutex_lock(&parentp->lock); 747 fibril_mutex_lock(&childp->lock); 748 assert(childp->lnkcnt == 1); 749 fibril_mutex_lock(&childp->idx->lock); 750 bs = block_bb_get(childp->idx->dev_handle); 751 bps = uint16_t_le2host(bs->bps); 752 753 rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc, 754 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 755 BLOCK_FLAGS_NONE); 756 if (rc != EOK) 757 goto error; 758 d = (fat_dentry_t *)b->data + 759 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 760 /* mark the dentry as not-currently-used */ 761 d->name[0] = FAT_DENTRY_ERASED; 762 b->dirty = true; /* need to sync block */ 763 rc = block_put(b); 764 if (rc != EOK) 765 goto error; 766 767 /* remove the index structure from the position hash */ 768 fat_idx_hashout(childp->idx); 769 /* clear position information */ 770 childp->idx->pfc = FAT_CLST_RES0; 771 childp->idx->pdi = 0; 772 fibril_mutex_unlock(&childp->idx->lock); 773 childp->lnkcnt = 0; 774 childp->dirty = true; 775 fibril_mutex_unlock(&childp->lock); 776 fibril_mutex_unlock(&parentp->lock); 777 778 return EOK; 779 780 error: 781 fibril_mutex_unlock(&parentp->idx->lock); 782 fibril_mutex_unlock(&childp->lock); 783 fibril_mutex_unlock(&childp->idx->lock); 784 return rc; 785 } 786 787 int fat_has_children(bool *has_children, fs_node_t *fn) 691 788 { 692 789 fat_bs_t *bs; … … 699 796 int rc; 700 797 701 if (nodep->type != FAT_DIRECTORY) 702 return false; 798 if (nodep->type != FAT_DIRECTORY) { 799 *has_children = false; 800 return EOK; 801 } 703 802 704 803 fibril_mutex_lock(&nodep->idx->lock); … … 713 812 714 813 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 715 assert(rc == EOK); 814 if (rc != EOK) { 815 fibril_mutex_unlock(&nodep->idx->lock); 816 return rc; 817 } 716 818 for (j = 0; j < dps; j++) { 717 819 d = ((fat_dentry_t *)b->data) + j; … … 722 824 case FAT_DENTRY_LAST: 723 825 rc = block_put(b); 724 assert(rc == EOK);725 826 fibril_mutex_unlock(&nodep->idx->lock); 726 return false; 827 *has_children = false; 828 return rc; 727 829 default: 728 830 case FAT_DENTRY_VALID: 729 831 rc = block_put(b); 730 assert(rc == EOK);731 832 fibril_mutex_unlock(&nodep->idx->lock); 732 return true; 833 *has_children = true; 834 return rc; 733 835 } 734 rc = block_put(b); 735 assert(rc == EOK); 836 } 837 rc = block_put(b); 838 if (rc != EOK) { 736 839 fibril_mutex_unlock(&nodep->idx->lock); 737 return true; 738 } 739 rc = block_put(b); 740 assert(rc == EOK); 840 return rc; 841 } 741 842 } 742 843 743 844 fibril_mutex_unlock(&nodep->idx->lock); 744 return false; 745 } 746 747 fs_node_t *fat_root_get(dev_handle_t dev_handle) 748 { 749 return fat_node_get(dev_handle, 0); 845 *has_children = false; 846 return EOK; 847 } 848 849 850 fs_index_t fat_index_get(fs_node_t *fn) 851 { 852 return FAT_NODE(fn)->idx->index; 853 } 854 855 size_t fat_size_get(fs_node_t *fn) 856 { 857 return FAT_NODE(fn)->size; 858 } 859 860 unsigned fat_lnkcnt_get(fs_node_t *fn) 861 { 862 return FAT_NODE(fn)->lnkcnt; 750 863 } 751 864 … … 763 876 { 764 877 return FAT_NODE(fn)->type == FAT_FILE; 878 } 879 880 dev_handle_t fat_device_get(fs_node_t *node) 881 { 882 return 0; 765 883 } 766 884 767 885 /** libfs operations */ 768 886 libfs_ops_t fat_libfs_ops = { 887 .root_get = fat_root_get, 769 888 .match = fat_match, 770 889 .node_get = fat_node_get, 890 .node_open = fat_node_open, 771 891 .node_put = fat_node_put, 772 892 .create = fat_create_node, … … 774 894 .link = fat_link, 775 895 .unlink = fat_unlink, 896 .has_children = fat_has_children, 776 897 .index_get = fat_index_get, 777 898 .size_get = fat_size_get, 778 899 .lnkcnt_get = fat_lnkcnt_get, 779 .has_children = fat_has_children, 780 .root_get = fat_root_get, 781 .plb_get_char = fat_plb_get_char, 900 .plb_get_char = fat_plb_get_char, 782 901 .is_directory = fat_is_directory, 783 .is_file = fat_is_file 902 .is_file = fat_is_file, 903 .device_get = fat_device_get 784 904 }; 785 905 … … 800 920 ipc_callid_t callid; 801 921 size_t size; 802 if (! ipc_data_write_receive(&callid, &size)) {922 if (!async_data_write_receive(&callid, &size)) { 803 923 ipc_answer_0(callid, EINVAL); 804 924 ipc_answer_0(rid, EINVAL); … … 811 931 return; 812 932 } 813 ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);933 ipcarg_t retval = async_data_write_finalize(callid, opts, size); 814 934 if (retval != EOK) { 815 935 ipc_answer_0(rid, retval); … … 833 953 834 954 /* prepare the boot block */ 835 rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE);955 rc = block_bb_read(dev_handle, BS_BLOCK); 836 956 if (rc != EOK) { 837 957 block_fini(dev_handle); … … 929 1049 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 930 1050 off_t pos = (off_t)IPC_GET_ARG3(*request); 931 fs_node_t *fn = fat_node_get(dev_handle, index);1051 fs_node_t *fn; 932 1052 fat_node_t *nodep; 933 1053 fat_bs_t *bs; … … 937 1057 int rc; 938 1058 1059 rc = fat_node_get(&fn, dev_handle, index); 1060 if (rc != EOK) { 1061 ipc_answer_0(rid, rc); 1062 return; 1063 } 939 1064 if (!fn) { 940 1065 ipc_answer_0(rid, ENOENT); … … 945 1070 ipc_callid_t callid; 946 1071 size_t len; 947 if (! ipc_data_read_receive(&callid, &len)) {1072 if (!async_data_read_receive(&callid, &len)) { 948 1073 fat_node_put(fn); 949 1074 ipc_answer_0(callid, EINVAL); … … 964 1089 /* reading beyond the EOF */ 965 1090 bytes = 0; 966 (void) ipc_data_read_finalize(callid, NULL, 0);1091 (void) async_data_read_finalize(callid, NULL, 0); 967 1092 } else { 968 1093 bytes = min(len, bps - pos % bps); … … 970 1095 rc = fat_block_get(&b, bs, nodep, pos / bps, 971 1096 BLOCK_FLAGS_NONE); 972 assert(rc == EOK); 973 (void) ipc_data_read_finalize(callid, b->data + pos % bps, 1097 if (rc != EOK) { 1098 fat_node_put(fn); 1099 ipc_answer_0(callid, rc); 1100 ipc_answer_0(rid, rc); 1101 return; 1102 } 1103 (void) async_data_read_finalize(callid, b->data + pos % bps, 974 1104 bytes); 975 1105 rc = block_put(b); 976 assert(rc == EOK); 1106 if (rc != EOK) { 1107 fat_node_put(fn); 1108 ipc_answer_0(rid, rc); 1109 return; 1110 } 977 1111 } 978 1112 } else { … … 998 1132 rc = fat_block_get(&b, bs, nodep, bnum, 999 1133 BLOCK_FLAGS_NONE); 1000 assert(rc == EOK); 1134 if (rc != EOK) 1135 goto err; 1001 1136 for (o = pos % (bps / sizeof(fat_dentry_t)); 1002 1137 o < bps / sizeof(fat_dentry_t); … … 1009 1144 case FAT_DENTRY_LAST: 1010 1145 rc = block_put(b); 1011 assert(rc == EOK); 1146 if (rc != EOK) 1147 goto err; 1012 1148 goto miss; 1013 1149 default: 1014 1150 case FAT_DENTRY_VALID: 1015 1151 fat_dentry_name_get(d, name); 1016 rc == block_put(b); 1017 assert(rc == EOK); 1152 rc = block_put(b); 1153 if (rc != EOK) 1154 goto err; 1018 1155 goto hit; 1019 1156 } 1020 1157 } 1021 1158 rc = block_put(b); 1022 assert(rc == EOK); 1159 if (rc != EOK) 1160 goto err; 1023 1161 bnum++; 1024 1162 } 1025 1163 miss: 1026 fat_node_put(fn); 1027 ipc_answer_0(callid, ENOENT); 1028 ipc_answer_1(rid, ENOENT, 0); 1029 return; 1164 rc = fat_node_put(fn); 1165 ipc_answer_0(callid, rc != EOK ? rc : ENOENT); 1166 ipc_answer_1(rid, rc != EOK ? rc : ENOENT, 0); 1167 return; 1168 1169 err: 1170 (void) fat_node_put(fn); 1171 ipc_answer_0(callid, rc); 1172 ipc_answer_0(rid, rc); 1173 return; 1174 1030 1175 hit: 1031 (void) ipc_data_read_finalize(callid, name, str_size(name) + 1);1176 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1032 1177 bytes = (pos - spos) + 1; 1033 1178 } 1034 1179 1035 fat_node_put(fn);1036 ipc_answer_1(rid, EOK, (ipcarg_t)bytes);1180 rc = fat_node_put(fn); 1181 ipc_answer_1(rid, rc, (ipcarg_t)bytes); 1037 1182 } 1038 1183 … … 1042 1187 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1043 1188 off_t pos = (off_t)IPC_GET_ARG3(*request); 1044 fs_node_t *fn = fat_node_get(dev_handle, index);1189 fs_node_t *fn; 1045 1190 fat_node_t *nodep; 1046 1191 fat_bs_t *bs; 1047 size_t bytes ;1192 size_t bytes, size; 1048 1193 block_t *b; 1049 1194 uint16_t bps; … … 1054 1199 int rc; 1055 1200 1201 rc = fat_node_get(&fn, dev_handle, index); 1202 if (rc != EOK) { 1203 ipc_answer_0(rid, rc); 1204 return; 1205 } 1056 1206 if (!fn) { 1057 1207 ipc_answer_0(rid, ENOENT); … … 1062 1212 ipc_callid_t callid; 1063 1213 size_t len; 1064 if (! ipc_data_write_receive(&callid, &len)) {1065 fat_node_put(fn);1214 if (!async_data_write_receive(&callid, &len)) { 1215 (void) fat_node_put(fn); 1066 1216 ipc_answer_0(callid, EINVAL); 1067 1217 ipc_answer_0(rid, EINVAL); … … 1094 1244 */ 1095 1245 rc = fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); 1096 assert(rc == EOK); 1246 if (rc != EOK) { 1247 (void) fat_node_put(fn); 1248 ipc_answer_0(callid, rc); 1249 ipc_answer_0(rid, rc); 1250 return; 1251 } 1097 1252 rc = fat_block_get(&b, bs, nodep, pos / bps, flags); 1098 assert(rc == EOK); 1099 (void) ipc_data_write_finalize(callid, b->data + pos % bps, 1253 if (rc != EOK) { 1254 (void) fat_node_put(fn); 1255 ipc_answer_0(callid, rc); 1256 ipc_answer_0(rid, rc); 1257 return; 1258 } 1259 (void) async_data_write_finalize(callid, b->data + pos % bps, 1100 1260 bytes); 1101 1261 b->dirty = true; /* need to sync block */ 1102 1262 rc = block_put(b); 1103 assert(rc == EOK); 1263 if (rc != EOK) { 1264 (void) fat_node_put(fn); 1265 ipc_answer_0(rid, rc); 1266 return; 1267 } 1104 1268 if (pos + bytes > nodep->size) { 1105 1269 nodep->size = pos + bytes; 1106 1270 nodep->dirty = true; /* need to sync node */ 1107 1271 } 1108 ipc_answer_2(rid, EOK, bytes, nodep->size); 1109 fat_node_put(fn); 1272 size = nodep->size; 1273 rc = fat_node_put(fn); 1274 ipc_answer_2(rid, rc, bytes, nodep->size); 1110 1275 return; 1111 1276 } else { … … 1114 1279 * clusters for the node and zero them out. 1115 1280 */ 1116 int status;1117 1281 unsigned nclsts; 1118 1282 fat_cluster_t mcl, lcl; … … 1120 1284 nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc; 1121 1285 /* create an independent chain of nclsts clusters in all FATs */ 1122 status= fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);1123 if ( status!= EOK) {1286 rc = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); 1287 if (rc != EOK) { 1124 1288 /* could not allocate a chain of nclsts clusters */ 1125 fat_node_put(fn);1126 ipc_answer_0(callid, status);1127 ipc_answer_0(rid, status);1289 (void) fat_node_put(fn); 1290 ipc_answer_0(callid, rc); 1291 ipc_answer_0(rid, rc); 1128 1292 return; 1129 1293 } 1130 1294 /* zero fill any gaps */ 1131 1295 rc = fat_fill_gap(bs, nodep, mcl, pos); 1132 assert(rc == EOK); 1296 if (rc != EOK) { 1297 (void) fat_free_clusters(bs, dev_handle, mcl); 1298 (void) fat_node_put(fn); 1299 ipc_answer_0(callid, rc); 1300 ipc_answer_0(rid, rc); 1301 return; 1302 } 1133 1303 rc = _fat_block_get(&b, bs, dev_handle, lcl, (pos / bps) % spc, 1134 1304 flags); 1135 assert(rc == EOK); 1136 (void) ipc_data_write_finalize(callid, b->data + pos % bps, 1305 if (rc != EOK) { 1306 (void) fat_free_clusters(bs, dev_handle, mcl); 1307 (void) fat_node_put(fn); 1308 ipc_answer_0(callid, rc); 1309 ipc_answer_0(rid, rc); 1310 return; 1311 } 1312 (void) async_data_write_finalize(callid, b->data + pos % bps, 1137 1313 bytes); 1138 1314 b->dirty = true; /* need to sync block */ 1139 1315 rc = block_put(b); 1140 assert(rc == EOK); 1316 if (rc != EOK) { 1317 (void) fat_free_clusters(bs, dev_handle, mcl); 1318 (void) fat_node_put(fn); 1319 ipc_answer_0(rid, rc); 1320 return; 1321 } 1141 1322 /* 1142 1323 * Append the cluster chain starting in mcl to the end of the … … 1144 1325 */ 1145 1326 rc = fat_append_clusters(bs, nodep, mcl); 1146 assert(rc == EOK); 1147 nodep->size = pos + bytes; 1327 if (rc != EOK) { 1328 (void) fat_free_clusters(bs, dev_handle, mcl); 1329 (void) fat_node_put(fn); 1330 ipc_answer_0(rid, rc); 1331 return; 1332 } 1333 nodep->size = size = pos + bytes; 1148 1334 nodep->dirty = true; /* need to sync node */ 1149 ipc_answer_2(rid, EOK, bytes, nodep->size);1150 fat_node_put(fn);1335 rc = fat_node_put(fn); 1336 ipc_answer_2(rid, rc, bytes, size); 1151 1337 return; 1152 1338 } … … 1158 1344 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1159 1345 size_t size = (off_t)IPC_GET_ARG3(*request); 1160 fs_node_t *fn = fat_node_get(dev_handle, index);1346 fs_node_t *fn; 1161 1347 fat_node_t *nodep; 1162 1348 fat_bs_t *bs; … … 1166 1352 int rc; 1167 1353 1354 rc = fat_node_get(&fn, dev_handle, index); 1355 if (rc != EOK) { 1356 ipc_answer_0(rid, rc); 1357 return; 1358 } 1168 1359 if (!fn) { 1169 1360 ipc_answer_0(rid, ENOENT); … … 1229 1420 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1230 1421 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1422 fs_node_t *fn; 1231 1423 int rc; 1232 1424 1233 fs_node_t *fn = fat_node_get(dev_handle, index); 1425 rc = fat_node_get(&fn, dev_handle, index); 1426 if (rc != EOK) { 1427 ipc_answer_0(rid, rc); 1428 return; 1429 } 1234 1430 if (!fn) { 1235 1431 ipc_answer_0(rid, ENOENT);
Note:
See TracChangeset
for help on using the changeset viewer.