Rev 2690 | Rev 2693 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2690 | Rev 2691 | ||
---|---|---|---|
Line 68... | Line 68... | ||
68 | 68 | ||
69 | /** Perform a path lookup. |
69 | /** Perform a path lookup. |
70 | * |
70 | * |
71 | * @param path Path to be resolved; it needn't be an ASCIIZ string. |
71 | * @param path Path to be resolved; it needn't be an ASCIIZ string. |
72 | * @param len Number of path characters pointed by path. |
72 | * @param len Number of path characters pointed by path. |
73 | * @param result Empty node structure where the result will be stored. |
73 | * @param result Empty structure where the lookup result will be stored. |
74 | * @param size Storage where the size of the node will be stored. Can |
- | |
75 | * be NULL. |
- | |
76 | * @param altroot If non-empty, will be used instead of rootfs as the root |
74 | * @param altroot If non-empty, will be used instead of rootfs as the root |
77 | * of the whole VFS tree. |
75 | * of the whole VFS tree. |
78 | * |
76 | * |
79 | * @return EOK on success or an error code from errno.h. |
77 | * @return EOK on success or an error code from errno.h. |
80 | */ |
78 | */ |
81 | int vfs_lookup_internal(char *path, size_t len, vfs_triplet_t *result, |
79 | int vfs_lookup_internal(char *path, size_t len, vfs_lookup_res_t *result, |
82 | size_t *size, vfs_pair_t *altroot) |
80 | vfs_pair_t *altroot) |
83 | { |
81 | { |
84 | vfs_pair_t *root; |
82 | vfs_pair_t *root; |
85 | 83 | ||
86 | if (!len) |
84 | if (!len) |
87 | return EINVAL; |
85 | return EINVAL; |
Line 177... | Line 175... | ||
177 | memset(&plb[first], 0, cnt1); |
175 | memset(&plb[first], 0, cnt1); |
178 | memset(plb, 0, cnt2); |
176 | memset(plb, 0, cnt2); |
179 | futex_up(&plb_futex); |
177 | futex_up(&plb_futex); |
180 | 178 | ||
181 | if (rc == EOK) { |
179 | if (rc == EOK) { |
182 | result->fs_handle = (int) IPC_GET_ARG1(answer); |
180 | result->triplet.fs_handle = (int) IPC_GET_ARG1(answer); |
183 | result->dev_handle = (int) IPC_GET_ARG2(answer); |
181 | result->triplet.dev_handle = (int) IPC_GET_ARG2(answer); |
184 | result->index = (int) IPC_GET_ARG3(answer); |
182 | result->triplet.index = (int) IPC_GET_ARG3(answer); |
185 | if (size) |
- | |
186 | *size = (size_t) IPC_GET_ARG4(answer); |
183 | result->size = (size_t) IPC_GET_ARG4(answer); |
187 | } |
184 | } |
188 | 185 | ||
189 | return rc; |
186 | return rc; |
190 | } |
187 | } |
191 | 188 | ||
Line 194... | Line 191... | ||
194 | .fs_handle = 0, |
191 | .fs_handle = 0, |
195 | .dev_handle = 0, |
192 | .dev_handle = 0, |
196 | .index = 0, |
193 | .index = 0, |
197 | }; |
194 | }; |
198 | 195 | ||
199 | static int lookup_root(int fs_handle, int dev_handle, vfs_triplet_t *root, |
196 | static int lookup_root(int fs_handle, int dev_handle, vfs_lookup_res_t *result) |
200 | size_t *size) |
- | |
201 | { |
197 | { |
202 | vfs_pair_t altroot = { |
198 | vfs_pair_t altroot = { |
203 | .fs_handle = fs_handle, |
199 | .fs_handle = fs_handle, |
204 | .dev_handle = dev_handle, |
200 | .dev_handle = dev_handle, |
205 | }; |
201 | }; |
206 | 202 | ||
207 | return vfs_lookup_internal("/", strlen("/"), root, size, &altroot); |
203 | return vfs_lookup_internal("/", strlen("/"), result, &altroot); |
208 | } |
204 | } |
209 | 205 | ||
210 | void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
206 | void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
211 | { |
207 | { |
212 | int dev_handle; |
208 | int dev_handle; |
Line 302... | Line 298... | ||
302 | * In this case, we don't need to take the namespace_futex as the root |
298 | * In this case, we don't need to take the namespace_futex as the root |
303 | * node cannot be removed. However, we do take a reference to it so |
299 | * node cannot be removed. However, we do take a reference to it so |
304 | * that we can track how many times it has been mounted. |
300 | * that we can track how many times it has been mounted. |
305 | */ |
301 | */ |
306 | int rc; |
302 | int rc; |
307 | vfs_triplet_t mounted_root; |
303 | vfs_lookup_res_t mr_res; |
308 | size_t mrsz; |
- | |
309 | rc = lookup_root(fs_handle, dev_handle, &mounted_root, &mrsz); |
304 | rc = lookup_root(fs_handle, dev_handle, &mr_res); |
310 | if (rc != EOK) { |
305 | if (rc != EOK) { |
311 | free(buf); |
306 | free(buf); |
312 | ipc_answer_0(rid, rc); |
307 | ipc_answer_0(rid, rc); |
313 | return; |
308 | return; |
314 | } |
309 | } |
315 | vfs_node_t *mr_node = vfs_node_get(&mounted_root, mrsz); |
310 | vfs_node_t *mr_node = vfs_node_get(&mr_res); |
316 | if (!mr_node) { |
311 | if (!mr_node) { |
317 | free(buf); |
312 | free(buf); |
318 | ipc_answer_0(rid, ENOMEM); |
313 | ipc_answer_0(rid, ENOMEM); |
319 | return; |
314 | return; |
320 | } |
315 | } |
321 | 316 | ||
322 | /* |
317 | /* |
323 | * Finally, we need to resolve the path to the mountpoint. |
318 | * Finally, we need to resolve the path to the mountpoint. |
324 | */ |
319 | */ |
325 | vfs_triplet_t mp; |
320 | vfs_lookup_res_t mp_res; |
326 | size_t mpsz; |
- | |
327 | futex_down(&rootfs_futex); |
321 | futex_down(&rootfs_futex); |
328 | if (rootfs.fs_handle) { |
322 | if (rootfs.fs_handle) { |
329 | /* |
323 | /* |
330 | * We already have the root FS. |
324 | * We already have the root FS. |
331 | */ |
325 | */ |
332 | rwlock_write_lock(&namespace_rwlock); |
326 | rwlock_write_lock(&namespace_rwlock); |
333 | rc = vfs_lookup_internal(buf, size, &mp, &mpsz, NULL); |
327 | rc = vfs_lookup_internal(buf, size, &mp_res, NULL); |
334 | if (rc != EOK) { |
328 | if (rc != EOK) { |
335 | /* |
329 | /* |
336 | * The lookup failed for some reason. |
330 | * The lookup failed for some reason. |
337 | */ |
331 | */ |
338 | rwlock_write_unlock(&namespace_rwlock); |
332 | rwlock_write_unlock(&namespace_rwlock); |
Line 340... | Line 334... | ||
340 | vfs_node_put(mr_node); /* failed -> drop reference */ |
334 | vfs_node_put(mr_node); /* failed -> drop reference */ |
341 | free(buf); |
335 | free(buf); |
342 | ipc_answer_0(rid, rc); |
336 | ipc_answer_0(rid, rc); |
343 | return; |
337 | return; |
344 | } |
338 | } |
345 | mp_node = vfs_node_get(&mp, mpsz); |
339 | mp_node = vfs_node_get(&mp_res); |
346 | if (!mp_node) { |
340 | if (!mp_node) { |
347 | rwlock_write_unlock(&namespace_rwlock); |
341 | rwlock_write_unlock(&namespace_rwlock); |
348 | futex_up(&rootfs_futex); |
342 | futex_up(&rootfs_futex); |
349 | vfs_node_put(mr_node); /* failed -> drop reference */ |
343 | vfs_node_put(mr_node); /* failed -> drop reference */ |
350 | free(buf); |
344 | free(buf); |
Line 363... | Line 357... | ||
363 | */ |
357 | */ |
364 | if ((size == 1) && (buf[0] == '/')) { |
358 | if ((size == 1) && (buf[0] == '/')) { |
365 | /* |
359 | /* |
366 | * For this simple, but important case, we are done. |
360 | * For this simple, but important case, we are done. |
367 | */ |
361 | */ |
368 | rootfs = mounted_root; |
362 | rootfs = mr_res.triplet; |
369 | futex_up(&rootfs_futex); |
363 | futex_up(&rootfs_futex); |
370 | free(buf); |
364 | free(buf); |
371 | ipc_answer_0(rid, EOK); |
365 | ipc_answer_0(rid, EOK); |
372 | return; |
366 | return; |
373 | } else { |
367 | } else { |
Line 390... | Line 384... | ||
390 | * At this point, we have all necessary pieces: file system and device |
384 | * At this point, we have all necessary pieces: file system and device |
391 | * handles, and we know the mount point VFS node and also the root node |
385 | * handles, and we know the mount point VFS node and also the root node |
392 | * of the file system being mounted. |
386 | * of the file system being mounted. |
393 | */ |
387 | */ |
394 | 388 | ||
395 | int phone = vfs_grab_phone(mp.fs_handle); |
389 | int phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
396 | /* Later we can use ARG3 to pass mode/flags. */ |
390 | /* Later we can use ARG3 to pass mode/flags. */ |
397 | aid_t req1 = async_send_3(phone, VFS_MOUNT, (ipcarg_t) mp.dev_handle, |
391 | aid_t req1 = async_send_3(phone, VFS_MOUNT, |
- | 392 | (ipcarg_t) mp_res.triplet.dev_handle, |
|
398 | (ipcarg_t) mp.index, 0, NULL); |
393 | (ipcarg_t) mp_res.triplet.index, 0, NULL); |
399 | /* The second call uses the same method. */ |
394 | /* The second call uses the same method. */ |
400 | aid_t req2 = async_send_3(phone, VFS_MOUNT, |
395 | aid_t req2 = async_send_3(phone, VFS_MOUNT, |
401 | (ipcarg_t) mounted_root.fs_handle, |
396 | (ipcarg_t) mr_res.triplet.fs_handle, |
402 | (ipcarg_t) mounted_root.dev_handle, (ipcarg_t) mounted_root.index, |
397 | (ipcarg_t) mr_res.triplet.dev_handle, |
403 | NULL); |
398 | (ipcarg_t) mr_res.triplet.index, NULL); |
404 | vfs_release_phone(phone); |
399 | vfs_release_phone(phone); |
405 | 400 | ||
406 | ipcarg_t rc1; |
401 | ipcarg_t rc1; |
407 | ipcarg_t rc2; |
402 | ipcarg_t rc2; |
408 | async_wait_for(req1, &rc1); |
403 | async_wait_for(req1, &rc1); |
Line 476... | Line 471... | ||
476 | rwlock_read_lock(&namespace_rwlock); |
471 | rwlock_read_lock(&namespace_rwlock); |
477 | 472 | ||
478 | /* |
473 | /* |
479 | * The path is now populated and we can call vfs_lookup_internal(). |
474 | * The path is now populated and we can call vfs_lookup_internal(). |
480 | */ |
475 | */ |
481 | vfs_triplet_t triplet; |
476 | vfs_lookup_res_t lr; |
482 | size_t size; |
- | |
483 | rc = vfs_lookup_internal(path, len, &triplet, &size, NULL); |
477 | rc = vfs_lookup_internal(path, len, &lr, NULL); |
484 | if (rc) { |
478 | if (rc) { |
485 | rwlock_read_unlock(&namespace_rwlock); |
479 | rwlock_read_unlock(&namespace_rwlock); |
486 | ipc_answer_0(rid, rc); |
480 | ipc_answer_0(rid, rc); |
487 | free(path); |
481 | free(path); |
488 | return; |
482 | return; |
Line 491... | Line 485... | ||
491 | /* |
485 | /* |
492 | * Path is no longer needed. |
486 | * Path is no longer needed. |
493 | */ |
487 | */ |
494 | free(path); |
488 | free(path); |
495 | 489 | ||
496 | vfs_node_t *node = vfs_node_get(&triplet, size); |
490 | vfs_node_t *node = vfs_node_get(&lr); |
497 | rwlock_read_unlock(&namespace_rwlock); |
491 | rwlock_read_unlock(&namespace_rwlock); |
498 | 492 | ||
499 | /* |
493 | /* |
500 | * Get ourselves a file descriptor and the corresponding vfs_file_t |
494 | * Get ourselves a file descriptor and the corresponding vfs_file_t |
501 | * structure. |
495 | * structure. |