Subversion Repositories HelenOS

Rev

Rev 2542 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2542 jermar 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
 
2552 jermar 48
vfs_node_t rootfs = { 0 };
2542 jermar 49
 
2552 jermar 50
static int lookup_root(int fs_handle, int dev_handle, vfs_node_t *root)
51
{
52
    vfs_node_t altroot = {
53
        .fs_handle = fs_handle,
54
        .dev_handle = dev_handle,
55
        /*
56
         * At this point, we don't know what is the index of the root
57
         * node. Finally, that's what this function is about.
58
         */
59
    };
60
 
61
    return vfs_lookup_internal("/", 1, root, &altroot);
62
}
63
 
2542 jermar 64
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
65
{
2552 jermar 66
    int dev_handle;
67
 
68
    /*
69
     * We expect the library to do the device-name to device-handle
70
     * translation for us, thus the device handle will arrive as ARG1
71
     * in the request.
72
     */
73
    dev_handle = IPC_GET_ARG1(*request);
74
 
75
    /*
76
     * For now, don't make use of ARG2 and ARG3, but they can be used to
77
     * carry mount options in the future.
78
     */
79
 
80
    /*
81
     * Now, we expect the client to send us data with the name of the file
82
     * system and the path of the mountpoint.
83
     */
84
    ipc_callid_t callid;
85
    ipc_call_t call;
86
    size_t size;
87
    if (!ipc_data_receive(&callid, &call, NULL, &size)) {
88
        ipc_answer_fast(callid, EINVAL, 0, 0);
89
        ipc_answer_fast(rid, EINVAL, 0, 0);
90
        return;
91
    }
92
 
93
    /*
94
     * There is no sense in receiving data that can't hold a single
95
     * character of path. We won't accept data that exceed certain limits
96
     * either.
97
     */
98
    if ((size < FS_NAME_MAXLEN + 1) ||
99
        (size > FS_NAME_MAXLEN + MAX_PATH_LEN)) {
100
        ipc_answer_fast(callid, EINVAL, 0, 0);
101
        ipc_answer_fast(rid, EINVAL, 0, 0);
102
        return;
103
    }
104
 
105
    /*
106
     * Allocate buffer for the data being received.
107
     */
108
    uint8_t *buf;
109
    buf = malloc(size);
110
    if (!buf) {
111
        ipc_answer_fast(callid, ENOMEM, 0, 0);
112
        ipc_answer_fast(rid, ENOMEM, 0, 0);
113
        return;
114
    }
115
 
116
    /*
117
     * Deliver the data.
118
     */
119
    (void) ipc_data_deliver(callid, &call, buf, size);
120
 
121
    char fs_name[FS_NAME_MAXLEN + 1];
122
    memcpy(fs_name, buf, FS_NAME_MAXLEN);
123
    fs_name[FS_NAME_MAXLEN] = '\0';
124
 
125
    /*
126
     * Check if we know a file system with the same name as is in fs_name.
127
     * This will also give us its file system handle.
128
     */
129
    int fs_handle = fs_name_to_handle(fs_name, true);
130
    if (!fs_handle) {
131
        free(buf);
132
        ipc_answer_fast(rid, ENOENT, 0, 0);
133
        return;
134
    }
135
 
136
    /*
137
     * Lookup the root node of the filesystem being mounted.
138
     */
139
    int rc;
140
    vfs_node_t mounted_root;
141
    rc = lookup_root(fs_handle, dev_handle, &mounted_root);
142
    if (rc != EOK) {
143
        free(buf);
144
        ipc_answer_fast(rid, rc, 0, 0);
145
        return;
146
    }
147
 
148
    /*
149
     * Finally, we need to resolve the path to the mountpoint.
150
     */
151
    vfs_node_t mp;
152
    if (rootfs.fs_handle) {
153
        /*
154
         * We already have the root FS.
155
         */
156
        rc = vfs_lookup_internal((char *) (buf + FS_NAME_MAXLEN),
157
            size - FS_NAME_MAXLEN, &mp, NULL);
158
        if (rc != EOK) {
159
            /*
160
             * The lookup failed for some reason.
161
             */
162
            free(buf);
163
            ipc_answer_fast(rid, rc, 0, 0);
164
            return;
165
        }
166
    } else {
167
        /*
168
         * We still don't have the root file system mounted.
169
         */
170
        if ((size - FS_NAME_MAXLEN == 1) &&
171
            (buf[FS_NAME_MAXLEN] == '/')) {
172
            /*
173
             * For this simple, but important case, we are done.
174
             */
175
            rootfs = mounted_root;
176
            free(buf);
177
            ipc_answer_fast(rid, EOK, 0, 0);
178
            return;
179
        } else {
180
            /*
181
             * We can't resolve this without the root filesystem
182
             * being mounted first.
183
             */
184
            free(buf);
185
            ipc_answer_fast(rid, ENOENT, 0, 0);
186
            return;
187
        }
188
    }
189
 
190
    /*
191
     * At this point, we have all necessary pieces: file system and device
192
     * handles, and we know the mount point VFS node and also the root node
193
     * of the file system being mounted.
194
     */
195
 
2542 jermar 196
}
197
 
198
/**
199
 * @}
200
 */