Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4667 → Rev 4668

/branches/dd/uspace/srv/kbd/ctl/pc.c
207,6 → 207,9
map = scanmap_e0;
map_length = sizeof(scanmap_e0) / sizeof(int);
break;
default:
map = NULL;
map_length = 0;
}
 
ds = ds_s;
218,7 → 221,7
type = KEY_PRESS;
}
 
if (scancode < 0 || scancode >= map_length)
if ((scancode < 0) || ((size_t) scancode >= map_length))
return;
 
key = map[scancode];
/branches/dd/uspace/srv/kbd/port/i8042.c
135,8 → 135,8
(void) pio_read_8(&i8042->data);
/* Enable kbd */
i8042_kbd.cmds[0].addr = &((i8042_t *) i8042_kernel)->status;
i8042_kbd.cmds[3].addr = &((i8042_t *) i8042_kernel)->data;
i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status;
i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data;
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), 0, &i8042_kbd);
 
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE;
/branches/dd/uspace/srv/kbd/genarch/gsp.c
244,7 → 244,7
key[0] = t->old_state;
key[1] = t->input;
 
hash_table_insert(&p->trans, &key, &t->link);
hash_table_insert(&p->trans, key, &t->link);
}
 
/** Allocate transition structure. */
276,7 → 276,8
gsp_trans_t *t;
 
t = hash_table_get_instance(item, gsp_trans_t, link);
return (key[0] == t->old_state && key[1] == t->input);
return ((key[0] == (unsigned long) t->old_state)
&& (key[1] == (unsigned long) t->input));
}
 
static void trans_op_remove_callback(link_t *item)
/branches/dd/uspace/srv/kbd/layout/us_qwerty.c
27,7 → 27,7
*/
 
/** @addtogroup kbd
* @brief US QWERTY leyout.
* @brief US QWERTY layout.
* @{
*/
 
/branches/dd/uspace/srv/kbd/layout/cz.c
27,7 → 27,7
*/
 
/** @addtogroup kbd
* @brief US QWERTY leyout.
* @brief Czech QWERTZ layout.
* @{
*/
 
399,6 → 399,8
case ms_carka:
return parse_ms_carka(ev);
}
return 0;
}
 
/**
/branches/dd/uspace/srv/ns/ns.c
108,13 → 108,6
task_id_t id;
ipcarg_t retval;
if (callid & IPC_CALLID_NOTIFICATION) {
id = (task_id_t)
MERGE_LOUP32(IPC_GET_ARG2(call), IPC_GET_ARG3(call));
wait_notification((wait_type_t) IPC_GET_ARG1(call), id);
continue;
}
switch (IPC_GET_METHOD(call)) {
case IPC_M_SHARE_IN:
switch (IPC_GET_ARG3(call)) {
133,7 → 126,7
}
continue;
case IPC_M_PHONE_HUNGUP:
retval = EOK;
retval = ns_task_disconnect(&call);
break;
case IPC_M_CONNECT_TO_ME:
/*
170,6 → 163,12
MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
wait_for_task(id, &call, callid);
continue;
case NS_ID_INTRO:
retval = ns_task_id_intro(&call);
break;
case NS_RETVAL:
retval = ns_task_retval(&call);
break;
default:
retval = ENOENT;
break;
/branches/dd/uspace/srv/ns/task.c
1,5 → 1,6
/*
* Copyright (c) 2009 Martin Decky
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
41,20 → 42,13
#include "ns.h"
 
#define TASK_HASH_TABLE_CHAINS 256
#define P2I_HASH_TABLE_CHAINS 256
 
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id);
 
/* TODO:
*
* The current implementation of waiting on a task is not perfect. If somebody
* wants to wait on a task which has already finished before the NS asked
* the kernel to receive notifications, it would block indefinitively.
*
* A solution to this is to fail immediately on a task for which no creation
* notification was received yet. However, there is a danger of a race condition
* in this solution -- the caller has to make sure that it is not trying to wait
* before the NS has a change to receive the task creation notification. This
* can be assured by waiting for this event in task_spawn().
*
* Finally, as there is currently no convention that each task has to be waited
* As there is currently no convention that each task has to be waited
* for, the NS can leak memory because of the zombie tasks.
*
*/
62,8 → 56,10
/** Task hash table item. */
typedef struct {
link_t link;
task_id_t id; /**< Task ID. */
bool destroyed;
task_id_t id; /**< Task ID. */
bool finished; /**< Task is done. */
bool have_rval; /**< Task returned a value. */
int retval; /**< The return value. */
} hashed_task_t;
 
/** Compute hash index into task hash table.
83,7 → 79,7
/** Compare a key with hashed item.
*
* @param key Array of keys.
* @param keys Must be lesser or equal to 2.
* @param keys Must be less than or equal to 2.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
125,6 → 121,65
/** Task hash table structure. */
static hash_table_t task_hash_table;
 
typedef struct {
link_t link;
ipcarg_t phash; /**< Task ID. */
task_id_t id; /**< Task ID. */
} p2i_entry_t;
 
/** Compute hash index into task hash table.
*
* @param key Array of keys.
* @return Hash index corresponding to key[0].
*
*/
static hash_index_t p2i_hash(unsigned long *key)
{
assert(key);
return (*key % TASK_HASH_TABLE_CHAINS);
}
 
/** Compare a key with hashed item.
*
* @param key Array of keys.
* @param keys Must be less than or equal to 1.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
*
*/
static int p2i_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
assert(key);
assert(keys == 1);
assert(item);
 
p2i_entry_t *e = hash_table_get_instance(item, p2i_entry_t, link);
 
return (key[0] == e->phash);
}
 
/** Perform actions after removal of item from the hash table.
*
* @param item Item that was removed from the hash table.
*
*/
static void p2i_remove(link_t *item)
{
assert(item);
free(hash_table_get_instance(item, p2i_entry_t, link));
}
 
/** Operations for task hash table. */
static hash_table_operations_t p2i_ops = {
.hash = p2i_hash,
.compare = p2i_compare,
.remove_callback = p2i_remove
};
 
/** Map phone hash to task ID */
static hash_table_t phone_to_id;
 
/** Pending task wait structure. */
typedef struct {
link_t link;
141,10 → 196,13
printf(NAME ": No memory available for tasks\n");
return ENOMEM;
}
 
if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS,
1, &p2i_ops)) {
printf(NAME ": No memory available for tasks\n");
return ENOMEM;
}
if (event_subscribe(EVENT_WAIT, 0) != EOK)
printf(NAME ": Error registering wait notifications\n");
list_initialize(&pending_wait);
return EOK;
154,6 → 212,7
void process_pending_wait(void)
{
link_t *cur;
task_exit_t texit;
loop:
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
169,12 → 228,16
continue;
hashed_task_t *ht = hash_table_get_instance(link, hashed_task_t, link);
if (!ht->destroyed)
if (!ht->finished)
continue;
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, EOK);
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) {
texit = ht->have_rval ? TASK_EXIT_NORMAL :
TASK_EXIT_UNEXPECTED;
ipc_answer_2(pr->callid, EOK, texit,
ht->retval);
}
 
hash_table_remove(&task_hash_table, keys, 2);
list_remove(cur);
free(pr);
182,66 → 245,27
}
}
 
static void fail_pending_wait(task_id_t id, int rc)
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid)
{
link_t *cur;
loop:
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
if (pr->id == id) {
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, rc);
list_remove(cur);
free(pr);
goto loop;
}
}
}
ipcarg_t retval;
task_exit_t texit;
 
void wait_notification(wait_type_t et, task_id_t id)
{
unsigned long keys[2] = {
LOWER32(id),
UPPER32(id)
};
link_t *link = hash_table_find(&task_hash_table, keys);
if (link == NULL) {
hashed_task_t *ht =
(hashed_task_t *) malloc(sizeof(hashed_task_t));
if (ht == NULL) {
fail_pending_wait(id, ENOMEM);
return;
}
link_initialize(&ht->link);
ht->id = id;
ht->destroyed = (et == TASK_CREATE) ? false : true;
hash_table_insert(&task_hash_table, keys, &ht->link);
} else {
hashed_task_t *ht =
hash_table_get_instance(link, hashed_task_t, link);
ht->destroyed = (et == TASK_CREATE) ? false : true;
}
}
 
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid)
{
ipcarg_t retval;
unsigned long keys[2] = {
LOWER32(id),
UPPER32(id)
};
link_t *link = hash_table_find(&task_hash_table, keys);
hashed_task_t *ht = (link != NULL) ?
hash_table_get_instance(link, hashed_task_t, link) : NULL;
if ((ht == NULL) || (!ht->destroyed)) {
 
if (ht == NULL) {
/* No such task exists. */
retval = ENOENT;
goto out;
}
 
if (!ht->finished) {
/* Add to pending list */
pending_wait_t *pr =
(pending_wait_t *) malloc(sizeof(pending_wait_t));
260,10 → 284,131
retval = EOK;
out:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
if (!(callid & IPC_CALLID_NOTIFICATION)) {
texit = ht->have_rval ? TASK_EXIT_NORMAL : TASK_EXIT_UNEXPECTED;
ipc_answer_2(callid, retval, texit, ht->retval);
}
}
 
int ns_task_id_intro(ipc_call_t *call)
{
task_id_t id;
unsigned long keys[2];
link_t *link;
p2i_entry_t *e;
hashed_task_t *ht;
 
id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
 
keys[0] = call->in_phone_hash;
 
link = hash_table_find(&phone_to_id, keys);
if (link != NULL)
return EEXISTS;
 
e = (p2i_entry_t *) malloc(sizeof(p2i_entry_t));
if (e == NULL)
return ENOMEM;
 
ht = (hashed_task_t *) malloc(sizeof(hashed_task_t));
if (ht == NULL)
return ENOMEM;
 
/* Insert to phone-to-id map. */
 
link_initialize(&e->link);
e->phash = call->in_phone_hash;
e->id = id;
hash_table_insert(&phone_to_id, keys, &e->link);
 
/* Insert to main table. */
 
keys[0] = LOWER32(id);
keys[1] = UPPER32(id);
 
link_initialize(&ht->link);
ht->id = id;
ht->finished = false;
ht->have_rval = false;
ht->retval = -1;
hash_table_insert(&task_hash_table, keys, &ht->link);
 
return EOK;
}
 
int ns_task_retval(ipc_call_t *call)
{
task_id_t id;
unsigned long keys[2];
int rc;
 
rc = get_id_by_phone(call->in_phone_hash, &id);
if (rc != EOK)
return rc;
 
keys[0] = LOWER32(id);
keys[1] = UPPER32(id);
link_t *link = hash_table_find(&task_hash_table, keys);
hashed_task_t *ht = (link != NULL) ?
hash_table_get_instance(link, hashed_task_t, link) : NULL;
if ((ht == NULL) || ht->finished)
return EINVAL;
 
ht->finished = true;
ht->have_rval = true;
ht->retval = IPC_GET_ARG1(*call);
 
return EOK;
}
 
int ns_task_disconnect(ipc_call_t *call)
{
unsigned long keys[2];
task_id_t id;
int rc;
 
rc = get_id_by_phone(call->in_phone_hash, &id);
if (rc != EOK)
return rc;
 
/* Delete from phone-to-id map. */
keys[0] = call->in_phone_hash;
hash_table_remove(&phone_to_id, keys, 1);
 
/* Mark task as finished. */
keys[0] = LOWER32(id);
keys[1] = UPPER32(id);
 
link_t *link = hash_table_find(&task_hash_table, keys);
hashed_task_t *ht =
hash_table_get_instance(link, hashed_task_t, link);
if (ht == NULL)
return EOK;
 
ht->finished = true;
 
return EOK;
}
 
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id)
{
unsigned long keys[1];
link_t *link;
p2i_entry_t *e;
 
keys[0] = phone_hash;
link = hash_table_find(&phone_to_id, keys);
if (link == NULL)
return ENOENT;
 
e = hash_table_get_instance(link, p2i_entry_t, link);
*id = e->id;
 
return EOK;
}
 
/**
* @}
*/
/branches/dd/uspace/srv/ns/task.h
42,6 → 42,11
extern void wait_notification(wait_type_t et, task_id_t id);
extern void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid);
 
extern int ns_task_id_intro(ipc_call_t *call);
extern int ns_task_disconnect(ipc_call_t *call);
extern int ns_task_retval(ipc_call_t *call);
 
 
#endif
 
/**
/branches/dd/uspace/srv/console/screenbuffer.h
135,6 → 135,8
return (a1.a.r.fg_color == a2.a.r.fg_color)
&& (a1.a.r.bg_color == a2.a.r.bg_color);
}
return 0;
}
 
 
/branches/dd/uspace/srv/console/console.c
51,6 → 51,7
#include <sysinfo.h>
#include <event.h>
#include <devmap.h>
#include <fibril_sync.h>
 
#include "console.h"
#include "gcons.h"
68,6 → 69,7
int phone; /**< Framebuffer phone */
ipcarg_t cols; /**< Framebuffer columns */
ipcarg_t rows; /**< Framebuffer rows */
int color_cap; /**< Color capabilities (FB_CCAP_xxx) */
} fb_info;
 
typedef struct {
97,64 → 99,9
size_t cnt; /**< Width of the span. */
} fb_pending;
 
/** Pending input structure. */
typedef struct {
link_t link;
console_t *cons; /**< Console waiting for input */
ipc_callid_t rid; /**< Call ID waiting for input */
ipc_callid_t callid; /**< Call ID waiting for IPC_DATA_READ */
size_t pos; /**< Position of the last stored data */
size_t size; /**< Size of ther buffer */
char *data; /**< Already stored data */
} pending_input_t;
static FIBRIL_MUTEX_INITIALIZE(input_mutex);
static FIBRIL_CONDVAR_INITIALIZE(input_cv);
 
LIST_INITIALIZE(pending_input);
 
/** Process pending input requests */
static void process_pending_input(void)
{
async_serialize_start();
link_t *cur;
loop:
for (cur = pending_input.next; cur != &pending_input; cur = cur->next) {
pending_input_t *pr = list_get_instance(cur, pending_input_t, link);
console_event_t ev;
if (keybuffer_pop(&pr->cons->keybuffer, &ev)) {
if (pr->data != NULL) {
if (ev.type == KEY_PRESS) {
pr->data[pr->pos] = ev.c;
pr->pos++;
}
} else {
ipc_answer_4(pr->rid, EOK, ev.type, ev.key, ev.mods, ev.c);
list_remove(cur);
free(pr);
goto loop;
}
}
if ((pr->data != NULL) && (pr->pos == pr->size)) {
(void) ipc_data_read_finalize(pr->callid, pr->data, pr->size);
ipc_answer_1(pr->rid, EOK, pr->size);
free(pr->data);
list_remove(cur);
free(pr);
goto loop;
}
}
async_serialize_end();
}
 
static void curs_visibility(bool visible)
{
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
226,6 → 173,19
}
}
 
int ccap_fb_to_con(int ccap_fb, int *ccap_con)
{
switch (ccap_fb) {
case FB_CCAP_NONE: *ccap_con = CONSOLE_CCAP_NONE; break;
case FB_CCAP_STYLE: *ccap_con = CONSOLE_CCAP_STYLE; break;
case FB_CCAP_INDEXED: *ccap_con = CONSOLE_CCAP_INDEXED; break;
case FB_CCAP_RGB: *ccap_con = CONSOLE_CCAP_RGB; break;
default: return EINVAL;
}
 
return EOK;
}
 
/** Send an area of screenbuffer to the FB driver. */
static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height)
{
287,9 → 247,12
/** Process a character from the client (TTY emulation). */
static void write_char(console_t *cons, wchar_t ch)
{
bool flush_cursor = false;
 
switch (ch) {
case '\n':
fb_pending_flush();
flush_cursor = true;
cons->scr.position_y++;
cons->scr.position_x = 0;
break;
315,8 → 278,10
cons->scr.position_x++;
}
if (cons->scr.position_x >= cons->scr.size_x)
if (cons->scr.position_x >= cons->scr.size_x) {
flush_cursor = true;
cons->scr.position_y++;
}
if (cons->scr.position_y >= cons->scr.size_y) {
fb_pending_flush();
327,7 → 292,9
if (cons == active_console)
async_msg_1(fb_info.phone, FB_SCROLL, 1);
}
 
if (cons == active_console && flush_cursor)
curs_goto(cons->scr.position_x, cons->scr.position_y);
cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
}
 
446,7 → 413,10
break;
}
fibril_mutex_lock(&input_mutex);
keybuffer_push(&active_console->keybuffer, &ev);
fibril_condvar_broadcast(&input_cv);
fibril_mutex_unlock(&input_mutex);
break;
default:
retval = ENOENT;
482,9 → 452,6
write_char(cons, ch);
}
if (cons == active_console)
curs_goto(cons->scr.position_x, cons->scr.position_y);
async_serialize_end();
gcons_notify_char(cons->index);
510,10 → 477,10
return;
}
async_serialize_start();
size_t pos = 0;
console_event_t ev;
fibril_mutex_lock(&input_mutex);
recheck:
while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
if (ev.type == KEY_PRESS) {
buf[pos] = ev.c;
526,50 → 493,25
ipc_answer_1(rid, EOK, size);
free(buf);
} else {
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
if (!pr) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
free(buf);
async_serialize_end();
return;
}
pr->cons = cons;
pr->rid = rid;
pr->callid = callid;
pr->pos = pos;
pr->size = size;
pr->data = buf;
list_append(&pr->link, &pending_input);
fibril_condvar_wait(&input_cv, &input_mutex);
goto recheck;
}
async_serialize_end();
fibril_mutex_unlock(&input_mutex);
}
 
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
async_serialize_start();
console_event_t ev;
 
fibril_mutex_lock(&input_mutex);
recheck:
if (keybuffer_pop(&cons->keybuffer, &ev)) {
ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
} else {
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
if (!pr) {
ipc_answer_0(rid, ENOMEM);
async_serialize_end();
return;
}
pr->cons = cons;
pr->rid = rid;
pr->callid = 0;
pr->data = NULL;
list_append(&pr->link, &pending_input);
fibril_condvar_wait(&input_cv, &input_mutex);
goto recheck;
}
async_serialize_end();
fibril_mutex_unlock(&input_mutex);
}
 
/** Default thread for new connections */
598,6 → 540,9
ipcarg_t arg1;
ipcarg_t arg2;
ipcarg_t arg3;
 
int cons_ccap;
int rc;
async_serialize_start();
if (cons->refcount == 0)
623,17 → 568,17
if (cons->refcount == 0)
gcons_notify_disconnect(cons->index);
return;
case VFS_READ:
case VFS_OUT_READ:
async_serialize_end();
cons_read(cons, callid, &call);
async_serialize_start();
continue;
case VFS_WRITE:
case VFS_OUT_WRITE:
async_serialize_end();
cons_write(cons, callid, &call);
async_serialize_start();
continue;
case VFS_SYNC:
case VFS_OUT_SYNC:
fb_pending_flush();
if (cons == active_console) {
async_req_0_0(fb_info.phone, FB_FLUSH);
660,6 → 605,14
arg1 = fb_info.cols;
arg2 = fb_info.rows;
break;
case CONSOLE_GET_COLOR_CAP:
rc = ccap_fb_to_con(fb_info.color_cap, &cons_ccap);
if (rc != EOK) {
ipc_answer_0(callid, rc);
continue;
}
arg1 = cons_ccap;
break;
case CONSOLE_SET_STYLE:
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
711,13 → 664,12
 
static bool console_init(void)
{
async_serialize_start();
ipcarg_t color_cap;
 
/* Connect to keyboard driver */
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
if (kbd_phone < 0) {
printf(NAME ": Failed to connect to keyboard service\n");
async_serialize_end();
return false;
}
724,18 → 676,15
ipcarg_t phonehash;
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
printf(NAME ": Failed to create callback from keyboard service\n");
async_serialize_end();
return false;
}
async_set_pending(process_pending_input);
async_new_connection(phonehash, 0, NULL, keyboard_events);
 
/* Connect to framebuffer driver */
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
if (fb_info.phone < 0) {
printf(NAME ": Failed to connect to video service\n");
async_serialize_end();
return -1;
}
743,7 → 692,6
int rc = devmap_driver_register(NAME, client_connection);
if (rc < 0) {
printf(NAME ": Unable to register driver (%d)\n", rc);
async_serialize_end();
return false;
}
753,6 → 701,8
/* Synchronize, the gcons could put something in queue */
async_req_0_0(fb_info.phone, FB_FLUSH);
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &color_cap);
fb_info.color_cap = color_cap;
/* Set up shared memory buffer. */
size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
779,7 → 729,6
if (screenbuffer_init(&consoles[i].scr,
fb_info.cols, fb_info.rows) == NULL) {
printf(NAME ": Unable to allocate screen buffer %u\n", i);
async_serialize_end();
return false;
}
screenbuffer_clear(&consoles[i].scr);
793,7 → 742,6
if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s\n", vc);
async_serialize_end();
return false;
}
}
803,11 → 751,13
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
/* Initialize the screen */
async_serialize_start();
gcons_redraw_console();
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
screen_clear();
curs_goto(0, 0);
curs_visibility(active_console->scr.is_cursor_visible);
async_serialize_end();
/* Receive kernel notifications */
if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
815,7 → 765,6
async_set_interrupt_received(interrupt_received);
async_serialize_end();
return true;
}
 
/branches/dd/uspace/srv/bd/file_bd/file_bd.c
44,11 → 44,12
#include <ipc/bd.h>
#include <async.h>
#include <as.h>
#include <futex.h>
#include <fibril_sync.h>
#include <devmap.h>
#include <sys/types.h>
#include <errno.h>
#include <bool.h>
#include <task.h>
 
#define NAME "file_bd"
 
56,12 → 57,12
static FILE *img;
 
static dev_handle_t dev_handle;
static atomic_t dev_futex = FUTEX_INITIALIZER;
static fibril_mutex_t dev_lock;
 
static int file_bd_init(const char *fname);
static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
static int file_bd_read(off_t blk_idx, off_t size, void *buf);
static int file_bd_write(off_t blk_idx, off_t size, void *buf);
static int file_bd_read(off_t blk_idx, size_t size, void *buf);
static int file_bd_write(off_t blk_idx, size_t size, void *buf);
 
int main(int argc, char **argv)
{
86,6 → 87,7
}
 
printf(NAME ": Accepting connections\n");
task_retval(0);
async_manager();
 
/* Not reached */
106,6 → 108,8
if (img == NULL)
return EINVAL;
 
fibril_mutex_initialize(&dev_lock);
 
return EOK;
}
 
118,7 → 122,7
int flags;
int retval;
off_t idx;
off_t size;
size_t size;
 
/* Answer the IPC_M_CONNECT_ME_TO call. */
ipc_answer_0(iid, EOK);
165,27 → 169,21
}
}
 
static int file_bd_read(off_t blk_idx, off_t size, void *buf)
static int file_bd_read(off_t blk_idx, size_t size, void *buf)
{
size_t n_rd;
 
printf("file_bd_read\n");
futex_down(&dev_futex);
fibril_mutex_lock(&dev_lock);
 
printf("seek\n");
fseek(img, blk_idx * size, SEEK_SET);
printf("read\n");
n_rd = fread(buf, 1, size, img);
printf("done\n");
 
printf("done\n");
 
if (ferror(img)) {
futex_up(&dev_futex);
fibril_mutex_unlock(&dev_lock);
return EIO; /* Read error */
}
 
futex_up(&dev_futex);
fibril_mutex_unlock(&dev_lock);
 
if (n_rd < size)
return EINVAL; /* Read beyond end of disk */
193,21 → 191,21
return EOK;
}
 
static int file_bd_write(off_t blk_idx, off_t size, void *buf)
static int file_bd_write(off_t blk_idx, size_t size, void *buf)
{
size_t n_wr;
 
futex_down(&dev_futex);
fibril_mutex_lock(&dev_lock);
 
fseek(img, blk_idx * size, SEEK_SET);
n_wr = fread(buf, 1, size, img);
 
if (ferror(img) || n_wr < size) {
futex_up(&dev_futex);
fibril_mutex_unlock(&dev_lock);
return EIO; /* Write error */
}
 
futex_up(&dev_futex);
fibril_mutex_unlock(&dev_lock);
 
return EOK;
}
/branches/dd/uspace/srv/bd/rd/rd.c
50,7 → 50,7
#include <async.h>
#include <align.h>
#include <async.h>
#include <futex.h>
#include <fibril_sync.h>
#include <stdio.h>
#include <devmap.h>
#include <ipc/bd.h>
63,12 → 63,12
static size_t rd_size;
 
/**
* This futex protects the ramdisk's data.
* This rwlock protects the ramdisk's data.
* If we were to serve multiple requests (read + write or several writes)
* concurrently (i.e. from two or more threads), each read and write needs to be
* protected by this futex.
* protected by this rwlock.
*/
atomic_t rd_futex = FUTEX_INITIALIZER;
fibril_rwlock_t rd_lock;
 
/** Handle one connection to ramdisk.
*
139,9 → 139,9
retval = ELIMIT;
break;
}
futex_down(&rd_futex);
fibril_rwlock_read_lock(&rd_lock);
memcpy(fs_va, rd_addr + offset * block_size, block_size);
futex_up(&rd_futex);
fibril_rwlock_read_unlock(&rd_lock);
retval = EOK;
break;
case BD_WRITE_BLOCK:
161,9 → 161,9
retval = ELIMIT;
break;
}
futex_up(&rd_futex);
fibril_rwlock_write_lock(&rd_lock);
memcpy(rd_addr + offset * block_size, fs_va, block_size);
futex_down(&rd_futex);
fibril_rwlock_write_unlock(&rd_lock);
retval = EOK;
break;
default:
216,6 → 216,8
printf(NAME ": Unable to register device\n");
return false;
}
 
fibril_rwlock_initialize(&rd_lock);
return true;
}
/branches/dd/uspace/srv/bd/gxe_bd/gxe_bd.c
42,10 → 42,11
#include <ipc/bd.h>
#include <async.h>
#include <as.h>
#include <futex.h>
#include <fibril_sync.h>
#include <devmap.h>
#include <sys/types.h>
#include <errno.h>
#include <task.h>
 
#define NAME "gxe_bd"
 
91,11 → 92,11
 
static dev_handle_t dev_handle[MAX_DISKS];
 
static atomic_t dev_futex = FUTEX_INITIALIZER;
static fibril_mutex_t dev_lock[MAX_DISKS];
 
static int gxe_bd_init(void);
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size,
void *buf);
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size,
void *buf);
110,6 → 111,7
return -1;
 
printf(NAME ": Accepting connections\n");
task_retval(0);
async_manager();
 
/* Not reached */
145,6 → 147,7
name);
return rc;
}
fibril_mutex_initialize(&dev_lock[i]);
}
 
return EOK;
160,7 → 163,7
int flags;
int retval;
off_t idx;
off_t size;
size_t size;
int disk_id, i;
 
/* Get the device handle. */
220,7 → 223,7
}
}
 
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size,
void *buf)
{
int rc;
256,7 → 259,7
size_t i;
uint32_t w;
 
futex_down(&dev_futex);
fibril_mutex_lock(&dev_lock[disk_id]);
pio_write_32(&dev->offset_lo, (uint32_t) offset);
pio_write_32(&dev->offset_hi, offset >> 32);
pio_write_32(&dev->disk_id, disk_id);
264,6 → 267,7
 
status = pio_read_32(&dev->status);
if (status == STATUS_FAILURE) {
fibril_mutex_unlock(&dev_lock[disk_id]);
return EIO;
}
 
271,7 → 275,7
((uint8_t *) buf)[i] = w = pio_read_8(&dev->buffer[i]);
}
 
futex_up(&dev_futex);
fibril_mutex_unlock(&dev_lock[disk_id]);
return EOK;
}
 
285,7 → 289,7
pio_write_8(&dev->buffer[i], ((const uint8_t *) buf)[i]);
}
 
futex_down(&dev_futex);
fibril_mutex_lock(&dev_lock[disk_id]);
pio_write_32(&dev->offset_lo, (uint32_t) offset);
pio_write_32(&dev->offset_hi, offset >> 32);
pio_write_32(&dev->disk_id, disk_id);
293,10 → 297,11
 
status = pio_read_32(&dev->status);
if (status == STATUS_FAILURE) {
fibril_mutex_unlock(&dev_lock[disk_id]);
return EIO;
}
 
futex_up(&dev_futex);
fibril_mutex_unlock(&dev_lock[disk_id]);
return EOK;
}
 
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.h
36,6 → 36,7
#define __ATA_BD_H__
 
#include <sys/types.h>
#include <fibril_sync.h>
 
enum {
CTL_READ_START = 0,
50,22 → 51,32
MAX_DISKS = 2
};
 
/** ATA Command Register Block. */
typedef union {
/* Read */
/* Read/Write */
struct {
uint8_t data_port;
uint8_t error;
uint16_t data_port;
uint8_t sector_count;
uint8_t sector_number;
uint8_t cylinder_low;
uint8_t cylinder_high;
uint8_t drive_head;
uint8_t pad_rw0;
};
 
/* Read Only */
struct {
uint8_t pad_ro0;
uint8_t error;
uint8_t pad_ro1[5];
uint8_t status;
};
 
/* Write */
/* Write Only */
struct {
uint8_t pad0[7];
uint8_t pad_wo0;
uint8_t features;
uint8_t pad_wo1[5];
uint8_t command;
};
} ata_cmd_t;
129,6 → 140,9
unsigned cylinders;
unsigned sectors;
uint64_t blocks;
 
fibril_mutex_t lock;
dev_handle_t dev_handle;
} disk_t;
 
#endif
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.c
37,6 → 37,9
* This driver currently works only with CHS addressing and uses PIO.
* Currently based on the (now obsolete) ANSI X3.221-1994 (ATA-1) standard.
* At this point only reading is possible, not writing.
*
* The driver services a single controller which can have up to two disks
* attached.
*/
 
#include <stdio.h>
46,11 → 49,12
#include <ipc/bd.h>
#include <async.h>
#include <as.h>
#include <futex.h>
#include <fibril_sync.h>
#include <devmap.h>
#include <sys/types.h>
#include <errno.h>
#include <bool.h>
#include <task.h>
 
#include "ata_bd.h"
 
64,15 → 68,12
static ata_cmd_t *cmd;
static ata_ctl_t *ctl;
 
static dev_handle_t dev_handle[MAX_DISKS];
 
static atomic_t dev_futex = FUTEX_INITIALIZER;
 
/** Per-disk state. */
static disk_t disk[MAX_DISKS];
 
static int ata_bd_init(void);
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size,
void *buf);
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
void *buf);
89,14 → 90,15
 
printf(NAME ": ATA disk driver\n");
 
printf("cmd_physical = 0x%x\n", cmd_physical);
printf("ctl_physical = 0x%x\n", ctl_physical);
printf("I/O address 0x%x\n", cmd_physical);
 
if (ata_bd_init() != EOK)
return -1;
 
/* Put drives to reset, disable interrupts. */
printf("Reset drives...\n");
printf("Reset drives... ");
fflush(stdout);
 
pio_write_8(&ctl->device_control, DCR_SRST);
/* FIXME: Find out how to do this properly. */
async_usleep(100);
107,8 → 109,6
} while ((status & SR_BSY) != 0);
printf("Done\n");
 
printf("Status = 0x%x\n", pio_read_8(&cmd->status));
 
(void) drive_identify(0, &disk[0]);
(void) drive_identify(1, &disk[1]);
 
120,7 → 120,7
continue;
 
snprintf(name, 16, "disk%d", i);
rc = devmap_device_register(name, &dev_handle[i]);
rc = devmap_device_register(name, &disk[i].dev_handle);
if (rc != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s.\n",
136,6 → 136,7
}
 
printf(NAME ": Accepting connections\n");
task_retval(0);
async_manager();
 
/* Not reached */
146,15 → 147,16
{
uint16_t data;
uint8_t status;
int i;
size_t i;
 
printf("Identify drive %d\n", disk_id);
printf("Identify drive %d... ", disk_id);
fflush(stdout);
 
pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0));
async_usleep(100);
pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
 
status = pio_read_8(&cmd->status);
printf("Status = 0x%x\n", status);
 
d->present = false;
 
181,8 → 183,6
}
}
 
printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status));
 
d->blocks = d->cylinders * d->heads * d->sectors;
 
printf("Geometry: %u cylinders, %u heads, %u sectors\n",
189,6 → 189,7
d->cylinders, d->heads, d->sectors);
 
d->present = true;
fibril_mutex_initialize(&d->lock);
 
return EOK;
}
234,7 → 235,7
int flags;
int retval;
off_t idx;
off_t size;
size_t size;
int disk_id, i;
 
/* Get the device handle. */
243,7 → 244,7
/* Determine which disk device is the client connecting to. */
disk_id = -1;
for (i = 0; i < MAX_DISKS; i++)
if (dev_handle[i] == dh)
if (disk[i].dev_handle == dh)
disk_id = i;
 
if (disk_id < 0 || disk[disk_id].present == false) {
294,14 → 295,14
}
}
 
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, off_t size,
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size,
void *buf)
{
int rc;
off_t now;
size_t now;
 
while (size > 0) {
now = size < block_size ? size : (off_t) block_size;
now = size < block_size ? size : block_size;
if (now != block_size)
return EINVAL;
 
355,7 → 356,7
((disk_id != 0) ? DHR_DRV : 0) |
(h & 0x0f);
 
futex_down(&dev_futex);
fibril_mutex_lock(&d->lock);
 
/* Program a Read Sectors operation. */
 
377,7 → 378,7
((uint16_t *) buf)[i] = data;
}
 
futex_up(&dev_futex);
fibril_mutex_unlock(&d->lock);
return EOK;
}
 
409,7 → 410,7
((disk_id != 0) ? DHR_DRV : 0) |
(h & 0x0f);
 
futex_down(&dev_futex);
fibril_mutex_lock(&d->lock);
 
/* Program a Read Sectors operation. */
 
430,7 → 431,7
pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]);
}
 
futex_up(&dev_futex);
fibril_mutex_unlock(&d->lock);
return EOK;
}
 
/branches/dd/uspace/srv/loader/main.c
52,6 → 52,8
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/loader.h>
#include <ipc/ns.h>
#include <macros.h>
#include <loader/pcb.h>
#include <errno.h>
#include <async.h>
79,7 → 81,7
/** Number of preset files */
static int filc = 0;
/** Preset files vector */
static char **filv = NULL;
static fdi_node_t **filv = NULL;
/** Buffer holding all preset files */
static fdi_node_t *fil_buf = NULL;
 
437,16 → 439,24
int main(int argc, char *argv[])
{
ipcarg_t phonead;
task_id_t id;
int rc;
 
connected = false;
 
/* Introduce this task to the NS (give it our task ID). */
id = task_get_id();
rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
if (rc != EOK)
return -1;
 
/* Set a handler of incomming connections. */
async_set_client_connection(ldr_connection);
/* Register at naming service. */
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
return -1;
return -2;
 
async_manager();
/* Never reached */
/branches/dd/uspace/srv/loader/elf_load.c
74,7 → 74,7
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
 
/** Read until the buffer is read in its entirety. */
static int my_read(int fd, char *buf, size_t len)
static int my_read(int fd, void *buf, size_t len)
{
int cnt = 0;
do {
331,21 → 331,26
int flags = 0;
uintptr_t bias;
uintptr_t base;
void *seg_ptr;
uintptr_t seg_addr;
size_t mem_sz;
int rc;
 
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
entry->p_memsz);
bias = elf->bias;
 
seg_addr = entry->p_vaddr + bias;
seg_ptr = (void *) seg_addr;
 
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", seg_addr,
entry->p_memsz);
 
if (entry->p_align > 1) {
if ((entry->p_offset % entry->p_align) !=
(entry->p_vaddr % entry->p_align)) {
(seg_addr % entry->p_align)) {
DPRINTF("Align check 1 failed offset%%align=%d, "
"vaddr%%align=%d\n",
entry->p_offset % entry->p_align,
entry->p_vaddr % entry->p_align
seg_addr % entry->p_align
);
return EE_INVALID;
}
364,7 → 369,7
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
DPRINTF("Map to p_vaddr=0x%x-0x%x.\n", entry->p_vaddr + bias,
DPRINTF("Map to seg_addr=0x%x-0x%x.\n", seg_addr,
entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
 
/*
379,7 → 384,7
}
 
DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
base + bias, mem_sz, flags, (uintptr_t)a);
 
/*
* Load segment data
399,7 → 404,7
uint8_t *dp;
 
left = entry->p_filesz;
dp = (uint8_t *)(entry->p_vaddr + bias);
dp = seg_ptr;
 
while (left > 0) {
now = 16384;
416,7 → 421,7
dp += now;
}
 
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
rc = as_area_change_flags(seg_ptr, flags);
if (rc != 0) {
DPRINTF("Failed to set memory area flags.\n");
return EE_MEMORY;
424,7 → 429,7
 
if (flags & AS_AREA_EXEC) {
/* Enforce SMC coherence for the segment */
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
if (smc_coherence(seg_ptr, entry->p_filesz))
return EE_MEMORY;
}
 
/branches/dd/uspace/srv/loader/arch/ia32/ia32.s
46,4 → 46,4
# Save a tiny bit of stack space
pop %ebp
 
jmp %eax
jmp *%eax
/branches/dd/uspace/srv/fb/serial_console.c
388,6 → 388,10
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_width, scr_height);
continue;
case FB_GET_COLOR_CAP:
ipc_answer_1(callid, EOK, color ? FB_CCAP_INDEXED :
FB_CCAP_STYLE);
continue;
case FB_CLEAR:
serial_clrscr();
retval = 0;
/branches/dd/uspace/srv/fb/fb.c
56,6 → 56,7
#include <async.h>
#include <fibril.h>
#include <bool.h>
#include <stdio.h>
 
#include "font-8x16.h"
#include "fb.h"
450,7 → 451,8
for (row = 0; row < vport->rows; row++) {
x = vport->x;
for (col = 0; col < vport->cols; col++) {
if ((row + lines >= 0) && (row + lines < vport->rows)) {
if (((int) row + lines >= 0) &&
((int) row + lines < (int) vport->rows)) {
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)];
bbp = &vport->backbuf[BB_POS(vport, col, row)];
1066,10 → 1068,11
if (IPC_GET_ARG1(*call) == shm_id) {
void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
shm_size = IPC_GET_ARG2(*call);
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest))
shm = dest;
else
if (ipc_answer_1(callid, EOK, (sysarg_t) dest)) {
shm_id = 0;
return false;
}
shm = dest;
if (shm[0] != 'P')
return false;
1644,6 → 1647,9
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, vport->cols, vport->rows);
continue;
case FB_GET_COLOR_CAP:
ipc_answer_1(callid, EOK, FB_CCAP_RGB);
continue;
case FB_SCROLL:
scroll = IPC_GET_ARG1(call);
if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) {
/branches/dd/uspace/srv/fb/ppm.c
89,7 → 89,7
{
unsigned int width, height;
unsigned int maxcolor;
int i;
unsigned int i;
unsigned int color;
unsigned int coef;
/branches/dd/uspace/srv/fb/ega.c
87,7 → 87,7
 
static void clrscr(void)
{
int i;
unsigned i;
for (i = 0; i < scr_width * scr_height; i++) {
scr_addr[i * 2] = ' ';
129,7 → 129,8
 
static void scroll(int rows)
{
int i;
unsigned i;
 
if (rows > 0) {
memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2,
scr_width * scr_height * 2 - rows * scr_width * 2);
318,6 → 319,9
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_width, scr_height);
continue;
case FB_GET_COLOR_CAP:
ipc_answer_1(callid, EOK, FB_CCAP_INDEXED);
continue;
case FB_CLEAR:
clrscr();
retval = 0;
345,7 → 349,7
break;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if (i > scr_height || i < -((int) scr_height)) {
if (i > (int) scr_height || i < -((int) scr_height)) {
retval = EINVAL;
break;
}
/branches/dd/uspace/srv/fs/devfs/devfs.c
65,37 → 65,39
ipc_callid_t callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case VFS_MOUNTED:
case IPC_M_PHONE_HUNGUP:
return;
case VFS_OUT_MOUNTED:
devfs_mounted(callid, &call);
break;
case VFS_MOUNT:
case VFS_OUT_MOUNT:
devfs_mount(callid, &call);
break;
case VFS_LOOKUP:
case VFS_OUT_LOOKUP:
devfs_lookup(callid, &call);
break;
case VFS_OPEN_NODE:
case VFS_OUT_OPEN_NODE:
devfs_open_node(callid, &call);
break;
case VFS_DEVICE:
devfs_device(callid, &call);
case VFS_OUT_STAT:
devfs_stat(callid, &call);
break;
case VFS_READ:
case VFS_OUT_READ:
devfs_read(callid, &call);
break;
case VFS_WRITE:
case VFS_OUT_WRITE:
devfs_write(callid, &call);
break;
case VFS_TRUNCATE:
case VFS_OUT_TRUNCATE:
devfs_truncate(callid, &call);
break;
case VFS_CLOSE:
case VFS_OUT_CLOSE:
devfs_close(callid, &call);
break;
case VFS_SYNC:
case VFS_OUT_SYNC:
devfs_sync(callid, &call);
break;
case VFS_DESTROY:
case VFS_OUT_DESTROY:
devfs_destroy(callid, &call);
break;
default:
/branches/dd/uspace/srv/fs/devfs/devfs_ops.c
41,7 → 41,9
#include <malloc.h>
#include <string.h>
#include <libfs.h>
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <sys/stat.h>
#include "devfs.h"
#include "devfs_ops.h"
 
58,6 → 60,9
/** Hash table of opened devices */
static hash_table_t devices;
 
/** Hash table mutex */
static FIBRIL_MUTEX_INITIALIZE(devices_mutex);
 
#define DEVICES_KEYS 1
#define DEVICES_KEY_HANDLE 0
#define DEVICES_BUCKETS 256
159,12 → 164,12
if (first >= last) {
/* Root entry */
if (lflag & L_DIRECTORY)
if (!(lflag & L_FILE))
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0);
else
ipc_answer_0(rid, ENOENT);
} else {
if (lflag & L_FILE) {
if (!(lflag & L_DIRECTORY)) {
size_t len;
if (last >= first)
len = last - first + 1;
195,10 → 200,12
[DEVICES_KEY_HANDLE] = (unsigned long) handle
};
fibril_mutex_lock(&devices_mutex);
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
int phone = devmap_device_connect(handle, 0);
if (phone < 0) {
fibril_mutex_unlock(&devices_mutex);
free(name);
ipc_answer_0(rid, ENOENT);
return;
206,6 → 213,7
device_t *dev = (device_t *) malloc(sizeof(device_t));
if (dev == NULL) {
fibril_mutex_unlock(&devices_mutex);
free(name);
ipc_answer_0(rid, ENOMEM);
return;
220,6 → 228,7
device_t *dev = hash_table_get_instance(lnk, device_t, link);
dev->refcount++;
}
fibril_mutex_unlock(&devices_mutex);
}
free(name);
238,10 → 247,12
[DEVICES_KEY_HANDLE] = (unsigned long) handle
};
fibril_mutex_lock(&devices_mutex);
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
int phone = devmap_device_connect(handle, 0);
if (phone < 0) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(rid, ENOENT);
return;
}
248,6 → 259,7
device_t *dev = (device_t *) malloc(sizeof(device_t));
if (dev == NULL) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(rid, ENOMEM);
return;
}
261,28 → 273,49
device_t *dev = hash_table_get_instance(lnk, device_t, link);
dev->refcount++;
}
fibril_mutex_unlock(&devices_mutex);
ipc_answer_3(rid, EOK, 0, 1, L_FILE);
}
 
void devfs_device(ipc_callid_t rid, ipc_call_t *request)
void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size) ||
size != sizeof(struct stat)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
struct stat stat;
memset(&stat, 0, sizeof(struct stat));
 
stat.fs_handle = devfs_reg.fs_handle;
stat.dev_handle = dev_handle;
stat.index = index;
stat.lnkcnt = 1;
stat.is_file = (index != 0);
stat.size = 0;
if (index != 0) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
fibril_mutex_lock(&devices_mutex);
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
ipc_answer_1(rid, EOK, (ipcarg_t) index);
} else
ipc_answer_0(rid, ENOTSUP);
if (lnk != NULL)
stat.devfs_stat.device = (dev_handle_t)index;
fibril_mutex_unlock(&devices_mutex);
}
 
ipc_data_read_finalize(callid, &stat, sizeof(struct stat));
ipc_answer_0(rid, EOK);
}
 
void devfs_read(ipc_callid_t rid, ipc_call_t *request)
295,8 → 328,10
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
fibril_mutex_lock(&devices_mutex);
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(rid, ENOENT);
return;
}
305,6 → 340,7
ipc_callid_t callid;
if (!ipc_data_read_receive(&callid, NULL)) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
318,6 → 354,7
/* Forward the IPC_M_DATA_READ request to the driver */
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
fibril_mutex_unlock(&devices_mutex);
/* Wait for reply from the driver. */
ipcarg_t rc;
369,8 → 406,10
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
fibril_mutex_lock(&devices_mutex);
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(rid, ENOENT);
return;
}
379,6 → 418,7
ipc_callid_t callid;
if (!ipc_data_write_receive(&callid, NULL)) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
393,6 → 433,8
/* Forward the IPC_M_DATA_WRITE request to the driver */
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
fibril_mutex_unlock(&devices_mutex);
/* Wait for reply from the driver. */
ipcarg_t rc;
async_wait_for(msg, &rc);
420,8 → 462,10
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
fibril_mutex_lock(&devices_mutex);
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(rid, ENOENT);
return;
}
434,6 → 478,8
hash_table_remove(&devices, key, DEVICES_KEYS);
}
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(rid, EOK);
} else
ipc_answer_0(rid, ENOTSUP);
448,8 → 494,10
[DEVICES_KEY_HANDLE] = (unsigned long) index
};
fibril_mutex_lock(&devices_mutex);
link_t *lnk = hash_table_find(&devices, key);
if (lnk == NULL) {
fibril_mutex_unlock(&devices_mutex);
ipc_answer_0(rid, ENOENT);
return;
}
461,6 → 509,8
aid_t msg = async_send_2(dev->phone, IPC_GET_METHOD(*request),
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
fibril_mutex_unlock(&devices_mutex);
/* Wait for reply from the driver */
ipcarg_t rc;
async_wait_for(msg, &rc);
/branches/dd/uspace/srv/fs/devfs/devfs_ops.h
42,7 → 42,7
extern void devfs_mount(ipc_callid_t, ipc_call_t *);
extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
extern void devfs_device(ipc_callid_t, ipc_call_t *);
extern void devfs_stat(ipc_callid_t, ipc_call_t *);
extern void devfs_sync(ipc_callid_t, ipc_call_t *);
extern void devfs_read(ipc_callid_t, ipc_call_t *);
extern void devfs_write(ipc_callid_t, ipc_call_t *);
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.h
86,10 → 86,10
extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
extern void tmpfs_device(ipc_callid_t, ipc_call_t *);
extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
 
extern bool tmpfs_restore(dev_handle_t);
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_dump.c
67,8 → 67,8
tmpfs_node_t *nodep;
uint32_t size;
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
TMPFS_BLOCK_SIZE) != EOK)
if (block_seqread(dev, bufpos, buflen, pos, &entry,
sizeof(entry), TMPFS_BLOCK_SIZE) != EOK)
return false;
entry.len = uint32_t_le2host(entry.len);
87,7 → 87,7
return false;
}
if (block_read(dev, bufpos, buflen, pos, fname,
if (block_seqread(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy(fn);
free(fname);
103,7 → 103,7
}
free(fname);
if (block_read(dev, bufpos, buflen, pos, &size,
if (block_seqread(dev, bufpos, buflen, pos, &size,
sizeof(size), TMPFS_BLOCK_SIZE) != EOK)
return false;
115,7 → 115,7
return false;
nodep->size = size;
if (block_read(dev, bufpos, buflen, pos, nodep->data,
if (block_seqread(dev, bufpos, buflen, pos, nodep->data,
size, TMPFS_BLOCK_SIZE) != EOK)
return false;
131,7 → 131,7
return false;
}
if (block_read(dev, bufpos, buflen, pos, fname,
if (block_seqread(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy(fn);
free(fname);
174,7 → 174,7
off_t pos = 0;
char tag[6];
if (block_read(dev, &bufpos, &buflen, &pos, tag, 5,
if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE) != EOK)
goto error;
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.c
96,37 → 96,39
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case VFS_MOUNTED:
case IPC_M_PHONE_HUNGUP:
return;
case VFS_OUT_MOUNTED:
tmpfs_mounted(callid, &call);
break;
case VFS_MOUNT:
case VFS_OUT_MOUNT:
tmpfs_mount(callid, &call);
break;
case VFS_LOOKUP:
case VFS_OUT_LOOKUP:
tmpfs_lookup(callid, &call);
break;
case VFS_READ:
case VFS_OUT_READ:
tmpfs_read(callid, &call);
break;
case VFS_WRITE:
case VFS_OUT_WRITE:
tmpfs_write(callid, &call);
break;
case VFS_TRUNCATE:
case VFS_OUT_TRUNCATE:
tmpfs_truncate(callid, &call);
break;
case VFS_CLOSE:
case VFS_OUT_CLOSE:
tmpfs_close(callid, &call);
break;
case VFS_DESTROY:
case VFS_OUT_DESTROY:
tmpfs_destroy(callid, &call);
break;
case VFS_OPEN_NODE:
case VFS_OUT_OPEN_NODE:
tmpfs_open_node(callid, &call);
break;
case VFS_DEVICE:
tmpfs_device(callid, &call);
case VFS_OUT_STAT:
tmpfs_stat(callid, &call);
break;
case VFS_SYNC:
case VFS_OUT_SYNC:
tmpfs_sync(callid, &call);
break;
default:
150,7 → 152,7
printf(NAME ": Unable to connect to VFS\n");
return -1;
}
 
int rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info,
tmpfs_connection);
if (rc != EOK) {
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_ops.c
628,9 → 628,9
libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
}
 
void tmpfs_device(ipc_callid_t rid, ipc_call_t *request)
void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
}
 
void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
/branches/dd/uspace/srv/fs/fat/fat_idx.c
42,7 → 42,7
#include <adt/hash_table.h>
#include <adt/list.h>
#include <assert.h>
#include <futex.h>
#include <fibril_sync.h>
 
/** Each instance of this type describes one interval of freed VFS indices. */
typedef struct {
68,8 → 68,8
link_t freed_head;
} unused_t;
 
/** Futex protecting the list of unused structures. */
static futex_t unused_futex = FUTEX_INITIALIZER;
/** Mutex protecting the list of unused structures. */
static FIBRIL_MUTEX_INITIALIZE(unused_lock);
 
/** List of unused structures. */
static LIST_INITIALIZE(unused_head);
89,7 → 89,7
link_t *l;
 
if (lock)
futex_down(&unused_futex);
fibril_mutex_lock(&unused_lock);
for (l = unused_head.next; l != &unused_head; l = l->next) {
u = list_get_instance(l, unused_t, link);
if (u->dev_handle == dev_handle)
96,12 → 96,12
return u;
}
if (lock)
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return NULL;
}
 
/** Futex protecting the up_hash and ui_hash. */
static futex_t used_futex = FUTEX_INITIALIZER;
/** Mutex protecting the up_hash and ui_hash. */
static FIBRIL_MUTEX_INITIALIZE(used_lock);
 
/**
* Global hash table of all used fat_idx_t structures.
231,7 → 231,7
*/
*index = u->next++;
--u->remaining;
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return true;
}
} else {
244,7 → 244,7
list_remove(&f->link);
free(f);
}
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return true;
}
/*
252,7 → 252,7
* theoretically still possible (e.g. too many open unlinked nodes or
* too many zero-sized nodes).
*/
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return false;
}
 
302,7 → 302,7
if (lnk->prev != &u->freed_head)
try_coalesce_intervals(lnk->prev, lnk,
lnk);
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return;
}
if (f->last == index - 1) {
310,7 → 310,7
if (lnk->next != &u->freed_head)
try_coalesce_intervals(lnk, lnk->next,
lnk);
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return;
}
if (index > f->first) {
321,7 → 321,7
n->first = index;
n->last = index;
list_insert_before(&n->link, lnk);
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return;
}
 
335,7 → 335,7
n->last = index;
list_append(&n->link, &u->freed_head);
}
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
}
 
static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)
352,7 → 352,7
link_initialize(&fidx->uph_link);
link_initialize(&fidx->uih_link);
futex_initialize(&fidx->lock, 1);
fibril_mutex_initialize(&fidx->lock);
fidx->dev_handle = dev_handle;
fidx->pfc = FAT_CLST_RES0; /* no parent yet */
fidx->pdi = 0;
365,10 → 365,10
{
fat_idx_t *fidx;
 
futex_down(&used_futex);
fibril_mutex_lock(&used_lock);
fidx = fat_idx_create(dev_handle);
if (!fidx) {
futex_up(&used_futex);
fibril_mutex_unlock(&used_lock);
return NULL;
}
378,8 → 378,8
};
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
futex_down(&fidx->lock);
futex_up(&used_futex);
fibril_mutex_lock(&fidx->lock);
fibril_mutex_unlock(&used_lock);
 
return fidx;
}
395,7 → 395,7
[UPH_PDI_KEY] = pdi,
};
 
futex_down(&used_futex);
fibril_mutex_lock(&used_lock);
l = hash_table_find(&up_hash, pkey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
402,7 → 402,7
} else {
fidx = fat_idx_create(dev_handle);
if (!fidx) {
futex_up(&used_futex);
fibril_mutex_unlock(&used_lock);
return NULL;
}
417,8 → 417,8
hash_table_insert(&up_hash, pkey, &fidx->uph_link);
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
}
futex_down(&fidx->lock);
futex_up(&used_futex);
fibril_mutex_lock(&fidx->lock);
fibril_mutex_unlock(&used_lock);
 
return fidx;
}
431,9 → 431,9
[UPH_PDI_KEY] = idx->pdi,
};
 
futex_down(&used_futex);
fibril_mutex_lock(&used_lock);
hash_table_insert(&up_hash, pkey, &idx->uph_link);
futex_up(&used_futex);
fibril_mutex_unlock(&used_lock);
}
 
void fat_idx_hashout(fat_idx_t *idx)
444,9 → 444,9
[UPH_PDI_KEY] = idx->pdi,
};
 
futex_down(&used_futex);
fibril_mutex_lock(&used_lock);
hash_table_remove(&up_hash, pkey, 3);
futex_up(&used_futex);
fibril_mutex_unlock(&used_lock);
}
 
fat_idx_t *
459,13 → 459,13
[UIH_INDEX_KEY] = index,
};
 
futex_down(&used_futex);
fibril_mutex_lock(&used_lock);
l = hash_table_find(&ui_hash, ikey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uih_link);
futex_down(&fidx->lock);
fibril_mutex_lock(&fidx->lock);
}
futex_up(&used_futex);
fibril_mutex_unlock(&used_lock);
 
return fidx;
}
483,7 → 483,7
 
assert(idx->pfc == FAT_CLST_RES0);
 
futex_down(&used_futex);
fibril_mutex_lock(&used_lock);
/*
* Since we can only free unlinked nodes, the index structure is not
* present in the position hash (uph). We therefore hash it out from
490,7 → 490,7
* the index hash only.
*/
hash_table_remove(&ui_hash, ikey, 2);
futex_up(&used_futex);
fibril_mutex_unlock(&used_lock);
/* Release the VFS index. */
fat_index_free(idx->dev_handle, idx->index);
/* Deallocate the structure. */
524,12 → 524,12
if (!u)
return ENOMEM;
unused_initialize(u, dev_handle);
futex_down(&unused_futex);
fibril_mutex_lock(&unused_lock);
if (!unused_find(dev_handle, false))
list_append(&u->link, &unused_head);
else
rc = EEXIST;
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
return rc;
}
 
540,7 → 540,7
u = unused_find(dev_handle, true);
assert(u);
list_remove(&u->link);
futex_up(&unused_futex);
fibril_mutex_unlock(&unused_lock);
 
while (!list_empty(&u->freed_head)) {
freed_t *f;
/branches/dd/uspace/srv/fs/fat/fat.h
35,6 → 35,7
 
#include "fat_fat.h"
#include <ipc/ipc.h>
#include <fibril_sync.h>
#include <libfs.h>
#include <atomic.h>
#include <sys/types.h>
160,7 → 161,7
/** Used indices (index) hash table link. */
link_t uih_link;
 
futex_t lock;
fibril_mutex_t lock;
dev_handle_t dev_handle;
fs_index_t index;
/**
181,7 → 182,7
/** Back pointer to the FS node. */
fs_node_t *bp;
futex_t lock;
fibril_mutex_t lock;
fat_node_type_t type;
fat_idx_t *idx;
/**
206,10 → 207,11
extern void fat_read(ipc_callid_t, ipc_call_t *);
extern void fat_write(ipc_callid_t, ipc_call_t *);
extern void fat_truncate(ipc_callid_t, ipc_call_t *);
extern void fat_stat(ipc_callid_t, ipc_call_t *);
extern void fat_close(ipc_callid_t, ipc_call_t *);
extern void fat_destroy(ipc_callid_t, ipc_call_t *);
extern void fat_open_node(ipc_callid_t, ipc_call_t *);
extern void fat_device(ipc_callid_t, ipc_call_t *);
extern void fat_stat(ipc_callid_t, ipc_call_t *);
extern void fat_sync(ipc_callid_t, ipc_call_t *);
 
extern fat_idx_t *fat_idx_get_new(dev_handle_t);
/branches/dd/uspace/srv/fs/fat/fat_fat.c
45,15 → 45,15
#include <byteorder.h>
#include <align.h>
#include <assert.h>
#include <futex.h>
#include <fibril_sync.h>
#include <mem.h>
 
/**
* The fat_alloc_lock futex protects all copies of the File Allocation Table
* The fat_alloc_lock mutex protects all copies of the File Allocation Table
* during allocation of clusters. The lock does not have to be held durring
* deallocation of clusters.
*/
static futex_t fat_alloc_lock = FUTEX_INITIALIZER;
static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
 
/** Walk the cluster chain.
*
326,7 → 326,7
/*
* Search FAT1 for unused clusters.
*/
futex_down(&fat_alloc_lock);
fibril_mutex_lock(&fat_alloc_lock);
for (b = 0, cl = 0; b < sf; b++) {
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
350,7 → 350,7
*mcl = lifo[found - 1];
*lcl = lifo[0];
free(lifo);
futex_up(&fat_alloc_lock);
fibril_mutex_unlock(&fat_alloc_lock);
return EOK;
}
}
357,7 → 357,7
}
block_put(blk);
}
futex_up(&fat_alloc_lock);
fibril_mutex_unlock(&fat_alloc_lock);
 
/*
* We could not find enough clusters. Now we need to free the clusters
/branches/dd/uspace/srv/fs/fat/fat.c
89,37 → 89,39
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case VFS_MOUNTED:
case IPC_M_PHONE_HUNGUP:
return;
case VFS_OUT_MOUNTED:
fat_mounted(callid, &call);
break;
case VFS_MOUNT:
case VFS_OUT_MOUNT:
fat_mount(callid, &call);
break;
case VFS_LOOKUP:
case VFS_OUT_LOOKUP:
fat_lookup(callid, &call);
break;
case VFS_READ:
case VFS_OUT_READ:
fat_read(callid, &call);
break;
case VFS_WRITE:
case VFS_OUT_WRITE:
fat_write(callid, &call);
break;
case VFS_TRUNCATE:
case VFS_OUT_TRUNCATE:
fat_truncate(callid, &call);
break;
case VFS_CLOSE:
case VFS_OUT_STAT:
fat_stat(callid, &call);
break;
case VFS_OUT_CLOSE:
fat_close(callid, &call);
break;
case VFS_DESTROY:
case VFS_OUT_DESTROY:
fat_destroy(callid, &call);
break;
case VFS_OPEN_NODE:
case VFS_OUT_OPEN_NODE:
fat_open_node(callid, &call);
break;
case VFS_DEVICE:
fat_device(callid, &call);
break;
case VFS_SYNC:
case VFS_OUT_SYNC:
fat_sync(callid, &call);
break;
default:
/branches/dd/uspace/srv/fs/fat/fat_ops.c
51,7 → 51,7
#include <adt/hash_table.h>
#include <adt/list.h>
#include <assert.h>
#include <futex.h>
#include <fibril_sync.h>
#include <sys/mman.h>
#include <align.h>
 
58,8 → 58,8
#define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL)
#define FS_NODE(node) ((node) ? (node)->bp : NULL)
 
/** Futex protecting the list of cached free FAT nodes. */
static futex_t ffn_futex = FUTEX_INITIALIZER;
/** Mutex protecting the list of cached free FAT nodes. */
static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
 
/** List of cached free FAT nodes. */
static LIST_INITIALIZE(ffn_head);
66,7 → 66,7
 
static void fat_node_initialize(fat_node_t *node)
{
futex_initialize(&node->lock, 1);
fibril_mutex_initialize(&node->lock);
node->bp = NULL;
node->idx = NULL;
node->type = 0;
115,30 → 115,30
fs_node_t *fn;
fat_node_t *nodep;
 
futex_down(&ffn_futex);
fibril_mutex_lock(&ffn_mutex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached free node structure. */
fat_idx_t *idxp_tmp;
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
if (!fibril_mutex_trylock(&nodep->lock))
goto skip_cache;
idxp_tmp = nodep->idx;
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
fibril_mutex_unlock(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
futex_up(&ffn_futex);
fibril_mutex_unlock(&ffn_mutex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
fibril_mutex_unlock(&nodep->lock);
fibril_mutex_unlock(&idxp_tmp->lock);
fn = FS_NODE(nodep);
} else {
skip_cache:
/* Try to allocate a new node structure. */
futex_up(&ffn_futex);
fibril_mutex_unlock(&ffn_mutex);
fn = (fs_node_t *)malloc(sizeof(fs_node_t));
if (!fn)
return NULL;
175,10 → 175,10
* We are lucky.
* The node is already instantiated in memory.
*/
futex_down(&idxp->nodep->lock);
fibril_mutex_lock(&idxp->nodep->lock);
if (!idxp->nodep->refcnt++)
list_remove(&idxp->nodep->ffn_link);
futex_up(&idxp->nodep->lock);
fibril_mutex_unlock(&idxp->nodep->lock);
return idxp->nodep;
}
 
268,7 → 268,7
return NULL;
/* idxp->lock held */
nodep = fat_node_get_core(idxp);
futex_up(&idxp->lock);
fibril_mutex_unlock(&idxp->lock);
return FS_NODE(nodep);
}
 
277,12 → 277,12
fat_node_t *nodep = FAT_NODE(fn);
bool destroy = false;
 
futex_down(&nodep->lock);
fibril_mutex_lock(&nodep->lock);
if (!--nodep->refcnt) {
if (nodep->idx) {
futex_down(&ffn_futex);
fibril_mutex_lock(&ffn_mutex);
list_append(&nodep->ffn_link, &ffn_head);
futex_up(&ffn_futex);
fibril_mutex_unlock(&ffn_mutex);
} else {
/*
* The node does not have any index structure associated
293,7 → 293,7
destroy = true;
}
}
futex_up(&nodep->lock);
fibril_mutex_unlock(&nodep->lock);
if (destroy) {
free(nodep->bp);
free(nodep);
360,7 → 360,7
nodep->idx = idxp;
idxp->nodep = nodep;
 
futex_up(&idxp->lock);
fibril_mutex_unlock(&idxp->lock);
return FS_NODE(nodep);
}
 
409,16 → 409,16
fat_cluster_t mcl, lcl;
int rc;
 
futex_down(&childp->lock);
fibril_mutex_lock(&childp->lock);
if (childp->lnkcnt == 1) {
/*
* On FAT, we don't support multiple hard links.
*/
futex_up(&childp->lock);
fibril_mutex_unlock(&childp->lock);
return EMLINK;
}
assert(childp->lnkcnt == 0);
futex_up(&childp->lock);
fibril_mutex_unlock(&childp->lock);
 
if (!fat_dentry_name_verify(name)) {
/*
432,7 → 432,7
* a new one.
*/
futex_down(&parentp->idx->lock);
fibril_mutex_lock(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
463,12 → 463,12
*/
if (parentp->idx->pfc == FAT_CLST_ROOT) {
/* Can't grow the root directory. */
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return ENOSPC;
}
rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
if (rc != EOK) {
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return rc;
}
fat_append_clusters(bs, parentp, mcl);
491,9 → 491,9
fat_dentry_name_set(d, name);
b->dirty = true; /* need to sync block */
block_put(b);
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
 
futex_down(&childp->idx->lock);
fibril_mutex_lock(&childp->idx->lock);
/*
* If possible, create the Sub-directory Identifier Entry and the
529,12 → 529,12
 
childp->idx->pfc = parentp->firstc;
childp->idx->pdi = i * dps + j;
futex_up(&childp->idx->lock);
fibril_mutex_unlock(&childp->idx->lock);
 
futex_down(&childp->lock);
fibril_mutex_lock(&childp->lock);
childp->lnkcnt = 1;
childp->dirty = true; /* need to sync node */
futex_up(&childp->lock);
fibril_mutex_unlock(&childp->lock);
 
/*
* Hash in the index structure into the position hash.
559,10 → 559,10
if (fat_has_children(cfn))
return ENOTEMPTY;
 
futex_down(&parentp->lock);
futex_down(&childp->lock);
fibril_mutex_lock(&parentp->lock);
fibril_mutex_lock(&childp->lock);
assert(childp->lnkcnt == 1);
futex_down(&childp->idx->lock);
fibril_mutex_lock(&childp->idx->lock);
bs = block_bb_get(childp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
 
581,11 → 581,11
/* clear position information */
childp->idx->pfc = FAT_CLST_RES0;
childp->idx->pdi = 0;
futex_up(&childp->idx->lock);
fibril_mutex_unlock(&childp->idx->lock);
childp->lnkcnt = 0;
childp->dirty = true;
futex_up(&childp->lock);
futex_up(&parentp->lock);
fibril_mutex_unlock(&childp->lock);
fibril_mutex_unlock(&parentp->lock);
 
return EOK;
}
602,7 → 602,7
fat_dentry_t *d;
block_t *b;
 
futex_down(&parentp->idx->lock);
fibril_mutex_lock(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
617,7 → 617,7
continue;
case FAT_DENTRY_LAST:
block_put(b);
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return NULL;
default:
case FAT_DENTRY_VALID:
636,7 → 636,7
fat_idx_t *idx = fat_idx_get_by_pos(
parentp->idx->dev_handle, parentp->firstc,
i * dps + j);
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
if (!idx) {
/*
* Can happen if memory is low or if we
646,7 → 646,7
return NULL;
}
nodep = fat_node_get_core(idx);
futex_up(&idx->lock);
fibril_mutex_unlock(&idx->lock);
block_put(b);
return FS_NODE(nodep);
}
654,7 → 654,7
block_put(b);
}
 
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return NULL;
}
 
686,7 → 686,7
if (nodep->type != FAT_DIRECTORY)
return false;
futex_down(&nodep->idx->lock);
fibril_mutex_lock(&nodep->idx->lock);
bs = block_bb_get(nodep->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
705,22 → 705,22
continue;
case FAT_DENTRY_LAST:
block_put(b);
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return false;
default:
case FAT_DENTRY_VALID:
block_put(b);
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return true;
}
block_put(b);
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return true;
}
block_put(b);
}
 
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return false;
}
 
770,6 → 770,7
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
enum cache_mode cmode;
fat_bs_t *bs;
uint16_t bps;
uint16_t rde;
797,6 → 798,12
}
opts[size] = '\0';
 
/* Check for option enabling write through. */
if (str_cmp(opts, "wtcache") == 0)
cmode = CACHE_MODE_WT;
else
cmode = CACHE_MODE_WB;
 
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE);
if (rc != EOK) {
826,7 → 833,7
}
 
/* Initialize the block cache */
rc = block_cache_init(dev_handle, bps, 0 /* XXX */);
rc = block_cache_init(dev_handle, bps, 0 /* XXX */, cmode);
if (rc != EOK) {
block_fini(dev_handle);
ipc_answer_0(rid, rc);
881,7 → 888,7
rootp->bp = rfn;
rfn->data = rootp;
futex_up(&ridxp->lock);
fibril_mutex_unlock(&ridxp->lock);
 
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
}
1195,9 → 1202,9
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_device(ipc_callid_t rid, ipc_call_t *request)
void fat_stat(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_sync(ipc_callid_t rid, ipc_call_t *request)
/branches/dd/uspace/srv/devmap/devmap.c
46,7 → 46,8
#include <string.h>
#include <ipc/devmap.h>
 
#define NAME "devmap"
#define NAME "devmap"
#define NULL_DEVICES 256
 
/** Representation of device driver.
*
83,16 → 84,8
devmap_driver_t *driver;
} devmap_device_t;
 
/** Pending lookup structure. */
typedef struct {
link_t link;
char *name; /**< Device name */
ipc_callid_t callid; /**< Call ID waiting for the lookup */
} pending_req_t;
 
LIST_INITIALIZE(devices_list);
LIST_INITIALIZE(drivers_list);
LIST_INITIALIZE(pending_req);
 
/* Locking order:
* drivers_list_mutex
102,10 → 95,13
**/
 
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
 
static dev_handle_t last_handle = 0;
static devmap_device_t *null_devices[NULL_DEVICES];
 
static dev_handle_t devmap_create_handle(void)
{
174,10 → 170,8
}
 
/**
*
* Unregister device and free it. It's assumed that driver's device list is
* already locked.
*
*/
static int devmap_device_unregister_core(devmap_device_t *device)
{
191,10 → 185,8
}
 
/**
*
* Read info about new driver and add it into linked list of registered
* drivers.
*
*/
static void devmap_driver_register(devmap_driver_t **odriver)
{
344,31 → 336,6
return EOK;
}
 
 
/** Process pending lookup requests */
static void process_pending_lookup(void)
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
const devmap_device_t *dev = devmap_device_find_name(pr->name);
if (!dev)
continue;
ipc_answer_1(pr->callid, EOK, dev->handle);
free(pr->name);
list_remove(cur);
free(pr);
goto loop;
}
}
 
 
/** Register instance of device
*
*/
445,6 → 412,7
list_append(&device->driver_devices, &device->driver->devices);
fibril_mutex_unlock(&device->driver->devices_mutex);
fibril_condvar_broadcast(&devices_list_cv);
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, device->handle);
530,10 → 498,14
}
name[size] = '\0';
fibril_mutex_lock(&devices_list_mutex);
const devmap_device_t *dev;
recheck:
 
/*
* Find device name in linked list of known devices.
* Find device name in the list of known devices.
*/
const devmap_device_t *dev = devmap_device_find_name(name);
dev = devmap_device_find_name(name);
/*
* Device was not found.
540,24 → 512,18
*/
if (dev == NULL) {
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
/* Blocking lookup, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(iid, ENOMEM);
free(name);
return;
}
pr->name = name;
pr->callid = iid;
list_append(&pr->link, &pending_req);
return;
/* Blocking lookup */
fibril_condvar_wait(&devices_list_cv,
&devices_list_mutex);
goto recheck;
}
ipc_answer_0(iid, ENOENT);
free(name);
fibril_mutex_unlock(&devices_list_mutex);
return;
}
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, dev->handle);
free(name);
655,21 → 621,43
ipc_answer_1(iid, EOK, pos);
}
 
/** Initialize device mapper.
*
*
*/
static bool devmap_init()
static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&null_devices_mutex);
unsigned int i;
bool fnd = false;
for (i = 0; i < NULL_DEVICES; i++) {
if (null_devices[i] == NULL) {
fnd = true;
break;
}
}
if (!fnd) {
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, ENOMEM);
return;
}
/* Create NULL device entry */
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
if (device == NULL)
return false;
if (device == NULL) {
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, ENOMEM);
return;
}
device->name = str_dup("null");
char null[DEVMAP_NAME_MAXLEN];
snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
device->name = str_dup(null);
if (device->name == NULL) {
fibril_mutex_unlock(&null_devices_mutex);
free(device);
return false;
ipc_answer_0(iid, ENOMEM);
return;
}
list_initialize(&(device->devices));
681,11 → 669,50
device->handle = devmap_create_handle();
device->driver = NULL;
/* Insert device into list of all devices */
/* Insert device into list of all devices
and into null devices array */
list_append(&device->devices, &devices_list);
null_devices[i] = device;
fibril_mutex_unlock(&devices_list_mutex);
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_1(iid, EOK, (ipcarg_t) i);
}
 
static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&null_devices_mutex);
ipcarg_t i = IPC_GET_ARG1(*icall);
if (null_devices[i] == NULL) {
ipc_answer_0(iid, ENOENT);
return;
}
devmap_device_unregister_core(null_devices[i]);
null_devices[i] = NULL;
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, EOK);
}
 
/** Initialize device mapper.
*
*
*/
static bool devmap_init(void)
{
fibril_mutex_lock(&null_devices_mutex);
unsigned int i;
for (i = 0; i < NULL_DEVICES; i++)
null_devices[i] = NULL;
fibril_mutex_unlock(&null_devices_mutex);
return true;
}
 
738,7 → 765,7
}
}
if (NULL != driver) {
if (driver != NULL) {
/*
* Unregister the device driver and all its devices.
*/
770,6 → 797,12
case DEVMAP_DEVICE_GET_NAME:
devmap_get_name(callid, &call);
break;
case DEVMAP_DEVICE_NULL_CREATE:
devmap_null_create(callid, &call);
break;
case DEVMAP_DEVICE_NULL_DESTROY:
devmap_null_destroy(callid, &call);
break;
case DEVMAP_DEVICE_GET_COUNT:
devmap_get_count(callid, &call);
break;
818,9 → 851,7
return -1;
}
/* Set a handler of incomming connections and
pending operations */
async_set_pending(process_pending_lookup);
/* Set a handler of incomming connections */
async_set_client_connection(devmap_connection);
/* Register device mapper at naming service */
/branches/dd/uspace/srv/vfs/vfs.c
43,7 → 43,6
#include <bool.h>
#include <string.h>
#include <as.h>
#include <adt/list.h>
#include <atomic.h>
#include "vfs.h"
 
80,56 → 79,52
case IPC_M_PHONE_HUNGUP:
keep_on_going = false;
break;
case VFS_REGISTER:
case VFS_IN_REGISTER:
vfs_register(callid, &call);
/*
* Keep the connection open so that a file system can
* later ask us to connect it to another file system.
* This is necessary to support non-root mounts.
*/
keep_on_going = false;
break;
case VFS_MOUNT:
case VFS_IN_MOUNT:
vfs_mount(callid, &call);
break;
case VFS_OPEN:
case VFS_IN_OPEN:
vfs_open(callid, &call);
break;
case VFS_OPEN_NODE:
case VFS_IN_OPEN_NODE:
vfs_open_node(callid, &call);
break;
case VFS_CLOSE:
case VFS_IN_CLOSE:
vfs_close(callid, &call);
break;
case VFS_READ:
case VFS_IN_READ:
vfs_read(callid, &call);
break;
case VFS_WRITE:
case VFS_IN_WRITE:
vfs_write(callid, &call);
break;
case VFS_SEEK:
case VFS_IN_SEEK:
vfs_seek(callid, &call);
break;
case VFS_TRUNCATE:
case VFS_IN_TRUNCATE:
vfs_truncate(callid, &call);
break;
case VFS_MKDIR:
case VFS_IN_FSTAT:
vfs_fstat(callid, &call);
break;
case VFS_IN_STAT:
vfs_stat(callid, &call);
break;
case VFS_IN_MKDIR:
vfs_mkdir(callid, &call);
break;
case VFS_UNLINK:
case VFS_IN_UNLINK:
vfs_unlink(callid, &call);
break;
case VFS_RENAME:
case VFS_IN_RENAME:
vfs_rename(callid, &call);
break;
case VFS_DEVICE:
vfs_device(callid, &call);
break;
case VFS_SYNC:
case VFS_IN_SYNC:
vfs_sync(callid, &call);
break;
case VFS_NODE:
vfs_node(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
144,11 → 139,6
printf(NAME ": HelenOS VFS server\n");
/*
* Initialize the list of registered file systems.
*/
list_initialize(&fs_head);
/*
* Initialize VFS node hash table.
*/
if (!vfs_nodes_init()) {
159,7 → 149,6
/*
* Allocate and initialize the Path Lookup Buffer.
*/
list_initialize(&plb_head);
plb = as_get_mappable_page(PLB_SIZE);
if (!plb) {
printf(NAME ": Cannot allocate a mappable piece of address space\n");
174,11 → 163,10
memset(plb, 0, PLB_SIZE);
/*
* Set a connectio handling function/fibril.
* Set a connection handling function/fibril.
*/
async_set_pending(vfs_process_pending_mount);
async_set_client_connection(vfs_connection);
 
/*
* Register at the naming service.
*/
/branches/dd/uspace/srv/vfs/vfs_ops.c
43,7 → 43,6
#include <stdlib.h>
#include <string.h>
#include <bool.h>
#include <futex.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <unistd.h>
55,20 → 54,6
/* Forward declarations of static functions. */
static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
 
/** Pending mount structure. */
typedef struct {
link_t link;
char *fs_name; /**< File system name */
char *mp; /**< Mount point */
char *opts; /**< Mount options. */
ipc_callid_t callid; /**< Call ID waiting for the mount */
ipc_callid_t rid; /**< Request ID */
dev_handle_t dev_handle; /**< Device handle */
} pending_req_t;
 
FIBRIL_MUTEX_INITIALIZE(pending_lock);
LIST_INITIALIZE(pending_req);
 
/**
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a
* concurrent VFS operation which modifies the file system namespace.
123,7 → 108,7
/*
* Now we hold a reference to mp_node.
* It will be dropped upon the corresponding VFS_UNMOUNT.
* It will be dropped upon the corresponding VFS_IN_UNMOUNT.
* This prevents the mount point from being deleted.
*/
} else {
136,20 → 121,20
/* Tell the mountee that it is being mounted. */
phone = vfs_grab_phone(fs_handle);
msg = async_send_1(phone, VFS_MOUNTED,
msg = async_send_1(phone, VFS_OUT_MOUNTED,
(ipcarg_t) dev_handle, &answer);
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts,
str_size(opts));
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(phone);
async_wait_for(msg, NULL);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
async_wait_for(msg, &rc);
vfs_release_phone(phone);
async_wait_for(msg, &rc);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
196,10 → 181,9
int mountee_phone = vfs_grab_phone(fs_handle);
assert(mountee_phone >= 0);
vfs_release_phone(mountee_phone);
 
phone = vfs_grab_phone(mp_res.triplet.fs_handle);
msg = async_send_4(phone, VFS_MOUNT,
msg = async_send_4(phone, VFS_OUT_MOUNT,
(ipcarg_t) mp_res.triplet.dev_handle,
(ipcarg_t) mp_res.triplet.index,
(ipcarg_t) fs_handle,
208,8 → 192,9
/* send connection */
rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(mountee_phone);
vfs_release_phone(phone);
async_wait_for(msg, NULL);
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
217,12 → 202,14
fibril_rwlock_write_unlock(&namespace_rwlock);
return;
}
 
vfs_release_phone(mountee_phone);
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(phone);
async_wait_for(msg, NULL);
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
230,8 → 217,8
ipc_answer_0(rid, rc);
return;
}
async_wait_for(msg, &rc);
vfs_release_phone(phone);
async_wait_for(msg, &rc);
if (rc == EOK) {
rindex = (fs_index_t) IPC_GET_ARG1(answer);
258,39 → 245,6
fibril_rwlock_write_unlock(&namespace_rwlock);
}
 
/** Process pending mount requests */
void vfs_process_pending_mount(void)
{
link_t *cur;
loop:
fibril_mutex_lock(&pending_lock);
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
 
fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true);
if (!fs_handle)
continue;
/* Acknowledge that we know fs_name. */
ipc_answer_0(pr->callid, EOK);
/* Do the mount */
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp,
pr->opts);
free(pr->fs_name);
free(pr->mp);
free(pr->opts);
list_remove(cur);
free(pr);
fibril_mutex_unlock(&pending_lock);
fibril_yield();
goto loop;
}
fibril_mutex_unlock(&pending_lock);
}
 
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
/*
444,35 → 398,17
* Check if we know a file system with the same name as is in fs_name.
* This will also give us its file system handle.
*/
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
fibril_mutex_lock(&fs_head_lock);
fs_handle_t fs_handle;
recheck:
fs_handle = fs_name_to_handle(fs_name, false);
if (!fs_handle) {
if (flags & IPC_FLAG_BLOCKING) {
pending_req_t *pr;
 
/* Blocking mount, add to pending list */
pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
free(mp);
free(fs_name);
free(opts);
return;
}
pr->fs_name = fs_name;
pr->mp = mp;
pr->opts = opts;
pr->callid = callid;
pr->rid = rid;
pr->dev_handle = dev_handle;
link_initialize(&pr->link);
fibril_mutex_lock(&pending_lock);
list_append(&pr->link, &pending_req);
fibril_mutex_unlock(&pending_lock);
return;
fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
goto recheck;
}
fibril_mutex_unlock(&fs_head_lock);
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
free(mp);
480,6 → 416,7
free(opts);
return;
}
fibril_mutex_unlock(&fs_head_lock);
/* Acknowledge that we know fs_name. */
ipc_answer_0(callid, EOK);
500,8 → 437,8
/*
* The POSIX interface is open(path, oflag, mode).
* We can receive oflags and mode along with the VFS_OPEN call; the path
* will need to arrive in another call.
* We can receive oflags and mode along with the VFS_IN_OPEN call;
* the path will need to arrive in another call.
*
* We also receive one private, non-POSIX set of flags called lflag
* used to pass information to vfs_lookup_internal().
618,7 → 555,7
* file is being opened and that a file structure is pointing to it.
* It is necessary so that the file will not disappear when
* vfs_node_put() is called. The reference will be dropped by the
* respective VFS_CLOSE.
* respective VFS_IN_CLOSE.
*/
vfs_node_addref(node);
vfs_node_put(node);
695,7 → 632,7
* file is being opened and that a file structure is pointing to it.
* It is necessary so that the file will not disappear when
* vfs_node_put() is called. The reference will be dropped by the
* respective VFS_CLOSE.
* respective VFS_IN_CLOSE.
*/
vfs_node_addref(node);
vfs_node_put(node);
704,7 → 641,7
ipc_answer_1(rid, EOK, fd);
}
 
void vfs_node(ipc_callid_t rid, ipc_call_t *request)
void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
715,21 → 652,6
return;
}
ipc_answer_3(rid, EOK, file->node->fs_handle, file->node->dev_handle,
file->node->index);
}
 
void vfs_device(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
/*
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
737,53 → 659,17
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_DEVICE request at the destination FS server. */
/* Make a VFS_OUT_SYMC request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
file->node->dev_handle, file->node->index, &answer);
vfs_release_phone(fs_phone);
msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->dev_handle,
file->node->index, &answer);
 
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
fibril_mutex_unlock(&file->lock);
ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer));
}
 
void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
/*
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_SYMC request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
file->node->dev_handle, file->node->index, &answer);
 
vfs_release_phone(fs_phone);
 
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, rc);
805,21 → 691,19
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_CLOSE request at the destination FS server. */
/* Make a VFS_OUT_CLOSE request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
file->node->dev_handle, file->node->index, &answer);
msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle,
file->node->index, &answer);
 
vfs_release_phone(fs_phone);
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
 
vfs_release_phone(fs_phone);
fibril_mutex_unlock(&file->lock);
int retval = IPC_GET_ARG1(answer);
899,7 → 783,7
ipc_call_t answer;
if (!read && file->append)
file->pos = file->node->size;
msg = async_send_3(fs_phone, IPC_GET_METHOD(*request),
msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE,
file->node->dev_handle, file->node->index, file->pos, &answer);
/*
910,12 → 794,12
*/
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 
vfs_release_phone(fs_phone);
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
vfs_release_phone(fs_phone);
size_t bytes = IPC_GET_ARG1(answer);
 
if (file->node->type == VFS_NODE_DIRECTORY)
1013,7 → 897,7
int fs_phone;
fs_phone = vfs_grab_phone(fs_handle);
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)dev_handle,
rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,
(ipcarg_t)index, (ipcarg_t)size);
vfs_release_phone(fs_phone);
return (int)rc;
1043,6 → 927,106
ipc_answer_0(rid, (ipcarg_t)rc);
}
 
void vfs_fstat(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
size_t size = IPC_GET_ARG2(*request);
ipcarg_t rc;
 
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
 
ipc_callid_t callid;
if (!ipc_data_read_receive(&callid, NULL)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
fibril_mutex_lock(&file->lock);
 
int fs_phone = vfs_grab_phone(file->node->fs_handle);
aid_t msg;
msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->dev_handle,
file->node->index, true, NULL);
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
async_wait_for(msg, &rc);
vfs_release_phone(fs_phone);
 
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, rc);
}
 
void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
{
size_t len;
ipc_callid_t callid;
 
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *path = malloc(len + 1);
if (!path) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
int rc;
if ((rc = ipc_data_write_finalize(callid, path, len))) {
ipc_answer_0(rid, rc);
free(path);
return;
}
path[len] = '\0';
 
if (!ipc_data_read_receive(&callid, NULL)) {
free(path);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
vfs_lookup_res_t lr;
fibril_rwlock_read_lock(&namespace_rwlock);
rc = vfs_lookup_internal(path, L_NONE, &lr, NULL);
free(path);
if (rc != EOK) {
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(callid, rc);
ipc_answer_0(rid, rc);
return;
}
vfs_node_t *node = vfs_node_get(&lr);
if (!node) {
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
 
fibril_rwlock_read_unlock(&namespace_rwlock);
 
int fs_phone = vfs_grab_phone(node->fs_handle);
aid_t msg;
msg = async_send_3(fs_phone, VFS_OUT_STAT, node->dev_handle,
node->index, false, NULL);
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
ipcarg_t rv;
async_wait_for(msg, &rv);
vfs_release_phone(fs_phone);
 
ipc_answer_0(rid, rv);
 
vfs_node_put(node);
}
 
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request)
{
int mode = IPC_GET_ARG1(*request);
1117,12 → 1101,12
/*
* The name has already been unlinked by vfs_lookup_internal().
* We have to get and put the VFS node to ensure that it is
* VFS_DESTROY'ed after the last reference to it is dropped.
* VFS_OUT_DESTROY'ed after the last reference to it is dropped.
*/
vfs_node_t *node = vfs_node_get(&lr);
futex_down(&nodes_futex);
fibril_mutex_lock(&nodes_mutex);
node->lnkcnt--;
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
fibril_rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, EOK);
1271,9 → 1255,9
free(new);
return;
}
futex_down(&nodes_futex);
fibril_mutex_lock(&nodes_mutex);
new_node->lnkcnt--;
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
break;
default:
fibril_rwlock_write_unlock(&namespace_rwlock);
1293,9 → 1277,9
free(new);
return;
}
futex_down(&nodes_futex);
fibril_mutex_lock(&nodes_mutex);
old_node->lnkcnt++;
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
/* Destroy the link for the old name. */
rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
if (rc != EOK) {
1308,9 → 1292,9
free(new);
return;
}
futex_down(&nodes_futex);
fibril_mutex_lock(&nodes_mutex);
old_node->lnkcnt--;
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
fibril_rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(old_node);
if (new_node)
/branches/dd/uspace/srv/vfs/vfs_register.c
52,8 → 52,9
#include <atomic.h>
#include "vfs.h"
 
FIBRIL_CONDVAR_INITIALIZE(fs_head_cv);
FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
link_t fs_head;
LIST_INITIALIZE(fs_head);
 
atomic_t fs_handle_next = {
.count = 1
268,6 → 269,7
fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next);
ipc_answer_1(rid, EOK, (ipcarg_t) fs_info->fs_handle);
fibril_condvar_broadcast(&fs_head_cv);
fibril_mutex_unlock(&fs_head_lock);
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
283,13 → 285,14
*/
int vfs_grab_phone(fs_handle_t handle)
{
int phone;
 
/*
* For now, we don't try to be very clever and very fast.
* We simply lookup the phone in the fs_head list. We currently don't
* open any additional phones (even though that itself would be pretty
* straightforward; housekeeping multiple open phones to a FS task would
* be more demanding). Instead, we simply take the respective
* phone_futex and keep it until vfs_release_phone().
* For now, we don't try to be very clever and very fast. We simply
* lookup the phone in the fs_head list and duplicate it. The duplicate
* phone will be returned to the client and the client will use it for
* communication. In the future, we should cache the connections so
* that they do not have to be reestablished over and over again.
*/
fibril_mutex_lock(&fs_head_lock);
link_t *cur;
299,7 → 302,11
if (fs->fs_handle == handle) {
fibril_mutex_unlock(&fs_head_lock);
fibril_mutex_lock(&fs->phone_lock);
return fs->phone;
phone = ipc_connect_me_to(fs->phone, 0, 0, 0);
fibril_mutex_unlock(&fs->phone_lock);
 
assert(phone > 0);
return phone;
}
}
fibril_mutex_unlock(&fs_head_lock);
306,31 → 313,14
return 0;
}
 
/** Tell VFS that the phone is in use for any request.
/** Tell VFS that the phone is not needed anymore.
*
* @param phone Phone to FS task.
*/
void vfs_release_phone(int phone)
{
bool found = false;
 
fibril_mutex_lock(&fs_head_lock);
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->phone == phone) {
found = true;
fibril_mutex_unlock(&fs_head_lock);
fibril_mutex_unlock(&fs->phone_lock);
return;
}
}
fibril_mutex_unlock(&fs_head_lock);
 
/*
* Not good to get here.
*/
assert(found == true);
/* TODO: implement connection caching */
ipc_hangup(phone);
}
 
/** Convert file system name to its handle.
/branches/dd/uspace/srv/vfs/vfs.h
36,7 → 36,6
#include <ipc/ipc.h>
#include <adt/list.h>
#include <fibril_sync.h>
#include <futex.h>
#include <sys/types.h>
#include <devmap.h>
#include <bool.h>
145,8 → 144,10
off_t pos;
} vfs_file_t;
 
extern futex_t nodes_futex;
extern fibril_mutex_t nodes_mutex;
 
extern fibril_condvar_t fs_head_cv;
extern fibril_mutex_t fs_head_lock;
extern link_t fs_head; /**< List of registered file systems. */
 
extern vfs_pair_t rootfs; /**< Root file system. */
158,7 → 159,7
size_t len; /**< Number of characters in this PLB entry. */
} plb_entry_t;
 
extern futex_t plb_futex; /**< Futex protecting plb and plb_head. */
extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */
extern uint8_t *plb; /**< Path Lookup Buffer */
extern link_t plb_head; /**< List of active PLB entries. */
 
193,19 → 194,19
extern void vfs_node_addref(vfs_node_t *);
extern void vfs_node_delref(vfs_node_t *);
 
extern void vfs_process_pending_mount(void);
extern void vfs_register(ipc_callid_t, ipc_call_t *);
extern void vfs_mount(ipc_callid_t, ipc_call_t *);
extern void vfs_open(ipc_callid_t, ipc_call_t *);
extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
extern void vfs_device(ipc_callid_t, ipc_call_t *);
extern void vfs_sync(ipc_callid_t, ipc_call_t *);
extern void vfs_node(ipc_callid_t, ipc_call_t *);
extern void vfs_close(ipc_callid_t, ipc_call_t *);
extern void vfs_read(ipc_callid_t, ipc_call_t *);
extern void vfs_write(ipc_callid_t, ipc_call_t *);
extern void vfs_seek(ipc_callid_t, ipc_call_t *);
extern void vfs_truncate(ipc_callid_t, ipc_call_t *);
extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
extern void vfs_stat(ipc_callid_t, ipc_call_t *);
extern void vfs_mkdir(ipc_callid_t, ipc_call_t *);
extern void vfs_unlink(ipc_callid_t, ipc_call_t *);
extern void vfs_rename(ipc_callid_t, ipc_call_t *);
/branches/dd/uspace/srv/vfs/vfs_node.c
38,7 → 38,6
#include "vfs.h"
#include <stdlib.h>
#include <string.h>
#include <futex.h>
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <assert.h>
45,8 → 44,8
#include <async.h>
#include <errno.h>
 
/** Futex protecting the VFS node hash table. */
futex_t nodes_futex = FUTEX_INITIALIZER;
/** Mutex protecting the VFS node hash table. */
FIBRIL_MUTEX_INITIALIZE(nodes_mutex);
 
#define NODES_BUCKETS_LOG 8
#define NODES_BUCKETS (1 << NODES_BUCKETS_LOG)
89,9 → 88,9
*/
void vfs_node_addref(vfs_node_t *node)
{
futex_down(&nodes_futex);
fibril_mutex_lock(&nodes_mutex);
_vfs_node_addref(node);
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
}
 
/** Decrement reference count of a VFS node.
105,7 → 104,7
bool free_vfs_node = false;
bool free_fs_node = false;
 
futex_down(&nodes_futex);
fibril_mutex_lock(&nodes_mutex);
if (node->refcnt-- == 1) {
/*
* We are dropping the last reference to this node.
121,7 → 120,7
if (!node->lnkcnt)
free_fs_node = true;
}
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
 
if (free_fs_node) {
/*
130,7 → 129,7
*/
int phone = vfs_grab_phone(node->fs_handle);
ipcarg_t rc;
rc = async_req_2_0(phone, VFS_DESTROY,
rc = async_req_2_0(phone, VFS_OUT_DESTROY,
(ipcarg_t)node->dev_handle, (ipcarg_t)node->index);
assert(rc == EOK);
vfs_release_phone(phone);
161,12 → 160,12
link_t *tmp;
vfs_node_t *node;
 
futex_down(&nodes_futex);
fibril_mutex_lock(&nodes_mutex);
tmp = hash_table_find(&nodes, key);
if (!tmp) {
node = (vfs_node_t *) malloc(sizeof(vfs_node_t));
if (!node) {
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
return NULL;
}
memset(node, 0, sizeof(vfs_node_t));
193,7 → 192,7
assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN);
 
_vfs_node_addref(node);
futex_up(&nodes_futex);
fibril_mutex_unlock(&nodes_mutex);
 
return node;
}
/branches/dd/uspace/srv/vfs/vfs_lookup.c
42,14 → 42,14
#include <string.h>
#include <stdarg.h>
#include <bool.h>
#include <futex.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <vfs/canonify.h>
 
#define min(a, b) ((a) < (b) ? (a) : (b))
 
futex_t plb_futex = FUTEX_INITIALIZER;
link_t plb_head; /**< PLB entry ring buffer. */
FIBRIL_MUTEX_INITIALIZE(plb_mutex);
LIST_INITIALIZE(plb_head); /**< PLB entry ring buffer. */
uint8_t *plb = NULL;
 
/** Perform a path lookup.
92,7 → 92,7
va_end(ap);
}
futex_down(&plb_futex);
fibril_mutex_lock(&plb_mutex);
 
plb_entry_t entry;
link_initialize(&entry.plb_link);
119,7 → 119,7
/*
* The buffer cannot absorb the path.
*/
futex_up(&plb_futex);
fibril_mutex_unlock(&plb_mutex);
return ELIMIT;
}
} else {
127,7 → 127,7
/*
* The buffer cannot absorb the path.
*/
futex_up(&plb_futex);
fibril_mutex_unlock(&plb_mutex);
return ELIMIT;
}
}
146,7 → 146,7
*/
list_append(&entry.plb_link, &plb_head);
futex_up(&plb_futex);
fibril_mutex_unlock(&plb_mutex);
 
/*
* Copy the path into PLB.
159,16 → 159,16
 
ipc_call_t answer;
int phone = vfs_grab_phone(root->fs_handle);
aid_t req = async_send_5(phone, VFS_LOOKUP, (ipcarg_t) first,
aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (ipcarg_t) first,
(ipcarg_t) (first + len - 1) % PLB_SIZE,
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index,
&answer);
vfs_release_phone(phone);
ipcarg_t rc;
async_wait_for(req, &rc);
vfs_release_phone(phone);
futex_down(&plb_futex);
fibril_mutex_lock(&plb_mutex);
list_remove(&entry.plb_link);
/*
* Erasing the path from PLB will come handy for debugging purposes.
175,7 → 175,7
*/
memset(&plb[first], 0, cnt1);
memset(plb, 0, cnt2);
futex_up(&plb_futex);
fibril_mutex_unlock(&plb_mutex);
 
if ((rc == EOK) && (result)) {
result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer);
204,14 → 204,14
int phone = vfs_grab_phone(result->triplet.fs_handle);
ipc_call_t answer;
aid_t req = async_send_2(phone, VFS_OPEN_NODE,
aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE,
(ipcarg_t) result->triplet.dev_handle,
(ipcarg_t) result->triplet.index, &answer);
vfs_release_phone(phone);
ipcarg_t rc;
async_wait_for(req, &rc);
vfs_release_phone(phone);
if (rc == EOK) {
result->size = (size_t) IPC_GET_ARG1(answer);
/branches/dd/uspace/srv/vfs/vfs_file.c
57,7 → 57,7
* first VFS_OPEN operation.
*
* This resource being per-connection and, in the first place, per-fibril, we
* don't need to protect it by a futex.
* don't need to protect it by a mutex.
*/
fibril_local vfs_file_t **files = NULL;