diff options
Diffstat (limited to 'src/kernel/user')
-rw-r--r-- | src/kernel/user/ipc.c | 47 | ||||
-rw-r--r-- | src/kernel/user/nullfs.c | 6 | ||||
-rw-r--r-- | src/kernel/user/vfs.c | 60 |
3 files changed, 73 insertions, 40 deletions
diff --git a/src/kernel/user/ipc.c b/src/kernel/user/ipc.c index dce1847..ff4d5c8 100644 --- a/src/kernel/user/ipc.c +++ b/src/kernel/user/ipc.c @@ -12,15 +12,17 @@ static size_t channel_read(fs_handle_t *c, size_t offset, size_t len, char* buf); static size_t channel_write(fs_handle_t *c, size_t offset, size_t len, const char* buf); static int channel_poll(fs_handle_t *c, void** out_wait_obj); +static bool channel_open(fs_node_ptr c, int mode); static bool channel_stat(fs_node_ptr c, stat_t *st); static void channel_close(fs_handle_t *c); +static void channel_dispose(fs_node_ptr c); static fs_node_ops_t channel_ops = { .read = channel_read, .write = channel_write, .close = channel_close, .poll = channel_poll, - .open = 0, + .open = channel_open, .readdir = 0, .ioctl = 0, .stat = channel_stat, @@ -28,7 +30,7 @@ static fs_node_ops_t channel_ops = { .create = 0, .move = 0, .delete = 0, - .dispose = 0, + .dispose = channel_dispose, }; typedef struct channel { @@ -41,6 +43,7 @@ typedef struct channel { } channel_t; fs_handle_pair_t make_channel(bool blocking) { + fs_node_t *na = 0, *nb = 0; fs_handle_pair_t ret = { .a = 0, .b = 0 }; channel_t *a = 0, *b = 0; @@ -56,17 +59,28 @@ fs_handle_pair_t make_channel(bool blocking) { ret.b = (fs_handle_t*)malloc(sizeof(fs_handle_t)); if (ret.b == 0) goto error; + na = (fs_node_t*)malloc(sizeof(fs_node_t)); + if (na == 0) goto error; + + nb = (fs_node_t*)malloc(sizeof(fs_node_t)); + if (nb == 0) goto error; + a->other_side = b; b->other_side = a; a->lock = b->lock = MUTEX_UNLOCKED; a->buf_use_begin = a->buf_used = 0; b->buf_use_begin = b->buf_used = 0; + memset(na, 0, sizeof(fs_node_t)); + memset(nb, 0, sizeof(fs_node_t)); + na->refs = nb->refs = 1; + na->ops = nb->ops = &channel_ops; + na->data = a; + nb->data = b; + ret.a->fs = ret.b->fs = 0; - ret.a->node = ret.b->node = 0; - ret.a->ops = ret.b->ops = &channel_ops; - ret.a->data = a; - ret.b->data = b; + ret.a->node = na; + ret.b->node = nb; ret.a->refs = ret.b->refs = 1; ret.a->mode = ret.b->mode = FM_READ | FM_WRITE | (blocking ? FM_BLOCKING : 0); @@ -77,12 +91,14 @@ error: if (b) free(b); if (ret.a) free(ret.a); if (ret.b) free(ret.b); + if (na) free(na); + if (nb) free(nb); ret.a = ret.b = 0; return ret; } size_t channel_read(fs_handle_t *h, size_t offset, size_t req_len, char* orig_buf) { - channel_t *c = (channel_t*)h->data; + channel_t *c = (channel_t*)h->node->data; size_t ret = 0; @@ -119,7 +135,7 @@ size_t channel_read(fs_handle_t *h, size_t offset, size_t req_len, char* orig_bu } size_t channel_write(fs_handle_t *h, size_t offset, size_t req_len, const char* orig_buf) { - channel_t *tc = (channel_t*)h->data; + channel_t *tc = (channel_t*)h->node->data; channel_t *c = tc->other_side; if (c == 0) return 0; @@ -160,7 +176,7 @@ size_t channel_write(fs_handle_t *h, size_t offset, size_t req_len, const char* } int channel_poll(fs_handle_t *h, void** out_wait_obj) { - channel_t *c = (channel_t*)h->data; + channel_t *c = (channel_t*)h->node->data; int ret = 0; @@ -173,6 +189,13 @@ int channel_poll(fs_handle_t *h, void** out_wait_obj) { return ret; } +bool channel_open(fs_node_ptr ch, int mode) { + int ok_modes = FM_READ | FM_WRITE | FM_BLOCKING; + + if (mode & ~ok_modes) return false; + return true; +} + bool channel_stat(fs_node_ptr ch, stat_t *st) { channel_t *c = (channel_t*)ch; @@ -188,7 +211,11 @@ bool channel_stat(fs_node_ptr ch, stat_t *st) { } void channel_close(fs_handle_t *ch) { - channel_t *c = (channel_t*)ch->data; + // do nothing +} + +void channel_dispose(fs_node_ptr ch) { + channel_t *c = (channel_t*)ch; mutex_lock(&c->lock); diff --git a/src/kernel/user/nullfs.c b/src/kernel/user/nullfs.c index 0dc1b22..1f40d88 100644 --- a/src/kernel/user/nullfs.c +++ b/src/kernel/user/nullfs.c @@ -415,7 +415,7 @@ void nullfs_d_dispose(fs_node_ptr n) { bool nullfs_d_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d) { // Very nonefficient !! - nullfs_dir_t *h = (nullfs_dir_t*)f->data; + nullfs_dir_t *h = (nullfs_dir_t*)f->node->data; mutex_lock(&h->lock); @@ -489,7 +489,7 @@ void nullfs_f_dispose(fs_node_ptr n) { // -- File handle -- static size_t nullfs_f_read(fs_handle_t *h, size_t offset, size_t len, char* buf) { - nullfs_file_t *f = (nullfs_file_t*)h->data; + nullfs_file_t *f = (nullfs_file_t*)h->node->data; mutex_lock(&f->lock); size_t ret = 0; @@ -506,7 +506,7 @@ end_read: } static size_t nullfs_f_write(fs_handle_t *h, size_t offset, size_t len, const char* buf) { - nullfs_file_t *f = (nullfs_file_t*)h->data; + nullfs_file_t *f = (nullfs_file_t*)h->node->data; mutex_lock(&f->lock); size_t ret = 0; diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c index 05b4a2c..1fa1cc2 100644 --- a/src/kernel/user/vfs.c +++ b/src/kernel/user/vfs.c @@ -121,24 +121,32 @@ void unref_fs_node(fs_node_t *n) { mutex_lock(&n->lock); n->refs--; if (n->refs == 0) { - ASSERT (n != n->fs->root); + // delete object! + if (n->fs) { + ASSERT (n != n->fs->root); - ASSERT(n->parent != 0); - ASSERT(n->name != 0); + ASSERT(n->parent != 0); + ASSERT(n->name != 0); - mutex_lock(&n->parent->lock); - hashtbl_remove(n->parent->children, n->name); - if (n->ops->dispose) n->ops->dispose(n->data); - mutex_unlock(&n->parent->lock); + mutex_lock(&n->parent->lock); + hashtbl_remove(n->parent->children, n->name); + if (n->ops->dispose) n->ops->dispose(n->data); + mutex_unlock(&n->parent->lock); - unref_fs_node(n->parent); - unref_fs(n->fs); + unref_fs_node(n->parent); + unref_fs(n->fs); - if (n->children != 0) { - ASSERT(hashtbl_count(n->children) == 0); - delete_hashtbl(n->children); + if (n->children != 0) { + ASSERT(hashtbl_count(n->children) == 0); + delete_hashtbl(n->children); + } + } else { + // stand-alone IPC/SHM object + ASSERT(n->parent == 0 && n->children == 0); + + if (n->ops->dispose) n->ops->dispose(n->data); } - free(n->name); + if (n->name) free(n->name); free(n); } else { mutex_unlock(&n->lock); @@ -427,8 +435,6 @@ fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) { h->fs = fs; h->node = n; h->mode = mode; - h->ops = n->ops; - h->data = n->data; // our reference to node n is transferred to the file handle mutex_unlock(&n->lock); @@ -449,8 +455,8 @@ void ref_file(fs_handle_t *file) { void unref_file(fs_handle_t *file) { file->refs--; if (file->refs == 0) { - file->ops->close(file); - if (file->node) unref_fs_node(file->node); + if (file->node->ops->close) file->node->ops->close(file); + unref_fs_node(file->node); if (file->fs) unref_fs(file->fs); free(file); } @@ -463,44 +469,44 @@ int file_get_mode(fs_handle_t *f) { size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf) { if (!(f->mode & FM_READ)) return 0; - if (f->ops->read == 0) return 0; + if (f->node->ops->read == 0) return 0; - return f->ops->read(f, offset, len, buf); + return f->node->ops->read(f, offset, len, buf); } size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) { if (!(f->mode & FM_WRITE)) return 0; - if (f->ops->write == 0) return 0; + if (f->node->ops->write == 0) return 0; - return f->ops->write(f, offset, len, buf); + return f->node->ops->write(f, offset, len, buf); } bool file_stat(fs_handle_t *f, stat_t *st) { - return f->ops->stat && f->ops->stat(f->data, st); + return f->node->ops->stat && f->node->ops->stat(f->node->data, st); } int file_ioctl(fs_handle_t *f, int command, void* data) { if (!(f->mode & FM_IOCTL)) return -1; - if (f->ops->ioctl == 0) return -1; + if (f->node->ops->ioctl == 0) return -1; - return f->ops->ioctl(f->data, command, data); + return f->node->ops->ioctl(f->node->data, command, data); } bool file_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d) { if (!(f->mode & FM_READDIR)) return 0; - return f->ops->readdir && f->ops->readdir(f, ent_no, d); + return f->node->ops->readdir && f->node->ops->readdir(f, ent_no, d); } int file_poll(fs_handle_t *f, void** out_wait_obj) { - if (!f->ops->poll) { + if (!f->node->ops->poll) { if (out_wait_obj) *out_wait_obj = 0; return 0; } - return f->ops->poll(f, out_wait_obj); + return f->node->ops->poll(f, out_wait_obj); } /* vim: set ts=4 sw=4 tw=0 noet :*/ |