Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4691 → Rev 4692

/branches/tracing/uspace/srv/vfs/vfs_register.c
45,15 → 45,16
#include <string.h>
#include <ctype.h>
#include <bool.h>
#include <futex.h>
#include <libadt/list.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <as.h>
#include <assert.h>
#include <atomic.h>
#include "vfs.h"
 
atomic_t fs_head_futex = FUTEX_INITIALIZER;
link_t fs_head;
FIBRIL_CONDVAR_INITIALIZE(fs_head_cv);
FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
LIST_INITIALIZE(fs_head);
 
atomic_t fs_handle_next = {
.count = 1
159,7 → 160,7
return;
}
link_initialize(&fs_info->fs_link);
futex_initialize(&fs_info->phone_futex, 1);
fibril_mutex_initialize(&fs_info->phone_lock);
rc = ipc_data_write_finalize(callid, &fs_info->vfs_info, size);
if (rc != EOK) {
180,8 → 181,7
return;
}
futex_down(&fs_head_futex);
fibril_inc_sercount();
fibril_mutex_lock(&fs_head_lock);
 
/*
* Check for duplicit registrations.
191,8 → 191,7
* We already register a fs like this.
*/
dprintf("FS is already registered.\n");
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
free(fs_info);
ipc_answer_0(callid, EEXISTS);
ipc_answer_0(rid, EEXISTS);
214,8 → 213,7
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
free(fs_info);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
233,8 → 231,7
if (!ipc_share_in_receive(&callid, &size)) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
248,8 → 245,7
if (size != PLB_SIZE) {
dprintf("Client suggests wrong size of PFB, size = %d\n", size);
list_remove(&fs_info->fs_link);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
273,16 → 269,11
fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next);
ipc_answer_1(rid, EOK, (ipcarg_t) fs_info->fs_handle);
fibril_dec_sercount();
futex_up(&fs_head_futex);
fibril_condvar_broadcast(&fs_head_cv);
fibril_mutex_unlock(&fs_head_lock);
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle);
/* Process pending mount requests possibly waiting
* for this filesystem implementation.
*/
vfs_process_pending_mount();
}
 
/** For a given file system handle, implement policy for allocating a phone.
294,76 → 285,49
*/
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.
*/
futex_down(&fs_head_futex);
fibril_mutex_lock(&fs_head_lock);
link_t *cur;
fs_info_t *fs;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->fs_handle == handle) {
futex_up(&fs_head_futex);
/*
* For now, take the futex unconditionally.
* Oh yeah, serialization rocks.
* It will be up'ed in vfs_release_phone().
*/
futex_down(&fs->phone_futex);
/*
* Avoid deadlock with other fibrils in the same thread
* by disabling fibril preemption.
*/
fibril_inc_sercount();
return fs->phone;
fibril_mutex_unlock(&fs_head_lock);
fibril_mutex_lock(&fs->phone_lock);
phone = ipc_connect_me_to(fs->phone, 0, 0, 0);
fibril_mutex_unlock(&fs->phone_lock);
 
assert(phone > 0);
return phone;
}
}
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
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;
 
/*
* Undo the fibril_inc_sercount() done in vfs_grab_phone().
*/
fibril_dec_sercount();
futex_down(&fs_head_futex);
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;
futex_up(&fs_head_futex);
futex_up(&fs->phone_futex);
return;
}
}
futex_up(&fs_head_futex);
 
/*
* Not good to get here.
*/
assert(found == true);
/* TODO: implement connection caching */
ipc_hangup(phone);
}
 
/** Convert file system name to its handle.
*
* @param name File system name.
* @param lock If true, the function will down and up the
* fs_head_futex.
* @param lock If true, the function will lock and unlock the
* fs_head_lock.
*
* @return File system handle or zero if file system not found.
*/
372,7 → 336,7
int handle = 0;
if (lock)
futex_down(&fs_head_futex);
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);
382,7 → 346,7
}
}
if (lock)
futex_up(&fs_head_futex);
fibril_mutex_unlock(&fs_head_lock);
return handle;
}