Subversion Repositories HelenOS

Rev

Rev 2403 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2403 Rev 2435
1
/*
1
/*
2
 * Copyright (c) 2006 Martin Decky
2
 * Copyright (c) 2007 Konopa-Jelen-Majer
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup fs
29
/** @addtogroup FileSystemTask
30
 * @{
30
 * @{
31
 */
31
 */
32
 
32
 
33
/**
33
/**
34
 * @file    fs.c
34
 * @file    fs.c
35
 * @brief   File system driver for HelenOS.
35
 * @brief   File system driver for HelenOS.
36
 */
36
 */
37
 
37
 
38
#include <ipc/ipc.h>
38
#include <ipc/ipc.h>
39
#include <ipc/services.h>
39
#include <ipc/services.h>
40
#include <ipc/ns.h>
40
#include <ipc/ns.h>
41
#include <sysinfo.h>
41
#include <sysinfo.h>
42
#include <io/io.h>
42
#include <io/io.h>
43
#include <as.h>
43
#include <as.h>
44
#include <ddi.h>
44
#include <ddi.h>
45
#include <align.h>
45
#include <align.h>
46
#include <bool.h>
46
#include <bool.h>
47
#include <errno.h>
47
#include <errno.h>
48
#include <async.h>
48
#include <async.h>
49
#include <cap.h>
49
#include <cap.h>
50
#include <sys/mman.h>
50
#include <sys/mman.h>
51
#include "fs.h"
51
#include "fs.h"
52
#include "dir.h"
52
#include "dir.h"
53
#include "../console/console.h"
53
#include "../console/console.h"
54
 
54
 
55
 
55
 
56
static int fs_call;
56
static int fs_call;
57
static ipc_call_t m_input;          /* the input message used for request */
57
static ipc_call_t m_input;          /**< the input message used for request */
58
static ipc_callid_t callid;         /* caller's number */
58
static ipc_callid_t callid;         /**< caller's number */
59
static int new_consument;       /* if new consumer wants to connect to FS */
59
static int new_consument;       /**< if new consumer wants to connect to FS */
60
static int check_con;           /* check of connection of consument */
60
static int check_con;           /**< check of connection of consument */
61
           
61
           
62
static void prepare_message(void);
62
static void prepare_message(void);
63
static int load_super(void);
63
static int load_super(void);
64
static int new_consument_map(void);
64
static int new_consument_map(void);
65
 
65
 
-
 
66
/**
-
 
67
 * Respond to incoming requests from user tasks
-
 
68
 */
66
static void fs_connection(ipc_callid_t iid, ipc_call_t *icall)
69
static void fs_connection(ipc_callid_t iid, ipc_call_t *icall)
67
{
70
{
68
 
71
 
69
    int result = 0;
72
    int result = 0;
70
    ipcarg_t arg = 0;
73
    ipcarg_t arg = 0;
71
 
74
 
72
    ipc_answer_fast(iid, 0, 0, 0);
75
    ipc_answer_fast(iid, 0, 0, 0);
73
   
76
   
74
    while (1)
77
    while (1)
75
    {
78
    {
76
        prepare_message();
79
        prepare_message();
77
       
80
       
78
        switch (fs_call)
81
        switch (fs_call)
79
        {
82
        {
80
            case IPC_M_PHONE_HUNGUP:
83
            case IPC_M_PHONE_HUNGUP:
81
                ipc_answer_fast(callid, 0,0,0);
84
                ipc_answer_fast(callid, 0,0,0);
82
                return;
85
                return;
83
 
86
 
84
            case FS_NEW_CONSUMER:
87
            case FS_NEW_CONSUMER:
85
                if (!new_consument) {
88
                if (!new_consument) {
86
                    result = FS_ECONNECT;  
89
                    result = FS_ECONNECT;  
87
                }
90
                }
88
                else {
91
                else {
89
                    result = new_consument_map();  
92
                    result = new_consument_map();  
90
                    if (!result) {
93
                    if (!result) {
91
                        new_consument = FALSE;     
94
                        new_consument = FALSE;     
92
                    }
95
                    }
93
                }
96
                }
94
                break;
97
                break;
95
 
98
 
96
            case IPC_M_AS_AREA_SEND:
99
            case IPC_M_AS_AREA_SEND:
97
                if (!new_consument)
100
                if (!new_consument)
98
                    result = FS_ECONNECT;      
101
                    result = FS_ECONNECT;      
99
                else {
102
                else {
100
                    result = 0;
103
                    result = 0;
101
                    arg = (uintptr_t)fp->buffer;
104
                    arg = (uintptr_t)fp->buffer;
102
                    fp = &fproc[new_consument];
105
                    fp = &fproc[new_consument];
103
                    fp->connected = TRUE;
106
                    fp->connected = TRUE;
104
                    new_consument = FALSE;
107
                    new_consument = FALSE;
105
                }
108
                }
106
                break;
109
                break;
107
 
110
 
108
            case FS_DROP_CONSUMER:
111
            case FS_DROP_CONSUMER:
109
                fproc->connected = FALSE;
112
                fproc->connected = FALSE;
110
                fproc->buffer = NULL;
113
                fproc->buffer = NULL;
111
                result = 0;
114
                result = 0;
112
                break;
115
                break;
113
 
116
 
114
            default:
117
            default:
115
                if (check_con < 0) {
118
                if (check_con < 0) {
116
                    result = err_code;
119
                    result = err_code;
117
                    check_con = TRUE;
120
                    check_con = TRUE;
118
                    break; 
121
                    break; 
119
                }
122
                }
120
                if (FS_IN_RANGE(fs_call)) {  
123
                if (FS_IN_RANGE(fs_call)) {  
121
                    result = call_vector[fs_call-FS_BASE]();
124
                    result = call_vector[fs_call-FS_BASE]();
122
                }
125
                }
123
                else {
126
                else {
124
                    result = FS_EBADCALL;
127
                    result = FS_EBADCALL;
125
                }
128
                }
126
                break; 
129
                break; 
127
           
130
           
128
        }
131
        }
129
   
132
   
130
        ipc_answer_fast(callid, result, arg, 0);
133
        ipc_answer_fast(callid, result, arg, 0);
131
        arg = 0;       
134
        arg = 0;       
132
    }  
135
    }  
133
}
136
}
134
 
137
 
-
 
138
/**
135
/* Extracts parameters from message and prepare them for later usage. */
139
 * Extracts parameters from message and prepare them for later usage.
-
 
140
 */
136
void prepare_message(void)
141
void prepare_message(void)
137
{
142
{
138
   
143
   
139
    int shift, id_task;
144
    int shift, id_task;
140
 
145
 
141
 
146
 
142
    callid = async_get_call(&m_input);
147
    callid = async_get_call(&m_input);
143
    fs_call = IPC_GET_METHOD(m_input);
148
    fs_call = IPC_GET_METHOD(m_input);
144
   
149
   
145
    if (fs_call == IPC_M_AS_AREA_SEND) {   
150
    if (fs_call == IPC_M_AS_AREA_SEND) {   
146
        if (!new_consument) {
151
        if (!new_consument) {
147
            new_consument = FALSE;
152
            new_consument = FALSE;
148
        }
153
        }
149
 
154
 
150
        return;
155
        return;
151
    }
156
    }
152
   
157
   
153
    id_task = IPC_GET_ARG1(m_input);    
158
    id_task = IPC_GET_ARG1(m_input);    
154
   
159
   
155
    /* Setup new consument. */
160
    /* Setup new consument. */
156
    if (fs_call == FS_NEW_CONSUMER) {
161
    if (fs_call == FS_NEW_CONSUMER) {
157
        if (!new_consument) {
162
        if (!new_consument) {
158
            new_consument = id_task;
163
            new_consument = id_task;
159
        }
164
        }
160
        else {
165
        else {
161
            new_consument = FALSE;
166
            new_consument = FALSE;
162
        }
167
        }
163
 
168
 
164
        return;
169
        return;
165
    }
170
    }
166
   
171
   
167
    /* Other messages discard process of new consument connecting. */
172
    /* Other messages discard process of new consument connecting. */
168
    if (new_consument) {
173
    if (new_consument) {
169
        new_consument = FALSE;
174
        new_consument = FALSE;
170
    }
175
    }
171
   
176
   
172
    if (id_task < 0 || id_task >= NR_PROCS) {
177
    if (id_task < 0 || id_task >= NR_PROCS) {
173
        check_con = FS_EINVAL;
178
        check_con = FS_EINVAL;
174
        return;    
179
        return;    
175
    }
180
    }
176
   
181
   
177
    /* Switch to active consument. */
182
    /* Switch to active consument. */
178
    fp = &fproc[id_task];
183
    fp = &fproc[id_task];
179
   
184
   
180
    /* Check if consument was connected. */
185
    /* Check if consument was connected. */
181
    if (!(fp->connected)) {
186
    if (!(fp->connected)) {
182
        check_con = FS_ENOTCONNECT;
187
        check_con = FS_ENOTCONNECT;
183
        return;
188
        return;
184
    }
189
    }
185
 
190
 
186
   
191
   
187
    /* Unpacking extended input message into message_params structure. */
192
    /* Unpacking extended input message into message_params structure. */
188
    unpack_message(&message_params, m_input, fp->buffer);
193
    unpack_message(&message_params, m_input, fp->buffer);
189
}
194
}
190
 
195
 
-
 
196
/**
191
/* Map some memory to the task */
197
 * Map some memory to the task
-
 
198
 */
192
int new_consument_map()
199
int new_consument_map()
193
{
200
{
194
   
201
   
195
    size_t size;
202
    size_t size;
196
    task_id_t task_id;
203
    task_id_t task_id;
197
 
204
 
198
    task_id = new_consument;   
205
    task_id = new_consument;   
199
    if (task_id < 0 || task_id >= NR_PROCS) {
206
    if (task_id < 0 || task_id >= NR_PROCS) {
200
        return FS_EINVAL;
207
        return FS_EINVAL;
201
    }
208
    }
202
 
209
 
203
    fp = &fproc[task_id];
210
    fp = &fproc[task_id];
204
    size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
211
    size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
205
    fp->buffer = as_get_mappable_page(size, PAGE_COLOR((uintptr_t)fp->buffer));
212
    fp->buffer = as_get_mappable_page(size, PAGE_COLOR((uintptr_t)fp->buffer));
206
 
213
 
207
    return TRUE;
214
    return TRUE;
208
}
215
}
209
/* Reads in the superblock from image. */
216
/* Reads in the superblock from image. */
210
int load_super(void)
217
int load_super(void)
211
{
218
{
212
   
219
   
213
    super_block_t *sp;
220
    super_block_t *sp;
214
   
221
   
215
    if (!init_super_block())
222
    if (!init_super_block())
216
        return FALSE;
223
        return FALSE;
217
 
224
 
218
        sp = get_super();
225
        sp = get_super();
219
    if (read_super(sp) != OK)
226
    if (read_super(sp) != OK)
220
    {
227
    {
221
        print_console("Super block read error\n");
228
        print_console("Super block read error\n");
222
        return FALSE;
229
        return FALSE;
223
    }
230
    }
224
 
231
 
225
    return TRUE;
232
    return TRUE;
226
}
233
}
227
 
234
 
-
 
235
/**
228
/* Basic initialization. */
236
 * Basic initialization.
-
 
237
 */
229
static bool fs_init(void)
238
static bool fs_init(void)
230
{
239
{
231
   
240
   
232
    register inode_t *rip;
241
    register inode_t *rip;
233
    int bad, i;
242
    int bad, i;
234
   
243
   
235
 
244
 
236
    bad = 0;
245
    bad = 0;
237
    callid = SERVICE_FS;
246
    callid = SERVICE_FS;
238
    fp = (fproc_t *)NULL;
247
    fp = (fproc_t *)NULL;
239
   
248
   
240
    print_console("FS initialization...");
249
    print_console("FS initialization...");
241
 
250
 
242
    /* Block cache initialization. */
251
    /* Block cache initialization. */
243
    if (!init_block())
252
    if (!init_block())
244
        return FALSE;
253
        return FALSE;
245
   
254
   
246
    /* Loading superblock. */
255
    /* Loading superblock. */
247
    if (!load_super())
256
    if (!load_super())
248
        return FALSE;
257
        return FALSE;
249
       
258
       
250
    for (i = 0; i < NR_PROCS; i++) {
259
    for (i = 0; i < NR_PROCS; i++) {
251
        if (i == SERVICE_FS)
260
        if (i == SERVICE_FS)
252
            continue;
261
            continue;
253
 
262
 
254
        fp = &fproc[i];
263
        fp = &fproc[i];
255
        rip = get_inode(ROOT_INODE);
264
        rip = get_inode(ROOT_INODE);
256
        fp->fp_rootdir = rip;
265
        fp->fp_rootdir = rip;
257
        dup_inode(rip);
266
        dup_inode(rip);
258
        fp->fp_workdir = rip;
267
        fp->fp_workdir = rip;
259
    }
268
    }
260
   
269
   
261
    fp = &fproc[SERVICE_FS];
270
    fp = &fproc[SERVICE_FS];
262
 
271
 
263
    /* Certain relations must hold for the file system to work at all. */
272
    /* Certain relations must hold for the file system to work at all. */
264
    if (SUPER_SIZE > BLOCK_SIZE) {
273
    if (SUPER_SIZE > BLOCK_SIZE) {
265
        print_console("SUPER_SIZE > BLOCK_SIZE\n");
274
        print_console("SUPER_SIZE > BLOCK_SIZE\n");
266
        bad++;
275
        bad++;
267
    }
276
    }
268
    if (BLOCK_SIZE % V1_INODE_SIZE != 0) { 
277
    if (BLOCK_SIZE % V1_INODE_SIZE != 0) { 
269
        print_console("BLOCK_SIZE mod V1_INODE_SIZE != 0\n");
278
        print_console("BLOCK_SIZE mod V1_INODE_SIZE != 0\n");
270
        bad++;
279
        bad++;
271
    }
280
    }
272
    if (OPEN_MAX > 127) {  
281
    if (OPEN_MAX > 127) {  
273
        print_console("OPEN_MAX > 127\n");
282
        print_console("OPEN_MAX > 127\n");
274
        bad++;
283
        bad++;
275
    }
284
    }
276
    if (V1_INODE_SIZE != 32) { 
285
    if (V1_INODE_SIZE != 32) { 
277
        print_console("V1 inode size != 32\n");
286
        print_console("V1 inode size != 32\n");
278
        bad++;
287
        bad++;
279
    }
288
    }
280
   
289
   
281
    if (V2_INODE_SIZE != 64) { 
290
    if (V2_INODE_SIZE != 64) { 
282
        print_console("V2 inode size != 64\n");
291
        print_console("V2 inode size != 64\n");
283
        bad++;
292
        bad++;
284
    }
293
    }
285
   
294
   
286
    if (bad)
295
    if (bad)
287
        return FALSE;
296
        return FALSE;
288
 
297
 
289
    /* New consument flag settings. */
298
    /* New consument flag settings. */
290
    new_consument = FALSE;
299
    new_consument = FALSE;
291
    check_con = FALSE;
300
    check_con = FALSE;
292
 
301
 
293
    print_console("OK\n");
302
    print_console("OK\n");
294
   
303
   
295
    return TRUE;
304
    return TRUE;
296
}
305
}
297
 
306
 
-
 
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
 */
298
int main(int argc, char **argv)
311
int main(int argc, char **argv)
299
{
312
{
300
   
313
   
301
    int retval, flags;
314
    int retval, flags;
302
    unsigned int size;
315
    unsigned int size;
303
 
316
 
304
 
317
 
305
    /* Initializing printing functions. */
318
    /* Initializing printing functions. */
306
    if (!init_printing())
319
    if (!init_printing())
307
        return -1;
320
        return -1;
308
 
321
 
309
    print_console("FS task\n");
322
    print_console("FS task\n");
310
 
323
 
311
    /* Connection to SERVICE_RD service. */
324
    /* Connection to SERVICE_RD service. */
312
    print_console("Connnection to SERVICE_RD...");
325
    print_console("Connnection to SERVICE_RD...");
313
    if (connect_to_rd(&rd_phone, RD_CONN_ATTEMPTS))
326
    if (connect_to_rd(&rd_phone, RD_CONN_ATTEMPTS))
314
        print_console("OK\n");
327
        print_console("OK\n");
315
    else {
328
    else {
316
        print_console("FALSE\n");
329
        print_console("FALSE\n");
317
        return -1;
330
        return -1;
318
    }
331
    }
319
   
332
   
320
    /* Creating shared memory for usage with SERVICE_RD.  */
333
    /* Creating shared memory for usage with SERVICE_RD.  */
321
    print_console("Creating address space area for share with SERVICE_RD task...");
334
    print_console("Creating address space area for share with SERVICE_RD task...");
322
    size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
335
    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);
336
    buffer = mmap(buffer, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
324
    if ((int)buffer < 0) {
337
    if ((int)buffer < 0) {
325
        print_console_int("As_area_create error %d", (int)buffer);
338
        print_console_int("As_area_create error %d", (int)buffer);
326
        return -1;
339
        return -1;
327
    }
340
    }
328
    print_console("OK\n");
341
    print_console("OK\n");
329
 
342
 
330
 
343
 
331
    /* Mapping memory to SERVICE_RD. */
344
    /* Mapping memory to SERVICE_RD. */
332
    print_console("Sending memory to RD_SERVICE...");
345
    print_console("Sending memory to RD_SERVICE...");
333
    flags = 0;
346
    flags = 0;
334
    flags = AS_AREA_READ | AS_AREA_WRITE;
347
    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);
348
    retval = async_req_3(rd_phone, IPC_M_AS_AREA_SEND, (uintptr_t)buffer, size, flags, NULL, NULL, NULL);
336
    if (retval < 0) {
349
    if (retval < 0) {
337
        print_console_int("%d\n", retval);
350
        print_console_int("%d\n", retval);
338
        return -1;
351
        return -1;
339
    }
352
    }
340
    print_console("OK\n");
353
    print_console("OK\n");
341
 
354
 
342
    if (fs_init()) {
355
    if (fs_init()) {
343
        ipcarg_t phonead;
356
        ipcarg_t phonead;
344
   
357
   
345
        async_set_client_connection(fs_connection);
358
        async_set_client_connection(fs_connection);
346
 
359
 
347
        /* Register service at nameserver */
360
        /* Register service at nameserver */
348
        if (ipc_connect_to_me(PHONE_NS, SERVICE_FS, 0, &phonead) != 0)
361
        if (ipc_connect_to_me(PHONE_NS, SERVICE_FS, 0, &phonead) != 0)
349
            return -1;
362
            return -1;
350
       
363
       
351
        async_manager();
364
        async_manager();
352
 
365
 
353
        /* Never reached */
366
        /* Never reached */
354
        return 0;
367
        return 0;
355
    }
368
    }
356
   
369
   
357
    return -1;
370
    return -1;
358
}
371
}
359
 
372
 
360
/**
373
/**
361
 * @}
374
 * @}
362
 */
375
 */
363
 
376