Re: active swapping using rumpdisk
On 30/08/2025 08:53, Samuel Thibault wrote:
Michael Kelly, le sam. 30 août 2025 08:43:04 +0100, a ecrit:
I've realised that the mig types and the C types each need separate
declarations so would you prefer a 'mach_port_ktype_t' typedef used for the
'ktype' argument or just leave it as unsigned?
Better use an explicit type.
Here are the revisions. Please make any minor adjustments that you think
are necessary (for example to the warning message) but hopefully these
patches will close this thread.
Regards,
Mike.
diff -ur hurd.git.sceen.net/rumpdisk/block-rump.c hurd/rumpdisk/block-rump.c
--- hurd.git.sceen.net/rumpdisk/block-rump.c 2025-07-31 20:36:06.014917781 +0100
+++ hurd/rumpdisk/block-rump.c 2025-08-30 09:43:54.447020534 +0100
@@ -27,6 +27,7 @@
#include <mach.h>
#include <mach/gnumach.h>
+#include <mach/port.h>
#include <hurd.h>
#include <hurd/ports.h>
#include <device/device.h>
@@ -329,6 +330,25 @@
return err;
}
+ /* Configure the receive port as a USER_DEVICE so that IPC messages
+ destined for rumpdisk will use page lists rather than page map
+ entries. This strategy prevents pages that are referenced in the
+ message body from being swapped out until the message has been
+ processed.
+ */
+ err = mach_port_set_ktype (master_host,
+ mach_task_self (),
+ bd->port.port_right,
+ MACH_PORT_RIGHT_RECEIVE,
+ MACH_PORT_KTYPE_USER_DEVICE);
+ if (err != 0)
+ {
+ fprintf (stderr,
+ "Warning: No USER_DEVICE (swapping will be unreliable): %s\n",
+ strerror (err));
+ fflush (stderr);
+ }
+
bd->taken = 1;
snprintf (bd->name, DISK_NAME_LEN, "%s", name);
bd->rump_fd = fd;
diff -ur gnumach.git.sceen.net/include/mach/mach_port.defs gnumach/include/mach/mach_port.defs
--- gnumach.git.sceen.net/include/mach/mach_port.defs 2025-07-31 20:34:14.836151975 +0100
+++ gnumach/include/mach/mach_port.defs 2025-08-30 03:15:54.370406673 +0100
@@ -358,3 +358,21 @@
routine mach_port_clear_protected_payload(
task : ipc_space_t;
name : mach_port_name_t);
+
+/*
+ * Set the kernel port type for specific kernel behaviour.
+ * ktype must be one of:
+ * MACH_PORT_KTYPE_NONE
+ * MACH_PORT_KTYPE_USER_DEVICE
+ * The named port must not be currently associated with any
+ * other kernel port type.
+ */
+
+type mach_port_ktype_t = unsigned;
+
+routine mach_port_set_ktype(
+ host : host_priv_t;
+ task : ipc_space_t;
+ name : mach_port_name_t;
+ right : mach_port_right_t;
+ ktype : mach_port_ktype_t);
diff -ur gnumach.git.sceen.net/include/mach/port.h gnumach/include/mach/port.h
--- gnumach.git.sceen.net/include/mach/port.h 2025-07-31 20:34:14.836151975 +0100
+++ gnumach/include/mach/port.h 2025-08-30 03:06:12.571747428 +0100
@@ -156,4 +156,10 @@
#define MACH_PORT_QLIMIT_DEFAULT ((mach_port_msgcount_t) 5)
#define MACH_PORT_QLIMIT_MAX ((mach_port_msgcount_t) 16)
+typedef unsigned int mach_port_ktype_t;
+
+/* Constants for calls to mach_port_set_ktype() */
+#define MACH_PORT_KTYPE_NONE 0
+#define MACH_PORT_KTYPE_USER_DEVICE 28
+
#endif /* _MACH_PORT_H_ */
diff -ur gnumach.git.sceen.net/ipc/ipc_object.c gnumach/ipc/ipc_object.c
--- gnumach.git.sceen.net/ipc/ipc_object.c 2025-07-31 20:34:14.840151931 +0100
+++ gnumach/ipc/ipc_object.c 2025-08-17 22:48:01.000000000 +0100
@@ -944,6 +944,7 @@
"(CLOCK) ",
"(CLOCK_CTRL) ",
"(PAGER_PROXY) ", /* 27 */
+ "(USER_DEVICE) ", /* 28 */
/* << new entries here */
"(UNKNOWN) " /* magic catchall */
}; /* Please keep in sync with kern/ipc_kobject.h */
diff -ur gnumach.git.sceen.net/ipc/mach_port.c gnumach/ipc/mach_port.c
--- gnumach.git.sceen.net/ipc/mach_port.c 2025-07-31 20:34:14.844151887 +0100
+++ gnumach/ipc/mach_port.c 2025-08-30 09:22:34.006764651 +0100
@@ -1567,6 +1567,45 @@
return KERN_SUCCESS;
}
+kern_return_t
+mach_port_set_ktype(
+ host_t host_priv,
+ ipc_space_t space,
+ mach_port_name_t name,
+ mach_port_right_t right,
+ mach_port_ktype_t ktype)
+{
+ ipc_port_t port;
+ kern_return_t kr;
+
+ if (host_priv == HOST_NULL)
+ return KERN_INVALID_HOST;
+
+ if (space == IS_NULL)
+ return KERN_INVALID_TASK;
+
+ if (ktype != MACH_PORT_KTYPE_NONE
+ && ktype != MACH_PORT_KTYPE_USER_DEVICE)
+ return KERN_INVALID_ARGUMENT;
+
+ kr = ipc_object_translate(space, name, right, (ipc_object_t *)&port);
+ if (kr != KERN_SUCCESS)
+ return kr;
+
+ /* port is locked and active */
+ if (ip_kotype(port) == IKOT_NONE || ip_kotype(port) == IKOT_USER_DEVICE)
+ ipc_kobject_set(port, IKO_NULL,
+ ktype == MACH_PORT_KTYPE_NONE
+ ? IKOT_NONE
+ : IKOT_USER_DEVICE);
+ else
+ kr = KERN_INVALID_ARGUMENT;
+
+ ip_unlock(port);
+
+ return kr;
+}
+
#if MACH_KDB
void
diff -ur gnumach.git.sceen.net/kern/ipc_kobject.h gnumach/kern/ipc_kobject.h
--- gnumach.git.sceen.net/kern/ipc_kobject.h 2025-07-31 20:34:14.844151887 +0100
+++ gnumach/kern/ipc_kobject.h 2025-08-18 07:10:15.378591611 +0100
@@ -77,9 +77,10 @@
#define IKOT_CLOCK 25
#define IKOT_CLOCK_CTRL 26
#define IKOT_PAGER_PROXY 27
+#define IKOT_USER_DEVICE 28
/* << new entries here */
-#define IKOT_UNKNOWN 28 /* magic catchall */
-#define IKOT_MAX_TYPE 29 /* # of IKOT_ types */
+#define IKOT_UNKNOWN 29 /* magic catchall */
+#define IKOT_MAX_TYPE 30 /* # of IKOT_ types */
/* Please keep ipc/ipc_object.c:ikot_print_array up to date */
#define is_ipc_kobject(ikot) (ikot != IKOT_NONE)
@@ -90,7 +91,9 @@
*/
#define ipc_kobject_vm_page_list(ikot) \
- ((ikot == IKOT_PAGING_REQUEST) || (ikot == IKOT_DEVICE))
+ ((ikot == IKOT_PAGING_REQUEST) || \
+ (ikot == IKOT_DEVICE) || \
+ (ikot == IKOT_USER_DEVICE))
#define ipc_kobject_vm_page_steal(ikot) (ikot == IKOT_PAGING_REQUEST)
Reply to: