Changes in uspace/lib/fs/libfs.c [b8dbe2f:f9b2cb4c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/fs/libfs.c
rb8dbe2f rf9b2cb4c 36 36 37 37 #include "libfs.h" 38 #include "../../srv/vfs/vfs.h" 38 39 #include <macros.h> 39 40 #include <errno.h> … … 44 45 #include <mem.h> 45 46 #include <sys/stat.h> 47 #include <sys/statfs.h> 46 48 #include <stdlib.h> 47 #include <fibril_synch.h>48 49 49 50 #define on_error(rc, action) \ … … 62 63 } while (0) 63 64 64 #define DPRINTF(...)65 66 #define LOG_EXIT(rc) \67 DPRINTF("Exiting %s() with rc = %d at line %d\n", __FUNC__, rc, __LINE__);68 69 65 static fs_reg_t reg; 70 66 … … 72 68 static libfs_ops_t *libfs_ops = NULL; 73 69 74 static void libfs_ link(libfs_ops_t *, fs_handle_t, ipc_callid_t,75 70 static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); 71 static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *); 76 72 static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, 77 73 ipc_call_t *); … … 79 75 static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t, 80 76 ipc_call_t *); 77 static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); 81 78 82 79 static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req) … … 107 104 } 108 105 106 static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req) 107 { 108 libfs_mount(libfs_ops, reg.fs_handle, rid, req); 109 } 110 109 111 static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req) 110 112 { … … 117 119 } 118 120 119 static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req) 120 { 121 libfs_link(libfs_ops, reg.fs_handle, rid, req); 121 static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req) 122 { 123 124 libfs_unmount(libfs_ops, rid, req); 122 125 } 123 126 … … 190 193 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 191 194 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 192 193 195 int rc; 194 fs_node_t *node = NULL; 195 rc = libfs_ops->node_get(&node, service_id, index); 196 if (rc == EOK && node != NULL) { 197 bool destroy = (libfs_ops->lnkcnt_get(node) == 0); 198 libfs_ops->node_put(node); 199 if (destroy) { 200 rc = vfs_out_ops->destroy(service_id, index); 201 } 202 } 196 197 rc = vfs_out_ops->destroy(service_id, index); 198 203 199 async_answer_0(rid, rc); 204 200 } … … 225 221 } 226 222 227 static void vfs_out_get_size(ipc_callid_t rid, ipc_call_t *req) 228 { 229 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 230 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 231 int rc; 232 233 fs_node_t *node = NULL; 234 rc = libfs_ops->node_get(&node, service_id, index); 235 if (rc != EOK) { 236 async_answer_0(rid, rc); 237 } 238 if (node == NULL) { 239 async_answer_0(rid, EINVAL); 240 } 241 242 uint64_t size = libfs_ops->size_get(node); 243 libfs_ops->node_put(node); 244 245 async_answer_2(rid, EOK, LOWER32(size), UPPER32(size)); 246 } 247 248 static void vfs_out_is_empty(ipc_callid_t rid, ipc_call_t *req) 249 { 250 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 251 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 252 int rc; 253 254 fs_node_t *node = NULL; 255 rc = libfs_ops->node_get(&node, service_id, index); 256 if (rc != EOK) { 257 async_answer_0(rid, rc); 258 } 259 if (node == NULL) { 260 async_answer_0(rid, EINVAL); 261 } 262 263 bool children = false; 264 rc = libfs_ops->has_children(&children, node); 265 libfs_ops->node_put(node); 266 267 if (rc != EOK) { 268 async_answer_0(rid, rc); 269 } 270 async_answer_0(rid, children ? ENOTEMPTY : EOK); 271 } 272 223 static void vfs_out_statfs(ipc_callid_t rid, ipc_call_t *req) 224 { 225 libfs_statfs(libfs_ops, reg.fs_handle, rid, req); 226 } 273 227 static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 274 228 { … … 293 247 vfs_out_mounted(callid, &call); 294 248 break; 249 case VFS_OUT_MOUNT: 250 vfs_out_mount(callid, &call); 251 break; 295 252 case VFS_OUT_UNMOUNTED: 296 253 vfs_out_unmounted(callid, &call); 297 254 break; 298 case VFS_OUT_ LINK:299 vfs_out_ link(callid, &call);255 case VFS_OUT_UNMOUNT: 256 vfs_out_unmount(callid, &call); 300 257 break; 301 258 case VFS_OUT_LOOKUP: … … 326 283 vfs_out_sync(callid, &call); 327 284 break; 328 case VFS_OUT_GET_SIZE: 329 vfs_out_get_size(callid, &call); 330 break; 331 case VFS_OUT_IS_EMPTY: 332 vfs_out_is_empty(callid, &call); 285 case VFS_OUT_STATFS: 286 vfs_out_statfs(callid, &call); 333 287 break; 334 288 default: … … 388 342 * Ask VFS for callback connection. 389 343 */ 390 async_connect_to_me(exch, 0, 0, 0, vfs_connection, NULL); 344 port_id_t port; 345 rc = async_create_callback_port(exch, INTERFACE_VFS_DRIVER_CB, 0, 0, 346 vfs_connection, NULL, &port); 391 347 392 348 /* … … 417 373 * the same connection fibril as well. 418 374 */ 419 async_set_ client_connection(vfs_connection);375 async_set_fallback_port_handler(vfs_connection, NULL); 420 376 421 377 return IPC_GET_RETVAL(answer); … … 427 383 } 428 384 385 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, 386 ipc_call_t *req) 387 { 388 service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req); 389 fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req); 390 fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req); 391 service_id_t mr_service_id = (service_id_t) IPC_GET_ARG4(*req); 392 393 async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL); 394 if (mountee_sess == NULL) { 395 async_answer_0(rid, EINVAL); 396 return; 397 } 398 399 fs_node_t *fn; 400 int res = ops->node_get(&fn, mp_service_id, mp_fs_index); 401 if ((res != EOK) || (!fn)) { 402 async_hangup(mountee_sess); 403 async_data_write_void(combine_rc(res, ENOENT)); 404 async_answer_0(rid, combine_rc(res, ENOENT)); 405 return; 406 } 407 408 if (fn->mp_data.mp_active) { 409 async_hangup(mountee_sess); 410 (void) ops->node_put(fn); 411 async_data_write_void(EBUSY); 412 async_answer_0(rid, EBUSY); 413 return; 414 } 415 416 async_exch_t *exch = async_exchange_begin(mountee_sess); 417 async_sess_t *sess = async_clone_establish(EXCHANGE_PARALLEL, exch); 418 419 if (!sess) { 420 async_exchange_end(exch); 421 async_hangup(mountee_sess); 422 (void) ops->node_put(fn); 423 async_data_write_void(errno); 424 async_answer_0(rid, errno); 425 return; 426 } 427 428 ipc_call_t answer; 429 int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED, 430 mr_service_id, &answer); 431 async_exchange_end(exch); 432 433 if (rc == EOK) { 434 fn->mp_data.mp_active = true; 435 fn->mp_data.fs_handle = mr_fs_handle; 436 fn->mp_data.service_id = mr_service_id; 437 fn->mp_data.sess = mountee_sess; 438 } 439 440 /* 441 * Do not release the FS node so that it stays in memory. 442 */ 443 async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), 444 IPC_GET_ARG3(answer), IPC_GET_ARG4(answer)); 445 } 446 447 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req) 448 { 449 service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req); 450 fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req); 451 fs_node_t *fn; 452 int res; 453 454 res = ops->node_get(&fn, mp_service_id, mp_fs_index); 455 if ((res != EOK) || (!fn)) { 456 async_answer_0(rid, combine_rc(res, ENOENT)); 457 return; 458 } 459 460 /* 461 * We are clearly expecting to find the mount point active. 462 */ 463 if (!fn->mp_data.mp_active) { 464 (void) ops->node_put(fn); 465 async_answer_0(rid, EINVAL); 466 return; 467 } 468 469 /* 470 * Tell the mounted file system to unmount. 471 */ 472 async_exch_t *exch = async_exchange_begin(fn->mp_data.sess); 473 res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.service_id); 474 async_exchange_end(exch); 475 476 /* 477 * If everything went well, perform the clean-up on our side. 478 */ 479 if (res == EOK) { 480 async_hangup(fn->mp_data.sess); 481 fn->mp_data.mp_active = false; 482 fn->mp_data.fs_handle = 0; 483 fn->mp_data.service_id = 0; 484 fn->mp_data.sess = NULL; 485 486 /* Drop the reference created in libfs_mount(). */ 487 (void) ops->node_put(fn); 488 } 489 490 (void) ops->node_put(fn); 491 async_answer_0(rid, res); 492 } 493 429 494 static char plb_get_char(unsigned pos) 430 495 { 431 496 return reg.plb_ro[pos % PLB_SIZE]; 432 }433 434 static int plb_get_component(char *dest, unsigned *sz, unsigned *ppos, unsigned last)435 {436 unsigned pos = *ppos;437 unsigned size = 0;438 439 if (pos == last) {440 *sz = 0;441 return ERANGE;442 }443 444 char c = plb_get_char(pos);445 if (c == '/') {446 pos++;447 }448 449 for (int i = 0; i <= NAME_MAX; i++) {450 c = plb_get_char(pos);451 if (pos == last || c == '/') {452 dest[i] = 0;453 *ppos = pos;454 *sz = size;455 return EOK;456 }457 dest[i] = c;458 pos++;459 size++;460 }461 return ENAMETOOLONG;462 }463 464 static int receive_fname(char *buffer)465 {466 size_t size;467 ipc_callid_t wcall;468 469 if (!async_data_write_receive(&wcall, &size)) {470 return ENOENT;471 }472 if (size > NAME_MAX + 1) {473 async_answer_0(wcall, ERANGE);474 return ERANGE;475 }476 return async_data_write_finalize(wcall, buffer, size);477 }478 479 /** Link a file at a path.480 */481 void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req)482 {483 service_id_t parent_sid = IPC_GET_ARG1(*req);484 fs_index_t parent_index = IPC_GET_ARG2(*req);485 fs_index_t child_index = IPC_GET_ARG3(*req);486 487 char component[NAME_MAX + 1];488 int rc = receive_fname(component);489 if (rc != EOK) {490 async_answer_0(rid, rc);491 return;492 }493 494 fs_node_t *parent = NULL;495 rc = ops->node_get(&parent, parent_sid, parent_index);496 if (parent == NULL) {497 async_answer_0(rid, rc == EOK ? EBADF : rc);498 return;499 }500 501 fs_node_t *child = NULL;502 rc = ops->node_get(&child, parent_sid, child_index);503 if (child == NULL) {504 async_answer_0(rid, rc == EOK ? EBADF : rc);505 ops->node_put(parent);506 return;507 }508 509 rc = ops->link(parent, child, component);510 ops->node_put(parent);511 ops->node_put(child);512 async_answer_0(rid, rc);513 497 } 514 498 … … 526 510 * 527 511 */ 528 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req) 529 { 530 unsigned first = IPC_GET_ARG1(*req); 531 unsigned len = IPC_GET_ARG2(*req); 512 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, 513 ipc_call_t *req) 514 { 515 unsigned int first = IPC_GET_ARG1(*req); 516 unsigned int last = IPC_GET_ARG2(*req); 517 unsigned int next = first; 532 518 service_id_t service_id = IPC_GET_ARG3(*req); 533 fs_index_t index = IPC_GET_ARG4(*req); 534 int lflag = IPC_GET_ARG5(*req); 535 536 assert((int) index != -1); 537 538 DPRINTF("Entered libfs_lookup()\n"); 539 540 // TODO: Validate flags. 541 542 unsigned next = first; 543 unsigned last = first + len; 544 519 int lflag = IPC_GET_ARG4(*req); 520 fs_index_t index = IPC_GET_ARG5(*req); 545 521 char component[NAME_MAX + 1]; 522 int len; 546 523 int rc; 524 525 if (last < next) 526 last += PLB_SIZE; 547 527 548 528 fs_node_t *par = NULL; 549 529 fs_node_t *cur = NULL; 550 530 fs_node_t *tmp = NULL; 551 unsigned clen = 0; 552 553 rc = ops->node_get(&cur, service_id, index); 554 if (rc != EOK) { 555 async_answer_0(rid, rc); 556 LOG_EXIT(rc); 557 goto out; 558 } 559 560 assert(cur != NULL); 561 562 /* Find the file and its parent. */ 563 564 unsigned last_next = 0; 565 566 while (next != last) { 567 if (cur == NULL) { 568 assert(par != NULL); 569 goto out1; 531 532 rc = ops->root_get(&cur, service_id); 533 on_error(rc, goto out_with_answer); 534 535 if (cur->mp_data.mp_active) { 536 async_exch_t *exch = async_exchange_begin(cur->mp_data.sess); 537 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last, 538 cur->mp_data.service_id, lflag, index, 539 IPC_FF_ROUTE_FROM_ME); 540 async_exchange_end(exch); 541 542 (void) ops->node_put(cur); 543 return; 544 } 545 546 /* Eat slash */ 547 if (plb_get_char(next) == '/') 548 next++; 549 550 while (next <= last) { 551 bool has_children; 552 553 rc = ops->has_children(&has_children, cur); 554 on_error(rc, goto out_with_answer); 555 if (!has_children) 556 break; 557 558 /* Collect the component */ 559 len = 0; 560 while ((next <= last) && (plb_get_char(next) != '/')) { 561 if (len + 1 == NAME_MAX) { 562 /* Component length overflow */ 563 async_answer_0(rid, ENAMETOOLONG); 564 goto out; 565 } 566 component[len++] = plb_get_char(next); 567 /* Process next character */ 568 next++; 570 569 } 571 572 if (!ops->is_directory(cur)) { 573 async_answer_0(rid, ENOTDIR); 574 LOG_EXIT(ENOTDIR); 570 571 assert(len); 572 component[len] = '\0'; 573 /* Eat slash */ 574 next++; 575 576 /* Match the component */ 577 rc = ops->match(&tmp, cur, component); 578 on_error(rc, goto out_with_answer); 579 580 /* 581 * If the matching component is a mount point, there are two 582 * legitimate semantics of the lookup operation. The first is 583 * the commonly used one in which the lookup crosses each mount 584 * point into the mounted file system. The second semantics is 585 * used mostly during unmount() and differs from the first one 586 * only in that the last mount point in the looked up path, 587 * which is also its last component, is not crossed. 588 */ 589 590 if ((tmp) && (tmp->mp_data.mp_active) && 591 (!(lflag & L_MP) || (next <= last))) { 592 if (next > last) 593 next = last = first; 594 else 595 next--; 596 597 async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess); 598 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, 599 last, tmp->mp_data.service_id, lflag, index, 600 IPC_FF_ROUTE_FROM_ME); 601 async_exchange_end(exch); 602 603 (void) ops->node_put(cur); 604 (void) ops->node_put(tmp); 605 if (par) 606 (void) ops->node_put(par); 607 return; 608 } 609 610 /* Handle miss: match amongst siblings */ 611 if (!tmp) { 612 if (next <= last) { 613 /* There are unprocessed components */ 614 async_answer_0(rid, ENOENT); 615 goto out; 616 } 617 618 /* Miss in the last component */ 619 if (lflag & (L_CREATE | L_LINK)) { 620 /* Request to create a new link */ 621 if (!ops->is_directory(cur)) { 622 async_answer_0(rid, ENOTDIR); 623 goto out; 624 } 625 626 fs_node_t *fn; 627 if (lflag & L_CREATE) 628 rc = ops->create(&fn, service_id, 629 lflag); 630 else 631 rc = ops->node_get(&fn, service_id, 632 index); 633 on_error(rc, goto out_with_answer); 634 635 if (fn) { 636 rc = ops->link(cur, fn, component); 637 if (rc != EOK) { 638 if (lflag & L_CREATE) 639 (void) ops->destroy(fn); 640 else 641 (void) ops->node_put(fn); 642 async_answer_0(rid, rc); 643 } else { 644 (void) ops->node_put(cur); 645 cur = fn; 646 goto out_with_answer; 647 } 648 } else 649 async_answer_0(rid, ENOSPC); 650 651 goto out; 652 } 653 654 async_answer_0(rid, ENOENT); 575 655 goto out; 576 656 } 577 657 578 last_next = next;579 /* Collect the component */580 rc = plb_get_component(component, &clen, &next, last);581 assert(rc != ERANGE);582 if (rc != EOK) {583 async_answer_0(rid, rc);584 LOG_EXIT(rc);585 goto out;586 }587 588 if (clen == 0) {589 /* The path is just "/". */590 break;591 }592 593 assert(component[clen] == 0);594 595 /* Match the component */596 rc = ops->match(&tmp, cur, component);597 if (rc != EOK) {598 async_answer_0(rid, rc);599 LOG_EXIT(rc);600 goto out;601 }602 603 /* Descend one level */604 658 if (par) { 605 659 rc = ops->node_put(par); 606 if (rc != EOK) { 607 async_answer_0(rid, rc); 608 LOG_EXIT(rc); 609 goto out; 610 } 660 on_error(rc, goto out_with_answer); 611 661 } 612 662 663 /* Descend one level */ 613 664 par = cur; 614 665 cur = tmp; … … 616 667 } 617 668 618 /* At this point, par is either NULL or a directory. 619 * If cur is NULL, the looked up file does not exist yet. 620 */ 621 622 assert(par == NULL || ops->is_directory(par)); 623 assert(par != NULL || cur != NULL); 624 625 /* Check for some error conditions. */ 626 627 if (cur && (lflag & L_FILE) && (ops->is_directory(cur))) { 628 async_answer_0(rid, EISDIR); 629 LOG_EXIT(EISDIR); 630 goto out; 631 } 632 633 if (cur && (lflag & L_DIRECTORY) && (ops->is_file(cur))) { 634 async_answer_0(rid, ENOTDIR); 635 LOG_EXIT(ENOTDIR); 636 goto out; 637 } 638 639 /* Unlink. */ 640 641 if (lflag & L_UNLINK) { 642 if (!cur) { 643 async_answer_0(rid, ENOENT); 644 LOG_EXIT(ENOENT); 645 goto out; 646 } 647 if (!par) { 648 async_answer_0(rid, EINVAL); 649 LOG_EXIT(EINVAL); 650 goto out; 651 } 652 653 rc = ops->unlink(par, cur, component); 654 if (rc == EOK) { 655 int64_t size = ops->size_get(cur); 656 int32_t lsize = LOWER32(size); 657 if (lsize != size) { 658 lsize = -1; 659 } 660 661 async_answer_5(rid, fs_handle, service_id, 662 ops->index_get(cur), last, lsize, 663 ops->is_directory(cur)); 664 LOG_EXIT(EOK); 665 } else { 666 async_answer_0(rid, rc); 667 LOG_EXIT(rc); 668 } 669 goto out; 670 } 671 672 /* Create. */ 673 674 if (lflag & L_CREATE) { 675 if (cur && (lflag & L_EXCLUSIVE)) { 676 async_answer_0(rid, EEXIST); 677 LOG_EXIT(EEXIST); 678 goto out; 679 } 680 681 if (!cur) { 682 rc = ops->create(&cur, service_id, lflag & (L_FILE|L_DIRECTORY)); 683 if (rc != EOK) { 684 async_answer_0(rid, rc); 685 LOG_EXIT(rc); 686 goto out; 687 } 688 if (!cur) { 689 async_answer_0(rid, ENOSPC); 690 LOG_EXIT(ENOSPC); 669 /* Handle miss: excessive components */ 670 if (next <= last) { 671 bool has_children; 672 rc = ops->has_children(&has_children, cur); 673 on_error(rc, goto out_with_answer); 674 675 if (has_children) 676 goto skip_miss; 677 678 if (lflag & (L_CREATE | L_LINK)) { 679 if (!ops->is_directory(cur)) { 680 async_answer_0(rid, ENOTDIR); 691 681 goto out; 692 682 } 693 683 694 rc = ops->link(par, cur, component); 695 if (rc != EOK) { 696 (void) ops->destroy(cur); 697 cur = NULL; 698 async_answer_0(rid, rc); 699 LOG_EXIT(rc); 700 goto out; 684 /* Collect next component */ 685 len = 0; 686 while (next <= last) { 687 if (plb_get_char(next) == '/') { 688 /* More than one component */ 689 async_answer_0(rid, ENOENT); 690 goto out; 691 } 692 693 if (len + 1 == NAME_MAX) { 694 /* Component length overflow */ 695 async_answer_0(rid, ENAMETOOLONG); 696 goto out; 697 } 698 699 component[len++] = plb_get_char(next); 700 /* Process next character */ 701 next++; 701 702 } 702 } 703 } 704 705 /* Return. */ 706 out1: 707 if (!cur) { 708 async_answer_5(rid, fs_handle, service_id, 709 ops->index_get(par), last_next, -1, true); 710 LOG_EXIT(EOK); 711 goto out; 712 } 713 714 if (lflag & L_OPEN) { 715 rc = ops->node_open(cur); 716 if (rc != EOK) { 717 async_answer_0(rid, rc); 718 LOG_EXIT(rc); 703 704 assert(len); 705 component[len] = '\0'; 706 707 fs_node_t *fn; 708 if (lflag & L_CREATE) 709 rc = ops->create(&fn, service_id, lflag); 710 else 711 rc = ops->node_get(&fn, service_id, index); 712 on_error(rc, goto out_with_answer); 713 714 if (fn) { 715 rc = ops->link(cur, fn, component); 716 if (rc != EOK) { 717 if (lflag & L_CREATE) 718 (void) ops->destroy(fn); 719 else 720 (void) ops->node_put(fn); 721 async_answer_0(rid, rc); 722 } else { 723 (void) ops->node_put(cur); 724 cur = fn; 725 goto out_with_answer; 726 } 727 } else 728 async_answer_0(rid, ENOSPC); 729 719 730 goto out; 720 731 } 721 } 722 723 int64_t size = ops->size_get(cur); 724 int32_t lsize = LOWER32(size); 725 if (lsize != size) { 726 lsize = -1; 727 } 728 729 async_answer_5(rid, fs_handle, service_id, 730 ops->index_get(cur), last, lsize, 731 ops->is_directory(cur)); 732 733 LOG_EXIT(EOK); 732 733 async_answer_0(rid, ENOENT); 734 goto out; 735 } 736 737 skip_miss: 738 739 /* Handle hit */ 740 if (lflag & L_UNLINK) { 741 unsigned int old_lnkcnt = ops->lnkcnt_get(cur); 742 rc = ops->unlink(par, cur, component); 743 744 if (rc == EOK) { 745 aoff64_t size = ops->size_get(cur); 746 async_answer_5(rid, fs_handle, service_id, 747 ops->index_get(cur), LOWER32(size), UPPER32(size), 748 old_lnkcnt); 749 } else 750 async_answer_0(rid, rc); 751 752 goto out; 753 } 754 755 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 756 (lflag & L_LINK)) { 757 async_answer_0(rid, EEXIST); 758 goto out; 759 } 760 761 if ((lflag & L_FILE) && (ops->is_directory(cur))) { 762 async_answer_0(rid, EISDIR); 763 goto out; 764 } 765 766 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { 767 async_answer_0(rid, ENOTDIR); 768 goto out; 769 } 770 771 if ((lflag & L_ROOT) && par) { 772 async_answer_0(rid, EINVAL); 773 goto out; 774 } 775 776 out_with_answer: 777 778 if (rc == EOK) { 779 if (lflag & L_OPEN) 780 rc = ops->node_open(cur); 781 782 if (rc == EOK) { 783 aoff64_t size = ops->size_get(cur); 784 async_answer_5(rid, fs_handle, service_id, 785 ops->index_get(cur), LOWER32(size), UPPER32(size), 786 ops->lnkcnt_get(cur)); 787 } else 788 async_answer_0(rid, rc); 789 790 } else 791 async_answer_0(rid, rc); 792 734 793 out: 735 if (par) { 794 795 if (par) 736 796 (void) ops->node_put(par); 737 } 738 739 if (cur) { 797 798 if (cur) 740 799 (void) ops->node_put(cur); 741 } 742 743 if (tmp) { 800 801 if (tmp) 744 802 (void) ops->node_put(tmp); 745 }746 803 } 747 804 … … 751 808 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request); 752 809 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 753 810 754 811 fs_node_t *fn; 755 812 int rc = ops->node_get(&fn, service_id, index); 756 813 on_error(rc, answer_and_return(rid, rc)); 757 814 758 815 ipc_callid_t callid; 759 816 size_t size; … … 765 822 return; 766 823 } 767 824 768 825 struct stat stat; 769 826 memset(&stat, 0, sizeof(struct stat)); 770 827 771 828 stat.fs_handle = fs_handle; 772 829 stat.service_id = service_id; … … 777 834 stat.size = ops->size_get(fn); 778 835 stat.service = ops->service_get(fn); 779 836 780 837 ops->node_put(fn); 781 838 839 782 840 async_data_read_finalize(callid, &stat, sizeof(struct stat)); 783 841 async_answer_0(rid, EOK); 784 842 } 843 844 void libfs_statfs(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, 845 ipc_call_t *request) 846 { 847 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request); 848 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 849 850 fs_node_t *fn; 851 int rc = ops->node_get(&fn, service_id, index); 852 on_error(rc, answer_and_return(rid, rc)); 853 854 ipc_callid_t callid; 855 size_t size; 856 if ((!async_data_read_receive(&callid, &size)) || 857 (size != sizeof(struct statfs))) { 858 goto error; 859 } 860 861 struct statfs st; 862 memset(&st, 0, sizeof(struct statfs)); 863 864 if (ops->size_block != NULL) { 865 rc = ops->size_block(service_id, &st.f_bsize); 866 if (rc != EOK) 867 goto error; 868 } 869 870 if (ops->total_block_count != NULL) { 871 rc = ops->total_block_count(service_id, &st.f_blocks); 872 if (rc != EOK) 873 goto error; 874 } 875 876 if (ops->free_block_count != NULL) { 877 rc = ops->free_block_count(service_id, &st.f_bfree); 878 if (rc != EOK) 879 goto error; 880 } 881 882 ops->node_put(fn); 883 async_data_read_finalize(callid, &st, sizeof(struct statfs)); 884 async_answer_0(rid, EOK); 885 return; 886 887 error: 888 ops->node_put(fn); 889 async_answer_0(callid, EINVAL); 890 async_answer_0(rid, EINVAL); 891 } 892 785 893 786 894 /** Open VFS triplet. … … 836 944 837 945 fibril_mutex_lock(&instances_mutex); 838 list_foreach(instances_list, link) { 839 fs_instance_t *cur = list_get_instance(link, fs_instance_t, 840 link); 841 946 list_foreach(instances_list, link, fs_instance_t, cur) { 842 947 if (cur->service_id == service_id) { 843 948 fibril_mutex_unlock(&instances_mutex); … … 862 967 { 863 968 fibril_mutex_lock(&instances_mutex); 864 list_foreach(instances_list, link) { 865 fs_instance_t *inst = list_get_instance(link, fs_instance_t, 866 link); 867 969 list_foreach(instances_list, link, fs_instance_t, inst) { 868 970 if (inst->service_id == service_id) { 869 971 *idp = inst->data; … … 879 981 { 880 982 fibril_mutex_lock(&instances_mutex); 881 list_foreach(instances_list, link) { 882 fs_instance_t *inst = list_get_instance(link, fs_instance_t, 883 link); 884 983 list_foreach(instances_list, link, fs_instance_t, inst) { 885 984 if (inst->service_id == service_id) { 886 985 list_remove(&inst->link);
Note:
See TracChangeset
for help on using the changeset viewer.