From be19299e44d643fd5801ce62789ff9dee890e566 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Mon, 25 May 2026 23:04:36 -0400 Subject: [PATCH 1/2] Use shared dynamic majors for devfs devices --- src/portal/portal_devfs.c | 97 +++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 13 deletions(-) diff --git a/src/portal/portal_devfs.c b/src/portal/portal_devfs.c index f2feba5..b81f4d9 100644 --- a/src/portal/portal_devfs.c +++ b/src/portal/portal_devfs.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include // Required for fput() @@ -85,6 +86,20 @@ static DEFINE_SPINLOCK(devfs_dir_lock); // We need a class to trigger devtmpfs to create /dev nodes. static struct class *portal_class = NULL; +/* + * Dynamic devices should share one devtmpfs major. Allocating a new + * dynamic major for every synthetic device makes /dev state unnecessarily + * fragmented and differs from how a single virtual driver normally behaves. + */ +#define PORTAL_DYNAMIC_DEV_MINORS 4096 +static DEFINE_MUTEX(portal_dynamic_chr_lock); +static dev_t portal_dynamic_chr_devt; +static atomic_t portal_dynamic_chr_minor = ATOMIC_INIT(0); + +static DEFINE_MUTEX(portal_dynamic_blk_lock); +static int portal_dynamic_blk_major; +static atomic_t portal_dynamic_blk_minor = ATOMIC_INIT(0); + /* * ------------------------------------------------------------------------- * Helpers * ------------------------------------------------------------------------- @@ -434,6 +449,59 @@ static void ensure_portal_class(void) } } +static int alloc_portal_dynamic_chrdev(dev_t *devt) +{ + int ret; + int minor; + + mutex_lock(&portal_dynamic_chr_lock); + if (!portal_dynamic_chr_devt) { + ret = alloc_chrdev_region(&portal_dynamic_chr_devt, 0, + PORTAL_DYNAMIC_DEV_MINORS, "portal"); + if (ret < 0) { + mutex_unlock(&portal_dynamic_chr_lock); + return ret; + } + } + + minor = atomic_inc_return(&portal_dynamic_chr_minor) - 1; + if (minor >= PORTAL_DYNAMIC_DEV_MINORS) { + mutex_unlock(&portal_dynamic_chr_lock); + return -ENOSPC; + } + + *devt = MKDEV(MAJOR(portal_dynamic_chr_devt), minor); + mutex_unlock(&portal_dynamic_chr_lock); + return 0; +} + +static int alloc_portal_dynamic_blkdev(int *major, int *minor) +{ + int ret; + int next_minor; + + mutex_lock(&portal_dynamic_blk_lock); + if (!portal_dynamic_blk_major) { + ret = register_blkdev(0, "portal"); + if (ret < 0) { + mutex_unlock(&portal_dynamic_blk_lock); + return ret; + } + portal_dynamic_blk_major = ret; + } + + next_minor = atomic_inc_return(&portal_dynamic_blk_minor) - 1; + if (next_minor >= PORTAL_DYNAMIC_DEV_MINORS) { + mutex_unlock(&portal_dynamic_blk_lock); + return -ENOSPC; + } + + *major = portal_dynamic_blk_major; + *minor = next_minor; + mutex_unlock(&portal_dynamic_blk_lock); + return 0; +} + /* * ------------------------------------------------------------------------- * Directory Logic (New) * ------------------------------------------------------------------------- @@ -561,13 +629,14 @@ void handle_op_devfs_create_device(portal_region *mem_region) * ===================================================================== */ if (pe->is_block) { int major = req->major; + int minor = req->minor; + bool fixed_blkdev_major = major >= 0; // 1. Register Major - if (major >= 0) { + if (fixed_blkdev_major) { ret = register_blkdev(major, final_device_name); } else { - ret = register_blkdev(0, final_device_name); - major = ret; + ret = alloc_portal_dynamic_blkdev(&major, &minor); } if (ret < 0) goto fail_alloc; @@ -595,28 +664,28 @@ void handle_op_devfs_create_device(portal_region *mem_region) pe->gd = blk_mq_alloc_disk(&pe->tag_set, &lim, pe); } if (IS_ERR(pe->gd)) { - unregister_blkdev(major, final_device_name); + if (fixed_blkdev_major) unregister_blkdev(major, final_device_name); goto fail_alloc; } pe->gd->minors = 1; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) pe->gd = blk_mq_alloc_disk(&pe->tag_set, pe); if (IS_ERR(pe->gd)) { - unregister_blkdev(major, final_device_name); + if (fixed_blkdev_major) unregister_blkdev(major, final_device_name); goto fail_alloc; } pe->gd->minors = 1; #else pe->gd = alloc_disk(1); if (!pe->gd) { - unregister_blkdev(major, final_device_name); + if (fixed_blkdev_major) unregister_blkdev(major, final_device_name); goto fail_alloc; } pe->gd->queue = blk_mq_init_queue(&pe->tag_set); #endif pe->gd->major = major; - pe->gd->first_minor = req->minor; + pe->gd->first_minor = minor; pe->gd->fops = &pe->bdops; pe->gd->private_data = pe; snprintf(pe->gd->disk_name, 32, "%s", req->name); @@ -632,24 +701,26 @@ void handle_op_devfs_create_device(portal_region *mem_region) ret = add_disk(pe->gd); if (ret) { put_disk(pe->gd); - unregister_blkdev(major, final_device_name); + if (fixed_blkdev_major) unregister_blkdev(major, final_device_name); goto fail_alloc; } #else add_disk(pe->gd); #endif - devt = MKDEV(major, req->minor); + devt = MKDEV(major, minor); } else { bool enable_default_mmap = (req->size > 0 || req->support_mmap); - if (req->major >= 0) { + bool fixed_chrdev_region = req->major >= 0; + + if (fixed_chrdev_region) { devt = MKDEV(req->major, req->minor); if (req->replace) unregister_chrdev_region(devt, 1); ret = register_chrdev_region(devt, 1, final_device_name); } else { - ret = alloc_chrdev_region(&devt, 0, 1, final_device_name); + ret = alloc_portal_dynamic_chrdev(&devt); } if (ret < 0) goto fail_alloc; @@ -661,7 +732,7 @@ void handle_op_devfs_create_device(portal_region *mem_region) pe->cdev.owner = THIS_MODULE; if (cdev_add(&pe->cdev, devt, 1)) { - unregister_chrdev_region(devt, 1); + if (fixed_chrdev_region) unregister_chrdev_region(devt, 1); goto fail_alloc; } @@ -678,7 +749,7 @@ void handle_op_devfs_create_device(portal_region *mem_region) list_del(&pe->list); spin_unlock(&devfs_entry_lock); cdev_del(&pe->cdev); - unregister_chrdev_region(devt, 1); + if (fixed_chrdev_region) unregister_chrdev_region(devt, 1); goto fail_alloc; } } From 0547f0acb5fe8001344105ce2198ae6f77df5976 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Tue, 26 May 2026 22:43:30 -0400 Subject: [PATCH 2/2] Drop unused task switch hypercall constant --- src/igloo_hypercall_consts.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/igloo_hypercall_consts.h b/src/igloo_hypercall_consts.h index cd40961..dcce71e 100644 --- a/src/igloo_hypercall_consts.h +++ b/src/igloo_hypercall_consts.h @@ -31,7 +31,6 @@ enum igloo_hypercall_constants { IGLOO_HYP_SYSCALL_RETURN = 0x1339, IGLOO_HYP_SETUP_TASK_COMM = 0x133a, IGLOO_HYP_SIGNAL_DELIVER = 0x133b, - IGLOO_HYP_OSI_TASK_SWITCH = 0x3337, /* Uprobe operations */ IGLOO_HYP_UPROBE_ENTER = 0x6901, @@ -51,4 +50,4 @@ enum igloo_hypercall_constants { IGLOO_SYSCALL = 0x6408400B, IGLOO_MODULE_BASE = 0x6408400C, IGLOO_INIT_MODULE = 0x6408400D, -}; \ No newline at end of file +};