Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3010 → Rev 3011

/branches/tracing/uspace/srv/fs/tmpfs/tmpfs.h
60,6 → 60,7
 
extern fs_reg_t tmpfs_reg;
 
extern void tmpfs_mount(ipc_callid_t, ipc_call_t *);
extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs.c
58,7 → 58,7
[IPC_METHOD_TO_VFS_OP(VFS_READ)] = VFS_OP_DEFINED,
[IPC_METHOD_TO_VFS_OP(VFS_WRITE)] = VFS_OP_DEFINED,
[IPC_METHOD_TO_VFS_OP(VFS_TRUNCATE)] = VFS_OP_DEFINED,
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_NULL,
[IPC_METHOD_TO_VFS_OP(VFS_MOUNT)] = VFS_OP_DEFINED,
[IPC_METHOD_TO_VFS_OP(VFS_UNMOUNT)] = VFS_OP_NULL,
[IPC_METHOD_TO_VFS_OP(VFS_DESTROY)] = VFS_OP_DEFINED,
}
103,6 → 103,9
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case VFS_MOUNT:
tmpfs_mount(callid, &call);
break;
case VFS_LOOKUP:
tmpfs_lookup(callid, &call);
break;
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_ops.c
393,6 → 393,21
return EOK;
}
 
void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t mr_dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t mr_index = (fs_index_t)IPC_GET_ARG2(*request);
fs_handle_t mp_fs_handle = (fs_handle_t)IPC_GET_ARG3(*request);
dev_handle_t mp_dev_handle = (dev_handle_t)IPC_GET_ARG4(*request);
fs_index_t mp_index = (fs_index_t)IPC_GET_ARG5(*request);
if ((mr_index == root->index) &&
(mp_fs_handle == tmpfs_reg.fs_handle) &&
(mp_index == mr_index))
ipc_answer_0(rid, EOK);
else
ipc_answer_0(rid, ENOTSUP);
}
 
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
{
/* Initialize TMPFS. */
/branches/tracing/uspace/srv/fs/fat/fat_idx.c
68,8 → 68,15
link_t freed_head;
} unused_t;
 
/** Futex protecting the list of unused structures. */
static futex_t unused_futex = FUTEX_INITIALIZER;
 
/** List of unused structures. */
static LIST_INITIALIZE(unused_head);
 
/** Futex protecting the up_hash and ui_hash. */
static futex_t used_futex = FUTEX_INITIALIZER;
 
/**
* Global hash table of all used fat_idx_t structures.
* The index structures are hashed by the dev_handle, parent node's first
187,12 → 194,14
unused_t *u;
assert(index);
futex_down(&unused_futex);
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)
goto hit;
}
 
futex_up(&unused_futex);
/* dev_handle not found */
return false;
 
205,6 → 214,7
*/
*index = u->next++;
--u->remaining;
futex_up(&unused_futex);
return true;
}
} else {
217,6 → 227,7
list_remove(&f->link);
free(f);
}
futex_up(&unused_futex);
return true;
}
/*
224,6 → 235,7
* theoretically still possible (e.g. too many open unlinked nodes or
* too many zero-sized nodes).
*/
futex_up(&unused_futex);
return false;
}
 
252,11 → 264,13
link_t *l;
unused_t *u;
 
futex_down(&unused_futex);
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)
goto hit;
}
futex_up(&unused_futex);
 
/* should not happen */
assert(0);
266,7 → 280,6
/* The index can be returned directly to the counter. */
u->next--;
u->remaining++;
return;
} else {
/*
* The index must be returned either to an existing freed
282,6 → 295,7
if (lnk->prev != &u->freed_head)
try_coalesce_intervals(lnk->prev, lnk,
lnk);
futex_up(&unused_futex);
return;
}
if (f->last == index - 1) {
289,6 → 303,7
if (lnk->next != &u->freed_head)
try_coalesce_intervals(lnk, lnk->next,
lnk);
futex_up(&unused_futex);
return;
}
if (index > f->first) {
299,6 → 314,7
n->first = index;
n->last = index;
list_insert_before(&n->link, lnk);
futex_up(&unused_futex);
return;
}
 
312,6 → 328,7
n->last = index;
list_append(&n->link, &u->freed_head);
}
futex_up(&unused_futex);
}
 
fat_idx_t *
325,6 → 342,7
[UPH_PDI_KEY] = pdi,
};
 
futex_down(&used_futex);
l = hash_table_find(&up_hash, pkey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
331,10 → 349,12
} else {
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
if (!fidx) {
futex_up(&used_futex);
return NULL;
}
if (!fat_idx_alloc(dev_handle, &fidx->index)) {
free(fidx);
futex_up(&used_futex);
return NULL;
}
345,6 → 365,7
link_initialize(&fidx->uph_link);
link_initialize(&fidx->uih_link);
futex_initialize(&fidx->lock, 1);
fidx->dev_handle = dev_handle;
fidx->pfc = pfc;
fidx->pdi = pdi;
353,6 → 374,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);
 
return fidx;
}
367,10 → 390,13
[UIH_INDEX_KEY] = index,
};
 
futex_down(&used_futex);
l = hash_table_find(&ui_hash, ikey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uih_link);
futex_down(&fidx->lock);
}
futex_up(&used_futex);
 
return fidx;
}
/branches/tracing/uspace/srv/fs/fat/fat.h
180,6 → 180,7
/** Used indices (index) hash table link. */
link_t uih_link;
 
futex_t lock;
dev_handle_t dev_handle;
fs_index_t index;
/**
197,6 → 198,7
 
/** FAT in-core node. */
typedef struct fat_node {
futex_t lock;
fat_node_type_t type;
fat_idx_t *idx;
/**
/branches/tracing/uspace/srv/fs/fat/fat_ops.c
50,9 → 50,12
 
#define BS_BLOCK 0
 
/** List of free FAT nodes that still contain valid data. */
LIST_INITIALIZE(ffn_head);
/** Futex protecting the list of cached free FAT nodes. */
static futex_t ffn_futex = FUTEX_INITIALIZER;
 
/** List of cached free FAT nodes. */
static LIST_INITIALIZE(ffn_head);
 
#define FAT_NAME_LEN 8
#define FAT_EXT_LEN 3
 
179,6 → 182,7
 
static void fat_node_initialize(fat_node_t *node)
{
futex_initialize(&node->lock, 1);
node->idx = NULL;
node->type = 0;
link_initialize(&node->ffn_link);
236,10 → 240,12
/* TODO */
}
 
/** Instantiate a FAT in-core node. */
static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
/** Internal version of fat_node_get().
*
* @param idxp Locked index structure.
*/
static void *fat_node_get_core(fat_idx_t *idxp)
{
fat_idx_t *idx;
block_t *b;
fat_dentry_t *d;
fat_node_t *nodep;
246,18 → 252,16
unsigned bps;
unsigned dps;
 
idx = fat_idx_get_by_index(dev_handle, index);
if (!idx)
return NULL;
 
if (idx->nodep) {
if (idxp->nodep) {
/*
* We are lucky.
* The node is already instantiated in memory.
*/
if (!idx->nodep->refcnt++)
futex_down(&idxp->nodep->lock);
if (!idxp->nodep->refcnt++)
list_remove(&nodep->ffn_link);
return idx->nodep;
futex_up(&idxp->nodep->lock);
return idxp->nodep;
}
 
/*
264,17 → 268,31
* We must instantiate the node from the file system.
*/
assert(idx->pfc);
assert(idxp->pfc);
 
futex_down(&ffn_futex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached unused node structure. */
/* 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)
goto skip_cache;
idxp_tmp = nodep->idx;
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
futex_up(&ffn_futex);
if (nodep->dirty)
fat_node_sync(nodep);
list_remove(&nodep->ffn_link);
nodep->idx->nodep = NULL;
idxp_tmp->nodep = NULL;
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
} else {
skip_cache:
/* Try to allocate a new node structure. */
futex_up(&ffn_futex);
nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!nodep)
return NULL;
281,15 → 299,15
}
fat_node_initialize(nodep);
 
bps = fat_bps_get(dev_handle);
bps = fat_bps_get(idxp->dev_handle);
dps = bps / sizeof(fat_dentry_t);
 
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(dev_handle, idx->pfc,
(idx->pdi * sizeof(fat_dentry_t)) / bps);
b = _fat_block_get(idxp->dev_handle, idxp->pfc,
(idxp->pdi * sizeof(fat_dentry_t)) / bps);
assert(b);
 
d = ((fat_dentry_t *)b->data) + (idx->pdi % dps);
d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
if (d->attr & FAT_ATTR_SUBDIR) {
/*
* The only directory which does not have this bit set is the
308,19 → 326,38
block_put(b);
 
/* Link the idx structure with the node structure. */
nodep->idx = idx;
idx->nodep = nodep;
nodep->idx = idxp;
idxp->nodep = nodep;
 
return nodep;
}
 
/** Instantiate a FAT in-core node. */
static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
{
void *node;
fat_idx_t *idxp;
 
idxp = fat_idx_get_by_index(dev_handle, index);
if (!idxp)
return NULL;
/* idxp->lock held */
node = fat_node_get_core(idxp);
futex_up(&idxp->lock);
return node;
}
 
static void fat_node_put(void *node)
{
fat_node_t *nodep = (fat_node_t *)node;
 
futex_down(&nodep->lock);
if (!--nodep->refcnt) {
futex_down(&ffn_futex);
list_append(&nodep->ffn_link, &ffn_head);
futex_up(&ffn_futex);
}
futex_up(&nodep->lock);
}
 
static void *fat_create(int flags)
354,6 → 391,7
fat_dentry_t *d;
block_t *b;
 
futex_down(&parentp->idx->lock);
bps = fat_bps_get(parentp->idx->dev_handle);
dps = bps / sizeof(fat_dentry_t);
blocks = parentp->size / bps + (parentp->size % bps != 0);
371,6 → 409,7
continue;
case FAT_DENTRY_LAST:
block_put(b);
futex_up(&parentp->idx->lock);
return NULL;
default:
case FAT_DENTRY_VALID:
379,9 → 418,17
}
if (strcmp(name, component) == 0) {
/* hit */
void *node;
/*
* Assume tree hierarchy for locking. We
* already have the parent and now we are going
* to lock the child. Never lock in the oposite
* order.
*/
fat_idx_t *idx = fat_idx_get_by_pos(
parentp->idx->dev_handle, parentp->firstc,
i * dps + j);
futex_up(&parentp->idx->lock);
if (!idx) {
/*
* Can happen if memory is low or if we
390,8 → 437,8
block_put(b);
return NULL;
}
void *node = fat_node_get(idx->dev_handle,
idx->index);
node = fat_node_get_core(idx);
futex_up(&idx->lock);
block_put(b);
return node;
}
398,7 → 445,7
}
block_put(b);
}
 
futex_up(&parentp->idx->lock);
return NULL;
}
 
432,6 → 479,7
if (nodep->type != FAT_DIRECTORY)
return false;
 
futex_down(&nodep->idx->lock);
bps = fat_bps_get(nodep->idx->dev_handle);
dps = bps / sizeof(fat_dentry_t);
 
452,18 → 500,22
continue;
case FAT_DENTRY_LAST:
block_put(b);
futex_up(&nodep->idx->lock);
return false;
default:
case FAT_DENTRY_VALID:
block_put(b);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
}
 
futex_up(&nodep->idx->lock);
return false;
}
 
/branches/tracing/uspace/srv/vfs/vfs_ops.c
84,6 → 84,8
{
dev_handle_t dev_handle;
vfs_node_t *mp_node = NULL;
int rc;
int phone;
 
/*
* We expect the library to do the device-name to device-handle
167,7 → 169,6
* node cannot be removed. However, we do take a reference to it so
* that we can track how many times it has been mounted.
*/
int rc;
vfs_lookup_res_t mr_res;
rc = lookup_root(fs_handle, dev_handle, &mr_res);
if (rc != EOK) {
225,11 → 226,29
} else {
/* We still don't have the root file system mounted. */
if ((size == 1) && (buf[0] == '/')) {
/* For this simple, but important case, we are done. */
rootfs = mr_res.triplet;
/*
* For this simple, but important case,
* we are almost done.
*/
free(buf);
/* Inform the mount point about the root mount. */
phone = vfs_grab_phone(mr_res.triplet.fs_handle);
rc = async_req_5_0(phone, VFS_MOUNT,
(ipcarg_t) mr_res.triplet.dev_handle,
(ipcarg_t) mr_res.triplet.index,
(ipcarg_t) mr_res.triplet.fs_handle,
(ipcarg_t) mr_res.triplet.dev_handle,
(ipcarg_t) mr_res.triplet.index);
vfs_release_phone(phone);
 
if (rc == EOK)
rootfs = mr_res.triplet;
else
vfs_node_put(mr_node);
 
futex_up(&rootfs_futex);
free(buf);
ipc_answer_0(rid, EOK);
ipc_answer_0(rid, rc);
return;
} else {
/*
253,24 → 272,20
* of the file system being mounted.
*/
 
int phone = vfs_grab_phone(mp_res.triplet.fs_handle);
/* Later we can use ARG3 to pass mode/flags. */
aid_t req1 = async_send_3(phone, VFS_MOUNT,
/**
* @todo
* Add more IPC parameters so that we can send mount mode/flags.
*/
phone = vfs_grab_phone(mp_res.triplet.fs_handle);
rc = async_req_5_0(phone, VFS_MOUNT,
(ipcarg_t) mp_res.triplet.dev_handle,
(ipcarg_t) mp_res.triplet.index, 0, NULL);
/* The second call uses the same method. */
aid_t req2 = async_send_3(phone, VFS_MOUNT,
(ipcarg_t) mp_res.triplet.index,
(ipcarg_t) mr_res.triplet.fs_handle,
(ipcarg_t) mr_res.triplet.dev_handle,
(ipcarg_t) mr_res.triplet.index, NULL);
(ipcarg_t) mr_res.triplet.index);
vfs_release_phone(phone);
 
ipcarg_t rc1;
ipcarg_t rc2;
async_wait_for(req1, &rc1);
async_wait_for(req2, &rc2);
 
if ((rc1 != EOK) || (rc2 != EOK)) {
if (rc != EOK) {
/* Mount failed, drop references to mr_node and mp_node. */
vfs_node_put(mr_node);
if (mp_node)
277,12 → 292,7
vfs_node_put(mp_node);
}
if (rc2 == EOK)
ipc_answer_0(rid, rc1);
else if (rc1 == EOK)
ipc_answer_0(rid, rc2);
else
ipc_answer_0(rid, rc1);
ipc_answer_0(rid, rc);
}
 
void vfs_open(ipc_callid_t rid, ipc_call_t *request)