Subversion Repositories HelenOS

Rev

Rev 2542 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2542 Rev 2552
Line 43... Line 43...
43
#include <bool.h>
43
#include <bool.h>
44
#include <futex.h>
44
#include <futex.h>
45
#include <libadt/list.h>
45
#include <libadt/list.h>
46
#include "vfs.h"
46
#include "vfs.h"
47
 
47
 
48
vfs_node_t *rootfs = NULL;
48
vfs_node_t rootfs = { 0 };
-
 
49
 
-
 
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
}
49
 
63
 
50
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
64
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
51
{
65
{
-
 
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
   
52
}
196
}
53
 
197
 
54
/**
198
/**
55
 * @}
199
 * @}
56
 */
200
 */