Subversion Repositories HelenOS

Rev

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

Rev Author Line No. Line
2006 decky 1
/*
2071 jermar 2
 * Copyright (c) 2006 Martin Decky
2006 decky 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    fs.c
35
 * @brief   File system driver for HelenOS.
36
 */
37
 
2248 jelen 38
#include <ipc/ipc.h>
39
#include <ipc/services.h>
40
#include <ipc/ns.h>
41
#include <sysinfo.h>
2388 konopa 42
#include <io/io.h>
2248 jelen 43
#include <as.h>
44
#include <ddi.h>
45
#include <align.h>
46
#include <bool.h>
47
#include <errno.h>
48
#include <async.h>
2388 konopa 49
#include <cap.h>
50
#include <sys/mman.h>
2248 jelen 51
#include "fs.h"
2388 konopa 52
#include "dir.h"
53
#include "../console/console.h"
2006 decky 54
 
2248 jelen 55
 
2388 konopa 56
static int fs_call;
57
static ipc_call_t m_input;          /* the input message used for request */
58
static ipc_callid_t callid;         /* caller's number */
59
static int new_consument;       /* if new consumer wants to connect to FS */
60
static int check_con;           /* check of connection of consument */
61
 
62
static void prepare_message(void);
63
static int load_super(void);
64
static int new_consument_map(void);
65
 
2248 jelen 66
static void fs_connection(ipc_callid_t iid, ipc_call_t *icall)
67
{
68
 
2403 konopa 69
    int result = 0;
70
    ipcarg_t arg = 0;
2388 konopa 71
 
2248 jelen 72
    ipc_answer_fast(iid, 0, 0, 0);
2403 konopa 73
 
2388 konopa 74
    while (1)
75
    {
76
        prepare_message();
77
 
2403 konopa 78
        switch (fs_call)
79
        {
80
            case IPC_M_PHONE_HUNGUP:
81
                ipc_answer_fast(callid, 0,0,0);
82
                return;
2388 konopa 83
 
2403 konopa 84
            case FS_NEW_CONSUMER:
85
                if (!new_consument) {
86
                    result = FS_ECONNECT;  
87
                }
88
                else {
89
                    result = new_consument_map();  
90
                    if (!result) {
91
                        new_consument = FALSE;     
92
                    }
93
                }
94
                break;
2388 konopa 95
 
2403 konopa 96
            case IPC_M_AS_AREA_SEND:
97
                if (!new_consument)
98
                    result = FS_ECONNECT;      
99
                else {
100
                    result = 0;
101
                    arg = (uintptr_t)fp->buffer;
102
                    fp = &fproc[new_consument];
103
                    fp->connected = TRUE;
104
                    new_consument = FALSE;
2388 konopa 105
                }
2403 konopa 106
                break;
2388 konopa 107
 
2403 konopa 108
            case FS_DROP_CONSUMER:
109
                fproc->connected = FALSE;
110
                fproc->buffer = NULL;
111
                result = 0;
112
                break;
2401 konopa 113
 
2403 konopa 114
            default:
115
                if (check_con < 0) {
116
                    result = err_code;
117
                    check_con = TRUE;
118
                    break; 
119
                }
120
                if (FS_IN_RANGE(fs_call)) {  
121
                    result = call_vector[fs_call-FS_BASE]();
122
                }
123
                else {
124
                    result = FS_EBADCALL;
125
                }
126
                break; 
127
 
2401 konopa 128
        }
2388 konopa 129
 
2403 konopa 130
        ipc_answer_fast(callid, result, arg, 0);
131
        arg = 0;       
2248 jelen 132
    }  
133
}
134
 
2388 konopa 135
/* Extracts parameters from message and prepare them for later usage. */
136
void prepare_message(void)
137
{
138
 
139
    int shift, id_task;
2403 konopa 140
 
141
 
2388 konopa 142
    callid = async_get_call(&m_input);
143
    fs_call = IPC_GET_METHOD(m_input);
144
 
145
    if (fs_call == IPC_M_AS_AREA_SEND) {   
146
        if (!new_consument) {
147
            new_consument = FALSE;
148
        }
2248 jelen 149
 
2388 konopa 150
        return;
151
    }
152
 
153
    id_task = IPC_GET_ARG1(m_input);    
154
 
155
    /* Setup new consument. */
156
    if (fs_call == FS_NEW_CONSUMER) {
157
        if (!new_consument) {
158
            new_consument = id_task;
159
        }
160
        else {
161
            new_consument = FALSE;
162
        }
163
 
164
        return;
165
    }
166
 
167
    /* Other messages discard process of new consument connecting. */
168
    if (new_consument) {
169
        new_consument = FALSE;
170
    }
171
 
172
    if (id_task < 0 || id_task >= NR_PROCS) {
173
        check_con = FS_EINVAL;
174
        return;    
175
    }
176
 
177
    /* Switch to active consument. */
178
    fp = &fproc[id_task];
179
 
180
    /* Check if consument was connected. */
181
    if (!(fp->connected)) {
182
        check_con = FS_ENOTCONNECT;
183
        return;
184
    }
185
 
186
 
187
    /* Unpacking extended input message into message_params structure. */
188
    unpack_message(&message_params, m_input, fp->buffer);
189
}
190
 
191
/* Map some memory to the task */
192
int new_consument_map()
193
{
194
 
195
    size_t size;
196
    task_id_t task_id;
197
 
198
    task_id = new_consument;   
199
    if (task_id < 0 || task_id >= NR_PROCS) {
200
        return FS_EINVAL;
201
    }
202
 
203
    fp = &fproc[task_id];
204
    size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
205
    fp->buffer = as_get_mappable_page(size, PAGE_COLOR((uintptr_t)fp->buffer));
206
 
207
    return TRUE;
208
}
209
/* Reads in the superblock from image. */
210
int load_super(void)
211
{
212
 
213
    super_block_t *sp;
214
 
215
    if (!init_super_block())
216
        return FALSE;
217
 
218
        sp = get_super();
219
    if (read_super(sp) != OK)
220
    {
221
        print_console("Super block read error\n");
222
        return FALSE;
223
    }
224
 
225
    return TRUE;
226
}
227
 
228
/* Basic initialization. */
2248 jelen 229
static bool fs_init(void)
230
{
231
 
2388 konopa 232
    register inode_t *rip;
233
    int bad, i;
234
 
235
 
236
    bad = 0;
237
    callid = SERVICE_FS;
238
    fp = (fproc_t *)NULL;
239
 
240
    print_console("FS initialization...");
241
 
242
    /* Block cache initialization. */
243
    if (!init_block())
244
        return FALSE;
245
 
246
    /* Loading superblock. */
247
    if (!load_super())
248
        return FALSE;
249
 
250
    for (i = 0; i < NR_PROCS; i++) {
251
        if (i == SERVICE_FS)
252
            continue;
253
 
254
        fp = &fproc[i];
255
        rip = get_inode(ROOT_INODE);
256
        fp->fp_rootdir = rip;
257
        dup_inode(rip);
258
        fp->fp_workdir = rip;
259
    }
260
 
261
    fp = &fproc[SERVICE_FS];
262
 
263
    /* Certain relations must hold for the file system to work at all. */
264
    if (SUPER_SIZE > BLOCK_SIZE) {
265
        print_console("SUPER_SIZE > BLOCK_SIZE\n");
266
        bad++;
267
    }
268
    if (BLOCK_SIZE % V1_INODE_SIZE != 0) { 
269
        print_console("BLOCK_SIZE mod V1_INODE_SIZE != 0\n");
270
        bad++;
271
    }
272
    if (OPEN_MAX > 127) {  
273
        print_console("OPEN_MAX > 127\n");
274
        bad++;
275
    }
276
    if (V1_INODE_SIZE != 32) { 
277
        print_console("V1 inode size != 32\n");
278
        bad++;
279
    }
280
 
281
    if (V2_INODE_SIZE != 64) { 
282
        print_console("V2 inode size != 64\n");
283
        bad++;
284
    }
285
 
286
    if (bad)
287
        return FALSE;
288
 
289
    /* New consument flag settings. */
290
    new_consument = FALSE;
291
    check_con = FALSE;
292
 
293
    print_console("OK\n");
294
 
295
    return TRUE;
2248 jelen 296
}
297
 
2006 decky 298
int main(int argc, char **argv)
299
{
2388 konopa 300
 
301
    int retval, flags;
302
    unsigned int size;
303
 
304
 
305
    /* Initializing printing functions. */
306
    if (!init_printing())
307
        return -1;
308
 
309
    print_console("FS task\n");
310
 
311
    /* Connection to SERVICE_RD service. */
312
    print_console("Connnection to SERVICE_RD...");
313
    if (connect_to_rd(&rd_phone, RD_CONN_ATTEMPTS))
314
        print_console("OK\n");
315
    else {
316
        print_console("FALSE\n");
317
        return -1;
318
    }
319
 
320
    /* Creating shared memory for usage with SERVICE_RD.  */
321
    print_console("Creating address space area for share with SERVICE_RD task...");
322
    size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
323
    buffer = mmap(buffer, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
324
    if ((int)buffer < 0) {
325
        print_console_int("As_area_create error %d", (int)buffer);
326
        return -1;
327
    }
328
    print_console("OK\n");
329
 
330
 
331
    /* Mapping memory to SERVICE_RD. */
332
    print_console("Sending memory to RD_SERVICE...");
333
    flags = 0;
334
    flags = AS_AREA_READ | AS_AREA_WRITE;
335
    retval = async_req_3(rd_phone, IPC_M_AS_AREA_SEND, (uintptr_t)buffer, size, flags, NULL, NULL, NULL);
336
    if (retval < 0) {
337
        print_console_int("%d\n", retval);
338
        return -1;
339
    }
340
    print_console("OK\n");
341
 
2248 jelen 342
    if (fs_init()) {
343
        ipcarg_t phonead;
2388 konopa 344
 
2248 jelen 345
        async_set_client_connection(fs_connection);
2388 konopa 346
 
2248 jelen 347
        /* Register service at nameserver */
348
        if (ipc_connect_to_me(PHONE_NS, SERVICE_FS, 0, &phonead) != 0)
349
            return -1;
350
 
351
        async_manager();
2388 konopa 352
 
2248 jelen 353
        /* Never reached */
354
        return 0;
355
    }
356
 
357
    return -1;
2006 decky 358
}
359
 
360
/**
361
 * @}
362
 */