Subversion Repositories HelenOS

Rev

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