Changes in / [d27ed12:2e37308] in mainline
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libfs/libfs.c
rd27ed12 r2e37308 46 46 #include <sys/stat.h> 47 47 48 #define on_error(rc, action) \ 49 do { \ 50 if ((rc) != EOK) \ 51 action; \ 52 } while (0) 53 54 #define combine_rc(rc1, rc2) \ 55 ((rc1) == EOK ? (rc2) : (rc1)) 56 57 #define answer_and_return(rid, rc) \ 58 do { \ 59 ipc_answer_0((rid), (rc)); \ 60 return; \ 61 } while (0) 62 48 63 /** Register file system server. 49 64 * … … 162 177 } 163 178 164 fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index); 165 if (!fn) { 179 fs_node_t *fn; 180 res = ops->node_get(&fn, mp_dev_handle, mp_fs_index); 181 if (res != EOK || !fn) { 166 182 ipc_hangup(mountee_phone); 167 ipc_answer_0(callid, ENOENT);168 ipc_answer_0(rid, ENOENT);183 ipc_answer_0(callid, combine_rc(res, ENOENT)); 184 ipc_answer_0(rid, combine_rc(res, ENOENT)); 169 185 return; 170 186 } … … 172 188 if (fn->mp_data.mp_active) { 173 189 ipc_hangup(mountee_phone); 174 ops->node_put(fn);190 (void) ops->node_put(fn); 175 191 ipc_answer_0(callid, EBUSY); 176 192 ipc_answer_0(rid, EBUSY); … … 179 195 180 196 rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); 181 if (rc != 0) {197 if (rc != EOK) { 182 198 ipc_hangup(mountee_phone); 183 ops->node_put(fn);199 (void) ops->node_put(fn); 184 200 ipc_answer_0(callid, rc); 185 201 ipc_answer_0(rid, rc); … … 230 246 char component[NAME_MAX + 1]; 231 247 int len; 248 int rc; 232 249 233 250 if (last < next) … … 235 252 236 253 fs_node_t *par = NULL; 237 fs_node_t *cur = ops->root_get(dev_handle);254 fs_node_t *cur = NULL; 238 255 fs_node_t *tmp = NULL; 256 257 rc = ops->root_get(&cur, dev_handle); 258 on_error(rc, goto out_with_answer); 239 259 240 260 if (cur->mp_data.mp_active) { … … 242 262 next, last, cur->mp_data.dev_handle, lflag, index, 243 263 IPC_FF_ROUTE_FROM_ME); 244 ops->node_put(cur);264 (void) ops->node_put(cur); 245 265 return; 246 266 } … … 249 269 next++; /* eat slash */ 250 270 251 while (next <= last && ops->has_children(cur)) { 271 while (next <= last) { 272 bool has_children; 273 274 rc = ops->has_children(&has_children, cur); 275 on_error(rc, goto out_with_answer); 276 if (!has_children) 277 break; 278 252 279 /* collect the component */ 253 280 len = 0; … … 267 294 268 295 /* match the component */ 269 tmp = ops->match(cur, component); 296 rc = ops->match(&tmp, cur, component); 297 on_error(rc, goto out_with_answer); 298 270 299 if (tmp && tmp->mp_data.mp_active) { 271 300 if (next > last) … … 277 306 VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle, 278 307 lflag, index, IPC_FF_ROUTE_FROM_ME); 279 ops->node_put(cur);280 ops->node_put(tmp);308 (void) ops->node_put(cur); 309 (void) ops->node_put(tmp); 281 310 if (par) 282 ops->node_put(par);311 (void) ops->node_put(par); 283 312 return; 284 313 } … … 300 329 fs_node_t *fn; 301 330 if (lflag & L_CREATE) 302 fn = ops->create(dev_handle, lflag); 331 rc = ops->create(&fn, dev_handle, 332 lflag); 303 333 else 304 fn = ops->node_get(dev_handle,334 rc = ops->node_get(&fn, dev_handle, 305 335 index); 336 on_error(rc, goto out_with_answer); 306 337 if (fn) { 307 int rc;308 309 338 rc = ops->link(cur, fn, component); 310 339 if (rc != EOK) { 311 if (lflag & L_CREATE) { 312 (void)ops->destroy(fn); 313 } 340 if (lflag & L_CREATE) 341 (void) ops->destroy(fn); 314 342 ipc_answer_0(rid, rc); 315 343 } else { … … 319 347 ops->size_get(fn), 320 348 ops->lnkcnt_get(fn)); 321 ops->node_put(fn);349 (void) ops->node_put(fn); 322 350 } 323 351 } else { … … 330 358 } 331 359 332 if (par) 333 ops->node_put(par); 360 if (par) { 361 rc = ops->node_put(par); 362 on_error(rc, goto out_with_answer); 363 } 334 364 335 365 /* descend one level */ … … 340 370 341 371 /* handle miss: excessive components */ 342 if (next <= last && !ops->has_children(cur)) { 372 if (next <= last) { 373 bool has_children; 374 375 rc = ops->has_children(&has_children, cur); 376 on_error(rc, goto out_with_answer); 377 if (has_children) 378 goto skip_miss; 379 343 380 if (lflag & (L_CREATE | L_LINK)) { 344 381 if (!ops->is_directory(cur)) { … … 368 405 fs_node_t *fn; 369 406 if (lflag & L_CREATE) 370 fn = ops->create(dev_handle, lflag);407 rc = ops->create(&fn, dev_handle, lflag); 371 408 else 372 fn = ops->node_get(dev_handle, index); 409 rc = ops->node_get(&fn, dev_handle, index); 410 on_error(rc, goto out_with_answer); 373 411 if (fn) { 374 int rc;375 376 412 rc = ops->link(cur, fn, component); 377 413 if (rc != EOK) { 378 414 if (lflag & L_CREATE) 379 (void) ops->destroy(fn);415 (void) ops->destroy(fn); 380 416 ipc_answer_0(rid, rc); 381 417 } else { … … 385 421 ops->size_get(fn), 386 422 ops->lnkcnt_get(fn)); 387 ops->node_put(fn);423 (void) ops->node_put(fn); 388 424 } 389 425 } else { … … 395 431 goto out; 396 432 } 433 skip_miss: 397 434 398 435 /* handle hit */ 399 436 if (lflag & L_UNLINK) { 400 437 unsigned old_lnkcnt = ops->lnkcnt_get(cur); 401 int res= ops->unlink(par, cur, component);402 ipc_answer_5(rid, (ipcarg_t)r es, fs_handle, dev_handle,438 rc = ops->unlink(par, cur, component); 439 ipc_answer_5(rid, (ipcarg_t)rc, fs_handle, dev_handle, 403 440 ops->index_get(cur), ops->size_get(cur), old_lnkcnt); 404 441 goto out; … … 418 455 } 419 456 420 ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur), 421 ops->size_get(cur), ops->lnkcnt_get(cur)); 457 out_with_answer: 458 if (rc == EOK) { 459 ipc_answer_5(rid, EOK, fs_handle, dev_handle, 460 ops->index_get(cur), ops->size_get(cur), 461 ops->lnkcnt_get(cur)); 462 } else { 463 ipc_answer_0(rid, rc); 464 } 422 465 423 466 out: 424 467 if (par) 425 ops->node_put(par);468 (void) ops->node_put(par); 426 469 if (cur) 427 ops->node_put(cur);470 (void) ops->node_put(cur); 428 471 if (tmp) 429 ops->node_put(tmp);472 (void) ops->node_put(tmp); 430 473 } 431 474 … … 435 478 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 436 479 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 437 fs_node_t *fn = ops->node_get(dev_handle, index); 480 fs_node_t *fn; 481 int rc; 482 483 rc = ops->node_get(&fn, dev_handle, index); 484 on_error(rc, answer_and_return(rid, rc)); 438 485 439 486 ipc_callid_t callid; … … 473 520 dev_handle_t dev_handle = IPC_GET_ARG1(*request); 474 521 fs_index_t index = IPC_GET_ARG2(*request); 475 476 fs_node_t *node = ops->node_get(dev_handle, index); 477 478 if (node == NULL) { 522 fs_node_t *fn; 523 int rc; 524 525 rc = ops->node_get(&fn, dev_handle, index); 526 on_error(rc, answer_and_return(rid, rc)); 527 528 if (fn == NULL) { 479 529 ipc_answer_0(rid, ENOENT); 480 530 return; 481 531 } 482 532 483 ipc_answer_5(rid, EOK, fs_handle, dev_handle, index, 484 ops-> size_get(node), ops->lnkcnt_get(node));485 486 ops->node_put(node);533 ipc_answer_5(rid, EOK, fs_handle, dev_handle, index, ops->size_get(fn), 534 ops->lnkcnt_get(fn)); 535 536 (void) ops->node_put(fn); 487 537 } 488 538 -
uspace/lib/libfs/libfs.h
rd27ed12 r2e37308 56 56 57 57 typedef struct { 58 fs_node_t * (* match)(fs_node_t *, const char *); 59 fs_node_t * (* node_get)(dev_handle_t, fs_index_t); 60 void (* node_put)(fs_node_t *); 61 fs_node_t * (* create)(dev_handle_t, int); 58 /* 59 * The first set of methods are functions that return an integer error 60 * code. If some additional return value is to be returned, the first 61 * argument holds the output argument. 62 */ 63 int (* root_get)(fs_node_t **, dev_handle_t); 64 int (* match)(fs_node_t **, fs_node_t *, const char *); 65 int (* node_get)(fs_node_t **, dev_handle_t, fs_index_t); 66 int (* node_put)(fs_node_t *); 67 int (* create)(fs_node_t **, dev_handle_t, int); 62 68 int (* destroy)(fs_node_t *); 63 69 int (* link)(fs_node_t *, fs_node_t *, const char *); 64 70 int (* unlink)(fs_node_t *, fs_node_t *, const char *); 71 int (* has_children)(bool *, fs_node_t *); 72 /* 73 * The second set of methods are usually mere getters that do not return 74 * an integer error code. 75 */ 65 76 fs_index_t (* index_get)(fs_node_t *); 66 77 size_t (* size_get)(fs_node_t *); 67 78 unsigned (* lnkcnt_get)(fs_node_t *); 68 bool (* has_children)(fs_node_t *);69 fs_node_t *(* root_get)(dev_handle_t);70 79 char (* plb_get_char)(unsigned pos); 71 80 bool (* is_directory)(fs_node_t *); -
uspace/srv/fs/fat/fat_ops.c
rd27ed12 r2e37308 250 250 * Forward declarations of FAT libfs operations. 251 251 */ 252 static fs_node_t *fat_node_get(dev_handle_t, fs_index_t); 253 static void fat_node_put(fs_node_t *); 254 static fs_node_t *fat_create_node(dev_handle_t, int); 252 static int fat_root_get(fs_node_t **, dev_handle_t); 253 static int fat_match(fs_node_t **, fs_node_t *, const char *); 254 static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t); 255 static int fat_node_put(fs_node_t *); 256 static int fat_create_node(fs_node_t **, dev_handle_t, int); 255 257 static int fat_destroy_node(fs_node_t *); 256 258 static int fat_link(fs_node_t *, fs_node_t *, const char *); 257 259 static int fat_unlink(fs_node_t *, fs_node_t *, const char *); 258 static fs_node_t *fat_match(fs_node_t *, const char*);260 static int fat_has_children(bool *, fs_node_t *); 259 261 static fs_index_t fat_index_get(fs_node_t *); 260 262 static size_t fat_size_get(fs_node_t *); 261 263 static unsigned fat_lnkcnt_get(fs_node_t *); 262 static bool fat_has_children(fs_node_t *);263 static fs_node_t *fat_root_get(dev_handle_t);264 264 static char fat_plb_get_char(unsigned); 265 265 static bool fat_is_directory(fs_node_t *); … … 270 270 */ 271 271 272 /** Instantiate a FAT in-core node. */ 273 fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index) 274 { 275 fat_node_t *nodep; 276 fat_idx_t *idxp; 277 278 idxp = fat_idx_get_by_index(dev_handle, index); 279 if (!idxp) 280 return NULL; 281 /* idxp->lock held */ 282 nodep = fat_node_get_core(idxp); 283 fibril_mutex_unlock(&idxp->lock); 284 return FS_NODE(nodep); 285 } 286 287 void fat_node_put(fs_node_t *fn) 288 { 289 fat_node_t *nodep = FAT_NODE(fn); 290 bool destroy = false; 291 292 fibril_mutex_lock(&nodep->lock); 293 if (!--nodep->refcnt) { 294 if (nodep->idx) { 295 fibril_mutex_lock(&ffn_mutex); 296 list_append(&nodep->ffn_link, &ffn_head); 297 fibril_mutex_unlock(&ffn_mutex); 298 } else { 299 /* 300 * The node does not have any index structure associated 301 * with itself. This can only mean that we are releasing 302 * the node after a failed attempt to allocate the index 303 * structure for it. 304 */ 305 destroy = true; 306 } 307 } 308 fibril_mutex_unlock(&nodep->lock); 309 if (destroy) { 310 free(nodep->bp); 311 free(nodep); 312 } 313 } 314 315 fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags) 316 { 317 fat_idx_t *idxp; 318 fat_node_t *nodep; 319 fat_bs_t *bs; 320 fat_cluster_t mcl, lcl; 321 uint16_t bps; 322 int rc; 323 324 bs = block_bb_get(dev_handle); 325 bps = uint16_t_le2host(bs->bps); 326 if (flags & L_DIRECTORY) { 327 /* allocate a cluster */ 328 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 329 if (rc != EOK) 330 return NULL; 331 } 332 333 nodep = fat_node_get_new(); 334 if (!nodep) { 335 (void) fat_free_clusters(bs, dev_handle, mcl); 336 return NULL; 337 } 338 idxp = fat_idx_get_new(dev_handle); 339 if (!idxp) { 340 (void) fat_free_clusters(bs, dev_handle, mcl); 341 fat_node_put(FS_NODE(nodep)); 342 return NULL; 343 } 344 /* idxp->lock held */ 345 if (flags & L_DIRECTORY) { 346 /* Populate the new cluster with unused dentries. */ 347 rc = fat_zero_cluster(bs, dev_handle, mcl); 348 assert(rc == EOK); 349 nodep->type = FAT_DIRECTORY; 350 nodep->firstc = mcl; 351 nodep->size = bps * bs->spc; 352 } else { 353 nodep->type = FAT_FILE; 354 nodep->firstc = FAT_CLST_RES0; 355 nodep->size = 0; 356 } 357 nodep->lnkcnt = 0; /* not linked anywhere */ 358 nodep->refcnt = 1; 359 nodep->dirty = true; 360 361 nodep->idx = idxp; 362 idxp->nodep = nodep; 363 364 fibril_mutex_unlock(&idxp->lock); 365 return FS_NODE(nodep); 366 } 367 368 int fat_destroy_node(fs_node_t *fn) 369 { 370 fat_node_t *nodep = FAT_NODE(fn); 371 fat_bs_t *bs; 372 int rc = EOK; 373 374 /* 375 * The node is not reachable from the file system. This means that the 376 * link count should be zero and that the index structure cannot be 377 * found in the position hash. Obviously, we don't need to lock the node 378 * nor its index structure. 379 */ 380 assert(nodep->lnkcnt == 0); 381 382 /* 383 * The node may not have any children. 384 */ 385 assert(fat_has_children(fn) == false); 386 387 bs = block_bb_get(nodep->idx->dev_handle); 388 if (nodep->firstc != FAT_CLST_RES0) { 389 assert(nodep->size); 390 /* Free all clusters allocated to the node. */ 391 rc = fat_free_clusters(bs, nodep->idx->dev_handle, 392 nodep->firstc); 393 } 394 395 fat_idx_destroy(nodep->idx); 396 free(nodep->bp); 397 free(nodep); 398 return rc; 399 } 400 401 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 402 { 403 fat_node_t *parentp = FAT_NODE(pfn); 404 fat_node_t *childp = FAT_NODE(cfn); 405 fat_dentry_t *d; 406 fat_bs_t *bs; 407 block_t *b; 408 unsigned i, j; 409 uint16_t bps; 410 unsigned dps; 411 unsigned blocks; 412 fat_cluster_t mcl, lcl; 413 int rc; 414 415 fibril_mutex_lock(&childp->lock); 416 if (childp->lnkcnt == 1) { 417 /* 418 * On FAT, we don't support multiple hard links. 419 */ 420 fibril_mutex_unlock(&childp->lock); 421 return EMLINK; 422 } 423 assert(childp->lnkcnt == 0); 424 fibril_mutex_unlock(&childp->lock); 425 426 if (!fat_dentry_name_verify(name)) { 427 /* 428 * Attempt to create unsupported name. 429 */ 430 return ENOTSUP; 431 } 432 433 /* 434 * Get us an unused parent node's dentry or grow the parent and allocate 435 * a new one. 436 */ 437 438 fibril_mutex_lock(&parentp->idx->lock); 439 bs = block_bb_get(parentp->idx->dev_handle); 440 bps = uint16_t_le2host(bs->bps); 441 dps = bps / sizeof(fat_dentry_t); 442 443 blocks = parentp->size / bps; 444 445 for (i = 0; i < blocks; i++) { 446 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 447 if (rc != EOK) { 448 fibril_mutex_unlock(&parentp->idx->lock); 449 return rc; 450 } 451 for (j = 0; j < dps; j++) { 452 d = ((fat_dentry_t *)b->data) + j; 453 switch (fat_classify_dentry(d)) { 454 case FAT_DENTRY_SKIP: 455 case FAT_DENTRY_VALID: 456 /* skipping used and meta entries */ 457 continue; 458 case FAT_DENTRY_FREE: 459 case FAT_DENTRY_LAST: 460 /* found an empty slot */ 461 goto hit; 462 } 463 } 464 rc = block_put(b); 465 if (rc != EOK) { 466 fibril_mutex_unlock(&parentp->idx->lock); 467 return rc; 468 } 469 } 470 j = 0; 471 472 /* 473 * We need to grow the parent in order to create a new unused dentry. 474 */ 475 if (parentp->firstc == FAT_CLST_ROOT) { 476 /* Can't grow the root directory. */ 477 fibril_mutex_unlock(&parentp->idx->lock); 478 return ENOSPC; 479 } 480 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 481 if (rc != EOK) { 482 fibril_mutex_unlock(&parentp->idx->lock); 483 return rc; 484 } 485 rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 486 if (rc != EOK) { 487 fibril_mutex_unlock(&parentp->idx->lock); 488 return rc; 489 } 490 rc = fat_append_clusters(bs, parentp, mcl); 491 if (rc != EOK) { 492 fibril_mutex_unlock(&parentp->idx->lock); 493 return rc; 494 } 495 parentp->size += bps * bs->spc; 496 parentp->dirty = true; /* need to sync node */ 497 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 498 if (rc != EOK) { 499 fibril_mutex_unlock(&parentp->idx->lock); 500 return rc; 501 } 502 d = (fat_dentry_t *)b->data; 503 504 hit: 505 /* 506 * At this point we only establish the link between the parent and the 507 * child. The dentry, except of the name and the extension, will remain 508 * uninitialized until the corresponding node is synced. Thus the valid 509 * dentry data is kept in the child node structure. 510 */ 511 memset(d, 0, sizeof(fat_dentry_t)); 512 fat_dentry_name_set(d, name); 513 b->dirty = true; /* need to sync block */ 514 rc = block_put(b); 515 fibril_mutex_unlock(&parentp->idx->lock); 516 if (rc != EOK) 517 return rc; 518 519 fibril_mutex_lock(&childp->idx->lock); 520 521 /* 522 * If possible, create the Sub-directory Identifier Entry and the 523 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 524 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 525 * not use them anyway, so this is rather a sign of our good will. 526 */ 527 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 528 if (rc != EOK) { 529 /* 530 * Rather than returning an error, simply skip the creation of 531 * these two entries. 532 */ 533 goto skip_dots; 534 } 535 d = (fat_dentry_t *)b->data; 536 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 537 str_cmp(d->name, FAT_NAME_DOT) == 0) { 538 memset(d, 0, sizeof(fat_dentry_t)); 539 str_cpy(d->name, 8, FAT_NAME_DOT); 540 str_cpy(d->ext, 3, FAT_EXT_PAD); 541 d->attr = FAT_ATTR_SUBDIR; 542 d->firstc = host2uint16_t_le(childp->firstc); 543 /* TODO: initialize also the date/time members. */ 544 } 545 d++; 546 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 547 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 548 memset(d, 0, sizeof(fat_dentry_t)); 549 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 550 str_cpy(d->ext, 3, FAT_EXT_PAD); 551 d->attr = FAT_ATTR_SUBDIR; 552 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 553 host2uint16_t_le(FAT_CLST_RES0) : 554 host2uint16_t_le(parentp->firstc); 555 /* TODO: initialize also the date/time members. */ 556 } 557 b->dirty = true; /* need to sync block */ 558 /* 559 * Ignore the return value as we would have fallen through on error 560 * anyway. 561 */ 562 (void) block_put(b); 563 skip_dots: 564 565 childp->idx->pfc = parentp->firstc; 566 childp->idx->pdi = i * dps + j; 567 fibril_mutex_unlock(&childp->idx->lock); 568 569 fibril_mutex_lock(&childp->lock); 570 childp->lnkcnt = 1; 571 childp->dirty = true; /* need to sync node */ 572 fibril_mutex_unlock(&childp->lock); 573 574 /* 575 * Hash in the index structure into the position hash. 576 */ 577 fat_idx_hashin(childp->idx); 578 579 return EOK; 580 } 581 582 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 583 { 584 fat_node_t *parentp = FAT_NODE(pfn); 585 fat_node_t *childp = FAT_NODE(cfn); 586 fat_bs_t *bs; 587 fat_dentry_t *d; 588 uint16_t bps; 589 block_t *b; 590 int rc; 591 592 if (!parentp) 593 return EBUSY; 594 595 if (fat_has_children(cfn)) 596 return ENOTEMPTY; 597 598 fibril_mutex_lock(&parentp->lock); 599 fibril_mutex_lock(&childp->lock); 600 assert(childp->lnkcnt == 1); 601 fibril_mutex_lock(&childp->idx->lock); 602 bs = block_bb_get(childp->idx->dev_handle); 603 bps = uint16_t_le2host(bs->bps); 604 605 rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc, 606 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 607 BLOCK_FLAGS_NONE); 608 if (rc != EOK) 609 goto error; 610 d = (fat_dentry_t *)b->data + 611 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 612 /* mark the dentry as not-currently-used */ 613 d->name[0] = FAT_DENTRY_ERASED; 614 b->dirty = true; /* need to sync block */ 615 rc = block_put(b); 616 if (rc != EOK) 617 goto error; 618 619 /* remove the index structure from the position hash */ 620 fat_idx_hashout(childp->idx); 621 /* clear position information */ 622 childp->idx->pfc = FAT_CLST_RES0; 623 childp->idx->pdi = 0; 624 fibril_mutex_unlock(&childp->idx->lock); 625 childp->lnkcnt = 0; 626 childp->dirty = true; 627 fibril_mutex_unlock(&childp->lock); 628 fibril_mutex_unlock(&parentp->lock); 629 630 return EOK; 631 632 error: 633 fibril_mutex_unlock(&parentp->idx->lock); 634 fibril_mutex_unlock(&childp->lock); 635 fibril_mutex_unlock(&childp->idx->lock); 636 return rc; 637 } 638 639 fs_node_t *fat_match(fs_node_t *pfn, const char *component) 272 int fat_root_get(fs_node_t **rfn, dev_handle_t dev_handle) 273 { 274 return fat_node_get(rfn, dev_handle, 0); 275 } 276 277 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 640 278 { 641 279 fat_bs_t *bs; … … 657 295 for (i = 0; i < blocks; i++) { 658 296 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 659 assert(rc == EOK); 297 if (rc != EOK) { 298 fibril_mutex_unlock(&parentp->idx->lock); 299 return rc; 300 } 660 301 for (j = 0; j < dps; j++) { 661 302 d = ((fat_dentry_t *)b->data) + j; … … 666 307 case FAT_DENTRY_LAST: 667 308 rc = block_put(b); 668 assert(rc == EOK); 309 /* expect EOK as b was not dirty */ 310 assert(rc == EOK); 669 311 fibril_mutex_unlock(&parentp->idx->lock); 670 return NULL; 312 *rfn = NULL; 313 return EOK; 671 314 default: 672 315 case FAT_DENTRY_VALID: … … 693 336 */ 694 337 rc = block_put(b); 695 assert(rc == EOK); 696 return NULL; 338 /* expect EOK as b was not dirty */ 339 assert(rc == EOK); 340 return ENOMEM; 697 341 } 698 342 nodep = fat_node_get_core(idx); 699 343 fibril_mutex_unlock(&idx->lock); 700 344 rc = block_put(b); 345 /* expect EOK as b was not dirty */ 701 346 assert(rc == EOK); 702 return FS_NODE(nodep); 347 *rfn = FS_NODE(nodep); 348 return EOK; 703 349 } 704 350 } 705 351 rc = block_put(b); 706 assert(rc == EOK); 352 assert(rc == EOK); /* expect EOK as b was not dirty */ 707 353 } 708 354 709 355 fibril_mutex_unlock(&parentp->idx->lock); 710 return NULL; 711 } 712 713 fs_index_t fat_index_get(fs_node_t *fn) 714 { 715 return FAT_NODE(fn)->idx->index; 716 } 717 718 size_t fat_size_get(fs_node_t *fn) 719 { 720 return FAT_NODE(fn)->size; 721 } 722 723 unsigned fat_lnkcnt_get(fs_node_t *fn) 724 { 725 return FAT_NODE(fn)->lnkcnt; 726 } 727 728 bool fat_has_children(fs_node_t *fn) 356 *rfn = NULL; 357 return EOK; 358 } 359 360 /** Instantiate a FAT in-core node. */ 361 int fat_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index) 362 { 363 fat_node_t *nodep; 364 fat_idx_t *idxp; 365 366 idxp = fat_idx_get_by_index(dev_handle, index); 367 if (!idxp) { 368 *rfn = NULL; 369 return EOK; 370 } 371 /* idxp->lock held */ 372 nodep = fat_node_get_core(idxp); 373 fibril_mutex_unlock(&idxp->lock); 374 *rfn = FS_NODE(nodep); 375 return EOK; 376 } 377 378 int fat_node_put(fs_node_t *fn) 379 { 380 fat_node_t *nodep = FAT_NODE(fn); 381 bool destroy = false; 382 383 fibril_mutex_lock(&nodep->lock); 384 if (!--nodep->refcnt) { 385 if (nodep->idx) { 386 fibril_mutex_lock(&ffn_mutex); 387 list_append(&nodep->ffn_link, &ffn_head); 388 fibril_mutex_unlock(&ffn_mutex); 389 } else { 390 /* 391 * The node does not have any index structure associated 392 * with itself. This can only mean that we are releasing 393 * the node after a failed attempt to allocate the index 394 * structure for it. 395 */ 396 destroy = true; 397 } 398 } 399 fibril_mutex_unlock(&nodep->lock); 400 if (destroy) { 401 free(nodep->bp); 402 free(nodep); 403 } 404 return EOK; 405 } 406 407 int fat_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int flags) 408 { 409 fat_idx_t *idxp; 410 fat_node_t *nodep; 411 fat_bs_t *bs; 412 fat_cluster_t mcl, lcl; 413 uint16_t bps; 414 int rc; 415 416 bs = block_bb_get(dev_handle); 417 bps = uint16_t_le2host(bs->bps); 418 if (flags & L_DIRECTORY) { 419 /* allocate a cluster */ 420 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 421 if (rc != EOK) 422 return rc; 423 /* populate the new cluster with unused dentries */ 424 rc = fat_zero_cluster(bs, dev_handle, mcl); 425 if (rc != EOK) { 426 (void) fat_free_clusters(bs, dev_handle, mcl); 427 return rc; 428 } 429 } 430 431 nodep = fat_node_get_new(); 432 if (!nodep) { 433 (void) fat_free_clusters(bs, dev_handle, mcl); 434 return ENOMEM; /* FIXME: determine the true error code */ 435 } 436 idxp = fat_idx_get_new(dev_handle); 437 if (!idxp) { 438 (void) fat_free_clusters(bs, dev_handle, mcl); 439 (void) fat_node_put(FS_NODE(nodep)); 440 return ENOMEM; /* FIXME: determine the true error code */ 441 } 442 /* idxp->lock held */ 443 if (flags & L_DIRECTORY) { 444 nodep->type = FAT_DIRECTORY; 445 nodep->firstc = mcl; 446 nodep->size = bps * bs->spc; 447 } else { 448 nodep->type = FAT_FILE; 449 nodep->firstc = FAT_CLST_RES0; 450 nodep->size = 0; 451 } 452 nodep->lnkcnt = 0; /* not linked anywhere */ 453 nodep->refcnt = 1; 454 nodep->dirty = true; 455 456 nodep->idx = idxp; 457 idxp->nodep = nodep; 458 459 fibril_mutex_unlock(&idxp->lock); 460 *rfn = FS_NODE(nodep); 461 return EOK; 462 } 463 464 int fat_destroy_node(fs_node_t *fn) 465 { 466 fat_node_t *nodep = FAT_NODE(fn); 467 fat_bs_t *bs; 468 bool has_children; 469 int rc; 470 471 /* 472 * The node is not reachable from the file system. This means that the 473 * link count should be zero and that the index structure cannot be 474 * found in the position hash. Obviously, we don't need to lock the node 475 * nor its index structure. 476 */ 477 assert(nodep->lnkcnt == 0); 478 479 /* 480 * The node may not have any children. 481 */ 482 rc = fat_has_children(&has_children, fn); 483 if (rc != EOK) 484 return rc; 485 assert(!has_children); 486 487 bs = block_bb_get(nodep->idx->dev_handle); 488 if (nodep->firstc != FAT_CLST_RES0) { 489 assert(nodep->size); 490 /* Free all clusters allocated to the node. */ 491 rc = fat_free_clusters(bs, nodep->idx->dev_handle, 492 nodep->firstc); 493 } 494 495 fat_idx_destroy(nodep->idx); 496 free(nodep->bp); 497 free(nodep); 498 return rc; 499 } 500 501 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 502 { 503 fat_node_t *parentp = FAT_NODE(pfn); 504 fat_node_t *childp = FAT_NODE(cfn); 505 fat_dentry_t *d; 506 fat_bs_t *bs; 507 block_t *b; 508 unsigned i, j; 509 uint16_t bps; 510 unsigned dps; 511 unsigned blocks; 512 fat_cluster_t mcl, lcl; 513 int rc; 514 515 fibril_mutex_lock(&childp->lock); 516 if (childp->lnkcnt == 1) { 517 /* 518 * On FAT, we don't support multiple hard links. 519 */ 520 fibril_mutex_unlock(&childp->lock); 521 return EMLINK; 522 } 523 assert(childp->lnkcnt == 0); 524 fibril_mutex_unlock(&childp->lock); 525 526 if (!fat_dentry_name_verify(name)) { 527 /* 528 * Attempt to create unsupported name. 529 */ 530 return ENOTSUP; 531 } 532 533 /* 534 * Get us an unused parent node's dentry or grow the parent and allocate 535 * a new one. 536 */ 537 538 fibril_mutex_lock(&parentp->idx->lock); 539 bs = block_bb_get(parentp->idx->dev_handle); 540 bps = uint16_t_le2host(bs->bps); 541 dps = bps / sizeof(fat_dentry_t); 542 543 blocks = parentp->size / bps; 544 545 for (i = 0; i < blocks; i++) { 546 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 547 if (rc != EOK) { 548 fibril_mutex_unlock(&parentp->idx->lock); 549 return rc; 550 } 551 for (j = 0; j < dps; j++) { 552 d = ((fat_dentry_t *)b->data) + j; 553 switch (fat_classify_dentry(d)) { 554 case FAT_DENTRY_SKIP: 555 case FAT_DENTRY_VALID: 556 /* skipping used and meta entries */ 557 continue; 558 case FAT_DENTRY_FREE: 559 case FAT_DENTRY_LAST: 560 /* found an empty slot */ 561 goto hit; 562 } 563 } 564 rc = block_put(b); 565 if (rc != EOK) { 566 fibril_mutex_unlock(&parentp->idx->lock); 567 return rc; 568 } 569 } 570 j = 0; 571 572 /* 573 * We need to grow the parent in order to create a new unused dentry. 574 */ 575 if (parentp->firstc == FAT_CLST_ROOT) { 576 /* Can't grow the root directory. */ 577 fibril_mutex_unlock(&parentp->idx->lock); 578 return ENOSPC; 579 } 580 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 581 if (rc != EOK) { 582 fibril_mutex_unlock(&parentp->idx->lock); 583 return rc; 584 } 585 rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 586 if (rc != EOK) { 587 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 588 fibril_mutex_unlock(&parentp->idx->lock); 589 return rc; 590 } 591 rc = fat_append_clusters(bs, parentp, mcl); 592 if (rc != EOK) { 593 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 594 fibril_mutex_unlock(&parentp->idx->lock); 595 return rc; 596 } 597 parentp->size += bps * bs->spc; 598 parentp->dirty = true; /* need to sync node */ 599 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 600 if (rc != EOK) { 601 fibril_mutex_unlock(&parentp->idx->lock); 602 return rc; 603 } 604 d = (fat_dentry_t *)b->data; 605 606 hit: 607 /* 608 * At this point we only establish the link between the parent and the 609 * child. The dentry, except of the name and the extension, will remain 610 * uninitialized until the corresponding node is synced. Thus the valid 611 * dentry data is kept in the child node structure. 612 */ 613 memset(d, 0, sizeof(fat_dentry_t)); 614 fat_dentry_name_set(d, name); 615 b->dirty = true; /* need to sync block */ 616 rc = block_put(b); 617 fibril_mutex_unlock(&parentp->idx->lock); 618 if (rc != EOK) 619 return rc; 620 621 fibril_mutex_lock(&childp->idx->lock); 622 623 /* 624 * If possible, create the Sub-directory Identifier Entry and the 625 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 626 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 627 * not use them anyway, so this is rather a sign of our good will. 628 */ 629 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 630 if (rc != EOK) { 631 /* 632 * Rather than returning an error, simply skip the creation of 633 * these two entries. 634 */ 635 goto skip_dots; 636 } 637 d = (fat_dentry_t *)b->data; 638 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 639 str_cmp(d->name, FAT_NAME_DOT) == 0) { 640 memset(d, 0, sizeof(fat_dentry_t)); 641 str_cpy(d->name, 8, FAT_NAME_DOT); 642 str_cpy(d->ext, 3, FAT_EXT_PAD); 643 d->attr = FAT_ATTR_SUBDIR; 644 d->firstc = host2uint16_t_le(childp->firstc); 645 /* TODO: initialize also the date/time members. */ 646 } 647 d++; 648 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 649 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 650 memset(d, 0, sizeof(fat_dentry_t)); 651 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 652 str_cpy(d->ext, 3, FAT_EXT_PAD); 653 d->attr = FAT_ATTR_SUBDIR; 654 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 655 host2uint16_t_le(FAT_CLST_RES0) : 656 host2uint16_t_le(parentp->firstc); 657 /* TODO: initialize also the date/time members. */ 658 } 659 b->dirty = true; /* need to sync block */ 660 /* 661 * Ignore the return value as we would have fallen through on error 662 * anyway. 663 */ 664 (void) block_put(b); 665 skip_dots: 666 667 childp->idx->pfc = parentp->firstc; 668 childp->idx->pdi = i * dps + j; 669 fibril_mutex_unlock(&childp->idx->lock); 670 671 fibril_mutex_lock(&childp->lock); 672 childp->lnkcnt = 1; 673 childp->dirty = true; /* need to sync node */ 674 fibril_mutex_unlock(&childp->lock); 675 676 /* 677 * Hash in the index structure into the position hash. 678 */ 679 fat_idx_hashin(childp->idx); 680 681 return EOK; 682 } 683 684 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 685 { 686 fat_node_t *parentp = FAT_NODE(pfn); 687 fat_node_t *childp = FAT_NODE(cfn); 688 fat_bs_t *bs; 689 fat_dentry_t *d; 690 uint16_t bps; 691 block_t *b; 692 bool has_children; 693 int rc; 694 695 if (!parentp) 696 return EBUSY; 697 698 rc = fat_has_children(&has_children, cfn); 699 if (rc != EOK) 700 return rc; 701 if (has_children) 702 return ENOTEMPTY; 703 704 fibril_mutex_lock(&parentp->lock); 705 fibril_mutex_lock(&childp->lock); 706 assert(childp->lnkcnt == 1); 707 fibril_mutex_lock(&childp->idx->lock); 708 bs = block_bb_get(childp->idx->dev_handle); 709 bps = uint16_t_le2host(bs->bps); 710 711 rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc, 712 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 713 BLOCK_FLAGS_NONE); 714 if (rc != EOK) 715 goto error; 716 d = (fat_dentry_t *)b->data + 717 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 718 /* mark the dentry as not-currently-used */ 719 d->name[0] = FAT_DENTRY_ERASED; 720 b->dirty = true; /* need to sync block */ 721 rc = block_put(b); 722 if (rc != EOK) 723 goto error; 724 725 /* remove the index structure from the position hash */ 726 fat_idx_hashout(childp->idx); 727 /* clear position information */ 728 childp->idx->pfc = FAT_CLST_RES0; 729 childp->idx->pdi = 0; 730 fibril_mutex_unlock(&childp->idx->lock); 731 childp->lnkcnt = 0; 732 childp->dirty = true; 733 fibril_mutex_unlock(&childp->lock); 734 fibril_mutex_unlock(&parentp->lock); 735 736 return EOK; 737 738 error: 739 fibril_mutex_unlock(&parentp->idx->lock); 740 fibril_mutex_unlock(&childp->lock); 741 fibril_mutex_unlock(&childp->idx->lock); 742 return rc; 743 } 744 745 int fat_has_children(bool *has_children, fs_node_t *fn) 729 746 { 730 747 fat_bs_t *bs; … … 737 754 int rc; 738 755 739 if (nodep->type != FAT_DIRECTORY) 740 return false; 756 if (nodep->type != FAT_DIRECTORY) { 757 *has_children = false; 758 return EOK; 759 } 741 760 742 761 fibril_mutex_lock(&nodep->idx->lock); … … 751 770 752 771 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 753 assert(rc == EOK); 772 if (rc != EOK) { 773 fibril_mutex_unlock(&nodep->idx->lock); 774 return rc; 775 } 754 776 for (j = 0; j < dps; j++) { 755 777 d = ((fat_dentry_t *)b->data) + j; … … 760 782 case FAT_DENTRY_LAST: 761 783 rc = block_put(b); 784 /* expect EOK as b was not dirty */ 762 785 assert(rc == EOK); 763 786 fibril_mutex_unlock(&nodep->idx->lock); 764 return false; 787 *has_children = false; 788 return EOK; 765 789 default: 766 790 case FAT_DENTRY_VALID: 767 791 rc = block_put(b); 792 /* expect EOK as b was not dirty */ 768 793 assert(rc == EOK); 769 794 fibril_mutex_unlock(&nodep->idx->lock); 770 return true; 795 *has_children = true; 796 return EOK; 771 797 } 772 rc = block_put(b);773 assert(rc == EOK);774 fibril_mutex_unlock(&nodep->idx->lock);775 return true;776 798 } 777 799 rc = block_put(b); 778 assert(rc == EOK); 800 assert(rc == EOK); /* expect EOK as b was not dirty */ 779 801 } 780 802 781 803 fibril_mutex_unlock(&nodep->idx->lock); 782 return false; 783 } 784 785 fs_node_t *fat_root_get(dev_handle_t dev_handle) 786 { 787 return fat_node_get(dev_handle, 0); 804 *has_children = false; 805 return EOK; 806 } 807 808 809 fs_index_t fat_index_get(fs_node_t *fn) 810 { 811 return FAT_NODE(fn)->idx->index; 812 } 813 814 size_t fat_size_get(fs_node_t *fn) 815 { 816 return FAT_NODE(fn)->size; 817 } 818 819 unsigned fat_lnkcnt_get(fs_node_t *fn) 820 { 821 return FAT_NODE(fn)->lnkcnt; 788 822 } 789 823 … … 805 839 /** libfs operations */ 806 840 libfs_ops_t fat_libfs_ops = { 841 .root_get = fat_root_get, 807 842 .match = fat_match, 808 843 .node_get = fat_node_get, … … 812 847 .link = fat_link, 813 848 .unlink = fat_unlink, 849 .has_children = fat_has_children, 814 850 .index_get = fat_index_get, 815 851 .size_get = fat_size_get, 816 852 .lnkcnt_get = fat_lnkcnt_get, 817 .has_children = fat_has_children,818 .root_get = fat_root_get,819 853 .plb_get_char = fat_plb_get_char, 820 854 .is_directory = fat_is_directory, … … 967 1001 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 968 1002 off_t pos = (off_t)IPC_GET_ARG3(*request); 969 fs_node_t *fn = fat_node_get(dev_handle, index);1003 fs_node_t *fn; 970 1004 fat_node_t *nodep; 971 1005 fat_bs_t *bs; … … 975 1009 int rc; 976 1010 1011 rc = fat_node_get(&fn, dev_handle, index); 1012 if (rc != EOK) { 1013 ipc_answer_0(rid, rc); 1014 return; 1015 } 977 1016 if (!fn) { 978 1017 ipc_answer_0(rid, ENOENT); … … 1052 1091 case FAT_DENTRY_VALID: 1053 1092 fat_dentry_name_get(d, name); 1054 rc = =block_put(b);1093 rc = block_put(b); 1055 1094 assert(rc == EOK); 1056 1095 goto hit; … … 1080 1119 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1081 1120 off_t pos = (off_t)IPC_GET_ARG3(*request); 1082 fs_node_t *fn = fat_node_get(dev_handle, index);1121 fs_node_t *fn; 1083 1122 fat_node_t *nodep; 1084 1123 fat_bs_t *bs; … … 1092 1131 int rc; 1093 1132 1133 rc = fat_node_get(&fn, dev_handle, index); 1134 if (rc != EOK) { 1135 ipc_answer_0(rid, rc); 1136 return; 1137 } 1094 1138 if (!fn) { 1095 1139 ipc_answer_0(rid, ENOENT); … … 1196 1240 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1197 1241 size_t size = (off_t)IPC_GET_ARG3(*request); 1198 fs_node_t *fn = fat_node_get(dev_handle, index);1242 fs_node_t *fn; 1199 1243 fat_node_t *nodep; 1200 1244 fat_bs_t *bs; … … 1204 1248 int rc; 1205 1249 1250 rc = fat_node_get(&fn, dev_handle, index); 1251 if (rc != EOK) { 1252 ipc_answer_0(rid, rc); 1253 return; 1254 } 1206 1255 if (!fn) { 1207 1256 ipc_answer_0(rid, ENOENT); … … 1267 1316 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1268 1317 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1318 fs_node_t *fn; 1269 1319 int rc; 1270 1320 1271 fs_node_t *fn = fat_node_get(dev_handle, index); 1321 rc = fat_node_get(&fn, dev_handle, index); 1322 if (rc != EOK) { 1323 ipc_answer_0(rid, rc); 1324 return; 1325 } 1272 1326 if (!fn) { 1273 1327 ipc_answer_0(rid, ENOENT); -
uspace/srv/fs/tmpfs/tmpfs_dump.c
rd27ed12 r2e37308 82 82 return false; 83 83 84 fn = ops->create(dev, L_FILE);85 if ( fn == NULL) {84 rc = ops->create(&fn, dev, L_FILE); 85 if (rc != EOK || fn == NULL) { 86 86 free(fname); 87 87 return false; … … 90 90 if (block_seqread(dev, bufpos, buflen, pos, fname, 91 91 entry.len) != EOK) { 92 ops->destroy(fn);92 (void) ops->destroy(fn); 93 93 free(fname); 94 94 return false; … … 98 98 rc = ops->link(pfn, fn, fname); 99 99 if (rc != EOK) { 100 ops->destroy(fn);100 (void) ops->destroy(fn); 101 101 free(fname); 102 102 return false; … … 126 126 return false; 127 127 128 fn = ops->create(dev, L_DIRECTORY);129 if ( fn == NULL) {128 rc = ops->create(&fn, dev, L_DIRECTORY); 129 if (rc != EOK || fn == NULL) { 130 130 free(fname); 131 131 return false; … … 134 134 if (block_seqread(dev, bufpos, buflen, pos, fname, 135 135 entry.len) != EOK) { 136 ops->destroy(fn);136 (void) ops->destroy(fn); 137 137 free(fname); 138 138 return false; … … 142 142 rc = ops->link(pfn, fn, fname); 143 143 if (rc != EOK) { 144 ops->destroy(fn);144 (void) ops->destroy(fn); 145 145 free(fname); 146 146 return false; … … 164 164 { 165 165 libfs_ops_t *ops = &tmpfs_libfs_ops; 166 fs_node_t *fn; 166 167 int rc; 167 168 … … 182 183 goto error; 183 184 184 if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, 185 ops->root_get(dev))) 185 rc = ops->root_get(&fn, dev); 186 if (rc != EOK) 187 goto error; 188 189 if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, fn)) 186 190 goto error; 187 191 -
uspace/srv/fs/tmpfs/tmpfs_ops.c
rd27ed12 r2e37308 67 67 68 68 /* Forward declarations of static functions. */ 69 static fs_node_t *tmpfs_match(fs_node_t *, const char *); 70 static fs_node_t *tmpfs_node_get(dev_handle_t, fs_index_t); 71 static void tmpfs_node_put(fs_node_t *); 72 static fs_node_t *tmpfs_create_node(dev_handle_t, int); 69 static int tmpfs_match(fs_node_t **, fs_node_t *, const char *); 70 static int tmpfs_node_get(fs_node_t **, dev_handle_t, fs_index_t); 71 static int tmpfs_node_put(fs_node_t *); 72 static int tmpfs_create_node(fs_node_t **, dev_handle_t, int); 73 static int tmpfs_destroy_node(fs_node_t *); 73 74 static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *); 74 75 static int tmpfs_unlink_node(fs_node_t *, fs_node_t *, const char *); 75 static int tmpfs_destroy_node(fs_node_t *);76 76 77 77 /* Implementation of helper functions. */ 78 static int tmpfs_root_get(fs_node_t **rfn, dev_handle_t dev_handle) 79 { 80 return tmpfs_node_get(rfn, dev_handle, TMPFS_SOME_ROOT); 81 } 82 83 static int tmpfs_has_children(bool *has_children, fs_node_t *fn) 84 { 85 *has_children = !list_empty(&TMPFS_NODE(fn)->cs_head); 86 return EOK; 87 } 88 78 89 static fs_index_t tmpfs_index_get(fs_node_t *fn) 79 90 { … … 89 100 { 90 101 return TMPFS_NODE(fn)->lnkcnt; 91 }92 93 static bool tmpfs_has_children(fs_node_t *fn)94 {95 return !list_empty(&TMPFS_NODE(fn)->cs_head);96 }97 98 static fs_node_t *tmpfs_root_get(dev_handle_t dev_handle)99 {100 return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT);101 102 } 102 103 … … 118 119 /** libfs operations */ 119 120 libfs_ops_t tmpfs_libfs_ops = { 121 .root_get = tmpfs_root_get, 120 122 .match = tmpfs_match, 121 123 .node_get = tmpfs_node_get, … … 125 127 .link = tmpfs_link_node, 126 128 .unlink = tmpfs_unlink_node, 129 .has_children = tmpfs_has_children, 127 130 .index_get = tmpfs_index_get, 128 131 .size_get = tmpfs_size_get, 129 132 .lnkcnt_get = tmpfs_lnkcnt_get, 130 .has_children = tmpfs_has_children,131 .root_get = tmpfs_root_get,132 133 .plb_get_char = tmpfs_plb_get_char, 133 134 .is_directory = tmpfs_is_directory, … … 197 198 { 198 199 fs_node_t *rfn; 200 int rc; 199 201 200 r fn = tmpfs_create_node(dev_handle, L_DIRECTORY);201 if ( !rfn)202 rc = tmpfs_create_node(&rfn, dev_handle, L_DIRECTORY); 203 if (rc != EOK || !rfn) 202 204 return false; 203 205 TMPFS_NODE(rfn)->lnkcnt = 0; /* FS root is not linked */ … … 205 207 } 206 208 207 fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component)209 int tmpfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 208 210 { 209 211 tmpfs_node_t *parentp = TMPFS_NODE(pfn); … … 212 214 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; 213 215 lnk = lnk->next) { 214 tmpfs_dentry_t *dentryp = list_get_instance(lnk, tmpfs_dentry_t, 215 link); 216 if (!str_cmp(dentryp->name, component)) 217 return FS_NODE(dentryp->node); 218 } 219 220 return NULL; 221 } 222 223 fs_node_t *tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index) 216 tmpfs_dentry_t *dentryp; 217 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); 218 if (!str_cmp(dentryp->name, component)) { 219 *rfn = FS_NODE(dentryp->node); 220 return EOK; 221 } 222 } 223 224 *rfn = NULL; 225 return EOK; 226 } 227 228 int tmpfs_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index) 224 229 { 225 230 unsigned long key[] = { … … 228 233 }; 229 234 link_t *lnk = hash_table_find(&nodes, key); 230 if (!lnk) 231 return NULL; 232 return FS_NODE(hash_table_get_instance(lnk, tmpfs_node_t, nh_link)); 233 } 234 235 void tmpfs_node_put(fs_node_t *fn) 235 if (lnk) { 236 tmpfs_node_t *nodep; 237 nodep = hash_table_get_instance(lnk, tmpfs_node_t, nh_link); 238 *rfn = FS_NODE(nodep); 239 } else { 240 *rfn = NULL; 241 } 242 return EOK; 243 } 244 245 int tmpfs_node_put(fs_node_t *fn) 236 246 { 237 247 /* nothing to do */ 238 } 239 240 fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag) 241 { 248 return EOK; 249 } 250 251 int tmpfs_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int lflag) 252 { 253 fs_node_t *rootfn; 254 int rc; 255 242 256 assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); 243 257 244 258 tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t)); 245 259 if (!nodep) 246 return NULL;260 return ENOMEM; 247 261 tmpfs_node_initialize(nodep); 248 262 nodep->bp = malloc(sizeof(fs_node_t)); 249 263 if (!nodep->bp) { 250 264 free(nodep); 251 return NULL;265 return ENOMEM; 252 266 } 253 267 fs_node_initialize(nodep->bp); 254 268 nodep->bp->data = nodep; /* link the FS and TMPFS nodes */ 255 if (!tmpfs_root_get(dev_handle)) 269 270 rc = tmpfs_root_get(&rootfn, dev_handle); 271 assert(rc == EOK); 272 if (!rootfn) 256 273 nodep->index = TMPFS_SOME_ROOT; 257 274 else … … 269 286 }; 270 287 hash_table_insert(&nodes, key, &nodep->nh_link); 271 return FS_NODE(nodep); 288 *rfn = FS_NODE(nodep); 289 return EOK; 290 } 291 292 int tmpfs_destroy_node(fs_node_t *fn) 293 { 294 tmpfs_node_t *nodep = TMPFS_NODE(fn); 295 296 assert(!nodep->lnkcnt); 297 assert(list_empty(&nodep->cs_head)); 298 299 unsigned long key[] = { 300 [NODES_KEY_INDEX] = nodep->index, 301 [NODES_KEY_DEV] = nodep->dev_handle 302 }; 303 hash_table_remove(&nodes, key, 2); 304 305 if (nodep->type == TMPFS_FILE) 306 free(nodep->data); 307 free(nodep->bp); 308 free(nodep); 309 return EOK; 272 310 } 273 311 … … 343 381 } 344 382 345 int tmpfs_destroy_node(fs_node_t *fn)346 {347 tmpfs_node_t *nodep = TMPFS_NODE(fn);348 349 assert(!nodep->lnkcnt);350 assert(list_empty(&nodep->cs_head));351 352 unsigned long key[] = {353 [NODES_KEY_INDEX] = nodep->index,354 [NODES_KEY_DEV] = nodep->dev_handle355 };356 hash_table_remove(&nodes, key, 2);357 358 if (nodep->type == TMPFS_FILE)359 free(nodep->data);360 free(nodep->bp);361 free(nodep);362 return EOK;363 }364 365 383 void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request) 366 384 { 367 385 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 386 int rc; 368 387 369 388 /* accept the mount options */ … … 395 414 } 396 415 397 tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle)); 416 fs_node_t *rootfn; 417 rc = tmpfs_root_get(&rootfn, dev_handle); 418 assert(rc == EOK); 419 tmpfs_node_t *rootp = TMPFS_NODE(rootfn); 398 420 if (str_cmp(opts, "restore") == 0) { 399 421 if (tmpfs_restore(dev_handle))
Note:
See TracChangeset
for help on using the changeset viewer.