Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/igloo_hypercall_consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -51,4 +50,4 @@ enum igloo_hypercall_constants {
IGLOO_SYSCALL = 0x6408400B,
IGLOO_MODULE_BASE = 0x6408400C,
IGLOO_INIT_MODULE = 0x6408400D,
};
};
97 changes: 84 additions & 13 deletions src/portal/portal_devfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/list.h>
#include <linux/atomic.h>
#include <linux/mutex.h>
#include <linux/version.h>
#include <linux/kallsyms.h>
#include <linux/file.h> // Required for fput()
Expand Down Expand Up @@ -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
* -------------------------------------------------------------------------
Expand Down Expand Up @@ -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)
* -------------------------------------------------------------------------
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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;
}
}
Expand Down
Loading