/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
- * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License'). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
/* Global defs */
#ifdef DEBUG
#else
int debug = 0;
#endif
+int *thread_status = NULL;
+pthread_cond_t cond;
+pthread_mutex_t mutex;
void nonfs __P((int));
-void reapchild __P((int));
void usage __P((void));
+void *nfsiod_thread __P((void *));
/*
* Nfsiod does asynchronous buffered I/O on behalf of the NFS client.
char *argv[];
{
int ch, num_servers;
+ int i, rv, threadcnt;
-#define MAXNFSDCNT 20
-#define DEFNFSDCNT 1
- num_servers = DEFNFSDCNT;
+#define MAXNFSIODCNT 32
+#define DEFNFSIODCNT 1
+ num_servers = DEFNFSIODCNT;
while ((ch = getopt(argc, argv, "n:")) != EOF)
switch (ch) {
case 'n':
num_servers = atoi(optarg);
- if (num_servers < 1 || num_servers > MAXNFSDCNT) {
+ if (num_servers < 1 || num_servers > MAXNFSIODCNT) {
warnx("nfsiod count %d; reset to %d",
- DEFNFSDCNT);
- num_servers = DEFNFSDCNT;
+ num_servers, DEFNFSIODCNT);
+ num_servers = DEFNFSIODCNT;
}
break;
case '?':
usage();
if (argc == 1) {
num_servers = atoi(argv[0]);
- if (num_servers < 1 || num_servers > MAXNFSDCNT) {
- warnx("nfsiod count %d; reset to %d", DEFNFSDCNT);
- num_servers = DEFNFSDCNT;
+ if (num_servers < 1 || num_servers > MAXNFSIODCNT) {
+ warnx("nfsiod count %d; reset to %d",
+ num_servers, DEFNFSIODCNT);
+ num_servers = DEFNFSIODCNT;
}
}
+ thread_status = malloc(sizeof(int) * num_servers);
+ if (thread_status == NULL)
+ errx(1, "unable to allocate memory");
+ rv = pthread_cond_init(&cond, NULL);
+ if (rv)
+ errc(1, rv, "condition variable init failed");
+ rv = pthread_mutex_init(&mutex, NULL);
+ if (rv)
+ errc(1, rv, "mutex init failed");
+
if (debug == 0) {
daemon(0, 0);
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGSYS, nonfs);
}
- (void)signal(SIGCHLD, reapchild);
openlog("nfsiod:", LOG_PID, LOG_DAEMON);
- while (num_servers--)
- switch (fork()) {
- case -1:
- syslog(LOG_ERR, "fork: %m");
- exit (1);
- case 0:
- if (nfssvc(NFSSVC_BIOD, NULL) < 0) {
- syslog(LOG_ERR, "nfssvc: %m");
- exit (1);
- }
- exit(0);
+ threadcnt = 0;
+ for (i=0; i < num_servers; i++) {
+ pthread_t thd;
+ thread_status[i] = 1;
+ rv = pthread_create(&thd, NULL, nfsiod_thread, (void*)i);
+ if (rv) {
+ syslog(LOG_ERR, "thread_create: %s", strerror(rv));
+ thread_status[i] = 0;
+ continue;
+ }
+ threadcnt++;
+ }
+ /* if no threads started exit */
+ if (!threadcnt)
+ errx(1, "unable to start any threads");
+ if (threadcnt != num_servers)
+ syslog(LOG_ERR, "only able to create %d of %d threads",
+ threadcnt, num_servers);
+
+ /* wait for threads to complete */
+ rv = pthread_mutex_lock(&mutex);
+ if (rv)
+ errc(1, rv, "mutex lock failed");
+ while (threadcnt > 0) {
+ rv = pthread_cond_wait(&cond, &mutex);
+ if (rv)
+ errc(1, rv, "nfsiod: cond wait failed");
+ for (i=0; i < num_servers; i++) {
+ if (!thread_status[i])
+ continue;
+ if (thread_status[i] == 1)
+ continue;
+ threadcnt--;
+ thread_status[i] = 0;
+ syslog(LOG_ERR, "lost nfsiod thread %d - "
+ "%d of %d threads remain",
+ i, threadcnt, num_servers);
}
+ rv = pthread_mutex_lock(&mutex);
+ if (rv)
+ errc(1, rv, "mutex lock failed");
+ }
+
exit (0);
}
-void
-nonfs(signo)
- int signo;
+void *
+nfsiod_thread(void *arg)
{
- syslog(LOG_ERR, "missing system call: NFS not available.");
+ int rv, thread = (int)arg;
+ if ((rv = nfssvc(NFSSVC_BIOD, NULL)) < 0) {
+ thread_status[thread] = rv;
+ syslog(LOG_ERR, "nfssvc: %s", strerror(rv));
+ pthread_cond_signal(&cond);
+ return NULL;
+ }
+ thread_status[thread] = 0;
+ pthread_cond_signal(&cond);
+ return NULL;
}
void
-reapchild(signo)
+nonfs(signo)
int signo;
{
-
- while (wait3(NULL, WNOHANG, NULL));
+ syslog(LOG_ERR, "missing system call: NFS not available.");
}
void