Changes in / [2e37308:d27ed12] in mainline
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libfs/libfs.c
r2e37308 rd27ed12 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 63 48 /** Register file system server. 64 49 * … … 177 162 } 178 163 179 fs_node_t *fn; 180 res = ops->node_get(&fn, mp_dev_handle, mp_fs_index); 181 if (res != EOK || !fn) { 164 fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index); 165 if (!fn) { 182 166 ipc_hangup(mountee_phone); 183 ipc_answer_0(callid, combine_rc(res, ENOENT));184 ipc_answer_0(rid, combine_rc(res, ENOENT));167 ipc_answer_0(callid, ENOENT); 168 ipc_answer_0(rid, ENOENT); 185 169 return; 186 170 } … … 188 172 if (fn->mp_data.mp_active) { 189 173 ipc_hangup(mountee_phone); 190 (void)ops->node_put(fn);174 ops->node_put(fn); 191 175 ipc_answer_0(callid, EBUSY); 192 176 ipc_answer_0(rid, EBUSY); … … 195 179 196 180 rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); 197 if (rc != EOK) {181 if (rc != 0) { 198 182 ipc_hangup(mountee_phone); 199 (void)ops->node_put(fn);183 ops->node_put(fn); 200 184 ipc_answer_0(callid, rc); 201 185 ipc_answer_0(rid, rc); … … 246 230 char component[NAME_MAX + 1]; 247 231 int len; 248 int rc;249 232 250 233 if (last < next) … … 252 235 253 236 fs_node_t *par = NULL; 254 fs_node_t *cur = NULL;237 fs_node_t *cur = ops->root_get(dev_handle); 255 238 fs_node_t *tmp = NULL; 256 257 rc = ops->root_get(&cur, dev_handle);258 on_error(rc, goto out_with_answer);259 239 260 240 if (cur->mp_data.mp_active) { … … 262 242 next, last, cur->mp_data.dev_handle, lflag, index, 263 243 IPC_FF_ROUTE_FROM_ME); 264 (void)ops->node_put(cur);244 ops->node_put(cur); 265 245 return; 266 246 } … … 269 249 next++; /* eat slash */ 270 250 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 251 while (next <= last && ops->has_children(cur)) { 279 252 /* collect the component */ 280 253 len = 0; … … 294 267 295 268 /* match the component */ 296 rc = ops->match(&tmp, cur, component); 297 on_error(rc, goto out_with_answer); 298 269 tmp = ops->match(cur, component); 299 270 if (tmp && tmp->mp_data.mp_active) { 300 271 if (next > last) … … 306 277 VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle, 307 278 lflag, index, IPC_FF_ROUTE_FROM_ME); 308 (void)ops->node_put(cur);309 (void)ops->node_put(tmp);279 ops->node_put(cur); 280 ops->node_put(tmp); 310 281 if (par) 311 (void)ops->node_put(par);282 ops->node_put(par); 312 283 return; 313 284 } … … 329 300 fs_node_t *fn; 330 301 if (lflag & L_CREATE) 331 rc = ops->create(&fn, dev_handle, 332 lflag); 302 fn = ops->create(dev_handle, lflag); 333 303 else 334 rc = ops->node_get(&fn,dev_handle,304 fn = ops->node_get(dev_handle, 335 305 index); 336 on_error(rc, goto out_with_answer);337 306 if (fn) { 307 int rc; 308 338 309 rc = ops->link(cur, fn, component); 339 310 if (rc != EOK) { 340 if (lflag & L_CREATE) 341 (void) ops->destroy(fn); 311 if (lflag & L_CREATE) { 312 (void)ops->destroy(fn); 313 } 342 314 ipc_answer_0(rid, rc); 343 315 } else { … … 347 319 ops->size_get(fn), 348 320 ops->lnkcnt_get(fn)); 349 (void)ops->node_put(fn);321 ops->node_put(fn); 350 322 } 351 323 } else { … … 358 330 } 359 331 360 if (par) { 361 rc = ops->node_put(par); 362 on_error(rc, goto out_with_answer); 363 } 332 if (par) 333 ops->node_put(par); 364 334 365 335 /* descend one level */ … … 370 340 371 341 /* handle miss: excessive components */ 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 342 if (next <= last && !ops->has_children(cur)) { 380 343 if (lflag & (L_CREATE | L_LINK)) { 381 344 if (!ops->is_directory(cur)) { … … 405 368 fs_node_t *fn; 406 369 if (lflag & L_CREATE) 407 rc = ops->create(&fn,dev_handle, lflag);370 fn = ops->create(dev_handle, lflag); 408 371 else 409 rc = ops->node_get(&fn, dev_handle, index); 410 on_error(rc, goto out_with_answer); 372 fn = ops->node_get(dev_handle, index); 411 373 if (fn) { 374 int rc; 375 412 376 rc = ops->link(cur, fn, component); 413 377 if (rc != EOK) { 414 378 if (lflag & L_CREATE) 415 (void) 379 (void)ops->destroy(fn); 416 380 ipc_answer_0(rid, rc); 417 381 } else { … … 421 385 ops->size_get(fn), 422 386 ops->lnkcnt_get(fn)); 423 (void)ops->node_put(fn);387 ops->node_put(fn); 424 388 } 425 389 } else { … … 431 395 goto out; 432 396 } 433 skip_miss:434 397 435 398 /* handle hit */ 436 399 if (lflag & L_UNLINK) { 437 400 unsigned old_lnkcnt = ops->lnkcnt_get(cur); 438 rc= ops->unlink(par, cur, component);439 ipc_answer_5(rid, (ipcarg_t)r c, fs_handle, dev_handle,401 int res = ops->unlink(par, cur, component); 402 ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle, 440 403 ops->index_get(cur), ops->size_get(cur), old_lnkcnt); 441 404 goto out; … … 455 418 } 456 419 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 } 420 ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur), 421 ops->size_get(cur), ops->lnkcnt_get(cur)); 465 422 466 423 out: 467 424 if (par) 468 (void)ops->node_put(par);425 ops->node_put(par); 469 426 if (cur) 470 (void)ops->node_put(cur);427 ops->node_put(cur); 471 428 if (tmp) 472 (void)ops->node_put(tmp);429 ops->node_put(tmp); 473 430 } 474 431 … … 478 435 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 479 436 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 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)); 437 fs_node_t *fn = ops->node_get(dev_handle, index); 485 438 486 439 ipc_callid_t callid; … … 520 473 dev_handle_t dev_handle = IPC_GET_ARG1(*request); 521 474 fs_index_t index = IPC_GET_ARG2(*request); 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) { 475 476 fs_node_t *node = ops->node_get(dev_handle, index); 477 478 if (node == NULL) { 529 479 ipc_answer_0(rid, ENOENT); 530 480 return; 531 481 } 532 482 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);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); 537 487 } 538 488 -
uspace/lib/libfs/libfs.h
r2e37308 rd27ed12 56 56 57 57 typedef struct { 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); 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); 68 62 int (* destroy)(fs_node_t *); 69 63 int (* link)(fs_node_t *, fs_node_t *, const char *); 70 64 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 return74 * an integer error code.75 */76 65 fs_index_t (* index_get)(fs_node_t *); 77 66 size_t (* size_get)(fs_node_t *); 78 67 unsigned (* lnkcnt_get)(fs_node_t *); 68 bool (* has_children)(fs_node_t *); 69 fs_node_t *(* root_get)(dev_handle_t); 79 70 char (* plb_get_char)(unsigned pos); 80 71 bool (* is_directory)(fs_node_t *); -
uspace/srv/fs/fat/fat_ops.c
r2e37308 rd27ed12 250 250 * Forward declarations of FAT libfs operations. 251 251 */ 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); 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); 257 255 static int fat_destroy_node(fs_node_t *); 258 256 static int fat_link(fs_node_t *, fs_node_t *, const char *); 259 257 static int fat_unlink(fs_node_t *, fs_node_t *, const char *); 260 static int fat_has_children(bool *, fs_node_t*);258 static fs_node_t *fat_match(fs_node_t *, const char *); 261 259 static fs_index_t fat_index_get(fs_node_t *); 262 260 static size_t fat_size_get(fs_node_t *); 263 261 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 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) 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) 278 640 { 279 641 fat_bs_t *bs; … … 295 657 for (i = 0; i < blocks; i++) { 296 658 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 297 if (rc != EOK) { 298 fibril_mutex_unlock(&parentp->idx->lock); 299 return rc; 300 } 659 assert(rc == EOK); 301 660 for (j = 0; j < dps; j++) { 302 661 d = ((fat_dentry_t *)b->data) + j; … … 307 666 case FAT_DENTRY_LAST: 308 667 rc = block_put(b); 309 /* expect EOK as b was not dirty */ 310 assert(rc == EOK); 668 assert(rc == EOK); 311 669 fibril_mutex_unlock(&parentp->idx->lock); 312 *rfn = NULL; 313 return EOK; 670 return NULL; 314 671 default: 315 672 case FAT_DENTRY_VALID: … … 336 693 */ 337 694 rc = block_put(b); 338 /* expect EOK as b was not dirty */ 339 assert(rc == EOK); 340 return ENOMEM; 695 assert(rc == EOK); 696 return NULL; 341 697 } 342 698 nodep = fat_node_get_core(idx); 343 699 fibril_mutex_unlock(&idx->lock); 344 700 rc = block_put(b); 345 /* expect EOK as b was not dirty */346 701 assert(rc == EOK); 347 *rfn = FS_NODE(nodep); 348 return EOK; 702 return FS_NODE(nodep); 349 703 } 350 704 } 351 705 rc = block_put(b); 352 assert(rc == EOK); /* expect EOK as b was not dirty */706 assert(rc == EOK); 353 707 } 354 708 355 709 fibril_mutex_unlock(&parentp->idx->lock); 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) 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) 746 729 { 747 730 fat_bs_t *bs; … … 754 737 int rc; 755 738 756 if (nodep->type != FAT_DIRECTORY) { 757 *has_children = false; 758 return EOK; 759 } 739 if (nodep->type != FAT_DIRECTORY) 740 return false; 760 741 761 742 fibril_mutex_lock(&nodep->idx->lock); … … 770 751 771 752 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 772 if (rc != EOK) { 773 fibril_mutex_unlock(&nodep->idx->lock); 774 return rc; 775 } 753 assert(rc == EOK); 776 754 for (j = 0; j < dps; j++) { 777 755 d = ((fat_dentry_t *)b->data) + j; … … 782 760 case FAT_DENTRY_LAST: 783 761 rc = block_put(b); 784 /* expect EOK as b was not dirty */785 762 assert(rc == EOK); 786 763 fibril_mutex_unlock(&nodep->idx->lock); 787 *has_children = false; 788 return EOK; 764 return false; 789 765 default: 790 766 case FAT_DENTRY_VALID: 791 767 rc = block_put(b); 792 /* expect EOK as b was not dirty */793 768 assert(rc == EOK); 794 769 fibril_mutex_unlock(&nodep->idx->lock); 795 *has_children = true; 796 return EOK; 770 return true; 797 771 } 772 rc = block_put(b); 773 assert(rc == EOK); 774 fibril_mutex_unlock(&nodep->idx->lock); 775 return true; 798 776 } 799 777 rc = block_put(b); 800 assert(rc == EOK); /* expect EOK as b was not dirty */778 assert(rc == EOK); 801 779 } 802 780 803 781 fibril_mutex_unlock(&nodep->idx->lock); 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; 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); 822 788 } 823 789 … … 839 805 /** libfs operations */ 840 806 libfs_ops_t fat_libfs_ops = { 841 .root_get = fat_root_get,842 807 .match = fat_match, 843 808 .node_get = fat_node_get, … … 847 812 .link = fat_link, 848 813 .unlink = fat_unlink, 849 .has_children = fat_has_children,850 814 .index_get = fat_index_get, 851 815 .size_get = fat_size_get, 852 816 .lnkcnt_get = fat_lnkcnt_get, 817 .has_children = fat_has_children, 818 .root_get = fat_root_get, 853 819 .plb_get_char = fat_plb_get_char, 854 820 .is_directory = fat_is_directory, … … 1001 967 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1002 968 off_t pos = (off_t)IPC_GET_ARG3(*request); 1003 fs_node_t *fn ;969 fs_node_t *fn = fat_node_get(dev_handle, index); 1004 970 fat_node_t *nodep; 1005 971 fat_bs_t *bs; … … 1009 975 int rc; 1010 976 1011 rc = fat_node_get(&fn, dev_handle, index);1012 if (rc != EOK) {1013 ipc_answer_0(rid, rc);1014 return;1015 }1016 977 if (!fn) { 1017 978 ipc_answer_0(rid, ENOENT); … … 1091 1052 case FAT_DENTRY_VALID: 1092 1053 fat_dentry_name_get(d, name); 1093 rc = block_put(b);1054 rc == block_put(b); 1094 1055 assert(rc == EOK); 1095 1056 goto hit; … … 1119 1080 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1120 1081 off_t pos = (off_t)IPC_GET_ARG3(*request); 1121 fs_node_t *fn ;1082 fs_node_t *fn = fat_node_get(dev_handle, index); 1122 1083 fat_node_t *nodep; 1123 1084 fat_bs_t *bs; … … 1131 1092 int rc; 1132 1093 1133 rc = fat_node_get(&fn, dev_handle, index);1134 if (rc != EOK) {1135 ipc_answer_0(rid, rc);1136 return;1137 }1138 1094 if (!fn) { 1139 1095 ipc_answer_0(rid, ENOENT); … … 1240 1196 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1241 1197 size_t size = (off_t)IPC_GET_ARG3(*request); 1242 fs_node_t *fn ;1198 fs_node_t *fn = fat_node_get(dev_handle, index); 1243 1199 fat_node_t *nodep; 1244 1200 fat_bs_t *bs; … … 1248 1204 int rc; 1249 1205 1250 rc = fat_node_get(&fn, dev_handle, index);1251 if (rc != EOK) {1252 ipc_answer_0(rid, rc);1253 return;1254 }1255 1206 if (!fn) { 1256 1207 ipc_answer_0(rid, ENOENT); … … 1316 1267 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1317 1268 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1318 fs_node_t *fn;1319 1269 int rc; 1320 1270 1321 rc = fat_node_get(&fn, dev_handle, index); 1322 if (rc != EOK) { 1323 ipc_answer_0(rid, rc); 1324 return; 1325 } 1271 fs_node_t *fn = fat_node_get(dev_handle, index); 1326 1272 if (!fn) { 1327 1273 ipc_answer_0(rid, ENOENT); -
uspace/srv/fs/tmpfs/tmpfs_dump.c
r2e37308 rd27ed12 82 82 return false; 83 83 84 rc = ops->create(&fn,dev, L_FILE);85 if ( rc != EOK ||fn == NULL) {84 fn = ops->create(dev, L_FILE); 85 if (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 (void)ops->destroy(fn);92 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 (void)ops->destroy(fn);100 ops->destroy(fn); 101 101 free(fname); 102 102 return false; … … 126 126 return false; 127 127 128 rc = ops->create(&fn,dev, L_DIRECTORY);129 if ( rc != EOK ||fn == NULL) {128 fn = ops->create(dev, L_DIRECTORY); 129 if (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 (void)ops->destroy(fn);136 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 (void)ops->destroy(fn);144 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;167 166 int rc; 168 167 … … 183 182 goto error; 184 183 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)) 184 if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, 185 ops->root_get(dev))) 190 186 goto error; 191 187 -
uspace/srv/fs/tmpfs/tmpfs_ops.c
r2e37308 rd27ed12 67 67 68 68 /* Forward declarations of static functions. */ 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 *); 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); 74 73 static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *); 75 74 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 89 78 static fs_index_t tmpfs_index_get(fs_node_t *fn) 90 79 { … … 100 89 { 101 90 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); 102 101 } 103 102 … … 119 118 /** libfs operations */ 120 119 libfs_ops_t tmpfs_libfs_ops = { 121 .root_get = tmpfs_root_get,122 120 .match = tmpfs_match, 123 121 .node_get = tmpfs_node_get, … … 127 125 .link = tmpfs_link_node, 128 126 .unlink = tmpfs_unlink_node, 129 .has_children = tmpfs_has_children,130 127 .index_get = tmpfs_index_get, 131 128 .size_get = tmpfs_size_get, 132 129 .lnkcnt_get = tmpfs_lnkcnt_get, 130 .has_children = tmpfs_has_children, 131 .root_get = tmpfs_root_get, 133 132 .plb_get_char = tmpfs_plb_get_char, 134 133 .is_directory = tmpfs_is_directory, … … 198 197 { 199 198 fs_node_t *rfn; 200 int rc;201 199 202 r c = tmpfs_create_node(&rfn,dev_handle, L_DIRECTORY);203 if ( rc != EOK || !rfn)200 rfn = tmpfs_create_node(dev_handle, L_DIRECTORY); 201 if (!rfn) 204 202 return false; 205 203 TMPFS_NODE(rfn)->lnkcnt = 0; /* FS root is not linked */ … … 207 205 } 208 206 209 int tmpfs_match(fs_node_t **rfn,fs_node_t *pfn, const char *component)207 fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component) 210 208 { 211 209 tmpfs_node_t *parentp = TMPFS_NODE(pfn); … … 214 212 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; 215 213 lnk = lnk->next) { 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) 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) 229 224 { 230 225 unsigned long key[] = { … … 233 228 }; 234 229 link_t *lnk = hash_table_find(&nodes, key); 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) 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) 246 236 { 247 237 /* nothing to do */ 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 238 } 239 240 fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag) 241 { 256 242 assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); 257 243 258 244 tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t)); 259 245 if (!nodep) 260 return ENOMEM;246 return NULL; 261 247 tmpfs_node_initialize(nodep); 262 248 nodep->bp = malloc(sizeof(fs_node_t)); 263 249 if (!nodep->bp) { 264 250 free(nodep); 265 return ENOMEM;251 return NULL; 266 252 } 267 253 fs_node_initialize(nodep->bp); 268 254 nodep->bp->data = nodep; /* link the FS and TMPFS nodes */ 269 270 rc = tmpfs_root_get(&rootfn, dev_handle); 271 assert(rc == EOK); 272 if (!rootfn) 255 if (!tmpfs_root_get(dev_handle)) 273 256 nodep->index = TMPFS_SOME_ROOT; 274 257 else … … 286 269 }; 287 270 hash_table_insert(&nodes, key, &nodep->nh_link); 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; 271 return FS_NODE(nodep); 310 272 } 311 273 … … 381 343 } 382 344 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_handle 355 }; 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 383 365 void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request) 384 366 { 385 367 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 386 int rc;387 368 388 369 /* accept the mount options */ … … 414 395 } 415 396 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); 397 tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle)); 420 398 if (str_cmp(opts, "restore") == 0) { 421 399 if (tmpfs_restore(dev_handle))
Note:
See TracChangeset
for help on using the changeset viewer.