Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4691 → Rev 4692

/branches/tracing/uspace/lib/libfs/libfs.c
1,5 → 1,5
/*
* Copyright (c) 2008 Jakub Jermar
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
42,6 → 42,8
#include <as.h>
#include <assert.h>
#include <dirent.h>
#include <mem.h>
#include <sys/stat.h>
 
/** Register file system server.
*
68,7 → 70,7
* out-of-order, when it knows that the operation succeeded or failed.
*/
ipc_call_t answer;
aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer);
aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer);
 
/*
* Send our VFS info structure to VFS.
103,7 → 105,7
}
/*
* Pick up the answer for the request to the VFS_REQUEST call.
* Pick up the answer for the request to the VFS_IN_REQUEST call.
*/
async_wait_for(req, NULL);
reg->fs_handle = (int) IPC_GET_ARG1(answer);
122,23 → 124,106
return IPC_GET_RETVAL(answer);
}
 
void fs_node_initialize(fs_node_t *fn)
{
memset(fn, 0, sizeof(fs_node_t));
}
 
void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request);
int res;
ipcarg_t rc;
 
ipc_call_t call;
ipc_callid_t callid;
 
/* accept the phone */
callid = async_get_call(&call);
int mountee_phone = (int)IPC_GET_ARG1(call);
if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) ||
mountee_phone < 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */
res = ipc_data_write_receive(&callid, NULL);
if (!res) {
ipc_hangup(mountee_phone);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index);
if (!fn) {
ipc_hangup(mountee_phone);
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
return;
}
 
if (fn->mp_data.mp_active) {
ipc_hangup(mountee_phone);
ops->node_put(fn);
ipc_answer_0(callid, EBUSY);
ipc_answer_0(rid, EBUSY);
return;
}
 
rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
if (rc != 0) {
ipc_hangup(mountee_phone);
ops->node_put(fn);
ipc_answer_0(callid, rc);
ipc_answer_0(rid, rc);
return;
}
ipc_call_t answer;
aid_t msg = async_send_1(mountee_phone, VFS_OUT_MOUNTED, mr_dev_handle,
&answer);
ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
async_wait_for(msg, &rc);
if (rc == EOK) {
fn->mp_data.mp_active = true;
fn->mp_data.fs_handle = mr_fs_handle;
fn->mp_data.dev_handle = mr_dev_handle;
fn->mp_data.phone = mountee_phone;
}
/*
* Do not release the FS node so that it stays in memory.
*/
ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
IPC_GET_ARG3(answer));
}
 
/** Lookup VFS triplet by name in the file system name space.
*
* The path passed in the PLB must be in the canonical file system path format
* as returned by the canonify() function.
*
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param fs_handle File system handle of the file system where to perform
* the lookup.
* @param rid Request ID of the VFS_LOOKUP request.
* @param request VFS_LOOKUP request data itself.
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param fs_handle File system handle of the file system where to perform
* the lookup.
* @param rid Request ID of the VFS_OUT_LOOKUP request.
* @param request VFS_OUT_LOOKUP request data itself.
*
*/
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
unsigned next = IPC_GET_ARG1(*request);
unsigned first = IPC_GET_ARG1(*request);
unsigned last = IPC_GET_ARG2(*request);
unsigned next = first;
dev_handle_t dev_handle = IPC_GET_ARG3(*request);
int lflag = IPC_GET_ARG4(*request);
fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */
152,6 → 237,14
fs_node_t *cur = ops->root_get(dev_handle);
fs_node_t *tmp = NULL;
 
if (cur->mp_data.mp_active) {
ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
next, last, cur->mp_data.dev_handle, lflag, index,
IPC_FF_ROUTE_FROM_ME);
ops->node_put(cur);
return;
}
 
if (ops->plb_get_char(next) == '/')
next++; /* eat slash */
174,6 → 267,21
 
/* match the component */
tmp = ops->match(cur, component);
if (tmp && tmp->mp_data.mp_active) {
if (next > last)
next = last = first;
else
next--;
ipc_forward_slow(rid, tmp->mp_data.phone,
VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle,
lflag, index, IPC_FF_ROUTE_FROM_ME);
ops->node_put(cur);
ops->node_put(tmp);
if (par)
ops->node_put(par);
return;
}
 
/* handle miss: match amongst siblings */
if (!tmp) {
321,5 → 429,62
ops->node_put(tmp);
}
 
void libfs_stat(libfs_ops_t *ops, fs_handle_t fs_handle, 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);
fs_node_t *fn = ops->node_get(dev_handle, index);
 
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 = fs_handle;
stat.dev_handle = dev_handle;
stat.index = index;
stat.lnkcnt = ops->lnkcnt_get(fn);
stat.is_file = ops->is_file(fn);
stat.size = ops->size_get(fn);
 
ipc_data_read_finalize(callid, &stat, sizeof(struct stat));
ipc_answer_0(rid, EOK);
}
 
/** Open VFS triplet.
*
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param rid Request ID of the VFS_OUT_OPEN_NODE request.
* @param request VFS_OUT_OPEN_NODE request data itself.
*
*/
void libfs_open_node(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t dev_handle = IPC_GET_ARG1(*request);
fs_index_t index = IPC_GET_ARG2(*request);
fs_node_t *node = ops->node_get(dev_handle, index);
if (node == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
ipc_answer_5(rid, EOK, fs_handle, dev_handle, index,
ops->size_get(node), ops->lnkcnt_get(node));
ops->node_put(node);
}
 
/** @}
*/