Subversion Repositories HelenOS

Rev

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