Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Sep 2006 12:09:21 GMT
From:      Alexander Leidinger <netchild@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 106547 for review
Message-ID:  <200609231209.k8NC9LKZ054036@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=106547

Change 106547 by netchild@netchild_magellan on 2006/09/23 12:09:15

	1. Flexible on-demand linking to FreeBSD native AIO module. Only when
	   linux_io_xxx() is called will native AIO module be loaded.
	2. Only two symbols "aio_init_aioinfo" and "aio_aqueue" of the native
	   AIO module need to be exported.
	Submitted by:	Intron <mag@intron.ac>
	Requested by:	netchild (something similar to 1)

Affected files ...

.. //depot/projects/linuxolator/src/sys/compat/linux/linux_aio.c#5 edit
.. //depot/projects/linuxolator/src/sys/kern/vfs_aio.c#3 edit
.. //depot/projects/linuxolator/src/sys/modules/aio/Makefile#3 edit

Differences ...

==== //depot/projects/linuxolator/src/sys/compat/linux/linux_aio.c#5 (text+ko) ====

@@ -44,6 +44,9 @@
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/sx.h>
+#include <sys/linker.h>
+#include <sys/sysctl.h>
+#include <sys/syscall.h>
 #include <sys/sysproto.h>
 
 #ifdef COMPAT_LINUX32
@@ -190,13 +193,13 @@
  */
 #define	LINUX_AIO_LOCK(p)	{					\
 	if ((p)->p_aioinfo == NULL)					\
-		aio_init_aioinfo(p);					\
+		p_aio_init_aioinfo(p);					\
 	mtx_lock((struct mtx *)((p)->p_aioinfo));			\
 }
 
 #define	LINUX_AIO_UNLOCK(p)	{					\
 	if ((p)->p_aioinfo == NULL)					\
-		aio_init_aioinfo(p);					\
+		p_aio_init_aioinfo(p);					\
 	mtx_unlock((struct mtx *)((p)->p_aioinfo));			\
 }
 
@@ -211,18 +214,43 @@
  * which is NOT a normal calling way and can cause kernel crash.
  */
 
-/* Variables in /sys/kern/vfs_aio.c, XXX defined with "static" */
-extern int max_aio_queue_per_proc; /* sysctl */
-extern int max_queue_count; /* sysctl */
+#define	NATIVE_AIO_MODULE_NAME		"aio"
+static struct mod_depend native_aio_module_depend = {1, 1, 1};
+static linker_file_t native_aio_module_handle = NULL;
+
+/* Mirror of sysctls in /sys/kern/vfs_aio.c */
+#define	NATIVE_AIO_SYSCTL_CAPACITY_PROC	"vfs.aio.max_aio_queue_per_proc"
+static int native_aio_capacity_proc;
+#define	NATIVE_AIO_SYSCTL_CAPACITY_SYS	"vfs.aio.max_aio_queue"
+static int native_aio_capacity_sys;
 
 /* For declaration of aio_aqueue(), defined in /sys/kern/vfs_aio.c */
 struct aioliojob;
 
 /* Functions in /sys/kern/vfs_aio.c, XXX defined with "static" */
-extern void	aio_init_aioinfo(struct proc *p);
-extern int	aio_aqueue(struct thread *td, struct aiocb *job,
+#define	GET_INTERNAL_FUNC_POINTER(s)	{				\
+	* ((caddr_t *) & p_ ## s) = linker_file_lookup_symbol(		\
+			native_aio_module_handle, #s, FALSE);		\
+	if (p_ ## s == NULL)						\
+		break;							\
+}
+static void (*p_aio_init_aioinfo) (struct proc *p);
+static int (*p_aio_aqueue) (struct thread *td, struct aiocb *job,
 			struct aioliojob *lio, int type, int osigev);
 
+/* System calls in /sys/kern/vfs_aio.c */
+#define	DEFINE_SYSCALL_POINTER_VARIABLE(s)				\
+	static int (* p_ ## s) (struct thread *, struct s ## _args *)
+#define	GET_SYSCALL_POINTER(s)		{				\
+	* ((sy_call_t **) & p_ ## s) = sysent[SYS_ ## s].sy_call;	\
+	if ((sy_call_t *) p_ ## s == (sy_call_t *)lkmressys)		\
+		break;							\
+}
+DEFINE_SYSCALL_POINTER_VARIABLE(aio_return);
+DEFINE_SYSCALL_POINTER_VARIABLE(aio_suspend);
+DEFINE_SYSCALL_POINTER_VARIABLE(aio_cancel);
+DEFINE_SYSCALL_POINTER_VARIABLE(aio_error);
+
 static int user_mem_rw_verify(void *p, size_t s)
 {
 	char buf[256];
@@ -394,6 +422,87 @@
 	return nerr;
 }
 
+static int link_to_native_aio_module(struct thread *td)
+{
+	int nerr;
+
+	if (native_aio_module_handle != NULL)
+	{ /* Linking has been done successfully. */
+		
+		return 0;
+	}
+
+	nerr = linker_reference_module(NATIVE_AIO_MODULE_NAME,
+			&native_aio_module_depend, &native_aio_module_handle);
+	if (nerr)
+		return nerr;
+
+	do {
+		nerr = EINVAL;
+
+		/* Kernel internal functions */
+		GET_INTERNAL_FUNC_POINTER(aio_init_aioinfo);
+		GET_INTERNAL_FUNC_POINTER(aio_aqueue);
+
+		/* System calls */
+		GET_SYSCALL_POINTER(aio_return);
+		GET_SYSCALL_POINTER(aio_suspend);
+		GET_SYSCALL_POINTER(aio_cancel);
+		GET_SYSCALL_POINTER(aio_error);
+
+		nerr = 0;
+	} while (0);
+
+	if (nerr)
+	{
+		linker_release_module(NULL, NULL, native_aio_module_handle);
+		native_aio_module_handle = NULL;
+		
+		printf(LMSG("Unable to link to the native module \""
+				NATIVE_AIO_MODULE_NAME "\" correctly."));
+		
+		return nerr;
+	}
+
+	return 0;
+}
+
+#define	LINK_TO_NATIVE_AIO_MODULE()					\
+	if (link_to_native_aio_module(td)) {				\
+		printf(LMSG("Please load the correct module \""		\
+			NATIVE_AIO_MODULE_NAME "\" correctly "		\
+			"to provide FreeBSD "				\
+			"native Asynchronous I/O support."));		\
+		return ENOSYS;						\
+}
+
+static int mirror_native_aio_sysctl(struct thread *td)
+{
+	int nerr = 0;
+	int l;
+
+	l = sizeof(native_aio_capacity_proc);
+	nerr = kernel_sysctlbyname(td, NATIVE_AIO_SYSCTL_CAPACITY_PROC,
+			&native_aio_capacity_proc, &l, NULL, 0,
+			NULL ,0);
+	if (nerr)
+		return nerr;
+
+	l = sizeof(native_aio_capacity_sys);
+	nerr = kernel_sysctlbyname(td, NATIVE_AIO_SYSCTL_CAPACITY_SYS,
+			&native_aio_capacity_sys, &l, NULL, 0,
+			NULL ,0);
+	if (nerr)
+		return nerr;
+
+	DPRINTF(NATIVE_AIO_SYSCTL_CAPACITY_PROC "=%d, "
+			NATIVE_AIO_SYSCTL_CAPACITY_SYS "=%d",
+			native_aio_capacity_proc,
+			native_aio_capacity_sys);
+
+	return nerr;
+}
+
 /* Linux system call io_setup(2) */
 int linux_io_setup(struct thread *td, struct linux_io_setup_args *args)
 {
@@ -404,18 +513,29 @@
 	int nerr = 0, nr, nrall, nq, arg_nr_reqs;
 
 	DARGPRINTF("%u, %p", args->nr_reqs, args->ctxp);
+	LINK_TO_NATIVE_AIO_MODULE();
+	nerr = mirror_native_aio_sysctl(td);
+	if (nerr)
+	{
+		printf(LMSG("linux_io_setup(): Unable to query sysctls "
+			       NATIVE_AIO_SYSCTL_CAPACITY_PROC
+			       " and/or " NATIVE_AIO_SYSCTL_CAPACITY_SYS
+			       " ."));
+		return nerr;
+	}
 
 	/* Signed integer is a little safer than unsigned */
 	arg_nr_reqs = args->nr_reqs;
 	if (arg_nr_reqs <= 0)
 		return EINVAL;
 
-	if (arg_nr_reqs > max_aio_queue_per_proc
-			|| arg_nr_reqs > max_queue_count)
+	if (arg_nr_reqs > native_aio_capacity_proc
+			|| arg_nr_reqs > native_aio_capacity_sys)
 	{
 		printf(LMSG("linux_io_setup(): Please increase sysctls "
-			       "vfs.aio.max_aio_queue_per_proc "
-			       "and/or vfs.aio.max_aio_queue. "));
+			       NATIVE_AIO_SYSCTL_CAPACITY_PROC
+			       " and/or " NATIVE_AIO_SYSCTL_CAPACITY_SYS
+			       " ."));
 		return ENOMEM;
 	}
 
@@ -455,12 +575,12 @@
 		nq, nr, nrall);
 
 	/* Check whether there are enough resources for requested queue */
-	if (arg_nr_reqs > max_aio_queue_per_proc - nr
-			|| arg_nr_reqs > max_queue_count - nrall) {
+	if (arg_nr_reqs > native_aio_capacity_proc - nr
+			|| arg_nr_reqs > native_aio_capacity_sys - nrall) {
 		printf(LMSG("linux_io_setup(): "
 			       "Please increase sysctls "
-			       "vfs.aio.max_aio_queue_per_proc "
-			       "and/or vfs.aio.max_aio_queue. "
+			       NATIVE_AIO_SYSCTL_CAPACITY_PROC
+			       " and/or " NATIVE_AIO_SYSCTL_CAPACITY_SYS " ."
 			       "Besides %d queues of %d requests totally "
 			       "for this process, and %d requests' queues "
 			       "totally for the whole system, "
@@ -519,6 +639,7 @@
 	struct aio_return_args aioretargs;
 
 	DARGPRINTF("%lx", (unsigned long)args->ctx);
+	LINK_TO_NATIVE_AIO_MODULE();
 
 	p = td->td_proc;
 
@@ -570,7 +691,7 @@
 		/* Cancel FreeBSD native clone */
 		cancelargs.fd = preq->req_linux.aio_fildes;
 		cancelargs.aiocbp = preq->req_pbsd;
-		aio_cancel(td, &cancelargs);
+		p_aio_cancel(td, &cancelargs);
 		DPRINTF("aio_cancel() returned %ld", (long)td->td_retval[0]);
 		if (td->td_retval[0] == AIO_NOTCANCELED)
 			printf(LMSG("linux_io_destroy(): Asynchronous IO "
@@ -584,7 +705,7 @@
 
 		if (td->td_retval[0] == AIO_ALLDONE) {
 			aioretargs.aiocbp = preq->req_pbsd;
-			aio_return(td, &aioretargs);
+			p_aio_return(td, &aioretargs);
 			DPRINTF("aio_return(%p) returned %ld",
 					aioretargs.aiocbp,
 					(long)td->td_retval[0]);
@@ -640,6 +761,7 @@
 			(unsigned long) args->ctx_id,
 			(long)args->min_nr, (long)args->nr,
 			args->events, args->timeout);
+	LINK_TO_NATIVE_AIO_MODULE();
 
 	if (args->nr <= 0)
 		return EINVAL;
@@ -731,7 +853,7 @@
 					break;
 
 				aioerrargs.aiocbp = preq->req_pbsd;
-				aio_error(td, &aioerrargs);
+				p_aio_error(td, &aioerrargs);
 				aio_ret = td->td_retval[0];
 				td->td_retval[0] = 0;
 
@@ -750,7 +872,7 @@
 				LINUX_AIO_REQ_UNHOOK(pctx, preq);
 
 				aioretargs.aiocbp = preq->req_pbsd;
-				aio_err = aio_return(td, &aioretargs);
+				aio_err = p_aio_return(td, &aioretargs);
 				aio_ret = td->td_retval[0];
 				td->td_retval[0] = 0;
 
@@ -846,7 +968,7 @@
 				aiosusargs.timeout = NULL;
 			}
 
-			aio_err = aio_suspend(td, &aiosusargs);
+			aio_err = p_aio_suspend(td, &aiosusargs);
 			DPRINTF("aio_suspend(%p, %d, %p) returned %ld",
 					aiosusargs.aiocbp, aiosusargs.nent,
 					aiosusargs.timeout, (long)aio_err);
@@ -911,7 +1033,9 @@
 	struct linux_iocb *porig;
 	struct aiocb iocb, *piocb;
 
-	DARGPRINTF("%lx, %ld, %p", (unsigned long)args->ctx_id, (long)args->nr, args->iocbpp);
+	DARGPRINTF("%lx, %ld, %p", (unsigned long)args->ctx_id,
+			(long)args->nr, args->iocbpp);
+	LINK_TO_NATIVE_AIO_MODULE();
 
 	if(args->nr <= 0)
 		return EINVAL;
@@ -977,7 +1101,7 @@
 		DUMP_FREEBSD_AIOCB(piocb, 1);
 
 		/* Submit user space control block */
-		nerr = aio_aqueue(td, piocb, NULL, iocb.aio_lio_opcode, 0);
+		nerr = p_aio_aqueue(td, piocb, NULL, iocb.aio_lio_opcode, 0);
 		if (nerr != 0) {
 			user_free(td, piocb, sizeof(*piocb));
 			break;
@@ -1022,7 +1146,9 @@
 	struct linux_io_event evt;
 	struct aio_cancel_args aiocnclargs;
 
-	DARGPRINTF("%lx, %p, %p", (unsigned long)args->ctx_id, args->iocb, args->result);
+	DARGPRINTF("%lx, %p, %p", (unsigned long)args->ctx_id,
+			args->iocb, args->result);
+	LINK_TO_NATIVE_AIO_MODULE();
 
 	nerr = copyin(args->iocb, &lcb, sizeof(lcb));
 	if (nerr != 0)
@@ -1086,7 +1212,7 @@
 		/* Cancel FreeBSD native clone */
 		aiocnclargs.fd = preq->req_linux.aio_fildes;
 		aiocnclargs.aiocbp = preq->req_pbsd;
-		aio_cancel(td, &aiocnclargs);
+		p_aio_cancel(td, &aiocnclargs);
 		DPRINTF("aio_cancel() returned %ld", (long)td->td_retval[0]);
 
 		if (td->td_retval[0] == AIO_CANCELED) {
@@ -1204,6 +1330,16 @@
 		mtx_destroy(&linux_aio_context_list_mtx);
 		uma_zdestroy(linux_aio_request_zone);
 		uma_zdestroy(linux_aio_context_zone);
+		if (native_aio_module_handle != NULL)
+		{
+			/*
+			 * linker_release_module() cannot be used here.
+			 * It tries to hold "kld_sx", conflicting against
+			 * module_unload().
+			 */
+			linker_file_unload(native_aio_module_handle,
+				LINKER_UNLOAD_NORMAL);
+		}
 		break;
 	case MOD_SHUTDOWN:
 		break;
@@ -1221,4 +1357,3 @@
 };
 
 DECLARE_MODULE(linuxaio, linux_aio_mod, SI_SUB_VFS, SI_ORDER_ANY);
-MODULE_DEPEND(linuxaio, aio, 1, 1, 1);

==== //depot/projects/linuxolator/src/sys/kern/vfs_aio.c#3 (text+ko) ====

@@ -139,7 +139,7 @@
 SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs, CTLFLAG_RW, &target_aio_procs,
 	0, "Preferred number of ready kernel threads for async IO");
 
-int max_queue_count = MAX_AIO_QUEUE;
+static int max_queue_count = MAX_AIO_QUEUE;
 SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue, CTLFLAG_RW, &max_queue_count, 0,
     "Maximum number of aio requests to queue, globally");
 
@@ -172,7 +172,7 @@
 SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, CTLFLAG_RW, &max_aio_per_proc,
     0, "Maximum active aio requests per process (stored in the process)");
 
-int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC;
+static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC;
 SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc, CTLFLAG_RW,
     &max_aio_queue_per_proc, 0,
     "Maximum queued aio requests per process (stored in the process)");

==== //depot/projects/linuxolator/src/sys/modules/aio/Makefile#3 (text+ko) ====

@@ -5,8 +5,6 @@
 KMOD=	aio
 SRCS=	vfs_aio.c opt_vfs_aio.h vnode_if.h
 
-EXPORT_SYMS= max_aio_queue_per_proc max_queue_count \
-	aio_init_aioinfo aio_aqueue aio_suspend \
-	aio_cancel aio_return aio_error
+EXPORT_SYMS= aio_init_aioinfo aio_aqueue
 
 .include <bsd.kmod.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609231209.k8NC9LKZ054036>