Changeset bf9dc4e2 in mainline
- Timestamp:
- 2013-07-28T19:32:36Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 778d26d
- Parents:
- d60ce4a
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/include/ipc/vfs.h
rd60ce4a rbf9dc4e2 97 97 VFS_OUT_STAT, 98 98 VFS_OUT_LOOKUP, 99 VFS_OUT_LINK, 99 100 VFS_OUT_DESTROY, 100 101 VFS_OUT_LAST … … 125 126 126 127 /** 127 * Lookup will succeed only if the object is a root directory. The flag is128 * mutually exclusive with L_FILE and L_MP.129 */130 #define L_ROOT 4131 132 /**133 128 * Lookup will succeed only if the object is a mount point. The flag is mutually 134 129 * exclusive with L_FILE and L_ROOT. … … 147 142 */ 148 143 #define L_CREATE 32 149 150 /**151 * L_LINK is used for linking to an already existing nodes.152 */153 #define L_LINK 64154 144 155 145 /** -
uspace/lib/fs/libfs.c
rd60ce4a rbf9dc4e2 62 62 } while (0) 63 63 64 #define DPRINTF(...) 65 66 #define LOG_EXIT(rc) \ 67 DPRINTF("Exiting %s() with rc = %d at line %d\n", __FUNC__, rc, __LINE__); 68 64 69 static fs_reg_t reg; 65 70 … … 69 74 static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); 70 75 static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *); 76 static void libfs_link(libfs_ops_t *, fs_handle_t, ipc_callid_t, 77 ipc_call_t *); 71 78 static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, 72 79 ipc_call_t *); … … 121 128 122 129 libfs_unmount(libfs_ops, rid, req); 130 } 131 132 static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req) 133 { 134 libfs_link(libfs_ops, reg.fs_handle, rid, req); 123 135 } 124 136 … … 250 262 vfs_out_unmount(callid, &call); 251 263 break; 264 case VFS_OUT_LINK: 265 vfs_out_link(callid, &call); 266 break; 252 267 case VFS_OUT_LOOKUP: 253 268 vfs_out_lookup(callid, &call); … … 486 501 } 487 502 503 static int plb_get_component(char *dest, unsigned *sz, unsigned *ppos, unsigned last) 504 { 505 unsigned pos = *ppos; 506 unsigned size = 0; 507 508 if (pos == last) { 509 *sz = 0; 510 return ERANGE; 511 } 512 513 char c = plb_get_char(pos); 514 if (c == '/') { 515 pos++; 516 } 517 518 for (int i = 0; i <= NAME_MAX; i++) { 519 c = plb_get_char(pos); 520 if (pos == last || c == '/') { 521 dest[i] = 0; 522 *ppos = pos; 523 *sz = size; 524 return EOK; 525 } 526 dest[i] = c; 527 pos++; 528 size++; 529 } 530 return ENAMETOOLONG; 531 } 532 533 static int receive_fname(char *buffer) 534 { 535 size_t size; 536 ipc_callid_t wcall; 537 538 if (!async_data_write_receive(&wcall, &size)) { 539 return ENOENT; 540 } 541 if (size > NAME_MAX + 1) { 542 async_answer_0(wcall, ERANGE); 543 return ERANGE; 544 } 545 return async_data_write_finalize(wcall, buffer, size); 546 } 547 548 /** Link a file at a path. 549 */ 550 void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req) 551 { 552 service_id_t parent_sid = IPC_GET_ARG1(*req); 553 fs_index_t parent_index = IPC_GET_ARG2(*req); 554 fs_index_t child_index = IPC_GET_ARG3(*req); 555 556 char component[NAME_MAX + 1]; 557 int rc = receive_fname(component); 558 if (rc != EOK) { 559 async_answer_0(rid, rc); 560 return; 561 } 562 563 fs_node_t *parent = NULL; 564 rc = ops->node_get(&parent, parent_sid, parent_index); 565 if (parent == NULL) { 566 async_answer_0(rid, rc == EOK ? EBADF : rc); 567 return; 568 } 569 570 fs_node_t *child = NULL; 571 rc = ops->node_get(&child, parent_sid, child_index); 572 if (child == NULL) { 573 async_answer_0(rid, rc == EOK ? EBADF : rc); 574 ops->node_put(parent); 575 return; 576 } 577 578 rc = ops->link(parent, child, component); 579 ops->node_put(parent); 580 ops->node_put(child); 581 async_answer_0(rid, rc); 582 } 583 488 584 /** Lookup VFS triplet by name in the file system name space. 489 585 * … … 499 595 * 500 596 */ 501 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, 502 ipc_call_t *req) 503 { 504 unsigned int first = IPC_GET_ARG1(*req); 505 unsigned int last = IPC_GET_ARG2(*req); 506 unsigned int next = first; 597 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req) 598 { 599 unsigned first = IPC_GET_ARG1(*req); 600 unsigned len = IPC_GET_ARG2(*req); 507 601 service_id_t service_id = IPC_GET_ARG3(*req); 508 int lflag = IPC_GET_ARG4(*req); 509 fs_index_t index = IPC_GET_ARG5(*req); 602 fs_index_t index = IPC_GET_ARG4(*req); 603 int lflag = IPC_GET_ARG5(*req); 604 605 DPRINTF("Entered libfs_lookup()\n"); 606 607 // TODO: Validate flags. 608 609 unsigned next = first; 610 unsigned last = first + len; 611 510 612 char component[NAME_MAX + 1]; 511 int len;512 613 int rc; 513 514 if (last < next)515 last += PLB_SIZE;516 614 517 615 fs_node_t *par = NULL; 518 616 fs_node_t *cur = NULL; 519 617 fs_node_t *tmp = NULL; 520 521 rc = ops->root_get(&cur, service_id); 522 on_error(rc, goto out_with_answer); 618 unsigned clen = 0; 619 620 if (index == (fs_index_t)-1) { 621 rc = ops->root_get(&cur, service_id); 622 } else { 623 rc = ops->node_get(&cur, service_id, index); 624 } 625 if (rc != EOK) { 626 async_answer_0(rid, rc); 627 LOG_EXIT(rc); 628 goto out; 629 } 630 631 assert(cur != NULL); 523 632 524 633 if (cur->mp_data.mp_active) { 525 634 async_exch_t *exch = async_exchange_begin(cur->mp_data.sess); 526 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last, 527 cur->mp_data.service_id, lflag, index, 528 IPC_FF_ROUTE_FROM_ME); 635 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last - next, 636 cur->mp_data.service_id, (fs_index_t) -1, lflag, IPC_FF_ROUTE_FROM_ME); 529 637 async_exchange_end(exch); 530 638 531 639 (void) ops->node_put(cur); 532 return; 533 } 534 535 /* Eat slash */ 536 if (plb_get_char(next) == '/') 537 next++; 538 539 while (next <= last) { 540 bool has_children; 541 542 rc = ops->has_children(&has_children, cur); 543 on_error(rc, goto out_with_answer); 544 if (!has_children) 545 break; 640 DPRINTF("Passing to another filesystem instance.\n"); 641 return; 642 } 643 644 /* Find the file and its parent. */ 645 646 while (next != last) { 647 if (cur == NULL) { 648 async_answer_0(rid, ENOENT); 649 LOG_EXIT(ENOENT); 650 goto out; 651 } 652 if (!ops->is_directory(cur)) { 653 async_answer_0(rid, ENOTDIR); 654 LOG_EXIT(ENOTDIR); 655 goto out; 656 } 546 657 547 658 /* Collect the component */ 548 len = 0; 549 while ((next <= last) && (plb_get_char(next) != '/')) { 550 if (len + 1 == NAME_MAX) { 551 /* Component length overflow */ 552 async_answer_0(rid, ENAMETOOLONG); 553 goto out; 554 } 555 component[len++] = plb_get_char(next); 556 /* Process next character */ 557 next++; 558 } 559 560 assert(len); 561 component[len] = '\0'; 562 /* Eat slash */ 563 next++; 659 rc = plb_get_component(component, &clen, &next, last); 660 assert(rc != ERANGE); 661 if (rc != EOK) { 662 async_answer_0(rid, rc); 663 LOG_EXIT(rc); 664 goto out; 665 } 666 667 if (clen == 0) { 668 /* The path is just "/". */ 669 break; 670 } 671 672 assert(component[clen] == 0); 564 673 565 674 /* Match the component */ 566 675 rc = ops->match(&tmp, cur, component); 567 on_error(rc, goto out_with_answer); 676 if (rc != EOK) { 677 async_answer_0(rid, rc); 678 LOG_EXIT(rc); 679 goto out; 680 } 568 681 569 682 /* … … 578 691 579 692 if ((tmp) && (tmp->mp_data.mp_active) && 580 (!(lflag & L_MP) || (next <= last))) { 581 if (next > last) 582 next = last = first; 583 else 584 next--; 585 693 (!(lflag & L_MP) || (next < last))) { 586 694 async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess); 587 695 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, 588 last , tmp->mp_data.service_id, lflag, index,696 last - next, tmp->mp_data.service_id, (fs_index_t) -1, lflag, 589 697 IPC_FF_ROUTE_FROM_ME); 590 698 async_exchange_end(exch); 591 592 (void) ops->node_put(cur); 593 (void) ops->node_put(tmp); 594 if (par) 595 (void) ops->node_put(par); 596 return; 597 } 598 599 /* Handle miss: match amongst siblings */ 600 if (!tmp) { 601 if (next <= last) { 602 /* There are unprocessed components */ 603 async_answer_0(rid, ENOENT); 699 DPRINTF("Passing to another filesystem instance.\n"); 700 goto out; 701 } 702 703 /* Descend one level */ 704 if (par) { 705 rc = ops->node_put(par); 706 if (rc != EOK) { 707 async_answer_0(rid, rc); 708 LOG_EXIT(rc); 604 709 goto out; 605 710 } 606 607 /* Miss in the last component */ 608 if (lflag & (L_CREATE | L_LINK)) { 609 /* Request to create a new link */ 610 if (!ops->is_directory(cur)) { 611 async_answer_0(rid, ENOTDIR); 612 goto out; 613 } 614 615 fs_node_t *fn; 616 if (lflag & L_CREATE) 617 rc = ops->create(&fn, service_id, 618 lflag); 619 else 620 rc = ops->node_get(&fn, service_id, 621 index); 622 on_error(rc, goto out_with_answer); 623 624 if (fn) { 625 rc = ops->link(cur, fn, component); 626 if (rc != EOK) { 627 if (lflag & L_CREATE) 628 (void) ops->destroy(fn); 629 else 630 (void) ops->node_put(fn); 631 async_answer_0(rid, rc); 632 } else { 633 (void) ops->node_put(cur); 634 cur = fn; 635 goto out_with_answer; 636 } 637 } else 638 async_answer_0(rid, ENOSPC); 639 640 goto out; 641 } 642 643 async_answer_0(rid, ENOENT); 644 goto out; 645 } 646 647 if (par) { 648 rc = ops->node_put(par); 649 on_error(rc, goto out_with_answer); 650 } 651 652 /* Descend one level */ 711 } 712 653 713 par = cur; 654 714 cur = tmp; … … 656 716 } 657 717 658 /* Handle miss: excessive components */ 659 if (next <= last) { 660 bool has_children; 661 rc = ops->has_children(&has_children, cur); 662 on_error(rc, goto out_with_answer); 663 664 if (has_children) 665 goto skip_miss; 666 667 if (lflag & (L_CREATE | L_LINK)) { 668 if (!ops->is_directory(cur)) { 669 async_answer_0(rid, ENOTDIR); 670 goto out; 671 } 672 673 /* Collect next component */ 674 len = 0; 675 while (next <= last) { 676 if (plb_get_char(next) == '/') { 677 /* More than one component */ 678 async_answer_0(rid, ENOENT); 679 goto out; 680 } 681 682 if (len + 1 == NAME_MAX) { 683 /* Component length overflow */ 684 async_answer_0(rid, ENAMETOOLONG); 685 goto out; 686 } 687 688 component[len++] = plb_get_char(next); 689 /* Process next character */ 690 next++; 691 } 692 693 assert(len); 694 component[len] = '\0'; 695 696 fs_node_t *fn; 697 if (lflag & L_CREATE) 698 rc = ops->create(&fn, service_id, lflag); 699 else 700 rc = ops->node_get(&fn, service_id, index); 701 on_error(rc, goto out_with_answer); 702 703 if (fn) { 704 rc = ops->link(cur, fn, component); 705 if (rc != EOK) { 706 if (lflag & L_CREATE) 707 (void) ops->destroy(fn); 708 else 709 (void) ops->node_put(fn); 710 async_answer_0(rid, rc); 711 } else { 712 (void) ops->node_put(cur); 713 cur = fn; 714 goto out_with_answer; 715 } 716 } else 717 async_answer_0(rid, ENOSPC); 718 718 /* At this point, par is either NULL or a directory. 719 * If cur is NULL, the looked up file does not exist yet. 720 */ 721 722 assert(par == NULL || ops->is_directory(par)); 723 assert(par != NULL || cur != NULL); 724 725 /* Check for some error conditions. */ 726 727 if (cur && (lflag & L_FILE) && (ops->is_directory(cur))) { 728 async_answer_0(rid, EISDIR); 729 LOG_EXIT(EISDIR); 730 goto out; 731 } 732 733 if (cur && (lflag & L_DIRECTORY) && (ops->is_file(cur))) { 734 async_answer_0(rid, ENOTDIR); 735 LOG_EXIT(ENOTDIR); 736 goto out; 737 } 738 739 /* Unlink. */ 740 741 if (lflag & L_UNLINK) { 742 if (!cur) { 743 async_answer_0(rid, ENOENT); 744 LOG_EXIT(ENOENT); 719 745 goto out; 720 746 } 721 722 async_answer_0(rid, ENOENT); 723 goto out; 724 } 725 726 skip_miss: 727 728 /* Handle hit */ 729 if (lflag & L_UNLINK) { 747 if (!par) { 748 async_answer_0(rid, EINVAL); 749 LOG_EXIT(EINVAL); 750 goto out; 751 } 752 730 753 unsigned int old_lnkcnt = ops->lnkcnt_get(cur); 731 754 rc = ops->unlink(par, cur, component); 732 733 755 if (rc == EOK) { 734 756 aoff64_t size = ops->size_get(cur); … … 736 758 ops->index_get(cur), LOWER32(size), UPPER32(size), 737 759 old_lnkcnt); 738 } else 760 LOG_EXIT(EOK); 761 } else { 739 762 async_answer_0(rid, rc); 740 763 LOG_EXIT(rc); 764 } 741 765 goto out; 742 766 } 743 767 744 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 745 (lflag & L_LINK)) { 746 async_answer_0(rid, EEXIST); 768 /* Create. */ 769 770 if (lflag & L_CREATE) { 771 if (cur && (lflag & L_EXCLUSIVE)) { 772 async_answer_0(rid, EEXIST); 773 LOG_EXIT(EEXIST); 774 goto out; 775 } 776 777 if (!cur) { 778 rc = ops->create(&cur, service_id, lflag & (L_FILE|L_DIRECTORY)); 779 if (rc != EOK) { 780 async_answer_0(rid, rc); 781 LOG_EXIT(rc); 782 goto out; 783 } 784 if (!cur) { 785 async_answer_0(rid, ENOSPC); 786 LOG_EXIT(ENOSPC); 787 goto out; 788 } 789 790 rc = ops->link(par, cur, component); 791 if (rc != EOK) { 792 (void) ops->destroy(cur); 793 cur = NULL; 794 async_answer_0(rid, rc); 795 LOG_EXIT(rc); 796 goto out; 797 } 798 } 799 } 800 801 /* Return. */ 802 803 if (!cur) { 804 async_answer_0(rid, ENOENT); 805 LOG_EXIT(ENOENT); 747 806 goto out; 748 807 } 749 808 750 if ((lflag & L_FILE) && (ops->is_directory(cur))) { 751 async_answer_0(rid, EISDIR); 752 goto out; 753 } 754 755 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { 756 async_answer_0(rid, ENOTDIR); 757 goto out; 758 } 759 760 if ((lflag & L_ROOT) && par) { 761 async_answer_0(rid, EINVAL); 762 goto out; 763 } 764 765 out_with_answer: 766 767 if (rc == EOK) { 768 if (lflag & L_OPEN) 769 rc = ops->node_open(cur); 770 771 if (rc == EOK) { 772 aoff64_t size = ops->size_get(cur); 773 async_answer_5(rid, fs_handle, service_id, 774 ops->index_get(cur), LOWER32(size), UPPER32(size), 775 ops->lnkcnt_get(cur)); 776 } else 809 if (lflag & L_OPEN) { 810 rc = ops->node_open(cur); 811 if (rc != EOK) { 777 812 async_answer_0(rid, rc); 778 779 } else 780 async_answer_0(rid, rc); 781 813 LOG_EXIT(rc); 814 goto out; 815 } 816 } 817 818 aoff64_t size = ops->size_get(cur); 819 async_answer_5(rid, fs_handle, service_id, 820 ops->index_get(cur), LOWER32(size), UPPER32(size), 821 ops->lnkcnt_get(cur)); 822 823 LOG_EXIT(EOK); 782 824 out: 783 784 if (par) 825 if (par) { 785 826 (void) ops->node_put(par); 786 787 if (cur) 827 } 828 829 if (cur) { 788 830 (void) ops->node_put(cur); 789 790 if (tmp) 831 } 832 833 if (tmp) { 791 834 (void) ops->node_put(tmp); 835 } 792 836 } 793 837 -
uspace/srv/vfs/vfs.h
rd60ce4a rbf9dc4e2 180 180 extern vfs_info_t *fs_handle_to_info(fs_handle_t); 181 181 182 extern int vfs_lookup_internal( char *, int, vfs_lookup_res_t *,183 vfs_pair_t *, ...);182 extern int vfs_lookup_internal(vfs_triplet_t *, char *, int, vfs_lookup_res_t *); 183 extern int vfs_link_internal(vfs_triplet_t *, char *, vfs_triplet_t *); 184 184 185 185 extern bool vfs_nodes_init(void); -
uspace/srv/vfs/vfs_lookup.c
rd60ce4a rbf9dc4e2 46 46 #include <adt/list.h> 47 47 #include <vfs/canonify.h> 48 #include <dirent.h> 49 #include <assert.h> 50 51 #define DPRINTF(...) 48 52 49 53 #define min(a, b) ((a) < (b) ? (a) : (b)) … … 53 57 uint8_t *plb = NULL; 54 58 55 /** Perform a path lookup. 56 * 57 * @param path Path to be resolved; it must be a NULL-terminated 58 * string. 59 * @param lflag Flags to be used during lookup. 60 * @param result Empty structure where the lookup result will be stored. 61 * Can be NULL. 62 * @param altroot If non-empty, will be used instead of rootfs as the root 63 * of the whole VFS tree. 64 * 65 * @return EOK on success or an error code from errno.h. 66 * 67 */ 68 int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result, 69 vfs_pair_t *altroot, ...) 70 { 71 vfs_pair_t *root; 72 73 if (altroot) 74 root = altroot; 75 else 76 root = &rootfs; 77 78 if (!root->fs_handle) 79 return ENOENT; 80 81 size_t len; 82 path = canonify(path, &len); 83 if (!path) 84 return EINVAL; 85 86 fs_index_t index = 0; 87 if (lflag & L_LINK) { 88 va_list ap; 89 90 va_start(ap, altroot); 91 index = va_arg(ap, fs_index_t); 92 va_end(ap); 93 } 94 59 static int plb_insert_entry(plb_entry_t *entry, char *path, size_t *start, size_t len) 60 { 95 61 fibril_mutex_lock(&plb_mutex); 96 62 97 plb_entry_t entry; 98 link_initialize(&entry.plb_link); 99 entry.len = len; 63 link_initialize(&entry->plb_link); 64 entry->len = len; 100 65 101 66 size_t first; /* the first free index */ … … 138 103 */ 139 104 140 entry .index = first;141 entry .len = len;105 entry->index = first; 106 entry->len = len; 142 107 143 108 /* … … 145 110 * buffer. 146 111 */ 147 list_append(&entry .plb_link, &plb_entries);112 list_append(&entry->plb_link, &plb_entries); 148 113 149 114 fibril_mutex_unlock(&plb_mutex); … … 158 123 memcpy(plb, &path[cnt1], cnt2); 159 124 160 ipc_call_t answer; 161 async_exch_t *exch = vfs_exchange_grab(root->fs_handle); 162 aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first, 163 (sysarg_t) (first + len - 1) % PLB_SIZE, 164 (sysarg_t) root->service_id, (sysarg_t) lflag, (sysarg_t) index, 165 &answer); 166 167 sysarg_t rc; 168 async_wait_for(req, &rc); 169 vfs_exchange_release(exch); 170 125 *start = first; 126 return EOK; 127 } 128 129 static void plb_clear_entry(plb_entry_t *entry, size_t first, size_t len) 130 { 171 131 fibril_mutex_lock(&plb_mutex); 172 list_remove(&entry .plb_link);132 list_remove(&entry->plb_link); 173 133 /* 174 134 * Erasing the path from PLB will come handy for debugging purposes. 175 135 */ 136 size_t cnt1 = min(len, (PLB_SIZE - first) + 1); 137 size_t cnt2 = len - cnt1; 176 138 memset(&plb[first], 0, cnt1); 177 139 memset(plb, 0, cnt2); 178 140 fibril_mutex_unlock(&plb_mutex); 179 180 if ((int) rc < EOK) 181 return (int) rc; 182 183 if (!result) 184 return EOK; 141 } 142 143 static char *_strrchr(char *path, int c) 144 { 145 char *res = NULL; 146 while (*path != 0) { 147 if (*path == c) { 148 res = path; 149 } 150 path++; 151 } 152 return res; 153 } 154 155 int vfs_link_internal(vfs_triplet_t *base, char *path, vfs_triplet_t *child) 156 { 157 assert(base != NULL); 158 assert(child != NULL); 159 assert(base->fs_handle); 160 assert(child->fs_handle); 161 assert(path != NULL); 162 163 vfs_lookup_res_t res; 164 char component[NAME_MAX + 1]; 165 int rc; 166 167 size_t len; 168 char *npath = canonify(path, &len); 169 if (!npath) { 170 rc = EINVAL; 171 goto out; 172 } 173 path = npath; 174 175 char *slash = _strrchr(path, '/'); 176 if (slash && slash != path) { 177 if (slash[1] == 0) { 178 rc = EINVAL; 179 goto out; 180 } 181 182 memcpy(component, slash + 1, str_size(slash)); 183 *slash = 0; 184 185 rc = vfs_lookup_internal(base, path, L_DIRECTORY, &res); 186 if (rc != EOK) { 187 goto out; 188 } 189 base = &res.triplet; 190 191 *slash = '/'; 192 } else { 193 memcpy(component, path + 1, str_size(path)); 194 } 195 196 if (base->fs_handle != child->fs_handle || base->service_id != child->service_id) { 197 rc = EXDEV; 198 goto out; 199 } 200 201 async_exch_t *exch = vfs_exchange_grab(base->fs_handle); 202 aid_t req = async_send_3(exch, VFS_OUT_LINK, base->service_id, base->index, child->index, NULL); 203 204 rc = async_data_write_start(exch, component, str_size(component) + 1); 205 sysarg_t orig_rc; 206 async_wait_for(req, &orig_rc); 207 vfs_exchange_release(exch); 208 if (orig_rc != EOK) { 209 rc = orig_rc; 210 } 211 212 out: 213 DPRINTF("vfs_link_internal() with path '%s' returns %d\n", path, rc); 214 return rc; 215 } 216 217 /** Perform a path lookup. 218 * 219 * @param base The file from which to perform the lookup. 220 * @param path Path to be resolved; it must be a NULL-terminated 221 * string. 222 * @param lflag Flags to be used during lookup. 223 * @param result Empty structure where the lookup result will be stored. 224 * Can be NULL. 225 * 226 * @return EOK on success or an error code from errno.h. 227 * 228 */ 229 int vfs_lookup_internal(vfs_triplet_t *base, char *path, int lflag, vfs_lookup_res_t *result) 230 { 231 assert(base != NULL); 232 assert(path != NULL); 233 234 sysarg_t rc; 235 236 if (!base->fs_handle) { 237 rc = ENOENT; 238 goto out; 239 } 240 241 size_t len; 242 char *npath = canonify(path, &len); 243 if (!npath) { 244 rc = EINVAL; 245 goto out; 246 } 247 path = npath; 248 249 assert(path[0] == '/'); 250 251 size_t first; 252 253 plb_entry_t entry; 254 rc = plb_insert_entry(&entry, path, &first, len); 255 if (rc != EOK) { 256 goto out; 257 } 258 259 ipc_call_t answer; 260 async_exch_t *exch = vfs_exchange_grab(base->fs_handle); 261 aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first, (sysarg_t) len, 262 (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer); 263 async_wait_for(req, &rc); 264 vfs_exchange_release(exch); 265 266 plb_clear_entry(&entry, first, len); 267 268 if ((int) rc < 0) { 269 goto out; 270 } 271 272 if (!result) { 273 rc = EOK; 274 goto out; 275 } 185 276 186 277 result->triplet.fs_handle = (fs_handle_t) rc; … … 197 288 else 198 289 result->type = VFS_NODE_UNKNOWN; 199 200 return EOK; 290 291 rc = EOK; 292 293 out: 294 DPRINTF("vfs_lookup_internal() with path '%s' returns %d\n", path, rc); 295 return rc; 201 296 } 202 297 -
uspace/srv/vfs/vfs_ops.c
rd60ce4a rbf9dc4e2 68 68 FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock); 69 69 70 vfs_pair_t rootfs = { 71 .fs_handle = 0, 72 .service_id = 0 73 }; 70 vfs_node_t *root = NULL; 74 71 75 72 static int vfs_mount_internal(ipc_callid_t rid, service_id_t service_id, … … 90 87 /* Resolve the path to the mountpoint. */ 91 88 fibril_rwlock_write_lock(&namespace_rwlock); 92 if (rootfs.fs_handle) { 93 /* We already have the root FS. */ 94 if (str_cmp(mp, "/") == 0) { 95 /* Trying to mount root FS over root FS */ 96 fibril_rwlock_write_unlock(&namespace_rwlock); 97 async_answer_0(rid, EBUSY); 98 return EBUSY; 99 } 100 101 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 102 if (rc != EOK) { 103 /* The lookup failed for some reason. */ 104 fibril_rwlock_write_unlock(&namespace_rwlock); 105 async_answer_0(rid, rc); 106 return rc; 107 } 108 109 mp_node = vfs_node_get(&mp_res); 110 if (!mp_node) { 111 fibril_rwlock_write_unlock(&namespace_rwlock); 112 async_answer_0(rid, ENOMEM); 113 return ENOMEM; 114 } 115 116 /* 117 * Now we hold a reference to mp_node. 118 * It will be dropped upon the corresponding VFS_IN_UNMOUNT. 119 * This prevents the mount point from being deleted. 120 */ 121 } else { 89 if (root == NULL) { 122 90 /* We still don't have the root file system mounted. */ 123 if (str_cmp(mp, "/") == 0) { 124 /* 125 * For this simple, but important case, 126 * we are almost done. 127 */ 128 129 /* Tell the mountee that it is being mounted. */ 130 exch = vfs_exchange_grab(fs_handle); 131 msg = async_send_1(exch, VFS_OUT_MOUNTED, 132 (sysarg_t) service_id, &answer); 133 /* Send the mount options */ 134 rc = async_data_write_start(exch, (void *)opts, 135 str_size(opts)); 136 vfs_exchange_release(exch); 137 138 if (rc != EOK) { 139 async_forget(msg); 140 fibril_rwlock_write_unlock(&namespace_rwlock); 141 async_answer_0(rid, rc); 142 return rc; 143 } 144 async_wait_for(msg, &rc); 145 146 if (rc != EOK) { 147 fibril_rwlock_write_unlock(&namespace_rwlock); 148 async_answer_0(rid, rc); 149 return rc; 150 } 151 152 rindex = (fs_index_t) IPC_GET_ARG1(answer); 153 rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer), 154 IPC_GET_ARG3(answer)); 155 rlnkcnt = (unsigned) IPC_GET_ARG4(answer); 156 157 mr_res.triplet.fs_handle = fs_handle; 158 mr_res.triplet.service_id = service_id; 159 mr_res.triplet.index = rindex; 160 mr_res.size = rsize; 161 mr_res.lnkcnt = rlnkcnt; 162 mr_res.type = VFS_NODE_DIRECTORY; 163 164 rootfs.fs_handle = fs_handle; 165 rootfs.service_id = service_id; 166 167 /* Add reference to the mounted root. */ 168 mr_node = vfs_node_get(&mr_res); 169 assert(mr_node); 170 171 fibril_rwlock_write_unlock(&namespace_rwlock); 172 async_answer_0(rid, rc); 173 return rc; 174 } else { 91 if (str_cmp(mp, "/") != 0) { 175 92 /* 176 93 * We can't resolve this without the root filesystem … … 181 98 return ENOENT; 182 99 } 183 } 100 101 /* 102 * For this simple, but important case, 103 * we are almost done. 104 */ 105 106 /* Tell the mountee that it is being mounted. */ 107 exch = vfs_exchange_grab(fs_handle); 108 msg = async_send_1(exch, VFS_OUT_MOUNTED, 109 (sysarg_t) service_id, &answer); 110 /* Send the mount options */ 111 rc = async_data_write_start(exch, (void *)opts, 112 str_size(opts)); 113 vfs_exchange_release(exch); 114 115 if (rc != EOK) { 116 async_forget(msg); 117 fibril_rwlock_write_unlock(&namespace_rwlock); 118 async_answer_0(rid, rc); 119 return rc; 120 } 121 async_wait_for(msg, &rc); 122 123 if (rc != EOK) { 124 fibril_rwlock_write_unlock(&namespace_rwlock); 125 async_answer_0(rid, rc); 126 return rc; 127 } 128 129 rindex = (fs_index_t) IPC_GET_ARG1(answer); 130 rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer), 131 IPC_GET_ARG3(answer)); 132 rlnkcnt = (unsigned) IPC_GET_ARG4(answer); 133 134 mr_res.triplet.fs_handle = fs_handle; 135 mr_res.triplet.service_id = service_id; 136 mr_res.triplet.index = rindex; 137 mr_res.size = rsize; 138 mr_res.lnkcnt = rlnkcnt; 139 mr_res.type = VFS_NODE_DIRECTORY; 140 141 /* Add reference to the mounted root. */ 142 root = vfs_node_get(&mr_res); 143 assert(root); 144 145 fibril_rwlock_write_unlock(&namespace_rwlock); 146 async_answer_0(rid, rc); 147 return rc; 148 } 149 150 /* We already have the root FS. */ 151 if (str_cmp(mp, "/") == 0) { 152 /* Trying to mount root FS over root FS */ 153 fibril_rwlock_write_unlock(&namespace_rwlock); 154 async_answer_0(rid, EBUSY); 155 return EBUSY; 156 } 157 158 rc = vfs_lookup_internal((vfs_triplet_t *) root, mp, L_DIRECTORY, &mp_res); 159 if (rc != EOK) { 160 /* The lookup failed. */ 161 fibril_rwlock_write_unlock(&namespace_rwlock); 162 async_answer_0(rid, rc); 163 return rc; 164 } 165 166 mp_node = vfs_node_get(&mp_res); 167 if (!mp_node) { 168 fibril_rwlock_write_unlock(&namespace_rwlock); 169 async_answer_0(rid, ENOMEM); 170 return ENOMEM; 171 } 172 173 /* 174 * Now we hold a reference to mp_node. 175 * It will be dropped upon the corresponding VFS_IN_UNMOUNT. 176 * This prevents the mount point from being deleted. 177 */ 184 178 185 179 /* … … 435 429 * Lookup the mounted root and instantiate it. 436 430 */ 437 rc = vfs_lookup_internal( mp, L_ROOT, &mr_res, NULL);431 rc = vfs_lookup_internal((vfs_triplet_t *) root, mp, 0, &mr_res); 438 432 if (rc != EOK) { 439 433 fibril_rwlock_write_unlock(&namespace_rwlock); … … 488 482 } 489 483 490 rootfs.fs_handle = 0; 491 rootfs.service_id = 0; 484 root = NULL; 492 485 } else { 493 486 … … 499 492 */ 500 493 501 rc = vfs_lookup_internal( mp, L_MP, &mp_res, NULL);494 rc = vfs_lookup_internal((vfs_triplet_t *) root, mp, L_MP, &mp_res); 502 495 if (rc != EOK) { 503 496 fibril_rwlock_write_unlock(&namespace_rwlock); … … 624 617 /* Lookup the file structure corresponding to the file descriptor. */ 625 618 vfs_file_t *parent = NULL; 626 vfs_ pair_t *parent_node = NULL;619 vfs_node_t *parent_node = root; 627 620 // TODO: Client-side root. 628 621 if (parentfd != -1) { … … 633 626 return; 634 627 } 635 parent_node = (vfs_pair_t *)parent->node;628 parent_node = parent->node; 636 629 } 637 630 … … 639 632 640 633 vfs_lookup_res_t lr; 641 rc = vfs_lookup_internal( path, walk_lookup_flags(flags), &lr, parent_node);634 rc = vfs_lookup_internal((vfs_triplet_t *) parent_node, path, walk_lookup_flags(flags), &lr); 642 635 free(path); 643 636 … … 1069 1062 vfs_file_t *parent = NULL; 1070 1063 vfs_file_t *expect = NULL; 1071 vfs_ pair_t *parent_node = NULL;1064 vfs_node_t *parent_node = root; 1072 1065 1073 1066 int parentfd = IPC_GET_ARG1(*request); … … 1091 1084 goto exit; 1092 1085 } 1093 parent_node = (vfs_pair_t *)parent->node;1086 parent_node = parent->node; 1094 1087 } 1095 1088 … … 1102 1095 1103 1096 vfs_lookup_res_t lr; 1104 rc = vfs_lookup_internal( path, lflag, &lr, parent_node);1097 rc = vfs_lookup_internal((vfs_triplet_t *) parent_node, path, lflag, &lr); 1105 1098 if (rc != EOK) { 1106 1099 goto exit; … … 1117 1110 1118 1111 vfs_lookup_res_t lr; 1119 rc = vfs_lookup_internal( path, lflag | L_UNLINK, &lr, parent_node);1112 rc = vfs_lookup_internal((vfs_triplet_t *) parent_node, path, lflag | L_UNLINK, &lr); 1120 1113 if (rc != EOK) { 1121 1114 goto exit; … … 1201 1194 1202 1195 /* Lookup the node belonging to the old file name. */ 1203 rc = vfs_lookup_internal( oldc, L_NONE, &old_lr, NULL);1196 rc = vfs_lookup_internal((vfs_triplet_t *) root, oldc, L_NONE, &old_lr); 1204 1197 if (rc != EOK) { 1205 1198 fibril_rwlock_write_unlock(&namespace_rwlock); … … 1237 1230 1238 1231 /* Lookup parent of the new file name. */ 1239 rc = vfs_lookup_internal( parentc, L_NONE, &new_par_lr, NULL);1232 rc = vfs_lookup_internal((vfs_triplet_t *) root, parentc, L_NONE, &new_par_lr); 1240 1233 free(parentc); /* not needed anymore */ 1241 1234 if (rc != EOK) { … … 1261 1254 /* Destroy the old link for the new name. */ 1262 1255 vfs_node_t *new_node = NULL; 1263 rc = vfs_lookup_internal( newc, L_UNLINK, &new_lr, NULL);1256 rc = vfs_lookup_internal((vfs_triplet_t *) root, newc, L_UNLINK, &new_lr); 1264 1257 1265 1258 switch (rc) { … … 1291 1284 1292 1285 /* Create the new link for the new name. */ 1293 rc = vfs_l ookup_internal(newc, L_LINK, NULL, NULL, old_node->index);1286 rc = vfs_link_internal((vfs_triplet_t *) root, newc, (vfs_triplet_t *) old_node); 1294 1287 if (rc != EOK) { 1295 1288 fibril_rwlock_write_unlock(&namespace_rwlock); … … 1308 1301 1309 1302 /* Destroy the link for the old name. */ 1310 rc = vfs_lookup_internal( oldc, L_UNLINK, NULL, NULL);1303 rc = vfs_lookup_internal((vfs_triplet_t *) root, oldc, L_UNLINK, NULL); 1311 1304 if (rc != EOK) { 1312 1305 fibril_rwlock_write_unlock(&namespace_rwlock);
Note:
See TracChangeset
for help on using the changeset viewer.