[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 2/3] cdi/fs: Auf LIOv2 umstellen



* cdi/fs: Das alte RPC-Interface durch einen LIOv2-Userspace-Service
  ersetzt.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 build/root-hd/config/servmgr/mount/deps |    1 -
 src/modules/cdi/include/cdi-osdep.h     |    2 +-
 src/modules/cdi/lib/fs/fs.c             |  136 ++----
 src/modules/cdi/lib/fs/lostio_if.c      |  712 ++++++++++++-------------------
 4 files changed, 325 insertions(+), 526 deletions(-)
 delete mode 100644 build/root-hd/config/servmgr/mount/deps

diff --git a/build/root-hd/config/servmgr/mount/deps b/build/root-hd/config/servmgr/mount/deps
deleted file mode 100644
index f73f309..0000000
--- a/build/root-hd/config/servmgr/mount/deps
+++ /dev/null
@@ -1 +0,0 @@
-file
diff --git a/src/modules/cdi/include/cdi-osdep.h b/src/modules/cdi/include/cdi-osdep.h
index ed8cc5d..94eba73 100644
--- a/src/modules/cdi/include/cdi-osdep.h
+++ b/src/modules/cdi/include/cdi-osdep.h
@@ -90,7 +90,7 @@ typedef struct {
  * \endenglish
  */
 typedef struct {
-    FILE* device;
+    struct lio_tree* tree;
 } cdi_fs_osdep;
 
 struct storage_drv_osdep {
diff --git a/src/modules/cdi/lib/fs/fs.c b/src/modules/cdi/lib/fs/fs.c
index 1ac1ab4..aeca3ea 100644
--- a/src/modules/cdi/lib/fs/fs.c
+++ b/src/modules/cdi/lib/fs/fs.c
@@ -36,105 +36,57 @@
 
 #include <stdint.h>
 #include <lostio.h>
+#include <stdlib.h>
 
 #include "cdi/fs.h"
 
-#define CDI_TYPEHANDLE 200
-#define CDI_TYPEHANDLE_SYMLINK 201
-
-
-struct cdi_fs_driver* the_one_and_only_driver = NULL;
-
-bool lostio_not_found_handler(char** path, uint8_t args, pid_t pid,
-    FILE* source);
-bool lostio_pre_open_handler(char** path, uint8_t args, pid_t pid,
-    FILE* source);
-size_t lostio_readahead_handler(lostio_filehandle_t* fh, void* buf,
-    size_t bs, size_t bc);
-size_t lostio_read_handler(lostio_filehandle_t* fh, void* buf,
-    size_t bs, size_t bc);
-size_t lostio_write_handler(lostio_filehandle_t* fh, size_t bs, size_t bc,
-    void* data);
-int lostio_seek_handler(lostio_filehandle_t* fh, uint64_t offset, int origin);
-int lostio_unlink_handler(lostio_filehandle_t* fh, const char* name);
-size_t lostio_symlink_read_handler(lostio_filehandle_t* fh, void* buf,
-    size_t bs, size_t bc);
-size_t lostio_symlink_write_handler(lostio_filehandle_t* fh, size_t bs,
-    size_t bc, void* data);
-
-typehandle_t cdi_typehandle = {
-    .id = CDI_TYPEHANDLE,
-    .not_found = &lostio_not_found_handler,
-    .pre_open = &lostio_pre_open_handler,
-    .post_open = NULL,
-    .read = &lostio_read_handler,
-    .readahead = &lostio_readahead_handler,
-    .write = &lostio_write_handler,
-    .seek = &lostio_seek_handler,
-    .unlink = &lostio_unlink_handler,
-    .close = NULL
-};
-
-typehandle_t cdi_symlink_typehandle = {
-    .id = CDI_TYPEHANDLE_SYMLINK,
-    .not_found = &lostio_not_found_handler,
-    .pre_open = &lostio_pre_open_handler,
-    .post_open = NULL,
-    .read = &lostio_symlink_read_handler,
-    .write = &lostio_symlink_write_handler,
-    .seek = &lostio_seek_handler,
-    .unlink = &lostio_unlink_handler,
-    .close = NULL
-};
-
-
-typehandle_t cdi_null_typehandle = {
-    .id = 0,
-    .not_found = &lostio_not_found_handler,
-    .pre_open = NULL,
-    .post_open = NULL,
-    .read = NULL,
-    .write = NULL,
-    .seek = NULL,
-    .close = NULL
-};
+struct lio_resource* cdi_fs_lio_load_root(struct lio_tree* tree);
+int cdi_fs_lio_load_children(struct lio_resource* res);
+int cdi_fs_lio_read(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void* buf);
+int cdi_fs_lio_write(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void* buf);
+int cdi_fs_lio_resize(struct lio_resource* res, uint64_t size);
+struct lio_resource* cdi_fs_lio_make_file(struct lio_resource* parent,
+    const char* name);
+struct lio_resource* cdi_fs_lio_make_dir(struct lio_resource* parent,
+    const char* name);
+struct lio_resource* cdi_fs_lio_make_symlink(struct lio_resource* parent,
+    const char* name, const char* target);
+int cdi_fs_lio_unlink(struct lio_resource* parent, const char* name);
+int cdi_fs_lio_sync(struct lio_resource* res);
 
 
 void cdi_fs_driver_init(struct cdi_fs_driver* driver)
 {
-    static int initialized = 0;
-
-    if (!initialized) {
-
-        lostio_init();
-        lostio_type_directory_use();
-        lostio_register_typehandle(&cdi_typehandle);
-        lostio_register_typehandle(&cdi_symlink_typehandle);
-        lostio_register_typehandle(&cdi_null_typehandle);
-
-
-        // Preopen-Handler fuer Verzeichnisse setzen
-        typehandle_t* typehandle = get_typehandle(LOSTIO_TYPES_DIRECTORY);
-        typehandle->pre_open = &lostio_pre_open_handler;
-        typehandle->not_found = &lostio_not_found_handler;
-        typehandle->post_open = NULL;
-        typehandle->unlink = &lostio_unlink_handler;
-
-        initialized = 1;
-    }
 }
 
 void cdi_fs_driver_destroy(struct cdi_fs_driver* driver)
 {
+    // TODO
 }
 
 void cdi_fs_driver_register(struct cdi_fs_driver* driver)
 {
-    if (the_one_and_only_driver) {
-        return;
-    }
+    struct lio_service* service;
+
+    service = malloc(sizeof(*service));
+    service->name = driver->drv.name;
+    service->opaque = driver;
+    service->lio_ops = (struct lio_driver) {
+        .load_root      = cdi_fs_lio_load_root,
+        .load_children  = cdi_fs_lio_load_children,
+        .read           = cdi_fs_lio_read,
+        .write          = cdi_fs_lio_write,
+        .resize         = cdi_fs_lio_resize,
+        .make_file      = cdi_fs_lio_make_file,
+        .make_dir       = cdi_fs_lio_make_dir,
+        .make_symlink   = cdi_fs_lio_make_symlink,
+        .unlink         = cdi_fs_lio_unlink,
+        .sync           = cdi_fs_lio_sync,
+    };
 
-    the_one_and_only_driver = driver;
+    lio_add_service(service);
 }
 
 
@@ -152,11 +104,14 @@ void cdi_fs_driver_register(struct cdi_fs_driver* driver)
 size_t cdi_fs_data_read(struct cdi_fs_filesystem* fs, uint64_t start,
     size_t size, void* buffer)
 {
-    if (fseek(fs->osdep.device, start, SEEK_SET) != 0) {
-        return -1;
+    ssize_t result;
+
+    if ((result = lio_pread(fs->osdep.tree->source, start, size, buffer)) < 0) {
+        // FIXME: Das ist irgendwie ein bescheiden
+        return 0;
     }
 
-    return fread(buffer, 1, size, fs->osdep.device);
+    return result;
 }
 
 /**
@@ -173,9 +128,12 @@ size_t cdi_fs_data_read(struct cdi_fs_filesystem* fs, uint64_t start,
 size_t cdi_fs_data_write(struct cdi_fs_filesystem* fs, uint64_t start,
     size_t size, const void* buffer)
 {
-    if (fseek(fs->osdep.device, start, SEEK_SET) != 0) {
-        return -1;
+    ssize_t result;
+
+    if ((result = lio_pwrite(fs->osdep.tree->source, start, size, buffer)) < 0) {
+        // FIXME: Das ist irgendwie ein bescheiden
+        return 0;
     }
 
-    return fwrite(buffer, 1, size, fs->osdep.device);
+    return result;
 }
diff --git a/src/modules/cdi/lib/fs/lostio_if.c b/src/modules/cdi/lib/fs/lostio_if.c
index ef0f5e6..2823c5f 100644
--- a/src/modules/cdi/lib/fs/lostio_if.c
+++ b/src/modules/cdi/lib/fs/lostio_if.c
@@ -44,472 +44,368 @@
 
 #include "cdi/fs.h"
 
-// FIXME -- doppelt mit fs.c
-#define CDI_TYPEHANDLE 200
-#define CDI_TYPEHANDLE_SYMLINK 201
+#define BLOCKSIZE 1024
 
-#define debug_print(x) puts(x)
 
-// So lang kann der Root-Pfad maximal werden
-#define ROOT_PATH_SIZE 27
-#define FULL_PATH_SIZE(x) (strlen(x) + ROOT_PATH_SIZE)
-
-static bool fs_fill_dir(vfstree_node_t* node);
-
-
-extern struct cdi_fs_driver* the_one_and_only_driver;
-
-/**
- * Diese Funktion generiert den Root-Pfad zu einem Source-Handle
- *
- * @param source Source-Handle
- * @param buffer Puffer, in dem der Pfad abgelegt werden soll (muss mindestens
- *               MAX_ROOT_PATH_SIZE Bytes lang sein.
- */
-static inline void get_root_path(io_resource_t* source, char* buffer)
-{
-    snprintf(buffer, ROOT_PATH_SIZE, "/%08d_%016d", source->pid, (uint32_t)
-        source->resid);
-}
-
-/**
- * Diese Funktion generiert den vollen Pfad zu einem Source-Handle
- *
- * @param source Source-Handle
- * @param path Pfad
- * @param buffer Puffer, in dem der Pfad abgelegt werden soll (muss mindestens
- *               FULL_PATH_SIZE Bytes lang sein.
- */
-static inline void get_full_path(io_resource_t* source, char* path,
-    char* buffer)
+static int ensure_loaded(struct cdi_fs_stream* s)
 {
-    size_t size = FULL_PATH_SIZE(path);
-    // Abschliessender Slash rauswerfen
-    if (path[strlen(path) - 1] == '/') {
-        size--;
+    if (s->res->loaded || s->res->res->load(s)) {
+        return 1;
     }
 
-    snprintf(buffer, size, "/%08d_%016d%s", source->pid,
-        (uint32_t) source->resid, path);
+    return 0;
 }
 
-static int handle_dirent(struct cdi_fs_res* res, vfstree_node_t* node)
+static struct lio_resource* create_liores(struct cdi_fs_filesystem* fs,
+    struct cdi_fs_res* cdires)
 {
-    char* name;
-    struct cdi_fs_stream* parent_stream = node->data;
-    struct cdi_fs_stream* s;
-    int flags;
-    int type;
-    uint64_t size;
+    struct lio_resource* liores;
+    struct cdi_fs_stream s;
 
-    name = res->name;
+    s.res = cdires;
+    s.fs = fs;
+    s.error = 0;
 
-    if (!strcmp(name, ".") || !strcmp(name, "..")) {
-        return 0;
+    if (!ensure_loaded(&s)) {
+        return NULL;
     }
 
-    s = malloc(sizeof(*s));
-    s->fs = parent_stream->fs;
-    s->res = res;
+    liores = lio_resource_create(fs->osdep.tree);
+    liores->opaque = cdires;
 
+    liores->moredata = 0;
 
-    if (!res->loaded) {
-        res->res->load(s);
+    /*
+     * CDI-Ressourcen können mehrere Klassen haben. Einige Kombinationen
+     * sind semantischer Müll, z.B. Datei und Symlink gleichzeitig. Wir geben
+     * Dateien den Vorzug. Gleichzeitig ein Verzeichnis zu sein ist vermutlich
+     * auch keine gute Idee, aber theoretisch irgendwie denkbar.
+     *
+     * Außerdem prüfen wir noch, ob die Flags überhaupt zu den Klassen
+     * passen.
+     */
+    if (cdires->file) {
+        liores->readable = liores->seekable = cdires->flags.read;
+        liores->writable = (cdires->flags.write && !fs->read_only);
+    } else if (cdires->link) {
+        liores->resolvable = cdires->flags.read_link;
+        liores->retargetable = cdires->flags.write_link;
     }
-
-    flags = 0;
-    size = 0;
-    type = CDI_TYPEHANDLE;
-    if (res->dir) {
-        flags |= LOSTIO_FLAG_BROWSABLE;
-        type = LOSTIO_TYPES_DIRECTORY;
-    } else if (res->link) {
-        flags |= LOSTIO_FLAG_SYMLINK;
-        type = CDI_TYPEHANDLE_SYMLINK;
-    } else {
-        type = CDI_TYPEHANDLE;
-
-        if (res->file) {
-            size = res->res->meta_read(s, CDI_FS_META_SIZE);
-            flags |= LOSTIO_FLAG_READAHEAD;
-        }
+    if (cdires->dir) {
+        liores->browsable = cdires->flags.browse;
+        liores->changeable = cdires->flags.create_child;
     }
 
+    liores->size = cdires->res->meta_read(&s, CDI_FS_META_SIZE);
+    liores->blocksize = BLOCKSIZE;
 
-    vfstree_create_child(node, name, type, size, s, flags);
+    lio_resource_modified(liores);
 
-    if (res->dir) {
-        fs_fill_dir(vfstree_get_node_by_name(node, name));
-    }
-
-    return 0;
+    return liores;
 }
 
-static bool fs_fill_dir(vfstree_node_t* node)
+struct lio_resource* cdi_fs_lio_load_root(struct lio_tree* tree)
 {
-    struct cdi_fs_stream* stream = node->data;
-
-    cdi_list_t children;
-    struct cdi_fs_res* cres;
-    int i;
+    struct cdi_fs_driver* driver = tree->service->opaque;
+    struct cdi_fs_filesystem* fs;
 
-    if (!stream->res->loaded) {
-        stream->res->res->load(stream);
+    if (tree->source == -1ULL) {
+        return NULL;
     }
 
-    if (stream->res->dir) {
-        children = stream->res->dir->list(stream);
+    fs = calloc(1, sizeof(*fs));
+    fs->driver = driver;
+    fs->osdep.tree = tree;
+    tree->opaque = fs;
 
-        for (i = 0; (cres = cdi_list_get(children, i)); i++) {
-            handle_dirent(cres, node);
-        }
+    if (!driver->fs_init(fs)) {
+        free(fs);
+        return NULL;
     }
 
-    return true;
+    return create_liores(fs, fs->root_res);
 }
 
-static bool fs_read_tree(struct cdi_fs_filesystem* fs)
+int cdi_fs_lio_load_children(struct lio_resource* res)
 {
-    char rp[ROOT_PATH_SIZE];
-    vfstree_node_t* node;
-    struct cdi_fs_stream* dh;
+    struct cdi_fs_filesystem* fs = res->tree->opaque;
+    struct cdi_fs_res* cdires = res->opaque;
+    struct cdi_fs_stream s;
+    cdi_list_t children;
+    struct cdi_fs_res* child;
+    struct lio_resource* liochild;
+    size_t i;
 
-    // Dirhandle = Verknuepfung zwischen LIO und Treiber
-    // FIXME Dahinter kommen eigentlich noch private Daten des Treibers...
-    dh = malloc(sizeof(*dh));
-    dh->fs = fs;
-    dh->res = fs->root_res;
+    s.fs = fs;
+    s.res = cdires;
+    s.error = 0;
 
-    get_root_path(fs->osdep.device->res, rp);
-    if ((!vfstree_create_node(rp, LOSTIO_TYPES_DIRECTORY, 0, dh,
-        LOSTIO_FLAG_BROWSABLE)) || (!(node = vfstree_get_node_by_path(rp))))
-    {
-        goto out_err;
+    if (!ensure_loaded(&s) || !cdires->dir) {
+        return -1;
     }
 
-    if (!fs_fill_dir(node)) {
-        goto out_err;
+    children = cdires->dir->list(&s);
+    for (i = 0; (child = cdi_list_get(children, i)); i++) {
+        liochild = create_liores(fs, child);
+        if (!liochild) {
+            return -1;
+        }
+        lio_node_create(res, liochild, child->name);
     }
 
-    return true;
-
-out_err:
-    free(dh);
-    return false;
+    return 0;
 }
 
-static bool fs_mount(FILE* source)
+int cdi_fs_lio_read_file(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void *buf)
 {
-    struct cdi_fs_filesystem* fs = malloc(sizeof(*fs));
-    struct cdi_fs_driver* drv = the_one_and_only_driver;
+    struct cdi_fs_filesystem* fs = res->tree->opaque;
+    struct cdi_fs_res* cdires = res->opaque;
+    struct cdi_fs_stream s;
+    int result;
 
-    // FIXME ;-)
-    fs->osdep.device = calloc(1, sizeof(*fs->osdep.device));
-    *fs->osdep.device = *source;
+    s.fs = fs;
+    s.res = cdires;
+    s.error = 0;
 
-    if (!drv->fs_init(fs)) {
-        goto out_err;
+    if (!ensure_loaded(&s) || !cdires->file || !cdires->file->read) {
+        return -1;
     }
 
-    if (!fs_read_tree(fs)) {
-        goto out_err;
+    if (offset + bytes > res->size) {
+        /* TODO Das ist grosszuegig */
+        memset(buf, 0, bytes);
+
+        if (res->size > offset) {
+            bytes = res->size - offset;
+        } else {
+            bytes = 0;
+        }
     }
 
-    return true;
+    if (bytes) {
+        result = -!(cdires->file->read(&s, offset, bytes, buf) == bytes);
+    } else {
+        result = 0;
+    }
 
-out_err:
-    free(fs->osdep.device);
-    free(fs);
-    return false;
+    return result;
 }
 
-/**
- * Dieser Handler wird bei jedem fopen() aufgerufen, da das immer
- * schief gehen wird weil ja die daten nicht direkt auf Root liegen. Dabei
- * werden nur die Pfade richtig umgebeogen und es wird geprueft ob alle
- * notwendigen Verzeichnisse geladen sind
- */
-bool lostio_not_found_handler(char** path, uint8_t args, pid_t pid,
-    FILE* source)
+int cdi_fs_lio_read_symlink(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void* buf)
 {
-    char root_path[ROOT_PATH_SIZE + 1];
-    char full_path[FULL_PATH_SIZE(*path) + 1];
-    vfstree_node_t* root_node;
-    cdi_fs_res_class_t type;
+    struct cdi_fs_filesystem* fs = res->tree->opaque;
+    struct cdi_fs_res* cdires = res->opaque;
+    struct cdi_fs_stream s;
+    const char* str;
+    size_t str_len;
 
+    s.fs = fs;
+    s.res = cdires;
+    s.error = 0;
 
-    p();
-    get_root_path(source->res, root_path);
-    get_full_path(source->res, *path, full_path);
-
-    // Wenn der Knoten nicht existiert muss gemountet werden
-    root_node = vfstree_get_node_by_path(root_path);
+    if (!ensure_loaded(&s) || !cdires->link || !cdires->link->read_link) {
+        return -1;
+    }
 
-    if (!root_node) {
-        if (!fs_mount(source)) {
-            // Wenn das mounten nicht klappt wird abgebrochen
-            puts("Fehler beim Mount!");
-            goto out_err;
-        }
+    str = cdires->link->read_link(&s);
+    str_len = strlen(str);
 
-        root_node = vfstree_get_node_by_path(root_path);
+    if (offset + bytes > str_len) {
+        bytes = str_len - offset;
     }
 
-    // Testen ob ein Verzeichnis oder eine Datei geoeffnet werden soll
-    if ((args & IO_OPEN_MODE_DIRECTORY) != 0) {
-        type = CDI_FS_CLASS_DIR;
-    } else if ((args & IO_OPEN_MODE_LINK) != 0) {
-        type = CDI_FS_CLASS_LINK;
+    memcpy(buf, str + offset, bytes);
+
+    return 0;
+}
+
+int cdi_fs_lio_read(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void* buf)
+{
+    if (res->resolvable) {
+        return cdi_fs_lio_read_symlink(res, offset, bytes, buf);
     } else {
-        type = CDI_FS_CLASS_FILE;
+        return cdi_fs_lio_read_file(res, offset, bytes, buf);
     }
+}
 
-    // Pfad aendern
-    *path = malloc(strlen(full_path) + 1);
-    memcpy(*path, full_path, strlen(full_path) + 1);
+int cdi_fs_lio_write_file(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void* buf)
+{
+    struct cdi_fs_filesystem* fs = res->tree->opaque;
+    struct cdi_fs_res* cdires = res->opaque;
+    struct cdi_fs_stream s;
+    int result;
 
-    // Jetzt wird der Knoten geholt, damit geprueft werden kann, ob auch kein
-    // Verzeichnis als Datei geoeffnet werden soll und sowas ;-)
-    vfstree_node_t* node = vfstree_get_node_by_path(*path);
-    struct cdi_fs_stream* stream;
+    s.fs = fs;
+    s.res = cdires;
+    s.error = 0;
 
-    // Abbrechen falls der Knoten nicht existiert und auch nicht erstellt
-    // werden soll
-    if ((node == NULL) && ((args & IO_OPEN_MODE_CREATE) == 0)) {
-        goto out_err;
-    } else if ((node == NULL)) {
-        // Der Knoten exisitiert nicht, soll aber erstellt werden
-        char* parent_path = vfstree_dirname(*path);
-        char* child_name = vfstree_basename(*path);
-        vfstree_node_t* parent = vfstree_get_node_by_path(parent_path);
-        free(parent_path);
+    if (offset + bytes > res->size) {
+        bytes = res->size - offset;
+    }
 
-        if (parent == NULL) {
-            goto out_err;
-        }
+    if (!ensure_loaded(&s) || !cdires->file || !cdires->file->write
+        || fs->read_only)
+    {
+        return -1;
+    }
 
-        // Kindeintraege koennen nur in Verzeichnissen angelegt werden
-        struct cdi_fs_stream* parent_stream = parent->data;
-        if (parent_stream->res->dir == NULL) {
-            goto out_err;
-        }
+    result = -!(cdires->file->write(&s, offset, bytes, buf) == bytes);
 
-        // Stream erstellen fuer die neue Ressource
-        struct cdi_fs_stream stream;;
-        memset(&stream, 0, sizeof(stream));
-        stream.fs = parent_stream->fs;
+    return result;
+}
 
-        if(!parent_stream->res->flags.create_child) {
-            goto out_err;
-        }
-        if (!parent_stream->res->dir->create_child(&stream, child_name,
-            parent_stream->res))
-        {
-            puts("cdi_fs: Fehler beim Anlegen der Kindressource");
-            goto out_err;
-        }
+int cdi_fs_lio_write_symlink(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void* buf)
+{
+    struct cdi_fs_filesystem* fs = res->tree->opaque;
+    struct cdi_fs_res* cdires = res->opaque;
+    struct cdi_fs_stream s;
+    int result;
+    char* path;
+    size_t path_len;
 
-        if (!stream.res->res->assign_class(&stream, type)) {
-            puts("cdi_fs: Fehler beim Zuweisen der Klasse fuer die neue"
-                "Ressource");
-            goto out_err;
-        }
+    s.fs = fs;
+    s.res = cdires;
+    s.error = 0;
 
-        handle_dirent(stream.res, parent);
-        node = vfstree_get_node_by_name(parent, child_name);
+    if (offset + bytes > res->size) {
+        bytes = res->size - offset;
     }
 
-    stream = node->data;
-
-    if (stream->res->link) {
-        type = CDI_FS_CLASS_LINK;
+    if (!ensure_loaded(&s) || !cdires->link || !cdires->link->write_link
+        || fs->read_only)
+    {
+        return -1;
     }
 
-    switch (type) {
-        case CDI_FS_CLASS_FILE:
-            if (stream->res->file == NULL) {
-                goto out_err;
-            }
-
-            if ((args & IO_OPEN_MODE_TRUNC)) {
-                if (!stream->res->file->truncate(stream, 0)) {
-                    puts("cdi_fs: Truncate fehlgeschlagen!");
-                    goto out_err;
-                }
-                node->size = 0;
-            }
-            break;
-
-        case CDI_FS_CLASS_DIR:
-            if (stream->res->dir == NULL) {
-                goto out_err;
-            }
-            break;
-
-        case CDI_FS_CLASS_LINK:
-            if (stream->res->link == NULL) {
-                goto out_err;
-            }
-            break;
-
-        default:
-            goto out_err;
+    path = strdup(cdires->link->read_link(&s));
+    path_len = strlen(path);
+    if (path_len < offset + bytes) {
+        path = realloc(path, offset + bytes + 1);
+        path[offset + bytes] = '\0';
     }
 
-    v();
-    return true;
+    memcpy(path + offset, buf, bytes);
+    result = -cdires->link->write_link(&s, path);
 
-out_err:
-    v();
-    return false;
+    return result;
 }
 
-/**
- * Handler der dazu benutzt wird, die Pfade umzubiegen
- */
-bool lostio_pre_open_handler(char** path, uint8_t args, pid_t pid,
-    FILE* source)
+int cdi_fs_lio_write(struct lio_resource* res, uint64_t offset,
+    size_t bytes, void* buf)
 {
-    if ((strcmp(*path, "/") == 0) || (vfstree_get_node_by_path(*path) == NULL))
-    {
-        if (lostio_not_found_handler(path, args, pid, source) == false) {
-            return false;
-        }
+    if (res->retargetable) {
+        return cdi_fs_lio_write_symlink(res, offset, bytes, buf);
+    } else {
+        return cdi_fs_lio_write_file(res, offset, bytes, buf);
     }
-    return true;
 }
 
-size_t lostio_readahead_handler(lostio_filehandle_t* fh, void* buf,
-    size_t bs, size_t bc)
+extern void caches_sync_all(void);
+int cdi_fs_lio_sync(struct lio_resource* res)
 {
-    size_t size = 0;
-    struct cdi_fs_stream* dh = fh->node->data;
-
-    p();
-
-    if (dh->res->file == NULL) {
-        goto out;
-    }
-
-    if (!dh->res->flags.read) {
-        goto out;
-    }
-
-    if (fh->pos > fh->node->size) {
-        goto out;
-    }
+    struct cdi_fs_filesystem* fs = res->tree->opaque;
 
-    size = bs * bc;
-    if (size > fh->node->size - fh->pos) {
-        size = fh->node->size - fh->pos;
-    }
-    if (size == 0) {
-        goto out;
-    }
+    // FIXME Rückgabewert
+    caches_sync_all();
 
-    size = dh->res->file->read(dh, fh->pos, size, buf);
-
-out:
-    v();
-    return size;
+    return lio_sync(fs->osdep.tree->source);
 }
 
-size_t lostio_read_handler(lostio_filehandle_t* fh, void* buf,
-    size_t bs, size_t bc)
+int cdi_fs_lio_resize(struct lio_resource* res, uint64_t size)
 {
-    size_t ret;
+    struct cdi_fs_filesystem* fs = res->tree->opaque;
+    struct cdi_fs_res* cdires = res->opaque;
+    struct cdi_fs_stream s;
 
-    p();
-    ret = lostio_readahead_handler(fh, buf, bs, bc);
-    fh->pos += ret;
-    if(fh->pos >= fh->node->size) {
-        fh->flags |= LOSTIO_FLAG_EOF;
-    } else {
-        fh->flags &= ~LOSTIO_FLAG_EOF;
+    s.fs = fs;
+    s.res = cdires;
+    s.error = 0;
+
+    if (cdires->file) {
+        if (!cdires->file->truncate || !cdires->file->truncate(&s, size)) {
+            return -1;
+        }
+    } else if (!cdires->link) {
+        return -1;
     }
-    v();
 
-    return ret;
+    res->size = size;
+    return 0;
 }
 
-size_t lostio_write_handler(lostio_filehandle_t* fh, size_t bs, size_t bc,
-    void* data)
+static struct lio_resource* make_object(struct lio_resource* parent,
+    const char* name, cdi_fs_res_class_t cls)
 {
-    size_t size = bs * bc;
-    struct cdi_fs_stream* stream = fh->node->data;
-    size_t result = 0;
+    struct cdi_fs_filesystem* fs = parent->tree->opaque;
+    struct cdi_fs_res* cdiparent = parent->opaque;
+    struct cdi_fs_stream s;
+    struct lio_resource* res;
 
-    p();
+    s.fs = fs;
+    s.res = NULL;
+    s.error = 0;
 
-    if (!size) {
-        goto out;
+    if (fs->read_only || !cdiparent->dir || !cdiparent->dir->create_child ||
+        !cdiparent->dir->create_child(&s, name, cdiparent))
+    {
+        return NULL;
     }
 
-    if(!stream->res->flags.write) {
-        goto out;
+    if (!ensure_loaded(&s)) {
+        return NULL;
     }
 
-    result = stream->res->file->write(stream, fh->pos, size, data);
-    fh->pos += size;
-
-    if (fh->pos > fh->node->size) {
-        fh->node->size = fh->pos;
+    if (!s.res->res->assign_class(&s, cls)) {
+        return NULL;
     }
 
-    if(fh->pos >= fh->node->size) {
-        fh->flags |= LOSTIO_FLAG_EOF;
-    } else {
-        fh->flags &= ~LOSTIO_FLAG_EOF;
+    res = create_liores(fs, s.res);
+    if (res) {
+        lio_node_create(parent, res, name);
     }
 
-out:
-    v();
-    return result;
+    return res;
 }
 
-
-
-int lostio_seek_handler(lostio_filehandle_t* fh, uint64_t offset, int origin)
+struct lio_resource* cdi_fs_lio_make_file(struct lio_resource* parent,
+    const char* name)
 {
-    uint64_t new_pos;
-
-    p();
+    return make_object(parent, name, CDI_FS_CLASS_FILE);
+}
 
-    switch(origin)
-    {
-        case SEEK_SET:
-            new_pos = offset;
-            break;
+struct lio_resource* cdi_fs_lio_make_dir(struct lio_resource* parent,
+    const char* name)
+{
+    return make_object(parent, name, CDI_FS_CLASS_DIR);
+}
 
-        case SEEK_CUR:
-            new_pos = fh->pos + offset;
-            break;
+struct lio_resource* cdi_fs_lio_make_symlink(struct lio_resource* parent,
+    const char* name, const char* target)
+{
+    struct lio_resource* res;
+    struct cdi_fs_res* cdires;
+    struct cdi_fs_filesystem* fs = parent->tree->opaque;
+    struct cdi_fs_stream s;
 
-        case SEEK_END:
-            new_pos = fh->node->size + offset;
-            break;
+    res = make_object(parent, name, CDI_FS_CLASS_LINK);
+    if (res) {
+        cdires = res->opaque;
+        s.fs = fs;
+        s.res = cdires;
+        s.error = 0;
 
-        default:
-            return -1;
-    }
+        cdires->link->write_link(&s, target);
 
-    if ((new_pos > fh->node->size) && ((origin == SEEK_SET) ||
-        (origin == SEEK_CUR)) && ((fh->flags & IO_OPEN_MODE_WRITE) == 0))
-    {
-        v();
-        return -1;
+        res->size = strlen(target);
+        lio_resource_modified(res);
     }
 
-    fh->pos = new_pos;
-
-    if(fh->pos >= fh->node->size) {
-        fh->flags |= LOSTIO_FLAG_EOF;
-    } else {
-        fh->flags &= ~LOSTIO_FLAG_EOF;
-    }
-
-    v();
-    return 0;
+    return res;
 }
 
 /**
@@ -545,100 +441,46 @@ static int cdi_remove_res(struct cdi_fs_stream* stream)
     return 0;
 }
 
-int lostio_unlink_handler(lostio_filehandle_t* fh, const char* name)
+int cdi_fs_lio_unlink(struct lio_resource* parent, const char* name)
 {
-    struct cdi_fs_stream* stream;
-    vfstree_node_t* node;
-    int i;
-    int result = 0;
-
-    p();
-
-    // Passender Kindknoten finden
-    for (i = 0; (node = list_get_element_at(fh->node->children, i)); i++) {
-        if (!strcmp(node->name, name)) {
-            goto found;
-        }
-    }
-
-    result = -1;
-    goto out;
+    struct cdi_fs_filesystem* fs = parent->tree->opaque;
+    struct cdi_fs_res* cdiparent = parent->opaque;
+    struct cdi_fs_res* child;
+    struct cdi_fs_stream s;
+    struct lio_node* node;
 
-found:
-    stream = node->data;
-
-    // Spezialfall: Es handelt sich um ein Verzeichnis. Das heisst es darf
-    // nur geloescht werden wenn es keine Kind-Eintraege mehr hat.
-    if (stream->res->dir && list_size(node->children)) {
-        result = -1;
-        goto out;
-    }
-
-    // Sonst kann die Ressource geloescht werden.
-    if (cdi_remove_res(stream) || !vfstree_delete_child(fh->node, name)) {
-        result = -1;
-    }
-
-out:
-    v();
-    return result;
-}
-
-size_t lostio_symlink_read_handler(lostio_filehandle_t* fh, void* buf,
-    size_t bs, size_t bc)
-{
-    size_t size = bs*bc;
-    struct cdi_fs_stream* dh = fh->node->data;
-    const char* link;
-
-    p();
-
-    if (dh->res->link == NULL) {
-        goto out;
-    }
-
-    if (!dh->res->flags.read_link) {
-        goto out;
+    if (fs->read_only) {
+        return -1;
     }
 
-    link = dh->res->link->read_link(dh);
-    if (size > strlen(link) + 1) {
-        size = strlen(link) + 1;
+    s.fs = fs;
+    s.res = cdiparent;
+    s.error = 0;
+    if (!ensure_loaded(&s)) {
+        return -1;
     }
-    strncpy(buf, link, size);
-
-out:
-    v();
-    return size;
-}
 
-size_t lostio_symlink_write_handler(lostio_filehandle_t* fh, size_t bs,
-    size_t bc, void* data)
-{
-    size_t size = bs * bc;
-    struct cdi_fs_stream* stream = fh->node->data;
-    size_t result = 0;
-
-    p();
-
-    if ((stream->res->link == NULL) || (((char*) data)[size - 1] != 0)) {
-        goto out;
+    if (!(node = lio_resource_get_child(parent, name))) {
+        return -1;
     }
+    child = node->res->opaque;
 
-    if (!size) {
-        goto out;
+    s.res = child;
+    if (!ensure_loaded(&s)) {
+        return -1;
     }
 
-    if (!stream->res->flags.write_link) {
-        goto out;
+    // Wir haben es mit einem Verzeichnis zu tun, das duerfen wir nur loeschen
+    // wenn es keine Kindeintraege mehr hat.
+    if (child->dir && cdi_list_size(child->children)) {
+        return -1;
     }
 
-    if (stream->res->link->write_link(stream, data)) {
-        result = size;
+    if (cdi_remove_res(&s)) {
+        return -1;
     }
+    lio_resource_remove_child(parent, node);
 
-out:
-    v();
-    return result;
+    return 0;
 }
 
-- 
1.7.7