source: mainline/uspace/srv/vfs/vfs_mount.c@ 4d21cf8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4d21cf8 was 4d21cf8, checked in by Jakub Jermar <jakub@…>, 18 years ago

VFS work.
Introduce the notion of VFS_PAIR which corresponds to a file system instance,
and VFS_TRIPLET, which corresponds to a file system node. Separate vfs_triplet_t
and vfs_node_t as the former one is the stateless counterpart of the latter.

  • Property mode set to 100644
File size: 5.9 KB
RevLine 
[bcf23cf]1/*
2 * Copyright (c) 2007 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup fs
30 * @{
31 */
32
33/**
34 * @file vfs.c
35 * @brief VFS_MOUNT method.
36 */
37
38#include <ipc/ipc.h>
39#include <async.h>
40#include <errno.h>
41#include <stdlib.h>
42#include <string.h>
43#include <bool.h>
44#include <futex.h>
45#include <libadt/list.h>
46#include "vfs.h"
47
[2c2e0c6]48atomic_t rootfs_futex = FUTEX_INITIALIZER;
[4d21cf8]49vfs_triplet_t rootfs = {
50 .fs_handle = 0,
51 .dev_handle = 0,
52 .index = 0,
53};
[7313e7a]54
[4d21cf8]55static int lookup_root(int fs_handle, int dev_handle, vfs_triplet_t *root)
[7313e7a]56{
[4d21cf8]57 vfs_pair_t altroot = {
[7313e7a]58 .fs_handle = fs_handle,
59 .dev_handle = dev_handle,
60 };
61
[2c2e0c6]62 return vfs_lookup_internal("/", strlen("/"), root, &altroot);
[7313e7a]63}
[bcf23cf]64
65void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
66{
[7313e7a]67 int dev_handle;
68
69 /*
70 * We expect the library to do the device-name to device-handle
71 * translation for us, thus the device handle will arrive as ARG1
72 * in the request.
73 */
74 dev_handle = IPC_GET_ARG1(*request);
75
76 /*
77 * For now, don't make use of ARG2 and ARG3, but they can be used to
78 * carry mount options in the future.
79 */
80
81 /*
82 * Now, we expect the client to send us data with the name of the file
83 * system and the path of the mountpoint.
84 */
85 ipc_callid_t callid;
86 ipc_call_t call;
87 size_t size;
88 if (!ipc_data_receive(&callid, &call, NULL, &size)) {
89 ipc_answer_fast(callid, EINVAL, 0, 0);
90 ipc_answer_fast(rid, EINVAL, 0, 0);
91 return;
92 }
93
94 /*
95 * There is no sense in receiving data that can't hold a single
96 * character of path. We won't accept data that exceed certain limits
97 * either.
98 */
99 if ((size < FS_NAME_MAXLEN + 1) ||
100 (size > FS_NAME_MAXLEN + MAX_PATH_LEN)) {
101 ipc_answer_fast(callid, EINVAL, 0, 0);
102 ipc_answer_fast(rid, EINVAL, 0, 0);
103 return;
104 }
105
106 /*
107 * Allocate buffer for the data being received.
108 */
109 uint8_t *buf;
110 buf = malloc(size);
111 if (!buf) {
112 ipc_answer_fast(callid, ENOMEM, 0, 0);
113 ipc_answer_fast(rid, ENOMEM, 0, 0);
114 return;
115 }
116
117 /*
118 * Deliver the data.
119 */
120 (void) ipc_data_deliver(callid, &call, buf, size);
121
122 char fs_name[FS_NAME_MAXLEN + 1];
123 memcpy(fs_name, buf, FS_NAME_MAXLEN);
124 fs_name[FS_NAME_MAXLEN] = '\0';
125
126 /*
127 * Check if we know a file system with the same name as is in fs_name.
128 * This will also give us its file system handle.
129 */
130 int fs_handle = fs_name_to_handle(fs_name, true);
131 if (!fs_handle) {
132 free(buf);
133 ipc_answer_fast(rid, ENOENT, 0, 0);
134 return;
135 }
136
137 /*
138 * Lookup the root node of the filesystem being mounted.
139 */
140 int rc;
[4d21cf8]141 vfs_triplet_t mounted_root;
[7313e7a]142 rc = lookup_root(fs_handle, dev_handle, &mounted_root);
143 if (rc != EOK) {
144 free(buf);
145 ipc_answer_fast(rid, rc, 0, 0);
146 return;
147 }
148
149 /*
150 * Finally, we need to resolve the path to the mountpoint.
151 */
[4d21cf8]152 vfs_triplet_t mp;
[2c2e0c6]153 futex_down(&rootfs_futex);
[7313e7a]154 if (rootfs.fs_handle) {
155 /*
156 * We already have the root FS.
157 */
158 rc = vfs_lookup_internal((char *) (buf + FS_NAME_MAXLEN),
159 size - FS_NAME_MAXLEN, &mp, NULL);
160 if (rc != EOK) {
161 /*
162 * The lookup failed for some reason.
163 */
[2c2e0c6]164 futex_up(&rootfs_futex);
[7313e7a]165 free(buf);
166 ipc_answer_fast(rid, rc, 0, 0);
167 return;
168 }
169 } else {
170 /*
171 * We still don't have the root file system mounted.
172 */
[2c2e0c6]173 if ((size - FS_NAME_MAXLEN == strlen("/")) &&
[7313e7a]174 (buf[FS_NAME_MAXLEN] == '/')) {
175 /*
176 * For this simple, but important case, we are done.
177 */
178 rootfs = mounted_root;
[2c2e0c6]179 futex_up(&rootfs_futex);
[7313e7a]180 free(buf);
181 ipc_answer_fast(rid, EOK, 0, 0);
182 return;
183 } else {
184 /*
185 * We can't resolve this without the root filesystem
186 * being mounted first.
187 */
[2c2e0c6]188 futex_up(&rootfs_futex);
[7313e7a]189 free(buf);
190 ipc_answer_fast(rid, ENOENT, 0, 0);
191 return;
192 }
193 }
[2c2e0c6]194 futex_up(&rootfs_futex);
195
[af0ff9b2]196 free(buf); /* The buffer is not needed anymore. */
197
[7313e7a]198 /*
199 * At this point, we have all necessary pieces: file system and device
200 * handles, and we know the mount point VFS node and also the root node
201 * of the file system being mounted.
202 */
[af0ff9b2]203
204 int phone = vfs_grab_phone(mp.fs_handle);
205 /* Later we can use ARG3 to pass mode/flags. */
206 aid_t req1 = async_send_3(phone, VFS_MOUNT, (ipcarg_t) mp.dev_handle,
207 (ipcarg_t) mp.index, 0, NULL);
208 /* The second call uses the same method. */
209 aid_t req2 = async_send_3(phone, VFS_MOUNT,
210 (ipcarg_t) mounted_root.fs_handle,
211 (ipcarg_t) mounted_root.dev_handle, (ipcarg_t) mounted_root.index,
212 NULL);
213
214 ipcarg_t rc1;
215 ipcarg_t rc2;
216 async_wait_for(req1, &rc1);
217 async_wait_for(req2, &rc2);
218 vfs_release_phone(phone);
219
[18525c5]220 if (rc2 == EOK)
[af0ff9b2]221 ipc_answer_fast(rid, rc1, 0, 0);
[18525c5]222 else if (rc1 == EOK)
[af0ff9b2]223 ipc_answer_fast(rid, rc2, 0, 0);
[18525c5]224 else
225 ipc_answer_fast(rid, rc1, 0, 0);
[bcf23cf]226}
227
228/**
229 * @}
230 */
Note: See TracBrowser for help on using the repository browser.