Subversion Repositories HelenOS

Rev

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

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