source: mainline/uspace/srv/vfs/vfs_mount.c@ 67f63c4

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

Make uspace rwlock API naming conventions consistent with kernel rwlock API.

  • Property mode set to 100644
File size: 7.1 KB
Line 
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_mount.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
48atomic_t rootfs_futex = FUTEX_INITIALIZER;
49vfs_triplet_t rootfs = {
50 .fs_handle = 0,
51 .dev_handle = 0,
52 .index = 0,
53};
54
55static int lookup_root(int fs_handle, int dev_handle, vfs_triplet_t *root,
56 size_t *size)
57{
58 vfs_pair_t altroot = {
59 .fs_handle = fs_handle,
60 .dev_handle = dev_handle,
61 };
62
63 return vfs_lookup_internal("/", strlen("/"), root, size, &altroot);
64}
65
66void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
67{
68 int dev_handle;
69 vfs_node_t *mp_node = NULL;
70
71 /*
72 * We expect the library to do the device-name to device-handle
73 * translation for us, thus the device handle will arrive as ARG1
74 * in the request.
75 */
76 dev_handle = IPC_GET_ARG1(*request);
77
78 /*
79 * For now, don't make use of ARG2 and ARG3, but they can be used to
80 * carry mount options in the future.
81 */
82
83 ipc_callid_t callid;
84 size_t size;
85
86 /*
87 * Now, we expect the client to send us data with the name of the file
88 * system.
89 */
90 if (!ipc_data_write_receive(&callid, &size)) {
91 ipc_answer_0(callid, EINVAL);
92 ipc_answer_0(rid, EINVAL);
93 return;
94 }
95
96 /*
97 * Don't receive more than is necessary for storing a full file system
98 * name.
99 */
100 if (size < 1 || size > FS_NAME_MAXLEN) {
101 ipc_answer_0(callid, EINVAL);
102 ipc_answer_0(rid, EINVAL);
103 return;
104 }
105
106 /*
107 * Deliver the file system name.
108 */
109 char fs_name[FS_NAME_MAXLEN + 1];
110 (void) ipc_data_write_finalize(callid, fs_name, size);
111 fs_name[size] = '\0';
112
113 /*
114 * Check if we know a file system with the same name as is in fs_name.
115 * This will also give us its file system handle.
116 */
117 int fs_handle = fs_name_to_handle(fs_name, true);
118 if (!fs_handle) {
119 ipc_answer_0(rid, ENOENT);
120 return;
121 }
122
123 /*
124 * Now, we want the client to send us the mount point.
125 */
126 if (!ipc_data_write_receive(&callid, &size)) {
127 ipc_answer_0(callid, EINVAL);
128 ipc_answer_0(rid, EINVAL);
129 return;
130 }
131
132 /*
133 * Check whether size is reasonable wrt. the mount point.
134 */
135 if (size < 1 || size > MAX_PATH_LEN) {
136 ipc_answer_0(callid, EINVAL);
137 ipc_answer_0(rid, EINVAL);
138 return;
139 }
140 /*
141 * Allocate buffer for the mount point data being received.
142 */
143 uint8_t *buf;
144 buf = malloc(size);
145 if (!buf) {
146 ipc_answer_0(callid, ENOMEM);
147 ipc_answer_0(rid, ENOMEM);
148 return;
149 }
150
151 /*
152 * Deliver the mount point.
153 */
154 (void) ipc_data_write_finalize(callid, buf, size);
155
156 /*
157 * Lookup the root node of the filesystem being mounted.
158 * In this case, we don't need to take the namespace_futex as the root
159 * node cannot be removed. However, we do take a reference to it so
160 * that we can track how many times it has been mounted.
161 */
162 int rc;
163 vfs_triplet_t mounted_root;
164 size_t mrsz;
165 rc = lookup_root(fs_handle, dev_handle, &mounted_root, &mrsz);
166 if (rc != EOK) {
167 free(buf);
168 ipc_answer_0(rid, rc);
169 return;
170 }
171 vfs_node_t *mr_node = vfs_node_get(&mounted_root, mrsz);
172 if (!mr_node) {
173 free(buf);
174 ipc_answer_0(rid, ENOMEM);
175 return;
176 }
177
178 /*
179 * Finally, we need to resolve the path to the mountpoint.
180 */
181 vfs_triplet_t mp;
182 size_t mpsz;
183 futex_down(&rootfs_futex);
184 if (rootfs.fs_handle) {
185 /*
186 * We already have the root FS.
187 */
188 rwlock_write_lock(&namespace_rwlock);
189 rc = vfs_lookup_internal(buf, size, &mp, &mpsz, NULL);
190 if (rc != EOK) {
191 /*
192 * The lookup failed for some reason.
193 */
194 rwlock_write_unlock(&namespace_rwlock);
195 futex_up(&rootfs_futex);
196 vfs_node_put(mr_node); /* failed -> drop reference */
197 free(buf);
198 ipc_answer_0(rid, rc);
199 return;
200 }
201 mp_node = vfs_node_get(&mp, mpsz);
202 if (!mp_node) {
203 rwlock_write_unlock(&namespace_rwlock);
204 futex_up(&rootfs_futex);
205 vfs_node_put(mr_node); /* failed -> drop reference */
206 free(buf);
207 ipc_answer_0(rid, ENOMEM);
208 return;
209 }
210 /*
211 * Now we hold a reference to mp_node.
212 * It will be dropped upon the corresponding VFS_UNMOUNT.
213 * This prevents the mount point from being deleted.
214 */
215 rwlock_write_unlock(&namespace_rwlock);
216 } else {
217 /*
218 * We still don't have the root file system mounted.
219 */
220 if ((size == 1) && (buf[0] == '/')) {
221 /*
222 * For this simple, but important case, we are done.
223 */
224 rootfs = mounted_root;
225 futex_up(&rootfs_futex);
226 free(buf);
227 ipc_answer_0(rid, EOK);
228 return;
229 } else {
230 /*
231 * We can't resolve this without the root filesystem
232 * being mounted first.
233 */
234 futex_up(&rootfs_futex);
235 free(buf);
236 vfs_node_put(mr_node); /* failed -> drop reference */
237 ipc_answer_0(rid, ENOENT);
238 return;
239 }
240 }
241 futex_up(&rootfs_futex);
242
243 free(buf); /* The buffer is not needed anymore. */
244
245 /*
246 * At this point, we have all necessary pieces: file system and device
247 * handles, and we know the mount point VFS node and also the root node
248 * of the file system being mounted.
249 */
250
251 int phone = vfs_grab_phone(mp.fs_handle);
252 /* Later we can use ARG3 to pass mode/flags. */
253 aid_t req1 = async_send_3(phone, VFS_MOUNT, (ipcarg_t) mp.dev_handle,
254 (ipcarg_t) mp.index, 0, NULL);
255 /* The second call uses the same method. */
256 aid_t req2 = async_send_3(phone, VFS_MOUNT,
257 (ipcarg_t) mounted_root.fs_handle,
258 (ipcarg_t) mounted_root.dev_handle, (ipcarg_t) mounted_root.index,
259 NULL);
260 vfs_release_phone(phone);
261
262 ipcarg_t rc1;
263 ipcarg_t rc2;
264 async_wait_for(req1, &rc1);
265 async_wait_for(req2, &rc2);
266
267 if ((rc1 != EOK) || (rc2 != EOK)) {
268 /* Mount failed, drop references to mr_node and mp_node. */
269 vfs_node_put(mr_node);
270 if (mp_node)
271 vfs_node_put(mp_node);
272 }
273
274 if (rc2 == EOK)
275 ipc_answer_0(rid, rc1);
276 else if (rc1 == EOK)
277 ipc_answer_0(rid, rc2);
278 else
279 ipc_answer_0(rid, rc1);
280}
281
282/**
283 * @}
284 */
Note: See TracBrowser for help on using the repository browser.