Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2657 → Rev 2658

/trunk/uspace/srv/fs/tmpfs/tmpfs.h
38,11 → 38,13
#include <atomic.h>
#include <sys/types.h>
#include <bool.h>
#include <libadt/hash_table.h>
 
#define dprintf(...) printf(__VA_ARGS__)
 
typedef struct tmpfs_dentry {
unsigned index; /**< TMPFS node index. */
unsigned long index; /**< TMPFS node index. */
link_t dh_link; /**< Dentries hash table link. */
struct tmpfs_dentry *parent;
struct tmpfs_dentry *sibling;
struct tmpfs_dentry *child;
59,6 → 61,7
extern fs_reg_t tmpfs_reg;
 
extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
 
#endif
 
/trunk/uspace/srv/fs/tmpfs/tmpfs.c
112,6 → 112,9
case VFS_LOOKUP:
tmpfs_lookup(callid, &call);
break;
case VFS_READ:
tmpfs_read(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/trunk/uspace/srv/fs/tmpfs/tmpfs_ops.c
45,9 → 45,46
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <libadt/hash_table.h>
#include <as.h>
 
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
 
#define PLB_GET_CHAR(i) (tmpfs_reg.plb_ro[(i) % PLB_SIZE])
 
#define DENTRIES_BUCKETS 256
 
/*
* Hash table of all directory entries.
*/
hash_table_t dentries;
 
static hash_index_t dentries_hash(unsigned long *key)
{
return *key % DENTRIES_BUCKETS;
}
 
static int dentries_compare(unsigned long *key, hash_count_t keys,
link_t *item)
{
tmpfs_dentry_t *dentry = hash_table_get_instance(item, tmpfs_dentry_t,
dh_link);
return dentry->index == *key;
}
 
static void dentries_remove_callback(link_t *item)
{
}
 
/** TMPFS dentries hash table operations. */
hash_table_operations_t dentries_ops = {
.hash = dentries_hash,
.compare = dentries_compare,
.remove_callback = dentries_remove_callback
};
 
unsigned tmpfs_next_index = 1;
 
static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentry)
60,6 → 97,7
dentry->type = TMPFS_NONE;
dentry->size = 0;
dentry->data = NULL;
link_initialize(&dentry->dh_link);
}
 
/*
70,14 → 108,17
 
static bool tmpfs_init(void)
{
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops))
return false;
 
root = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!root) {
if (!root)
return false;
}
tmpfs_dentry_initialize(root);
root->index = tmpfs_next_index++;
root->name = "";
root->type = TMPFS_DIRECTORY;
hash_table_insert(&dentries, &root->index, &root->dh_link);
 
/*
* This is only for debugging. Once we can create files and directories
96,6 → 137,7
d->parent = root;
d->type = TMPFS_DIRECTORY;
d->name = "dir1";
hash_table_insert(&dentries, &d->index, &d->dh_link);
 
d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!d) {
110,6 → 152,7
d->parent = root;
d->type = TMPFS_DIRECTORY;
d->name = "dir2";
hash_table_insert(&dentries, &d->index, &d->dh_link);
d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!d) {
127,6 → 170,7
d->name = "file1";
d->data = "This is the contents of /dir1/file1.\n";
d->size = strlen(d->data);
hash_table_insert(&dentries, &d->index, &d->dh_link);
 
d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!d) {
145,6 → 189,7
d->name = "file2";
d->data = "This is the contents of /dir2/file2.\n";
d->size = strlen(d->data);
hash_table_insert(&dentries, &d->index, &d->dh_link);
 
return true;
}
232,6 → 277,60
ipc_answer_3(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index);
}
 
void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
{
int dev_handle = IPC_GET_ARG1(*request);
unsigned long index = IPC_GET_ARG2(*request);
off_t pos = IPC_GET_ARG3(*request);
size_t size = IPC_GET_ARG4(*request);
 
/*
* Lookup the respective dentry.
*/
link_t *hlp;
hlp = hash_table_find(&dentries, &index);
if (!hlp) {
ipc_answer_0(rid, ENOENT);
return;
}
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t,
dh_link);
 
/*
* Receive the communication area.
*/
ipc_callid_t callid;
ipc_call_t call;
callid = async_get_call(&call);
if (IPC_GET_METHOD(call) != IPC_M_AS_AREA_SEND) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
int flags = IPC_GET_ARG3(call);
if (!(flags & AS_AREA_WRITE)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
size_t sz = IPC_GET_ARG2(call);
uint8_t *buf = as_get_mappable_page(sz);
if (!buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
ipc_answer_1(callid, EOK, buf); /* commit to share the area */
 
size_t bytes = max(0, min(dentry->size - pos, size));
memcpy(buf, dentry->data + pos, bytes);
 
(void) as_area_destroy(buf);
 
ipc_answer_1(rid, EOK, bytes);
}
 
/**
* @}
*/
/trunk/uspace/srv/vfs/vfs_read.c
49,7 → 49,7
* operations are serialized (i.e. the reads and writes cannot
* interleave and a file cannot be closed while it is being read).
*
* Additional synchronization needs to be added once table table of
* Additional synchronization needs to be added once the table of
* open files supports parallel access!
*/
 
60,6 → 60,7
*/
 
int fd = IPC_GET_ARG1(*request);
size_t size = IPC_GET_ARG2(*request);
 
/*
* Lookup the file structure corresponding to the file descriptor.
88,8 → 89,9
* Make a VFS_READ request at the destination FS server.
*/
aid_t msg;
msg = async_send_3(fs_phone, VFS_READ, file->node->dev_handle,
file->node->index, file->pos, NULL);
ipc_call_t answer;
msg = async_send_4(fs_phone, VFS_READ, file->node->dev_handle,
file->node->index, file->pos, size, &answer);
/*
* Forward the address space area offer to the destination FS server.
105,12 → 107,13
*/
ipcarg_t rc;
async_wait_for(msg, &rc);
size_t bytes = IPC_GET_ARG1(answer);
 
/*
* FS server's reply is the final result of the whole operation we
* return to the client.
*/
ipc_answer_0(rid, rc);
ipc_answer_1(rid, rc, bytes);
}
 
/**