From 51addd2cdb4e35f0f36021c6c4003192600d9eb1 Mon Sep 17 00:00:00 2001 From: Ryuta Kambe Date: Fri, 31 Jan 2025 18:02:45 +0900 Subject: [PATCH] fix(kmod): restore sys/module debug (#343) Signed-off-by: veqcc --- kmod/agnocast.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 245 insertions(+), 8 deletions(-) diff --git a/kmod/agnocast.c b/kmod/agnocast.c index 5e951654..4df32bd1 100644 --- a/kmod/agnocast.c +++ b/kmod/agnocast.c @@ -456,29 +456,266 @@ static int insert_message_entry( // ========================================= // "/sys/module/agnocast/status/*" +// NOTE: +// show_xx may overflow when used more than PAGE_SIZE. +// The implementations have few error-handling. + +// Example +// +// $ sudo cat /sys/module/agnocast/status/process_list +// process: pid=123, addr=4398046511104, size=67108864 +// publisher +// /my_dynamic_topic +// /my_static_topic +// subscription +// +// process: pid=456, addr=4398180728832, size=16777216 +// publisher +// subscription +// /my_dynamic_topic +// /my_static_topic +// +// process: pid=789, addr=4398113619968, size=67108864 +// publisher +// /my_dynamic_topic +// subscription +// /my_static_topic static ssize_t show_processes(struct kobject * kobj, struct kobj_attribute * attr, char * buf) { - // TODO - return 0; + mutex_lock(&global_mutex); + + int used_size = 0; + int ret; + + struct process_info * proc_info; + int bkt_proc_info; + hash_for_each(proc_info_htable, bkt_proc_info, proc_info, node) + { + ret = scnprintf( + buf + used_size, PAGE_SIZE - used_size, "process: pid=%u, addr=%llu, size=%llu\n", + proc_info->pid, proc_info->shm_addr, proc_info->shm_size); + used_size += ret; + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " publisher\n"); + used_size += ret; + + struct topic_wrapper * wrapper; + int bkt_topic; + hash_for_each(topic_hashtable, bkt_topic, wrapper, node) + { + struct publisher_info * pub_info; + int bkt_pub_info; + hash_for_each(wrapper->topic.pub_info_htable, bkt_pub_info, pub_info, node) + { + if (proc_info->pid == pub_info->pid) { + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " %s\n", wrapper->key); + used_size += ret; + } + } + } + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " subscription\n"); + used_size += ret; + + hash_for_each(topic_hashtable, bkt_topic, wrapper, node) + { + struct subscriber_info * sub_info; + int bkt_sub_info; + hash_for_each(wrapper->topic.sub_info_htable, bkt_sub_info, sub_info, node) + { + if (proc_info->pid == sub_info->pid) { + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " %s\n", wrapper->key); + used_size += ret; + } + } + } + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "\n"); + used_size += ret; + } + + if (used_size >= PAGE_SIZE) { + dev_warn(agnocast_device, "Exceeding PAGE_SIZE. Truncating output...\n"); + mutex_unlock(&global_mutex); + return -ENOSPC; + } + + mutex_unlock(&global_mutex); + return used_size; } +// Example +// +// $ sudo cat /sys/module/agnocast/status/topic_list +// topic: /my_dynamic_topic +// publisher: 15198, 15171, +// subscription: 15237, +// +// topic: /my_static_topic +// publisher: 15171, +// subscription: 15237, 15198, static ssize_t show_topics(struct kobject * kobj, struct kobj_attribute * attr, char * buf) { - // TODO - return 0; + mutex_lock(&global_mutex); + + int used_size = 0; + int ret; + + struct topic_wrapper * wrapper; + int bkt_topic; + hash_for_each(topic_hashtable, bkt_topic, wrapper, node) + { + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "topic: %s\n", wrapper->key); + used_size += ret; + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " publisher:"); + used_size += ret; + + struct publisher_info * pub_info; + int bkt_pub_info; + hash_for_each(wrapper->topic.pub_info_htable, bkt_pub_info, pub_info, node) + { + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " %d,", pub_info->pid); + used_size += ret; + } + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "\n"); + used_size += ret; + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " subscription:"); + used_size += ret; + + struct subscriber_info * sub_info; + int bkt_sub_info; + hash_for_each(wrapper->topic.sub_info_htable, bkt_sub_info, sub_info, node) + { + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " %d,", sub_info->pid); + used_size += ret; + } + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "\n\n"); + used_size += ret; + } + + if (used_size >= PAGE_SIZE) { + dev_warn(agnocast_device, "Exceeding PAGE_SIZE. Truncating output...\n"); + mutex_unlock(&global_mutex); + return -ENOSPC; + } + + mutex_unlock(&global_mutex); + return used_size; } +static char * debug_topic_name; + +// Example +// $ echo "/my_dynamic_topic" | sudo tee /sys/module/agnocast/status/topic_info static ssize_t store_topic_name( struct kobject * kobj, struct kobj_attribute * attr, const char * buf, size_t count) { - // TODO - return 0; + mutex_lock(&global_mutex); + + if (debug_topic_name) { + kfree(debug_topic_name); + } + + debug_topic_name = kstrdup(buf, GFP_KERNEL); + if (!debug_topic_name) { + dev_warn(agnocast_device, "kstrdup failed\n"); + } + + mutex_unlock(&global_mutex); + return count; } +// Example +// +// $ sudo cat /sys/module/agnocast/status/topic_info +// topic: /my_dynamic_topic +// publisher: 9495, 9468, +// subscription: 9534, +// entries: +// time=123456, topic_local_id=0, addr=4398118383424, published=1, referencing=[9534,] +// time=123457, topic_local_id=1, addr=4398051231552, published=1, referencing=[] static ssize_t show_topic_info(struct kobject * kobj, struct kobj_attribute * attr, char * buf) { - // TODO - return 0; + mutex_lock(&global_mutex); + + int used_size = 0; + int ret; + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "topic: %s", debug_topic_name); + used_size += ret; + + if (!debug_topic_name) { + mutex_unlock(&global_mutex); + return ret; + } + + struct topic_wrapper * wrapper; + int bkt_topic; + hash_for_each(topic_hashtable, bkt_topic, wrapper, node) + { + if (strncmp(debug_topic_name, wrapper->key, strlen(wrapper->key)) != 0) continue; + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " publisher:"); + used_size += ret; + + struct publisher_info * pub_info; + int bkt_pub_info; + hash_for_each(wrapper->topic.pub_info_htable, bkt_pub_info, pub_info, node) + { + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " %d,", pub_info->pid); + used_size += ret; + } + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "\n subscription:"); + used_size += ret; + + struct subscriber_info * sub_info; + int bkt_sub_info; + hash_for_each(wrapper->topic.sub_info_htable, bkt_sub_info, sub_info, node) + { + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, " %d,", sub_info->pid); + used_size += ret; + } + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "\n entries:\n"); + used_size += ret; + + struct rb_root * root = &wrapper->topic.entries; + struct rb_node * node; + for (node = rb_first(root); node; node = rb_next(node)) { + struct entry_node * en = container_of(node, struct entry_node, node); + + ret = scnprintf( + buf + used_size, PAGE_SIZE - used_size, + " time=%lld, topic_local_id=%u, addr=%lld, published=%d, referencing=[", en->timestamp, + en->publisher_id, en->msg_virtual_address, en->published); + used_size += ret; + + for (int i = 0; i < MAX_SUBSCRIBER_NUM; i++) { + if (en->referencing_subscriber_ids[i] == -1) break; + + ret = scnprintf( + buf + used_size, PAGE_SIZE - used_size, "%u,", en->referencing_subscriber_ids[i]); + used_size += ret; + } + + ret = scnprintf(buf + used_size, PAGE_SIZE - used_size, "]\n"); + used_size += ret; + } + } + + if (used_size >= PAGE_SIZE) { + dev_warn(agnocast_device, "Exceeding PAGE_SIZE. Truncating output...\n"); + mutex_unlock(&global_mutex); + return -ENOSPC; + } + + mutex_unlock(&global_mutex); + return used_size; } static struct kobject * status_kobj;