Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Oct 2010 08:57:02 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r213380 - stable/8/sys/nfsclient
Message-ID:  <201010030857.o938v2Hx069355@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Oct  3 08:57:02 2010
New Revision: 213380
URL: http://svn.freebsd.org/changeset/base/213380

Log:
  MFC r212506:
  Do not fork nfsiod directly from the vop methods.
  Schedule the task that performs fork to be executed in
  the taskqueue context.

Modified:
  stable/8/sys/nfsclient/nfs.h
  stable/8/sys/nfsclient/nfs_nfsiod.c
  stable/8/sys/nfsclient/nfs_subs.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/nfsclient/nfs.h
==============================================================================
--- stable/8/sys/nfsclient/nfs.h	Sun Oct  3 08:12:17 2010	(r213379)
+++ stable/8/sys/nfsclient/nfs.h	Sun Oct  3 08:57:02 2010	(r213380)
@@ -125,6 +125,7 @@ extern struct uma_zone *nfsmount_zone;
 
 extern struct nfsstats nfsstats;
 extern struct mtx nfs_iod_mtx;
+extern struct task nfs_nfsiodnew_task;
 
 extern int nfs_numasync;
 extern unsigned int nfs_iodmax;
@@ -253,6 +254,7 @@ int	nfs_commit(struct vnode *vp, u_quad_
 	    struct ucred *cred, struct thread *td);
 int	nfs_readdirrpc(struct vnode *, struct uio *, struct ucred *);
 int	nfs_nfsiodnew(int);
+void	nfs_nfsiodnew_tq(__unused void *, int);
 int	nfs_asyncio(struct nfsmount *, struct buf *, struct ucred *, struct thread *);
 int	nfs_doio(struct vnode *, struct buf *, struct ucred *, struct thread *);
 void	nfs_doio_directwrite (struct buf *);

Modified: stable/8/sys/nfsclient/nfs_nfsiod.c
==============================================================================
--- stable/8/sys/nfsclient/nfs_nfsiod.c	Sun Oct  3 08:12:17 2010	(r213379)
+++ stable/8/sys/nfsclient/nfs_nfsiod.c	Sun Oct  3 08:57:02 2010	(r213380)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/fcntl.h>
 #include <sys/lockf.h>
 #include <sys/mutex.h>
+#include <sys/taskqueue.h>
 
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -75,6 +76,16 @@ static MALLOC_DEFINE(M_NFSSVC, "nfsclien
 
 static void	nfssvc_iod(void *);
 
+struct nfsiod_str {
+	STAILQ_ENTRY(nfsiod_str) ni_links;
+	int *ni_inst;
+	int ni_iod;
+	int ni_error;
+	int ni_done;
+};
+static STAILQ_HEAD(, nfsiod_str) nfsiodhead =
+    STAILQ_HEAD_INITIALIZER(nfsiodhead);
+
 static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
 
 SYSCTL_DECL(_vfs_nfs);
@@ -159,11 +170,30 @@ SYSCTL_PROC(_vfs_nfs, OID_AUTO, iodmax, 
     sizeof (nfs_iodmax), sysctl_iodmax, "IU",
     "Max number of nfsiod kthreads");
 
+void
+nfs_nfsiodnew_tq(__unused void *arg, int pending)
+{
+	struct nfsiod_str *nip;
+
+	mtx_lock(&nfs_iod_mtx);
+	while ((nip = STAILQ_FIRST(&nfsiodhead)) != NULL) {
+		STAILQ_REMOVE_HEAD(&nfsiodhead, ni_links);
+		mtx_unlock(&nfs_iod_mtx);
+		nip->ni_error = kproc_create(nfssvc_iod, nip->ni_inst, NULL,
+		    RFHIGHPID, 0, "nfsiod %d", nip->ni_iod);
+		nip->ni_done = 1;
+		mtx_lock(&nfs_iod_mtx);
+		wakeup(nip);
+	}
+	mtx_unlock(&nfs_iod_mtx);
+}
+
 int
 nfs_nfsiodnew(int set_iodwant)
 {
 	int error, i;
 	int newiod;
+	struct nfsiod_str *nip;
 
 	if (nfs_numasync >= nfs_iodmax)
 		return (-1);
@@ -179,9 +209,16 @@ nfs_nfsiodnew(int set_iodwant)
 	if (set_iodwant > 0)
 		nfs_iodwant[i] = NFSIOD_CREATED_FOR_NFS_ASYNCIO;
 	mtx_unlock(&nfs_iod_mtx);
-	error = kproc_create(nfssvc_iod, nfs_asyncdaemon + i, NULL, RFHIGHPID,
-	    0, "nfsiod %d", newiod);
+	nip = malloc(sizeof(*nip), M_TEMP, M_WAITOK | M_ZERO);
+	nip->ni_inst = nfs_asyncdaemon + i;
+	nip->ni_iod = newiod;
 	mtx_lock(&nfs_iod_mtx);
+	STAILQ_INSERT_TAIL(&nfsiodhead, nip, ni_links);
+	taskqueue_enqueue(taskqueue_thread, &nfs_nfsiodnew_task);
+	while (!nip->ni_done)
+		mtx_sleep(nip, &nfs_iod_mtx, 0, "niwt", 0);
+	error = nip->ni_error;
+	free(nip, M_TEMP);
 	if (error) {
 		if (set_iodwant > 0)
 			nfs_iodwant[i] = NFSIOD_NOT_AVAILABLE;

Modified: stable/8/sys/nfsclient/nfs_subs.c
==============================================================================
--- stable/8/sys/nfsclient/nfs_subs.c	Sun Oct  3 08:12:17 2010	(r213379)
+++ stable/8/sys/nfsclient/nfs_subs.c	Sun Oct  3 08:57:02 2010	(r213380)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysent.h>
 #include <sys/syscall.h>
 #include <sys/sysproto.h>
+#include <sys/taskqueue.h>
 
 #include <vm/vm.h>
 #include <vm/vm_object.h>
@@ -117,6 +118,7 @@ int		nfs_pbuf_freecnt = -1;	/* start out
 
 struct nfs_bufq	nfs_bufq;
 static struct mtx nfs_xid_mtx;
+struct task	nfs_nfsiodnew_task;
 
 /*
  * and the reverse mapping from generic to Version 2 procedure numbers
@@ -354,6 +356,7 @@ nfs_init(struct vfsconf *vfsp)
 	 */
 	mtx_init(&nfs_iod_mtx, "NFS iod lock", NULL, MTX_DEF);
 	mtx_init(&nfs_xid_mtx, "NFS xid lock", NULL, MTX_DEF);
+	TASK_INIT(&nfs_nfsiodnew_task, 0, nfs_nfsiodnew_tq, NULL);
 
 	nfs_pbuf_freecnt = nswbuf / 2 + 1;
 
@@ -368,9 +371,13 @@ nfs_uninit(struct vfsconf *vfsp)
 	/*
 	 * Tell all nfsiod processes to exit. Clear nfs_iodmax, and wakeup
 	 * any sleeping nfsiods so they check nfs_iodmax and exit.
+	 * Drain nfsiodnew task before we wait for them to finish.
 	 */
 	mtx_lock(&nfs_iod_mtx);
 	nfs_iodmax = 0;
+	mtx_unlock(&nfs_iod_mtx);
+	taskqueue_drain(taskqueue_thread, &nfs_nfsiodnew_task);
+	mtx_lock(&nfs_iod_mtx);
 	for (i = 0; i < nfs_numasync; i++)
 		if (nfs_iodwant[i] == NFSIOD_AVAILABLE)
 			wakeup(&nfs_iodwant[i]);



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