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

[tyndur-devel] [PATCH 03/11] LIOv2: lio_probe_service für Userspaceservices



+ LIOv2: Userspace-LIO-Services können jetzt auch lio_probe_service
  unterstützen

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/include/syscall_structs.h         | 15 +++++++++
 src/kernel2/src/syscalls/lio_server.c | 61 +++++++++++++++++++++++++++++++++++
 src/modules/include/lostio.h          |  6 ++++
 src/modules/lib/lostio/lio_server.c   | 16 +++++++++
 4 files changed, 98 insertions(+)

diff --git a/src/include/syscall_structs.h b/src/include/syscall_structs.h
index 3ba12b9..d433779 100644
--- a/src/include/syscall_structs.h
+++ b/src/include/syscall_structs.h
@@ -303,6 +303,11 @@ enum lio_opcode {
      * Stream der Ressource wird geschlossen
      */
     LIO_OP_CLOSE = 15,
+
+    /**
+     * Prüfen, ob die Ressource als Pipequelle benutzt werden kann
+     */
+    LIO_OP_PROBE = 16,
 };
 
 /// Flags fuer Operationen
@@ -547,6 +552,16 @@ struct lio_op_sync {
     void* opaque;
 } __attribute__((packed));
 
+struct lio_op_probe {
+    struct lio_op op;
+
+    /// Stream fuer die Pipequelle
+    lio_usp_stream_t source;
+
+    /// Rückgabe: Informationen über Dateisystem
+    struct lio_probe_service_result* probe_data;
+} __attribute__((packed));
+
 
 /// Flags fuer Server-Ressourcen
 enum lio_server_flags {
diff --git a/src/kernel2/src/syscalls/lio_server.c b/src/kernel2/src/syscalls/lio_server.c
index 5127d7a..4b1b03d 100644
--- a/src/kernel2/src/syscalls/lio_server.c
+++ b/src/kernel2/src/syscalls/lio_server.c
@@ -68,6 +68,8 @@ static struct lio_resource* make_symlink(struct lio_resource* parent,
     const char* name, const char* target);
 static int truncate(struct lio_resource* res, uint64_t size);
 static int unlink(struct lio_resource* parent, const char* name);
+static int probe(struct lio_service* serv, struct lio_stream* source,
+                 struct lio_probe_service_result* probe_data);
 
 struct lio_pending_op {
     struct tree_item    tinfo;
@@ -136,6 +138,7 @@ int syscall_lio_srv_service_register(const char* name, size_t name_len,
 
     // TODO: Ein paar is_userspace
     service->name = strdup(name);
+    service->lio_ops.probe= probe;
     service->lio_ops.load_root = load_root;
     service->lio_ops.load_children = load_children;
     service->lio_ops.close = close;
@@ -831,3 +834,61 @@ static int unlink(struct lio_resource* parent, const char* name)
     return result;
 
 }
+
+static int probe(struct lio_service* serv, struct lio_stream* source,
+                 struct lio_probe_service_result* probe_data)
+{
+    struct lio_userspace_service* s = serv->opaque;
+    struct lio_probe_service_result* result;
+    struct lio_usp_stream* usp_fd;
+    struct lio_op_probe* op;
+    void* user_buf;
+    int ret;
+
+    if (s->provider == NULL) {
+        return -EBADF;
+    }
+
+    op = (struct lio_op_probe*) alloc_ring_op(&s->ring, sizeof(*op));
+
+    usp_fd = lio_usp_add_stream(s->provider->process, source);
+    if (!usp_fd) {
+        return -EBADF;
+    }
+
+    BUILD_BUG_ON(sizeof(*result) > PAGE_SIZE);
+    result = mmc_valloc(&mmc_current_context(), 1, MM_FLAGS_KERNEL_CODE);
+    if (result == NULL) {
+        ret = -ENOMEM;
+        goto fail_alloc_page;
+    }
+    memset(result, 0, PAGE_SIZE);
+
+    user_buf = mmc_automap_user(&s->provider->process->context,
+                                &mmc_current_context(), result, 1,
+                                MM_USER_START, MM_USER_END, MM_FLAGS_USER_DATA);
+    if (user_buf == NULL) {
+        ret = -ENOMEM;
+        goto fail_map;
+    }
+
+    op->op.opcode = LIO_OP_PROBE;
+    op->source = usp_fd->usp_id;
+    op->probe_data = user_buf;
+
+    ret = commit_ring_op(&s->ring, s->provider, &op->op, NULL);
+    if (ret == 0) {
+        strlcpy(result->service, serv->name, sizeof(result->service));
+        memcpy(probe_data, result, sizeof(*probe_data));
+    }
+
+    mmc_unmap(&s->provider->process->context, user_buf, 1);
+fail_map:
+    mmc_vfree(&mmc_current_context(), result, 1);
+fail_alloc_page:
+    /* Wir dürfen kein close() machen, der Kernel braucht den Stream noch */
+    source->usp_refcount++;
+    lio_usp_unref_stream(s->provider->process, usp_fd);
+    BUG_ON(--source->usp_refcount != 0);
+    return ret;
+}
diff --git a/src/modules/include/lostio.h b/src/modules/include/lostio.h
index 06dafec..9ad8c33 100644
--- a/src/modules/include/lostio.h
+++ b/src/modules/include/lostio.h
@@ -252,8 +252,14 @@ int64_t lio_compat_tell(io_resource_t* io_res);
  */
 void lio_dispatch(void);
 
+struct lio_service;
 struct lio_tree;
 struct lio_driver {
+    /// Prüfen, ob die Ressource als Pipequelle benutzt werden kann
+    int (*probe)(struct lio_service* service,
+                 lio_stream_t source,
+                 struct lio_probe_service_result* probe_data);
+
     /// Root-Ressource eines Baums laden
     struct lio_resource* (*load_root)(struct lio_tree* tree);
 
diff --git a/src/modules/lib/lostio/lio_server.c b/src/modules/lib/lostio/lio_server.c
index 64206f5..2f3825d 100644
--- a/src/modules/lib/lostio/lio_server.c
+++ b/src/modules/lib/lostio/lio_server.c
@@ -50,6 +50,7 @@ static void tree_dispatch(struct lio_tree* tree);
 static void process_op(struct lio_service* service, struct lio_op* op);
 
 // Operationen
+static void op_probe(struct lio_service* service, struct lio_op* op);
 static void op_load_root(struct lio_service* service, struct lio_op* op);
 static void op_load_children(struct lio_service* service, struct lio_op* op);
 static void op_close(struct lio_service* service, struct lio_op* op);
@@ -94,6 +95,10 @@ void lio_dispatch(void)
                     op_load_root(s, op);
                     break;
 
+                case LIO_OP_PROBE:
+                    op_probe(s, op);
+                    break;
+
                 default:
                     printf("lio_dispatch: Fehler, unerwarteter Opcode 0x%x\n",
                         op->opcode);
@@ -203,6 +208,17 @@ static void process_op(struct lio_service* service, struct lio_op* op)
     op->flags &= ~LIO_OPFL_USP;
 }
 
+static void op_probe(struct lio_service* service, struct lio_op* op)
+{
+    struct lio_op_probe* opr = (struct lio_op_probe*) op;
+    int ret = -EINVAL;
+
+    if (service->lio_ops.probe) {
+        ret = service->lio_ops.probe(service, opr->source, opr->probe_data);
+    }
+    lio_srv_op_done(op, ret, 0);
+}
+
 static void op_load_root(struct lio_service* service, struct lio_op* op)
 {
     struct lio_op_load_root* olr = (struct lio_op_load_root*) op;
-- 
2.1.4