Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2387 → Rev 2388

/branches/fs/uspace/fs/fs.c
39,8 → 39,7
#include <ipc/services.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <io/io.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
47,66 → 46,300
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <cap.h>
#include <sys/mman.h>
#include "fs.h"
#include "dir.h"
#include "../console/console.h"
 
 
static int fs_call;
static ipc_call_t m_input; /* the input message used for request */
static ipc_callid_t callid; /* caller's number */
static int new_consument; /* if new consumer wants to connect to FS */
static int check_con; /* check of connection of consument */
static void prepare_message(void);
static int load_super(void);
static int new_consument_map(void);
 
static void fs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
 
int result;
 
ipc_answer_fast(iid, 0, 0, 0);
 
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
while (1)
{
prepare_message();
if (fs_call == IPC_M_PHONE_HUNGUP) {
ipc_answer_fast(callid, 0,0,0);
return;
case FS_OPEN:
//Why doesn't printf do anything in this task?
printf("FS_OPEN called");
char * f_name = (char *) IPC_GET_ARG1(call);
printf("I should open file: %s \n",f_name);
retval = 73;
break;
case FS_READ:
printf("FS_READ called");
unsigned int file_handle = IPC_GET_ARG1(call);
void * buffer = (void *) IPC_GET_ARG2(call);
unsigned int count = IPC_GET_ARG3(call);
//I still don't know how to copy memory to another task :(
//Or can i only map memory?
retval = 0;
break;
default:
retval = EINVAL;
}
ipc_answer_fast(callid, retval, 0, 0);
 
if (fs_call == FS_NEW_CONSUMER) {
if (!new_consument) {
ipc_answer_fast(callid, FS_ECONNECT, 0, 0);
}
else {
result = new_consument_map();
ipc_answer_fast(callid, result, 0, 0);
 
if (!result) {
new_consument = FALSE;
}
}
continue;
}
 
if (fs_call == IPC_M_AS_AREA_SEND) {
if (!new_consument)
ipc_answer_fast(callid, FS_ECONNECT, 0, 0);
else {
ipc_answer_fast(callid, 0, (uintptr_t)fp->buffer, 0);
fp = &fproc[new_consument];
fp->connected = TRUE;
new_consument = FALSE;
}
continue;
}
if (check_con < 0) {
ipc_answer_fast(callid, err_code, 0, 0);
check_con = TRUE;
continue;
}
 
if (FS_IN_RANGE(fs_call)) {
result = call_vector[fs_call-FS_BASE]();
}
else {
result = FS_EBADCALL;
}
 
ipc_answer_fast(callid, result, 0, 0);
}
}
 
/* Extracts parameters from message and prepare them for later usage. */
void prepare_message(void)
{
int shift, id_task;
callid = async_get_call(&m_input);
fs_call = IPC_GET_METHOD(m_input);
if (fs_call == IPC_M_AS_AREA_SEND) {
if (!new_consument) {
new_consument = FALSE;
}
 
return;
}
id_task = IPC_GET_ARG1(m_input);
/* Setup new consument. */
if (fs_call == FS_NEW_CONSUMER) {
if (!new_consument) {
new_consument = id_task;
}
else {
new_consument = FALSE;
}
 
return;
}
/* Other messages discard process of new consument connecting. */
if (new_consument) {
new_consument = FALSE;
}
if (id_task < 0 || id_task >= NR_PROCS) {
check_con = FS_EINVAL;
return;
}
/* Switch to active consument. */
fp = &fproc[id_task];
/* Check if consument was connected. */
if (!(fp->connected)) {
check_con = FS_ENOTCONNECT;
return;
}
 
/* Unpacking extended input message into message_params structure. */
unpack_message(&message_params, m_input, fp->buffer);
}
 
/* Map some memory to the task */
int new_consument_map()
{
size_t size;
task_id_t task_id;
 
task_id = new_consument;
if (task_id < 0 || task_id >= NR_PROCS) {
return FS_EINVAL;
}
 
fp = &fproc[task_id];
size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
fp->buffer = as_get_mappable_page(size, PAGE_COLOR((uintptr_t)fp->buffer));
 
return TRUE;
}
/* Reads in the superblock from image. */
int load_super(void)
{
super_block_t *sp;
if (!init_super_block())
return FALSE;
 
sp = get_super();
if (read_super(sp) != OK)
{
print_console("Super block read error\n");
return FALSE;
}
 
return TRUE;
}
 
/* Basic initialization. */
static bool fs_init(void)
{
return true;
register inode_t *rip;
int bad, i;
 
bad = 0;
callid = SERVICE_FS;
fp = (fproc_t *)NULL;
print_console("FS initialization...");
 
/* Block cache initialization. */
if (!init_block())
return FALSE;
/* Loading superblock. */
if (!load_super())
return FALSE;
for (i = 0; i < NR_PROCS; i++) {
if (i == SERVICE_FS)
continue;
 
fp = &fproc[i];
rip = get_inode(ROOT_INODE);
fp->fp_rootdir = rip;
dup_inode(rip);
fp->fp_workdir = rip;
}
fp = &fproc[SERVICE_FS];
 
/* Certain relations must hold for the file system to work at all. */
if (SUPER_SIZE > BLOCK_SIZE) {
print_console("SUPER_SIZE > BLOCK_SIZE\n");
bad++;
}
if (BLOCK_SIZE % V1_INODE_SIZE != 0) {
print_console("BLOCK_SIZE mod V1_INODE_SIZE != 0\n");
bad++;
}
if (OPEN_MAX > 127) {
print_console("OPEN_MAX > 127\n");
bad++;
}
if (V1_INODE_SIZE != 32) {
print_console("V1 inode size != 32\n");
bad++;
}
if (V2_INODE_SIZE != 64) {
print_console("V2 inode size != 64\n");
bad++;
}
if (bad)
return FALSE;
 
/* New consument flag settings. */
new_consument = FALSE;
check_con = FALSE;
 
print_console("OK\n");
return TRUE;
}
 
int main(int argc, char **argv)
{
int retval, flags;
unsigned int size;
 
 
/* Initializing printing functions. */
if (!init_printing())
return -1;
 
print_console("FS task\n");
 
/* Connection to SERVICE_RD service. */
print_console("Connnection to SERVICE_RD...");
if (connect_to_rd(&rd_phone, RD_CONN_ATTEMPTS))
print_console("OK\n");
else {
print_console("FALSE\n");
return -1;
}
/* Creating shared memory for usage with SERVICE_RD. */
print_console("Creating address space area for share with SERVICE_RD task...");
size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
buffer = mmap(buffer, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
if ((int)buffer < 0) {
print_console_int("As_area_create error %d", (int)buffer);
return -1;
}
print_console("OK\n");
 
 
/* Mapping memory to SERVICE_RD. */
print_console("Sending memory to RD_SERVICE...");
flags = 0;
flags = AS_AREA_READ | AS_AREA_WRITE;
retval = async_req_3(rd_phone, IPC_M_AS_AREA_SEND, (uintptr_t)buffer, size, flags, NULL, NULL, NULL);
if (retval < 0) {
print_console_int("%d\n", retval);
return -1;
}
print_console("OK\n");
 
if (fs_init()) {
ipcarg_t phonead;
async_set_client_connection(fs_connection);
 
/* Register service at nameserver */
if (ipc_connect_to_me(PHONE_NS, SERVICE_FS, 0, &phonead) != 0)
return -1;
async_manager();
 
/* Never reached */
return 0;
}