/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; |
} |