From bc1bc9fec54e92717ba2de58aef2bfd08385d366 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 25 Feb 2023 19:12:09 +0000 Subject: [PATCH] obj: add set and namespace object callbacks --- include/socks/object.h | 8 ++--- include/socks/status.h | 1 + obj/namespace.c | 46 +++++++++++++++++++++---- obj/object.c | 23 +++++++------ obj/set.c | 76 +++++++++++++++++++++++++++--------------- 5 files changed, 106 insertions(+), 48 deletions(-) diff --git a/include/socks/object.h b/include/socks/object.h index 8b3588e..7d8c4dc 100644 --- a/include/socks/object.h +++ b/include/socks/object.h @@ -40,7 +40,7 @@ typedef struct object_type { vm_cache_t ob_cache; queue_entry_t ob_list; queue_t ob_attrib; - const object_ops_t *ob_ops; + object_ops_t ob_ops; } object_type_t; typedef struct object { @@ -77,13 +77,11 @@ static inline kern_status_t object_get(const char *path, object_t **out) { return object_namespace_get_object(global_namespace(), path, out); } -extern object_t *object_get_child_named(object_t *obj, const char *name); -extern object_t *object_get_child_at(object_t *obj, size_t at); +extern kern_status_t object_get_child_named(object_t *obj, const char *name, object_t **out); +extern kern_status_t object_get_child_at(object_t *obj, size_t at, object_t **out); extern kern_status_t object_query_name(object_t *obj, char name[OBJECT_NAME_MAX]); extern object_t *set_create(const char *name); -extern kern_status_t set_lock(object_t *obj, unsigned long *flags); -extern kern_status_t set_unlock(object_t *obj, unsigned long flags); extern kern_status_t set_add_object(object_t *set, object_t *obj); extern kern_status_t set_remove_object(object_t *set, object_t *obj); extern bool object_is_set(object_t *obj); diff --git a/include/socks/status.h b/include/socks/status.h index 1ff7a1e..4607891 100644 --- a/include/socks/status.h +++ b/include/socks/status.h @@ -9,5 +9,6 @@ typedef unsigned int kern_status_t; #define KERN_INVALID_ARGUMENT (3) #define KERN_UNSUPPORTED (4) #define KERN_NO_MEMORY (5) +#define KERN_NO_ENTRY (6) #endif diff --git a/obj/namespace.c b/obj/namespace.c index a03d307..986e363 100644 --- a/obj/namespace.c +++ b/obj/namespace.c @@ -1,17 +1,42 @@ #include #include +static object_namespace_t *global_ns; + struct object_namespace { /* root directory set object */ object_t *ns_root; }; +static kern_status_t ns_query_name(object_t *obj, char out[OBJECT_NAME_MAX]) +{ + out[0] = '/'; + out[1] = 0; + return KERN_OK; +} + +static kern_status_t ns_get_child_at(object_t *obj, size_t at, object_t **out) +{ + object_namespace_t *ns = object_data(obj); + return object_get_child_at(ns->ns_root, at, out); +} + +static kern_status_t ns_get_child_named(object_t *obj, const char *name, object_t **out) +{ + object_namespace_t *ns = object_data(obj); + return object_get_child_named(ns->ns_root, name, out); +} + static object_type_t ns_type = { .ob_name = "namespace", .ob_size = sizeof(object_namespace_t), + .ob_ops = { + .query_name = ns_query_name, + .get_named = ns_get_child_named, + .get_at = ns_get_child_at, + }, }; -static object_namespace_t *global_ns; void init_global_namespace(void) { @@ -100,21 +125,30 @@ kern_status_t object_publish(object_namespace_t *ns, const char *path, object_t unsigned long flags; while (tok) { - set_lock(cur, &flags); + object_lock(cur, &flags); - object_t *next = object_get_child_named(cur, tok); - if (!next) { + object_t *next; + kern_status_t status = object_get_child_named(cur, tok, &next); + if (status == KERN_NO_ENTRY) { next = set_create(tok); if (!next) { + object_unlock(cur, flags); kfree(rpath); return KERN_NO_MEMORY; } - set_add_object(cur, next); + status = set_add_object(cur, next); } - set_unlock(cur, flags); + if (status != KERN_OK) { + object_unlock(cur, flags); + kfree(rpath); + return status; + } + + object_unlock(cur, flags); cur = next; + tok = strtok_r(NULL, "/", &sp); } kfree(rpath); diff --git a/obj/object.c b/obj/object.c index d9f751f..8be759b 100644 --- a/obj/object.c +++ b/obj/object.c @@ -2,7 +2,7 @@ #include #include -#define HAS_OP(obj, opname) ((obj)->ob_type->ob_ops && (obj)->ob_type->ob_ops->opname) +#define HAS_OP(obj, opname) ((obj)->ob_type->ob_ops.opname) static queue_t object_types; static spin_lock_t object_types_lock = SPIN_LOCK_INIT; @@ -53,6 +53,7 @@ object_t *object_create(object_type_t *type) return NULL; } + obj->ob_type = type; obj->ob_lock = SPIN_LOCK_INIT; obj->ob_magic = OBJECT_MAGIC; obj->ob_refcount = 1; @@ -85,7 +86,7 @@ void object_deref(object_t *obj) } if (HAS_OP(obj, delete)) { - obj->ob_type->ob_ops->delete(obj); + obj->ob_type->ob_ops.delete(obj); } vm_cache_free(&obj->ob_type->ob_cache, obj); @@ -118,32 +119,32 @@ object_t *object_header(void *p) return obj; } -object_t *object_get_child_named(object_t *obj, const char *name) +kern_status_t object_get_child_named(object_t *obj, const char *name, object_t **out) { - object_t *out = NULL; + kern_status_t status = KERN_UNSUPPORTED; if (HAS_OP(obj, get_named)) { - obj->ob_type->ob_ops->get_named(obj, name, &out); + status = obj->ob_type->ob_ops.get_named(obj, name, out); } - return out; + return status; } -object_t *object_get_child_at(object_t *obj, size_t at) +kern_status_t object_get_child_at(object_t *obj, size_t at, object_t **out) { - object_t *out = NULL; + kern_status_t status = KERN_UNSUPPORTED; if (HAS_OP(obj, get_at)) { - obj->ob_type->ob_ops->get_at(obj, at, &out); + status = obj->ob_type->ob_ops.get_at(obj, at, out); } - return out; + return status; } kern_status_t object_query_name(object_t *obj, char name[OBJECT_NAME_MAX]) { if (HAS_OP(obj, query_name)) { - return obj->ob_type->ob_ops->query_name(obj, name); + return obj->ob_type->ob_ops.query_name(obj, name); } return KERN_UNSUPPORTED; diff --git a/obj/set.c b/obj/set.c index b46d375..582bf07 100644 --- a/obj/set.c +++ b/obj/set.c @@ -3,12 +3,61 @@ struct set { queue_t s_list; char s_name[OBJECT_NAME_MAX]; - spin_lock_t s_lock; }; +static kern_status_t set_query_name(object_t *obj, char out[OBJECT_NAME_MAX]) +{ + struct set *set = object_data(obj); + strncpy(out, set->s_name, OBJECT_NAME_MAX - 1); + out[OBJECT_NAME_MAX - 1] = 0; + + return KERN_OK; +} + +static kern_status_t set_get_child_at(object_t *obj, size_t at, object_t **out) +{ + struct set *set = object_data(obj); + size_t i = 0; + queue_foreach(object_t, child, &set->s_list, ob_list) { + if (i == at) { + *out = child; + return KERN_OK; + } + + i++; + } + + return KERN_NO_ENTRY; +} + +static kern_status_t set_get_child_named(object_t *obj, const char *name, object_t **out) +{ + struct set *set = object_data(obj); + char child_name[OBJECT_NAME_MAX]; + + queue_foreach(object_t, child, &set->s_list, ob_list) { + kern_status_t status = object_query_name(child, child_name); + if (status != KERN_OK) { + continue; + } + + if (!strcmp(child_name, name)) { + *out = child; + return KERN_OK; + } + } + + return KERN_NO_ENTRY; +} + static object_type_t set_type = { .ob_name = "set", .ob_size = sizeof(struct set), + .ob_ops = { + .query_name = set_query_name, + .get_named = set_get_child_named, + .get_at = set_get_child_at, + }, }; void init_set_objects(void) @@ -25,37 +74,12 @@ object_t *set_create(const char *name) struct set *set = object_data(set_obj); set->s_list = QUEUE_INIT; - set->s_lock = SPIN_LOCK_INIT; strncpy(set->s_name, name, sizeof set->s_name - 1); set->s_name[sizeof set->s_name - 1] = 0; return set_obj; } -kern_status_t set_lock(object_t *obj, unsigned long *flags) -{ - if (!object_is_set(obj)) { - return KERN_INVALID_ARGUMENT; - } - - struct set *set = object_data(obj); - spin_lock_irqsave(&set->s_lock, flags); - - return KERN_OK; -} - -kern_status_t set_unlock(object_t *obj, unsigned long flags) -{ - if (!object_is_set(obj)) { - return KERN_INVALID_ARGUMENT; - } - - struct set *set = object_data(obj); - spin_unlock_irqrestore(&set->s_lock, flags); - - return KERN_OK; -} - kern_status_t set_add_object(object_t *set_obj, object_t *obj) { if (!object_is_set(set_obj)) {