[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: