]> git.saurik.com Git - apple/network_cmds.git/blobdiff - nfsiod.tproj/nfsiod.c
network_cmds-176.tar.gz
[apple/network_cmds.git] / nfsiod.tproj / nfsiod.c
index 07a87ffe908c94dc5551dae125ee6a67bb26ec0d..dfc48d004bcefa9571f7cba814f66cec8045013e 100644 (file)
@@ -1,23 +1,24 @@
 /*
- * 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@
  */
@@ -77,6 +78,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <string.h>
+#include <pthread.h>
 
 /* Global defs */
 #ifdef DEBUG
@@ -84,10 +87,13 @@ int debug = 1;
 #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.
@@ -100,18 +106,19 @@ main(argc, argv)
        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 '?':
@@ -129,12 +136,23 @@ main(argc, argv)
                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);
@@ -142,38 +160,75 @@ main(argc, argv)
                (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