dafs-20060317
[openafs.git] / src / viced / viced.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  *
9  * Portions Copyright (c) 2006 Sine Nomine Associates
10  */
11
12 /*  viced.c     - File Server main loop                                  */
13 /*                                                                       */
14 /*  Date: 5/1/85                                                         */
15 /*                                                                       */
16 /*  Function    - This routine has the initialization code for           */
17 /*                FileServer II                                          */
18 /*                                                                       */
19 /* ********************************************************************** */
20
21 #include <afsconfig.h>
22 #include <afs/param.h>
23
24 RCSID
25     ("$Header$");
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <afs/procmgmt.h>       /* signal(), kill(), wait(), etc. */
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #ifdef AFS_NT40_ENV
35 #include <io.h>
36 #include <windows.h>
37 #include <WINNT/afsevent.h>
38 #else
39 #include <sys/file.h>
40 #include <netinet/in.h>
41 #include <netdb.h>
42 #include <unistd.h>             /* sysconf() */
43
44 #ifdef HAVE_STRING_H
45 #include <string.h>
46 #else
47 #ifdef HAVE_STRINGS_H
48 #include <strings.h>
49 #endif
50 #endif
51
52 #ifndef ITIMER_REAL
53 #include <sys/time.h>
54 #endif /* ITIMER_REAL */
55 #include <sys/resource.h>
56 #endif /* AFS_NT40_ENV */
57 #include <afs/stds.h>
58 #undef SHARED
59 #include <rx/xdr.h>
60 #include <afs/nfs.h>
61 #ifdef AFS_PTHREAD_ENV
62 #include <assert.h>
63 #else /* AFS_PTHREAD_ENV */
64 #include <afs/assert.h>
65 #endif /* AFS_PTHREAD_ENV */
66 #include <lwp.h>
67 #include <lock.h>
68 #include <afs/ptclient.h>
69 #include <afs/afsint.h>
70 #include <afs/vldbint.h>
71 #include <afs/errors.h>
72 #include <afs/ihandle.h>
73 #include <afs/vnode.h>
74 #include <afs/volume.h>
75 #include <afs/auth.h>
76 #include <afs/cellconfig.h>
77 #include <afs/acl.h>
78 #include <afs/prs_fs.h>
79 #include <rx/rx.h>
80 #include <rx/rxkad.h>
81 #include <afs/keys.h>
82 #include <afs/afs_args.h>
83 #include <afs/vlserver.h>
84 #include <afs/afsutil.h>
85 #include <afs/fileutil.h>
86 #include <afs/ptuser.h>
87 #include <afs/audit.h>
88 #include <afs/partition.h>
89 #ifndef AFS_NT40_ENV
90 #include <afs/netutils.h>
91 #endif
92 #include "viced.h"
93 #include "host.h"
94 #ifdef AFS_PTHREAD_ENV
95 #include "softsig.h"
96 #endif
97 #if defined(AFS_SGI_ENV)
98 #include "sys/schedctl.h"
99 #include "sys/lock.h"
100 #endif
101 #include <rx/rx_globals.h>
102
103 #ifdef O_LARGEFILE
104 #define afs_stat        stat64
105 #define afs_fstat       fstat64
106 #define afs_open        open64
107 #define afs_fopen       fopen64
108 #else /* !O_LARGEFILE */
109 #define afs_stat        stat
110 #define afs_fstat       fstat
111 #define afs_open        open
112 #define afs_fopen       fopen
113 #endif /* !O_LARGEFILE */
114
115 extern int BreakVolumeCallBacks(), InitCallBack();
116 extern int BreakVolumeCallBacks(), InitCallBack(), BreakLaterCallBacks();
117 extern int BreakVolumeCallBacksLater();
118 extern int LogLevel, etext;
119 extern afs_int32 BlocksSpare, PctSpare;
120
121 int ShutDown(void);
122 static void ClearXStatValues(), NewParms(), PrintCounters();
123 static void ResetCheckDescriptors(void), ResetCheckSignal(void);
124 static int CheckSignal(void);
125 extern int GetKeysFromToken();
126 extern int RXAFS_ExecuteRequest();
127 extern int RXSTATS_ExecuteRequest();
128 afs_int32 Do_VLRegisterRPC();
129
130 int eventlog = 0, rxlog = 0;
131 FILE *debugFile;
132 FILE *console = NULL;
133
134 #ifdef AFS_PTHREAD_ENV
135 pthread_mutex_t fsync_glock_mutex;
136 pthread_cond_t fsync_cond;
137 #else
138 char fsync_wait[1];
139 #endif /* AFS_PTHREAD_ENV */
140
141 #ifdef AFS_NT40_ENV
142 #define AFS_QUIETFS_ENV 1
143 #define NT_OPEN_MAX    1024     /* This is an arbitrary no. we came up with for 
144                                  * now. We hope this will be replaced by a more
145                                  * intelligent estimate later. */
146 #endif
147
148 int SystemId;                   /* ViceID of "Administrators" */
149 int SystemAnyUser;              /* Viceid of "System:AnyUser" */
150 prlist SystemAnyUserCPS;        /* CPS for "system:AnyUser */
151 int AnonymousID = 0;            /* ViceId of "Anonymous" */
152 prlist AnonCPS;                 /* CPS for "Anonymous" */
153
154 struct afsconf_dir *confDir;    /* Configuration dir object */
155
156 int restartMode = RESTART_ORDINARY;
157
158 int Testing = 0;                /* for ListViceInodes */
159
160 /*
161  * Home for the performance statistics.
162  */
163 struct afs_PerfStats afs_perfstats;
164
165 extern int LogLevel;
166 extern int Statistics;
167
168 int busyonrst = 1;
169 int timeout = 30;
170 int SawSpare;
171 int SawPctSpare;
172 int debuglevel = 0;
173 int printBanner = 0;
174 int rxJumbograms = 1;           /* default is to send and receive jumbograms. */
175 int rxMaxMTU = -1;
176 afs_int32 implicitAdminRights = PRSFS_LOOKUP;   /* The ADMINISTER right is 
177                                                  * already implied */
178 afs_int32 readonlyServer = 0;
179
180 int stack = 24;
181 int stackSize = 24000;
182 int fiveminutes = 300;          /* 5 minutes.  Change this for debugging only */
183 int CurrentConnections = 0;
184 int hostaclRefresh = 7200;      /* refresh host clients' acls every 2 hrs */
185 #if defined(AFS_SGI_ENV)
186 int SawLock;
187 #endif
188 time_t StartTime;
189
190 int rxpackets = 150;            /* 100 */
191 int nSmallVns = 400;            /* 200 */
192 int large = 400;                /* 200 */
193 int volcache = 400;             /* 400 */
194 int numberofcbs = 60000;        /* 60000 */
195 int lwps = 9;                   /* 6 */
196 int buffs = 90;                 /* 70 */
197 int novbc = 0;                  /* Enable Volume Break calls */
198 int busy_threshold = 600;
199 int abort_threshold = 10;
200 int udpBufSize = 0;             /* UDP buffer size for receive */
201 int sendBufSize = 16384;        /* send buffer size */
202
203 struct timeval tp;
204
205 /*
206  * FileServer's name and IP address, both network byte order and
207  * host byte order.
208  */
209 #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
210
211 char FS_HostName[128] = "localhost";
212 afs_uint32 FS_HostAddr_NBO;
213 afs_uint32 FS_HostAddr_HBO;
214 afs_uint32 FS_HostAddrs[ADDRSPERSITE], FS_HostAddr_cnt = 0, FS_registered = 0;
215 /* All addresses in FS_HostAddrs are in NBO */
216 afsUUID FS_HostUUID;
217
218 static void FlagMsg();
219
220 #ifdef AFS_DEMAND_ATTACH_FS
221 /*
222  * demand attach fs
223  * fileserver mode support
224  *
225  * during fileserver shutdown, we have to track the graceful shutdown of
226  * certain background threads before we are allowed to dump state to
227  * disk
228  */
229 struct fs_state fs_state = 
230     { FS_MODE_NORMAL, 
231       0, 
232       0, 
233       0, 
234       0,
235       { 1,1,1,1 },
236       PTHREAD_COND_INITIALIZER,
237       PTHREAD_RWLOCK_INITIALIZER
238     };
239 #endif /* AFS_DEMAND_ATTACH_FS */
240
241 /*
242  * Home for the performance statistics.
243  */
244
245 /* DEBUG HACK */
246 static int
247 CheckDescriptors()
248 {
249 #ifndef AFS_NT40_ENV
250     struct afs_stat status;
251     register int tsize = getdtablesize();
252     register int i;
253     for (i = 0; i < tsize; i++) {
254         if (afs_fstat(i, &status) != -1) {
255             printf("%d: dev %x, inode %u, length %u, type/mode %x\n", i,
256                    status.st_dev, status.st_ino, status.st_size,
257                    status.st_mode);
258         }
259     }
260     fflush(stdout);
261     ResetCheckDescriptors();
262     return 0;
263 #endif
264 }                               /*CheckDescriptors */
265
266
267 #ifdef AFS_PTHREAD_ENV
268 void
269 CheckSignal_Signal(x)
270 {
271     CheckSignal();
272 }
273
274 void
275 ShutDown_Signal(x)
276 {
277     ShutDown();
278 }
279
280 void
281 CheckDescriptors_Signal(x)
282 {
283     CheckDescriptors();
284 }
285 #else /* AFS_PTHREAD_ENV */
286 void
287 CheckSignal_Signal(x)
288 {
289     IOMGR_SoftSig(CheckSignal, 0);
290 }
291
292 void
293 ShutDown_Signal(x)
294 {
295     IOMGR_SoftSig(ShutDown, 0);
296 }
297
298 void
299 CheckDescriptors_Signal(x)
300 {
301     IOMGR_SoftSig(CheckDescriptors, 0);
302 }
303 #endif /* AFS_PTHREAD_ENV */
304
305 /* check whether caller is authorized to manage RX statistics */
306 int
307 fs_rxstat_userok(struct rx_call *call)
308 {
309     return afsconf_SuperUser(confDir, call, NULL);
310 }
311
312 static void
313 ResetCheckSignal(void)
314 {
315     int signo;
316
317 #if defined(AFS_HPUX_ENV)
318     signo = SIGPOLL;
319 #else
320 #if defined(AFS_NT40_ENV)
321     signo = SIGUSR2;
322 #else
323     signo = SIGXCPU;
324 #endif
325 #endif
326
327 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
328     softsig_signal(signo, CheckSignal_Signal);
329 #else
330     signal(signo, CheckSignal_Signal);
331 #endif
332 }
333
334 static void
335 ResetCheckDescriptors(void)
336 {
337 #ifndef AFS_NT40_ENV
338 #if defined(AFS_PTHREAD_ENV)
339     softsig_signal(SIGTERM, CheckDescriptors_Signal);
340 #else
341     (void)signal(SIGTERM, CheckDescriptors_Signal);
342 #endif
343 #endif
344 }
345
346 #if defined(AFS_PTHREAD_ENV)
347 char *
348 threadNum(void)
349 {
350     return pthread_getspecific(rx_thread_id_key);
351 }
352 #endif
353
354 /* proc called by rxkad module to get a key */
355 static int
356 get_key(char *arock, register afs_int32 akvno, char *akey)
357 {
358     /* find the key */
359     static struct afsconf_key tkey;
360     register afs_int32 code;
361
362     if (!confDir) {
363         ViceLog(0, ("conf dir not open\n"));
364         return 1;
365     }
366     code = afsconf_GetKey(confDir, akvno, tkey.key);
367     if (code) {
368         ViceLog(0, ("afsconf_GetKey failure: kvno %d code %d\n", akvno, code));
369         return code;
370     }
371     memcpy(akey, tkey.key, sizeof(tkey.key));
372     return 0;
373
374 }                               /*get_key */
375
376 #ifndef AFS_NT40_ENV
377 int
378 viced_syscall(afs_uint32 a3, afs_uint32 a4, void *a5)
379 {
380     afs_uint32 rcode;
381     void (*old) ();
382
383 #ifndef AFS_LINUX20_ENV
384     old = (void (*)())signal(SIGSYS, SIG_IGN);
385 #endif
386     rcode = syscall(AFS_SYSCALL, 28 /* AFSCALL_CALL */ , a3, a4, a5);
387 #ifndef AFS_LINUX20_ENV
388     signal(SIGSYS, old);
389 #endif
390
391     return rcode;
392 }
393 #endif
394
395 #if !defined(AFS_NT40_ENV)
396 #include "AFS_component_version_number.c"
397 #endif /* !AFS_NT40_ENV */
398
399 #define MAXADMINNAME 64
400 char adminName[MAXADMINNAME];
401
402 static void
403 CheckAdminName()
404 {
405     int fd = 0;
406     struct afs_stat status;
407
408     if ((afs_stat("/AdminName", &status)) ||    /* if file does not exist */
409         (status.st_size <= 0) ||        /* or it is too short */
410         (status.st_size >= (MAXADMINNAME)) ||   /* or it is too long */
411         !(fd = afs_open("/AdminName", O_RDONLY, 0))) {  /* or the open fails */
412         strcpy(adminName, "System:Administrators");     /* use the default name */
413     } else {
414         (void)read(fd, adminName, status.st_size);      /* use name from the file */
415     }
416     if (fd)
417         close(fd);              /* close fd if it was opened */
418
419 }                               /*CheckAdminName */
420
421
422 static void
423 setThreadId(char *s)
424 {
425 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
426     /* set our 'thread-id' so that the host hold table works */
427     MUTEX_ENTER(&rx_stats_mutex);       /* protects rxi_pthread_hinum */
428     ++rxi_pthread_hinum;
429     pthread_setspecific(rx_thread_id_key, (void *)rxi_pthread_hinum);
430     MUTEX_EXIT(&rx_stats_mutex);
431     ViceLog(0,
432             ("Set thread id %d for '%s'\n",
433              pthread_getspecific(rx_thread_id_key), s));
434 #endif
435 }
436
437 /* This LWP does things roughly every 5 minutes */
438 static void
439 FiveMinuteCheckLWP()
440 {
441     static int msg = 0;
442     char tbuffer[32];
443
444     ViceLog(1, ("Starting five minute check process\n"));
445     setThreadId("FiveMinuteCheckLWP");
446
447 #ifdef AFS_DEMAND_ATTACH_FS
448     FS_STATE_WRLOCK;
449     while (fs_state.mode == FS_MODE_NORMAL) {
450         fs_state.FiveMinuteLWP_tranquil = 1;
451         FS_STATE_UNLOCK;
452 #else
453     while (1) {
454 #endif
455
456 #ifdef AFS_PTHREAD_ENV
457         sleep(fiveminutes);
458 #else /* AFS_PTHREAD_ENV */
459         IOMGR_Sleep(fiveminutes);
460 #endif /* AFS_PTHREAD_ENV */
461
462 #ifdef AFS_DEMAND_ATTACH_FS
463         FS_STATE_WRLOCK;
464         if (fs_state.mode != FS_MODE_NORMAL) {
465             break;
466         }
467         fs_state.FiveMinuteLWP_tranquil = 0;
468         FS_STATE_UNLOCK;
469 #endif
470
471         /* close the log so it can be removed */
472         ReOpenLog(AFSDIR_SERVER_FILELOG_FILEPATH);      /* don't trunc, just append */
473         ViceLog(2, ("Cleaning up timed out callbacks\n"));
474         if (CleanupTimedOutCallBacks())
475             ViceLog(5, ("Timed out callbacks deleted\n"));
476         ViceLog(2, ("Set disk usage statistics\n"));
477         VSetDiskUsage();
478         if (FS_registered == 1)
479             Do_VLRegisterRPC();
480         /* Force wakeup in case we missed something; pthreads does timedwait */
481 #ifndef AFS_PTHREAD_ENV
482         LWP_NoYieldSignal(fsync_wait);
483 #endif
484         if (printBanner && (++msg & 1)) {       /* Every 10 minutes */
485             time_t now = FT_ApproxTime();
486             if (console != NULL) {
487 #ifndef AFS_QUIETFS_ENV
488                 fprintf(console, "File server is running at %s\r",
489                         afs_ctime(&now, tbuffer, sizeof(tbuffer)));
490 #endif /* AFS_QUIETFS_ENV */
491                 ViceLog(2,
492                         ("File server is running at %s\n",
493                          afs_ctime(&now, tbuffer, sizeof(tbuffer))));
494             }
495         }
496 #ifdef AFS_DEMAND_ATTACH_FS
497         FS_STATE_WRLOCK;
498 #endif
499     }
500 #ifdef AFS_DEMAND_ATTACH_FS
501     fs_state.FiveMinuteLWP_tranquil = 1;
502     FS_LOCK;
503     assert(pthread_cond_broadcast(&fs_state.worker_done_cv)==0);
504     FS_UNLOCK;
505     FS_STATE_UNLOCK;
506 #endif
507 }                               /*FiveMinuteCheckLWP */
508
509
510 /* This LWP does host checks every 5 minutes:  it should not be used for
511  * other 5 minute activities because it may be delayed by timeouts when
512  * it probes the workstations
513  */
514
515 static void
516 HostCheckLWP()
517 {
518     ViceLog(1, ("Starting Host check process\n"));
519     setThreadId("HostCheckLWP");
520 #ifdef AFS_DEMAND_ATTACH_FS
521     FS_STATE_WRLOCK;
522     while (fs_state.mode == FS_MODE_NORMAL) {
523         fs_state.HostCheckLWP_tranquil = 1;
524         FS_STATE_UNLOCK;
525 #else
526     while(1) {
527 #endif
528
529 #ifdef AFS_PTHREAD_ENV
530         sleep(fiveminutes);
531 #else /* AFS_PTHREAD_ENV */
532         IOMGR_Sleep(fiveminutes);
533 #endif /* AFS_PTHREAD_ENV */
534
535 #ifdef AFS_DEMAND_ATTACH_FS
536         FS_STATE_WRLOCK;
537         if (fs_state.mode != FS_MODE_NORMAL) {
538             break;
539         }
540         fs_state.HostCheckLWP_tranquil = 0;
541         FS_STATE_UNLOCK;
542 #endif
543
544         ViceLog(2, ("Checking for dead venii & clients\n"));
545         h_CheckHosts();
546
547 #ifdef AFS_DEMAND_ATTACH_FS
548         FS_STATE_WRLOCK;
549 #endif
550     }
551 #ifdef AFS_DEMAND_ATTACH_FS
552     fs_state.HostCheckLWP_tranquil = 1;
553     FS_LOCK;
554     assert(pthread_cond_broadcast(&fs_state.worker_done_cv)==0);
555     FS_UNLOCK;
556     FS_STATE_UNLOCK;
557 #endif
558 }                               /*HostCheckLWP */
559
560 /* This LWP does fsync checks every 5 minutes:  it should not be used for
561  * other 5 minute activities because it may be delayed by timeouts when
562  * it probes the workstations
563  */
564 static void
565 FsyncCheckLWP()
566 {
567     afs_int32 code;
568 #ifdef AFS_PTHREAD_ENV
569     struct timespec fsync_next;
570 #endif
571     ViceLog(1, ("Starting fsync check process\n"));
572
573     setThreadId("FsyncCheckLWP");
574
575 #ifdef AFS_PTHREAD_ENV
576     assert(pthread_cond_init(&fsync_cond, NULL) == 0);
577     assert(pthread_mutex_init(&fsync_glock_mutex, NULL) == 0);
578 #endif
579
580 #ifdef AFS_DEMAND_ATTACH_FS
581     FS_STATE_WRLOCK;
582     while (fs_state.mode == FS_MODE_NORMAL) {
583         fs_state.FsyncCheckLWP_tranquil = 1;
584         FS_STATE_UNLOCK;
585 #else
586     while(1) {
587 #endif
588         FSYNC_LOCK;
589 #ifdef AFS_PTHREAD_ENV
590         /* rounding is fine */
591         fsync_next.tv_nsec = 0;
592         fsync_next.tv_sec = time(0) + fiveminutes;
593
594         code =
595             pthread_cond_timedwait(&fsync_cond, &fsync_glock_mutex,
596                                    &fsync_next);
597         if (code != 0 && code != ETIMEDOUT)
598             ViceLog(0, ("pthread_cond_timedwait returned %d\n", code));
599 #else /* AFS_PTHREAD_ENV */
600         if ((code = LWP_WaitProcess(fsync_wait)) != LWP_SUCCESS)
601             ViceLog(0, ("LWP_WaitProcess returned %d\n", code));
602 #endif /* AFS_PTHREAD_ENV */
603         FSYNC_UNLOCK;
604
605 #ifdef AFS_DEMAND_ATTACH_FS
606         FS_STATE_WRLOCK;
607         if (fs_state.mode != FS_MODE_NORMAL) {
608             break;
609         }
610         fs_state.FsyncCheckLWP_tranquil = 0;
611         FS_STATE_UNLOCK;
612 #endif /* AFS_DEMAND_ATTACH_FS */
613
614         ViceLog(2, ("Checking for fsync events\n"));
615         do {
616             code = BreakLaterCallBacks();
617         } while (code != 0);
618 #ifdef AFS_DEMAND_ATTACH_FS
619         FS_STATE_WRLOCK;
620 #endif
621     }
622 #ifdef AFS_DEMAND_ATTACH_FS
623     fs_state.FsyncCheckLWP_tranquil = 1;
624     FS_LOCK;
625     assert(pthread_cond_broadcast(&fs_state.worker_done_cv)==0);
626     FS_UNLOCK;
627     FS_STATE_UNLOCK;
628 #endif /* AFS_DEMAND_ATTACH_FS */
629 }
630
631 /*------------------------------------------------------------------------
632  * PRIVATE ClearXStatValues
633  *
634  * Description:
635  *      Initialize all of the values collected via the xstat
636  *      interface.
637  *
638  * Arguments:
639  *      None.
640  *
641  * Returns:
642  *      Nothing.
643  *
644  * Environment:
645  *      Must be called during File Server initialization.
646  *
647  * Side Effects:
648  *      As advertised.
649  *------------------------------------------------------------------------*/
650
651 static void
652 ClearXStatValues()
653 {                               /*ClearXStatValues */
654
655     struct fs_stats_opTimingData *opTimeP;      /*Ptr to timing struct */
656     struct fs_stats_xferData *opXferP;  /*Ptr to xfer struct */
657     int i;                      /*Loop counter */
658
659     /*
660      * Zero all xstat-related structures.
661      */
662     memset((char *)(&afs_perfstats), 0, sizeof(struct afs_PerfStats));
663 #if FS_STATS_DETAILED
664     memset((char *)(&afs_FullPerfStats), 0,
665            sizeof(struct fs_stats_FullPerfStats));
666
667     /*
668      * That's not enough.  We have to set reasonable minima for
669      * time and xfer values in the detailed stats.
670      */
671     opTimeP = &(afs_FullPerfStats.det.rpcOpTimes[0]);
672     for (i = 0; i < FS_STATS_NUM_RPC_OPS; i++, opTimeP++)
673         opTimeP->minTime.tv_sec = 999999;
674
675     opXferP = &(afs_FullPerfStats.det.xferOpTimes[0]);
676     for (i = 0; i < FS_STATS_NUM_XFER_OPS; i++, opXferP++) {
677         opXferP->minTime.tv_sec = 999999;
678         opXferP->minBytes = 999999999;
679     }
680
681     /*
682      * There's more.  We have to set our unique system identifier, as
683      * declared in param.h.  If such a thing is not defined, we bitch
684      * and declare ourselves to be an unknown system type.
685      */
686 #ifdef SYS_NAME_ID
687     afs_perfstats.sysname_ID = SYS_NAME_ID;
688 #else
689 #ifndef AFS_NT40_ENV
690     ViceLog(0, ("Sys name ID constant not defined in param.h!!\n"));
691     ViceLog(0, ("[Choosing ``undefined'' sys name ID.\n"));
692 #endif
693     afs_perfstats.sysname_ID = SYS_NAME_ID_UNDEFINED;
694 #endif /* SYS_NAME_ID */
695 #endif
696
697 }                               /*ClearXStatValues */
698
699
700 static void
701 PrintCounters()
702 {
703     int dirbuff, dircall, dirio;
704     struct timeval tpl;
705     int workstations, activeworkstations, delworkstations;
706     int processSize = 0;
707     char tbuffer[32];
708
709     TM_GetTimeOfDay(&tpl, 0);
710     Statistics = 1;
711     ViceLog(0,
712             ("Vice was last started at %s\n",
713              afs_ctime(&StartTime, tbuffer, sizeof(tbuffer))));
714
715 #ifdef AFS_DEMAND_ATTACH_FS
716     /* XXX perhaps set extended stats verbosity flags
717      * based upon LogLevel ?? */
718     VPrintExtendedCacheStats(VOL_STATS_PER_CHAIN2);
719 #endif
720     VPrintCacheStats();
721     VPrintDiskStats();
722     DStat(&dirbuff, &dircall, &dirio);
723     ViceLog(0,
724             ("With %d directory buffers; %d reads resulted in %d read I/Os\n",
725              dirbuff, dircall, dirio));
726     rx_PrintStats(stderr);
727     h_PrintStats();
728     PrintCallBackStats();
729 #ifdef AFS_NT40_ENV
730     processSize = -1;           /* TODO: */
731 #else
732     processSize = (int)((long)sbrk(0) >> 10);
733 #endif
734     ViceLog(0,
735             ("There are %d connections, process size %d\n",
736              CurrentConnections, processSize));
737     h_GetWorkStats(&workstations, &activeworkstations, &delworkstations,
738                    tpl.tv_sec - 15 * 60);
739     ViceLog(0,
740             ("There are %d workstations, %d are active (req in < 15 mins), %d marked \"down\"\n",
741              workstations, activeworkstations, delworkstations));
742     Statistics = 0;
743
744 }                               /*PrintCounters */
745
746
747
748 static int
749 CheckSignal()
750 {
751     if (FS_registered > 0) {
752         /*
753          * We have proper ip addresses; tell the vlserver what we got; the following
754          * routine will do the proper reporting for us
755          */
756         Do_VLRegisterRPC();
757     }
758     h_DumpHosts();
759     h_PrintClients();
760     DumpCallBackState();
761     PrintCounters();
762     ResetCheckSignal();
763     return 0;
764 }                               /*CheckSignal */
765
766 void
767 ShutDownAndCore(int dopanic)
768 {
769     time_t now = time(0);
770     char tbuffer[32];
771
772     /* do not allows new reqests to be served from now on, all new requests
773      * are returned with an error code of RX_RESTARTING ( transient failure ) */
774     rx_SetRxTranquil();         /* dhruba */
775
776 #ifdef AFS_DEMAND_ATTACH_FS
777     FS_STATE_WRLOCK;
778     fs_state.mode = FS_MODE_SHUTDOWN;
779     FS_STATE_UNLOCK;
780 #endif
781
782     ViceLog(0,
783             ("Shutting down file server at %s",
784              afs_ctime(&now, tbuffer, sizeof(tbuffer))));
785     if (dopanic)
786         ViceLog(0, ("ABNORMAL SHUTDOWN, see core file.\n"));
787 #ifndef AFS_QUIETFS_ENV
788     if (console != NULL) {
789         fprintf(console, "File server restart/shutdown received at %s\r",
790                 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
791     }
792 #endif
793     DFlush();
794     if (!dopanic)
795         PrintCounters();
796
797     /* shut down volume package */
798     VShutdown();
799
800 #ifdef AFS_DEMAND_ATTACH_FS
801     if (fs_state.options.fs_state_save) {
802         /* 
803          * demand attach fs
804          * save fileserver state to disk */
805
806         /* make sure background threads have finished all of their asynchronous 
807          * work on host and callback structures */
808         FS_STATE_RDLOCK;
809         while (!fs_state.FiveMinuteLWP_tranquil ||
810                !fs_state.HostCheckLWP_tranquil ||
811                !fs_state.FsyncCheckLWP_tranquil) {
812             FS_LOCK;
813             FS_STATE_UNLOCK;
814             ViceLog(0, ("waiting for background host/callback threads to quiesce before saving fileserver state...\n"));
815             assert(pthread_cond_wait(&fs_state.worker_done_cv, &fileproc_glock_mutex) == 0);
816             FS_UNLOCK;
817             FS_STATE_RDLOCK;
818         }
819
820         /* ok. it should now be fairly safe. let's do the state dump */
821         fs_stateSave();
822     }
823 #endif /* AFS_DEMAND_ATTACH_FS */
824
825     if (debugFile) {
826         rx_PrintStats(debugFile);
827         fflush(debugFile);
828     }
829     if (console != NULL) {
830         now = time(0);
831         if (dopanic) {
832 #ifndef AFS_QUIETFS_ENV
833             fprintf(console, "File server has terminated abnormally at %s\r",
834                     afs_ctime(&now, tbuffer, sizeof(tbuffer)));
835 #endif
836             ViceLog(0,
837                     ("File server has terminated abnormally at %s\n",
838                      afs_ctime(&now, tbuffer, sizeof(tbuffer))));
839         } else {
840 #ifndef AFS_QUIETFS_ENV
841             fprintf(console, "File server has terminated normally at %s\r",
842                     afs_ctime(&now, tbuffer, sizeof(tbuffer)));
843 #endif
844             ViceLog(0,
845                     ("File server has terminated normally at %s\n",
846                      afs_ctime(&now, tbuffer, sizeof(tbuffer))));
847         }
848     }
849
850     exit(0);
851 }
852
853 int
854 ShutDown(void)
855 {                               /* backward compatibility */
856     ShutDownAndCore(DONTPANIC);
857     return 0;
858 }
859
860
861 static void
862 FlagMsg()
863 {
864     char buffer[2048];
865
866     /* default supports help flag */
867
868     strcpy(buffer, "Usage: fileserver ");
869     strcpy(buffer, "[-auditlog <log path>] ");
870     strcat(buffer, "[-d <debug level>] ");
871     strcat(buffer, "[-p <number of processes>] ");
872     strcat(buffer, "[-spare <number of spare blocks>] ");
873     strcat(buffer, "[-pctspare <percentage spare>] ");
874     strcat(buffer, "[-b <buffers>] ");
875     strcat(buffer, "[-l <large vnodes>] ");
876     strcat(buffer, "[-s <small vnodes>] ");
877     strcat(buffer, "[-vc <volume cachesize>] ");
878     strcat(buffer, "[-w <call back wait interval>] ");
879     strcat(buffer, "[-cb <number of call backs>] ");
880     strcat(buffer, "[-banner (print banner every 10 minutes)] ");
881     strcat(buffer, "[-novbc (whole volume cbs disabled)] ");
882     strcat(buffer, "[-implicit <admin mode bits: rlidwka>] ");
883     strcat(buffer, "[-readonly (read-only file server)] ");
884     strcat(buffer,
885            "[-hr <number of hours between refreshing the host cps>] ");
886     strcat(buffer, "[-busyat <redirect clients when queue > n>] ");
887     strcat(buffer, "[-nobusy <no VBUSY before a volume is attached>] ");
888     strcat(buffer, "[-rxpck <number of rx extra packets>] ");
889     strcat(buffer, "[-rxdbg (enable rx debugging)] ");
890     strcat(buffer, "[-rxdbge (enable rxevent debugging)] ");
891     strcat(buffer, "[-rxmaxmtu <bytes>] ");
892 #ifdef AFS_DEMAND_ATTACH_FS
893     strcat(buffer, "[-fs-state-dont-save (disable state save during shutdown)] ");
894     strcat(buffer, "[-fs-state-dont-restore (disable state restore during startup)] ");
895     strcat(buffer, "[-fs-state-verify <none|save|restore|both> (default is both)] ");
896     strcat(buffer, "[-vattachpar <max number of volume attach/shutdown threads> (default is 1)] ");
897     strcat(buffer, "[-vhashsize <log(2) of number of volume hash buckets> (default is 8)] ");
898     strcat(buffer, "[-vlrudisable (disable VLRU functionality)] ");
899     strcat(buffer, "[-vlruthresh <minutes before unused volumes become eligible for soft detach> (default is 2 hours)] ");
900     strcat(buffer, "[-vlruinterval <seconds between VLRU scans> (default is 2 minutes)] ");
901     strcat(buffer, "[-vlrumax <max volumes to soft detach in one VLRU scan> (default is 8)] ");
902 #elif AFS_PTHREAD_ENV
903     strcat(buffer, "[-vattachpar <number of volume attach threads> (default is 1)] ");
904 #endif
905 #ifdef  AFS_AIX32_ENV
906     strcat(buffer, "[-m <min percentage spare in partition>] ");
907 #endif
908 #if defined(AFS_SGI_ENV)
909     strcat(buffer, "[-lock (keep fileserver from swapping)] ");
910 #endif
911     strcat(buffer, "[-L (large server conf)] ");
912     strcat(buffer, "[-S (small server conf)] ");
913     strcat(buffer, "[-k <stack size>] ");
914     strcat(buffer, "[-realm <Kerberos realm name>] ");
915     strcat(buffer, "[-udpsize <size of socket buffer in bytes>] ");
916     strcat(buffer, "[-sendsize <size of send buffer in bytes>] ");
917     strcat(buffer, "[-abortthreshold <abort threshold>] ");
918 /*   strcat(buffer, "[-enable_peer_stats] "); */
919 /*   strcat(buffer, "[-enable_process_stats] "); */
920     strcat(buffer, "[-help]\n");
921 /*
922     ViceLog(0, ("%s", buffer));
923 */
924
925     printf("%s", buffer);
926     fflush(stdout);
927
928 }                               /*FlagMsg */
929
930
931 static afs_int32
932 ParseRights(char *arights)
933 {
934     afs_int32 mode = 0;
935     int i, len;
936     char tc;
937
938     if (!arights || !strcmp(arights, "")) {
939         printf("Missing list of mode bits on -implicit option\n");
940         return -1;
941     }
942     if (!strcmp(arights, "none"))
943         mode = 0;
944     else if (!strcmp(arights, "read"))
945         mode = PRSFS_READ | PRSFS_LOOKUP;
946     else if (!strcmp(arights, "write"))
947         mode =
948             PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
949             PRSFS_WRITE | PRSFS_LOCK;
950     else if (!strcmp(arights, "all"))
951         mode =
952             PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
953             PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
954     else {
955         len = strlen(arights);
956         for (i = 0; i < len; i++) {
957             tc = *arights++;
958             if (tc == 'r')
959                 mode |= PRSFS_READ;
960             else if (tc == 'l')
961                 mode |= PRSFS_LOOKUP;
962             else if (tc == 'i')
963                 mode |= PRSFS_INSERT;
964             else if (tc == 'd')
965                 mode |= PRSFS_DELETE;
966             else if (tc == 'w')
967                 mode |= PRSFS_WRITE;
968             else if (tc == 'k')
969                 mode |= PRSFS_LOCK;
970             else if (tc == 'a')
971                 mode |= PRSFS_ADMINISTER;
972             else if (tc == 'A')
973                 mode |= PRSFS_USR0;
974             else if (tc == 'B')
975                 mode |= PRSFS_USR1;
976             else if (tc == 'C')
977                 mode |= PRSFS_USR2;
978             else if (tc == 'D')
979                 mode |= PRSFS_USR3;
980             else if (tc == 'E')
981                 mode |= PRSFS_USR4;
982             else if (tc == 'F')
983                 mode |= PRSFS_USR5;
984             else if (tc == 'G')
985                 mode |= PRSFS_USR6;
986             else if (tc == 'H')
987                 mode |= PRSFS_USR7;
988             else {
989                 printf("Illegal -implicit rights character '%c'.\n", tc);
990                 return -1;
991             }
992         }
993     }
994     return mode;
995 }
996
997 /*
998  * Limit MAX_FILESERVER_THREAD by the system limit on the number of
999  * pthreads (sysconf(_SC_THREAD_THREADS_MAX)), if applicable and
1000  * available.
1001  *
1002  * AIX:         sysconf() limit is real
1003  * HP-UX:       sysconf() limit is real
1004  * IRIX:        sysconf() limit is apparently NOT real -- too small
1005  * DUX:         sysconf() limit is apparently NOT real -- too big
1006  * Linux:       sysconf() limit is apparently NOT real -- too big
1007  * Solaris:     no sysconf() limit
1008  */
1009 static int
1010 max_fileserver_thread(void)
1011 {
1012 #if defined(AFS_PTHREAD_ENV)
1013 #if defined(AFS_AIX_ENV) || defined(AFS_HPUX_ENV)
1014     long ans;
1015
1016     ans = sysconf(_SC_THREAD_THREADS_MAX);
1017     if (0 < ans && ans < MAX_FILESERVER_THREAD)
1018         return (int)ans;
1019 #endif
1020 #endif /* defined(AFS_PTHREAD_ENV) */
1021     return MAX_FILESERVER_THREAD;
1022 }
1023
1024 static int
1025 ParseArgs(int argc, char *argv[])
1026 {
1027     int SawL = 0, SawS = 0, SawVC = 0;
1028     int Sawrxpck = 0, Sawsmall = 0, Sawlarge = 0, Sawcbs = 0, Sawlwps =
1029         0, Sawbufs = 0;
1030     int Sawbusy = 0;
1031     int i;
1032     int bufSize = 0;            /* temp variable to read in udp socket buf size */
1033
1034     for (i = 1; i < argc; i++) {
1035         if (!strcmp(argv[i], "-d")) {
1036             if ((i + 1) >= argc) {
1037                 fprintf(stderr, "missing argument for -d\n"); 
1038                 return -1; 
1039             }
1040             debuglevel = atoi(argv[++i]);
1041             LogLevel = debuglevel;
1042         } else if (!strcmp(argv[i], "-banner")) {
1043             printBanner = 1;
1044         } else if (!strcmp(argv[i], "-implicit")) {
1045             if ((i + 1) >= argc) {
1046                 fprintf(stderr, "missing argument for -implicit\n"); 
1047                 return -1; 
1048             }
1049             implicitAdminRights = ParseRights(argv[++i]);
1050             if (implicitAdminRights < 0)
1051                 return implicitAdminRights;
1052         } else if (!strcmp(argv[i], "-readonly")) {
1053             readonlyServer = 1;
1054         } else if (!strcmp(argv[i], "-L")) {
1055             SawL = 1;
1056         } else if (!strcmp(argv[i], "-S")) {
1057             SawS = 1;
1058         } else if (!strcmp(argv[i], "-p")) {
1059             int lwps_max =
1060                 max_fileserver_thread() - FILESERVER_HELPER_THREADS;
1061             Sawlwps = 1;
1062             if ((i + 1) >= argc) {
1063                 fprintf(stderr, "missing argument for -p\n"); 
1064                 return -1; 
1065             }
1066             lwps = atoi(argv[++i]);
1067             if (lwps > lwps_max)
1068                 lwps = lwps_max;
1069             else if (lwps < 6)
1070                 lwps = 6;
1071         } else if (!strcmp(argv[i], "-b")) {
1072             Sawbufs = 1;
1073             if ((i + 1) >= argc) {
1074                 fprintf(stderr, "missing argument for -b\n"); 
1075                 return -1; 
1076             }
1077             buffs = atoi(argv[++i]);
1078         } else if (!strcmp(argv[i], "-l")) {
1079             Sawlarge = 1;
1080             if ((i + 1) >= argc) {
1081                 fprintf(stderr, "missing argument for -l\n"); 
1082                 return -1; 
1083             }
1084             large = atoi(argv[++i]);
1085         } else if (!strcmp(argv[i], "-vc")) {
1086             SawVC = 1;
1087             if ((i + 1) >= argc) {
1088                 fprintf(stderr, "missing argument for -vc\n"); 
1089                 return -1; 
1090             }
1091             volcache = atoi(argv[++i]);
1092         } else if (!strcmp(argv[i], "-novbc")) {
1093             novbc = 1;
1094         } else if (!strcmp(argv[i], "-rxpck")) {
1095             Sawrxpck = 1;
1096             if ((i + 1) >= argc) {
1097                 fprintf(stderr, "missing argument for -rxpck\n"); 
1098                 return -1; 
1099             }
1100             rxpackets = atoi(argv[++i]);
1101 #ifdef AFS_PTHREAD_ENV
1102         } else if (!strcmp(argv[i], "-vattachpar")) {
1103             if ((i + 1) >= argc) {
1104                 fprintf(stderr, "missing argument for %s\n", argv[i]); 
1105                 return -1; 
1106             }
1107             vol_attach_threads = atoi(argv[++i]);
1108 #endif /* AFS_PTHREAD_ENV */
1109 #ifdef AFS_DEMAND_ATTACH_FS
1110         } else if (!strcmp(argv[i], "-fs-state-dont-save")) {
1111             fs_state.options.fs_state_save = 0;
1112         } else if (!strcmp(argv[i], "-fs-state-dont-restore")) {
1113             fs_state.options.fs_state_restore = 0;
1114         } else if (!strcmp(argv[i], "-fs-state-verify")) {
1115             if ((i + 1) >= argc) {
1116                 fprintf(stderr, "missing argument for %s\n", argv[i]); 
1117                 return -1; 
1118             }
1119             i++;
1120             if (!strcmp(argv[i], "none")) {
1121                 fs_state.options.fs_state_verify_before_save = 0;
1122                 fs_state.options.fs_state_verify_after_restore = 0;
1123             } else if (!strcmp(argv[i], "save")) {
1124                 fs_state.options.fs_state_verify_after_restore = 0;
1125             } else if (!strcmp(argv[i], "restore")) {
1126                 fs_state.options.fs_state_verify_before_save = 0;
1127             } else if (!strcmp(argv[i], "both")) {
1128                 /* default */
1129             } else {
1130                 fprintf(stderr, "invalid argument for %s\n", argv[i-1]);
1131                 return -1;
1132             }
1133         } else if (!strcmp(argv[i], "-vhashsize")) {
1134             if ((i + 1) >= argc) {
1135                 fprintf(stderr, "missing argument for %s\n", argv[i]); 
1136                 return -1; 
1137             }
1138             VSetVolHashSize(atoi(argv[++i]));
1139         } else if (!strcmp(argv[i], "-vlrudisable")) {
1140             VLRU_SetOptions(VLRU_SET_ENABLED, 0);
1141         } else if (!strcmp(argv[i], "-vlruthresh")) {
1142             if ((i + 1) >= argc) {
1143                 fprintf(stderr, "missing argument for %s\n", argv[i]); 
1144                 return -1; 
1145             }
1146             VLRU_SetOptions(VLRU_SET_THRESH, 60*atoi(argv[++i]));
1147         } else if (!strcmp(argv[i], "-vlruinterval")) {
1148             if ((i + 1) >= argc) {
1149                 fprintf(stderr, "missing argument for %s\n", argv[i]); 
1150                 return -1; 
1151             }
1152             VLRU_SetOptions(VLRU_SET_INTERVAL, atoi(argv[++i]));
1153         } else if (!strcmp(argv[i], "-vlrumax")) {
1154             if ((i + 1) >= argc) {
1155                 fprintf(stderr, "missing argument for %s\n", argv[i]); 
1156                 return -1; 
1157             }
1158             VLRU_SetOptions(VLRU_SET_MAX, atoi(argv[++i]));
1159 #endif /* AFS_DEMAND_ATTACH_FS */
1160         } else if (!strcmp(argv[i], "-s")) {
1161             Sawsmall = 1;
1162             if ((i + 1) >= argc) {
1163                 fprintf(stderr, "missing argument for -s\n"); 
1164                 return -1; 
1165             }
1166             nSmallVns = atoi(argv[++i]);
1167         } else if (!strcmp(argv[i], "-abortthreshold")) {
1168             if ((i + 1) >= argc) {
1169                 fprintf(stderr, "missing argument for -abortthreshold\n"); 
1170                 return -1; 
1171             }
1172             abort_threshold = atoi(argv[++i]);
1173         } else if (!strcmp(argv[i], "-k")) {
1174             if ((i + 1) >= argc) {
1175                 fprintf(stderr, "missing argument for -k\n"); 
1176                 return -1; 
1177             }
1178             stack = atoi(argv[++i]);
1179         }
1180 #if defined(AFS_SGI_ENV)
1181         else if (!strcmp(argv[i], "-lock")) {
1182             SawLock = 1;
1183         }
1184 #endif
1185         else if (!strcmp(argv[i], "-spare")) {
1186             if ((i + 1) >= argc) {
1187                 fprintf(stderr, "missing argument for -spare\n"); 
1188                 return -1; 
1189             }
1190             BlocksSpare = atoi(argv[++i]);
1191             SawSpare = 1;
1192         } else if (!strcmp(argv[i], "-pctspare")) {
1193             if ((i + 1) >= argc) {
1194                 fprintf(stderr, "missing argument for -pctspare\n"); 
1195                 return -1; 
1196             }
1197             PctSpare = atoi(argv[++i]);
1198             BlocksSpare = 0;    /* has non-zero default */
1199             SawPctSpare = 1;
1200         } else if (!strcmp(argv[i], "-w")) {
1201             if ((i + 1) >= argc) {
1202                 fprintf(stderr, "missing argument for -w\n"); 
1203                 return -1; 
1204             }
1205             fiveminutes = atoi(argv[++i]);
1206         } else if (!strcmp(argv[i], "-hr")) {
1207             int hr;
1208             if ((i + 1) >= argc) {
1209                 fprintf(stderr, "missing argument for -hr\n"); 
1210                 return -1; 
1211             }
1212             hr = atoi(argv[++i]);
1213             if ((hr < 1) || (hr > 36)) {
1214                 printf
1215                     ("host acl refresh interval of %d hours is invalid; hours must be between 1 and 36\n\n",
1216                      hr);
1217                 return -1;
1218             }
1219             hostaclRefresh = hr * 60 * 60;
1220         } else if (!strcmp(argv[i], "-rxdbg"))
1221             rxlog = 1;
1222         else if (!strcmp(argv[i], "-rxdbge"))
1223             eventlog = 1;
1224         else if (!strcmp(argv[i], "-cb")) {
1225             Sawcbs = 1;
1226             if ((i + 1) >= argc) {
1227                 fprintf(stderr, "missing argument for -cb\n"); 
1228                 return -1; 
1229             }
1230             numberofcbs = atoi(argv[++i]);
1231             if ((numberofcbs < 10000) || (numberofcbs > 2147483647)) {
1232                 printf
1233                     ("number of cbs %d invalid; must be between 10000 and 2147483647\n",
1234                      numberofcbs);
1235                 return -1;
1236             }
1237         } else if (!strcmp(argv[i], "-busyat")) {
1238             Sawbusy = 1;
1239             if ((i + 1) >= argc) {
1240                 fprintf(stderr, "missing argument for -busyat\n"); 
1241                 return -1; 
1242             }
1243             busy_threshold = atoi(argv[++i]);
1244             if (busy_threshold < 10) {
1245                 printf
1246                     ("Busy threshold %d is too low, will compute default.\n",
1247                      busy_threshold);
1248                 Sawbusy = 0;
1249             }
1250         } else if (!strcmp(argv[i], "-nobusy"))
1251             busyonrst = 0;
1252 #ifdef  AFS_AIX32_ENV
1253         else if (!strcmp(argv[i], "-m")) {
1254             extern int aixlow_water;
1255             if ((i + 1) >= argc) {
1256                 fprintf(stderr, "missing argument for -m\n"); 
1257                 return -1; 
1258             }
1259             aixlow_water = atoi(argv[++i]);
1260             if ((aixlow_water < 0) || (aixlow_water > 30)) {
1261                 printf("space reserved %d% invalid; must be between 0-30%\n",
1262                        aixlow_water);
1263                 return -1;
1264             }
1265         }
1266 #endif
1267         else if (!strcmp(argv[i], "-nojumbo")) {
1268             rxJumbograms = 0;
1269         } else if (!strcmp(argv[i], "-rxmaxmtu")) {
1270             if ((i + 1) >= argc) {
1271                 fprintf(stderr, "missing argument for -rxmaxmtu\n"); 
1272                 return -1; 
1273             }
1274             rxMaxMTU = atoi(argv[++i]);
1275             if ((rxMaxMTU < RX_MIN_PACKET_SIZE) || 
1276                 (rxMaxMTU > RX_MAX_PACKET_DATA_SIZE)) {
1277                 printf("rxMaxMTU %d%% invalid; must be between %d-%d\n",
1278                        rxMaxMTU, RX_MIN_PACKET_SIZE, 
1279                        RX_MAX_PACKET_DATA_SIZE);
1280                 return -1;
1281             }
1282         } else if (!strcmp(argv[i], "-realm")) {
1283             extern char local_realms[AFS_NUM_LREALMS][AFS_REALM_SZ];
1284             extern int  num_lrealms;
1285             if ((i + 1) >= argc) {
1286                 fprintf(stderr, "missing argument for -realm\n"); 
1287                 return -1; 
1288             }
1289             if (strlen(argv[++i]) >= AFS_REALM_SZ) {
1290                 printf
1291                     ("-realm argument must contain fewer than %d characters.\n",
1292                      AFS_REALM_SZ);
1293                 return -1;
1294             }
1295             if (num_lrealms == -1) 
1296                 num_lrealms = 0;
1297             if (num_lrealms >= AFS_NUM_LREALMS) {
1298                 printf
1299                     ("a maximum of %d -realm arguments can be specified.\n",
1300                      AFS_NUM_LREALMS);
1301                 return -1;
1302             }
1303             strncpy(local_realms[num_lrealms++], argv[i], AFS_REALM_SZ);
1304         } else if (!strcmp(argv[i], "-udpsize")) {
1305             if ((i + 1) >= argc) {
1306                 printf("You have to specify -udpsize <integer value>\n");
1307                 return -1;
1308             }
1309             bufSize = atoi(argv[++i]);
1310             if (bufSize < rx_GetMinUdpBufSize())
1311                 printf
1312                     ("Warning:udpsize %d is less than minimum %d; ignoring\n",
1313                      bufSize, rx_GetMinUdpBufSize());
1314             else
1315                 udpBufSize = bufSize;
1316         } else if (!strcmp(argv[i], "-sendsize")) {
1317             if ((i + 1) >= argc) {
1318                 printf("You have to specify -sendsize <integer value>\n");
1319                 return -1;
1320             }
1321             bufSize = atoi(argv[++i]);
1322             if (bufSize < 16384)
1323                 printf
1324                     ("Warning:sendsize %d is less than minimum %d; ignoring\n",
1325                      bufSize, 16384);
1326             else
1327                 sendBufSize = bufSize;
1328         } else if (!strcmp(argv[i], "-enable_peer_stats")) {
1329             rx_enablePeerRPCStats();
1330         } else if (!strcmp(argv[i], "-enable_process_stats")) {
1331             rx_enableProcessRPCStats();
1332         }
1333         else if (strcmp(argv[i], "-auditlog") == 0) {
1334             int tempfd, flags;
1335             FILE *auditout;
1336             char oldName[MAXPATHLEN];
1337             char *fileName = argv[++i];
1338             
1339 #ifndef AFS_NT40_ENV
1340             struct stat statbuf;
1341             
1342             if ((lstat(fileName, &statbuf) == 0) 
1343                 && (S_ISFIFO(statbuf.st_mode))) {
1344                 flags = O_WRONLY | O_NONBLOCK;
1345             } else 
1346 #endif
1347             {
1348                 strcpy(oldName, fileName);
1349                 strcat(oldName, ".old");
1350                 renamefile(fileName, oldName);
1351                 flags = O_WRONLY | O_TRUNC | O_CREAT;
1352             }
1353             tempfd = open(fileName, flags, 0666);
1354             if (tempfd > -1) {
1355                 auditout = fdopen(tempfd, "a");
1356                 if (auditout) {
1357                     osi_audit_file(auditout);
1358                 } else
1359                     printf("Warning: auditlog %s not writable, ignored.\n", fileName);
1360             } else
1361                 printf("Warning: auditlog %s not writable, ignored.\n", fileName);
1362         }
1363 #ifndef AFS_NT40_ENV
1364         else if (strcmp(argv[i], "-syslog") == 0) {
1365             /* set syslog logging flag */
1366             serverLogSyslog = 1;
1367         } else if (strncmp(argv[i], "-syslog=", 8) == 0) {
1368             serverLogSyslog = 1;
1369             serverLogSyslogFacility = atoi(argv[i] + 8);
1370         }
1371 #endif
1372         else if (strcmp(argv[i], "-mrafslogs") == 0) {
1373             /* set syslog logging flag */
1374             mrafsStyleLogs = 1;
1375         } 
1376         else {
1377             return (-1);
1378         }
1379     }
1380     if (SawS && SawL) {
1381         printf("Only one of -L, or -S must be specified\n");
1382         return -1;
1383     }
1384     if (SawS) {
1385         if (!Sawrxpck)
1386             rxpackets = 100;
1387         if (!Sawsmall)
1388             nSmallVns = 200;
1389         if (!Sawlarge)
1390             large = 200;
1391         if (!Sawcbs)
1392             numberofcbs = 20000;
1393         if (!Sawlwps)
1394             lwps = 6;
1395         if (!Sawbufs)
1396             buffs = 70;
1397         if (!SawVC)
1398             volcache = 200;
1399     }
1400     if (SawL) {
1401         if (!Sawrxpck)
1402             rxpackets = 200;
1403         if (!Sawsmall)
1404             nSmallVns = 600;
1405         if (!Sawlarge)
1406             large = 600;
1407         if (!Sawcbs)
1408             numberofcbs = 64000;
1409         if (!Sawlwps)
1410             lwps = 12;
1411         if (!Sawbufs)
1412             buffs = 120;
1413         if (!SawVC)
1414             volcache = 600;
1415     }
1416     if (!Sawbusy)
1417         busy_threshold = 3 * rxpackets / 2;
1418
1419     return (0);
1420
1421 }                               /*ParseArgs */
1422
1423
1424 #define MAXPARMS 15
1425
1426 static void
1427 NewParms(int initializing)
1428 {
1429     static struct afs_stat sbuf;
1430     register int i, fd;
1431     char *parms;
1432     char *argv[MAXPARMS];
1433     register int argc;
1434
1435     if (!(afs_stat("/vice/file/parms", &sbuf))) {
1436         parms = (char *)malloc(sbuf.st_size);
1437         if (!parms)
1438             return;
1439         fd = afs_open("parms", O_RDONLY, 0666);
1440         if (fd <= 0) {
1441             ViceLog(0, ("Open for parms failed with errno = %d\n", errno));
1442             return;
1443         }
1444
1445         i = read(fd, parms, sbuf.st_size);
1446         close(fd);
1447         if (i != sbuf.st_size) {
1448             if (i < 0) {
1449                 ViceLog(0, ("Read on parms failed with errno = %d\n", errno));
1450             } else {
1451                 ViceLog(0,
1452                         ("Read on parms failed; expected %d bytes but read %d\n",
1453                          sbuf.st_size, i));
1454             }
1455             free(parms);
1456             return;
1457         }
1458
1459         for (i = 0; i < MAXPARMS; argv[i++] = 0);
1460
1461         for (argc = i = 0; i < sbuf.st_size; i++) {
1462             if ((*(parms + i) != ' ') && (*(parms + i) != '\n')) {
1463                 if (argv[argc] == 0)
1464                     argv[argc] = (parms + i);
1465             } else {
1466                 *(parms + i) = '\0';
1467                 if (argv[argc] != 0) {
1468                     if (++argc == MAXPARMS)
1469                         break;
1470                 }
1471                 while ((*(parms + i + 1) == ' ')
1472                        || (*(parms + i + 1) == '\n'))
1473                     i++;
1474             }
1475         }
1476         if (ParseArgs(argc, argv) == 0) {
1477             ViceLog(0, ("Change parameters to:"));
1478         } else {
1479             ViceLog(0, ("Invalid parameter in:"));
1480         }
1481         for (i = 0; i < argc; i++) {
1482             ViceLog(0, (" %s", argv[i]));
1483         }
1484         ViceLog(0, ("\n"));
1485         free(parms);
1486     } else if (!initializing)
1487         ViceLog(0,
1488                 ("Received request to change parms but no parms file exists\n"));
1489
1490 }                               /*NewParms */
1491
1492
1493 /* Miscellaneous routines */
1494 void
1495 Die(char *msg)
1496 {
1497     ViceLog(0, ("%s\n", msg));
1498     assert(0);
1499
1500 }                               /*Die */
1501
1502
1503 afs_int32
1504 InitPR()
1505 {
1506     int code;
1507
1508     /*
1509      * If this fails, it's because something major is wrong, and is not
1510      * likely to be time dependent.
1511      */
1512     code = pr_Initialize(2, AFSDIR_SERVER_ETC_DIRPATH, 0);
1513     if (code != 0) {
1514         ViceLog(0,
1515                 ("Couldn't initialize protection library; code=%d.\n", code));
1516         return code;
1517     }
1518     SystemId = SYSADMINID;
1519     SystemAnyUser = ANYUSERID;
1520     SystemAnyUserCPS.prlist_len = 0;
1521     SystemAnyUserCPS.prlist_val = NULL;
1522     AnonCPS.prlist_len = 0;
1523     AnonCPS.prlist_val = NULL;
1524     while (1) {
1525         code = pr_GetCPS(SystemAnyUser, &SystemAnyUserCPS);
1526         if (code != 0) {
1527             ViceLog(0,
1528                     ("Couldn't get CPS for AnyUser, will try again in 30 seconds; code=%d.\n",
1529                      code));
1530             goto sleep;
1531         }
1532         code = pr_GetCPS(ANONYMOUSID, &AnonCPS);
1533         if (code != 0) {
1534             ViceLog(0,
1535                     ("Couldn't get Anonymous CPS, exiting; code=%d.\n",
1536                      code));
1537             return -1;
1538         }
1539         AnonymousID = ANONYMOUSID;
1540         return 0;
1541       sleep:
1542 #ifdef AFS_PTHREAD_ENV
1543         sleep(30);
1544 #else /* AFS_PTHREAD_ENV */
1545         IOMGR_Sleep(30);
1546 #endif /* AFS_PTHREAD_ENV */
1547     }
1548 }                               /*InitPR */
1549
1550 struct rx_connection *serverconns[MAXSERVERS];
1551 struct ubik_client *cstruct;
1552
1553 afs_int32
1554 vl_Initialize(const char *confDir)
1555 {
1556     afs_int32 code, scIndex = 0, i;
1557     struct afsconf_dir *tdir;
1558     struct rx_securityClass *sc;
1559     struct afsconf_cell info;
1560
1561     tdir = afsconf_Open(confDir);
1562     if (!tdir) {
1563         ViceLog(0,
1564                 ("Could not open configuration directory (%s).\n", confDir));
1565         exit(1);
1566     }
1567     code = afsconf_ClientAuth(tdir, &sc, &scIndex);
1568     if (code) {
1569         ViceLog(0, ("Could not get security object for localAuth\n"));
1570         exit(1);
1571     }
1572     code = afsconf_GetCellInfo(tdir, NULL, AFSCONF_VLDBSERVICE, &info);
1573     if (info.numServers > MAXSERVERS) {
1574         ViceLog(0,
1575                 ("vl_Initialize: info.numServers=%d (> MAXSERVERS=%d)\n",
1576                  info.numServers, MAXSERVERS));
1577         exit(1);
1578     }
1579     for (i = 0; i < info.numServers; i++)
1580         serverconns[i] =
1581             rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
1582                              info.hostAddr[i].sin_port, USER_SERVICE_ID, sc,
1583                              scIndex);
1584     code = ubik_ClientInit(serverconns, &cstruct);
1585     if (code) {
1586         ViceLog(0, ("vl_Initialize: ubik client init failed.\n"));
1587         return code;
1588     }
1589     return 0;
1590 }
1591
1592 #define SYSIDMAGIC      0x88aabbcc
1593 #define SYSIDVERSION    1
1594
1595 afs_int32
1596 ReadSysIdFile()
1597 {
1598     afs_int32 fd, nentries, i;
1599     struct versionStamp vsn;
1600     struct afs_stat status;
1601     afsUUID uuid;
1602
1603     if ((afs_stat(AFSDIR_SERVER_SYSID_FILEPATH, &status))
1604         || (status.st_size <= 0)) {
1605         ViceLog(0, ("%s: doesn't exist\n", AFSDIR_SERVER_SYSID_FILEPATH));
1606         return ENOENT;
1607     }
1608     if (!(fd = afs_open(AFSDIR_SERVER_SYSID_FILEPATH, O_RDONLY, 0))) {
1609         ViceLog(0,
1610                 ("%s: can't open (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1611                  errno));
1612         return EIO;
1613     }
1614     if ((i = read(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1615         ViceLog(0,
1616                 ("%s: Read failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1617                  errno));
1618         return EIO;
1619     }
1620     if (vsn.magic != SYSIDMAGIC) {
1621         ViceLog(0,
1622                 ("%s: wrong magic %x (we support %x)\n",
1623                  AFSDIR_SERVER_SYSID_FILEPATH, vsn.magic, SYSIDMAGIC));
1624         return EIO;
1625     }
1626     if (vsn.version != SYSIDVERSION) {
1627         ViceLog(0,
1628                 ("%s: wrong version %d (we support %d)\n",
1629                  AFSDIR_SERVER_SYSID_FILEPATH, vsn.version, SYSIDVERSION));
1630         return EIO;
1631     }
1632     if ((i =
1633          read(fd, (char *)&uuid,
1634               sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1635         ViceLog(0,
1636                 ("%s: read of uuid failed (%d)\n",
1637                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1638         return EIO;
1639     }
1640     afs_ntohuuid(&uuid);
1641     FS_HostUUID = uuid;
1642     if ((i =
1643          read(fd, (char *)&nentries,
1644               sizeof(afs_int32))) != sizeof(afs_int32)) {
1645         ViceLog(0,
1646                 ("%s: Read of entries failed (%d)\n",
1647                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1648         return EIO;
1649     }
1650     if (nentries <= 0 || nentries > ADDRSPERSITE) {
1651         ViceLog(0,
1652                 ("%s: invalid num of interfaces: %d\n",
1653                  AFSDIR_SERVER_SYSID_FILEPATH, nentries));
1654         return EIO;
1655     }
1656     FS_HostAddr_cnt = nentries;
1657     for (i = 0; i < nentries; i++) {
1658         if (read(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) !=
1659             sizeof(afs_int32)) {
1660             ViceLog(0,
1661                     ("%s: Read of addresses failed (%d)\n",
1662                      AFSDIR_SERVER_SYSID_FILEPATH, errno));
1663             FS_HostAddr_cnt = 0;        /* reset it */
1664             return EIO;
1665         }
1666     }
1667     close(fd);
1668     return 0;
1669 }
1670
1671 afs_int32
1672 WriteSysIdFile()
1673 {
1674     afs_int32 fd, i;
1675     struct versionStamp vsn;
1676     struct afs_stat status;
1677     afsUUID uuid;
1678
1679     if (!afs_stat(AFSDIR_SERVER_SYSID_FILEPATH, &status)) {
1680         /*
1681          * File exists; keep the old one around
1682          */
1683         renamefile(AFSDIR_SERVER_SYSID_FILEPATH,
1684                    AFSDIR_SERVER_OLDSYSID_FILEPATH);
1685     }
1686     fd = afs_open(AFSDIR_SERVER_SYSID_FILEPATH, O_WRONLY | O_TRUNC | O_CREAT,
1687                   0666);
1688     if (fd < 1) {
1689         ViceLog(0,
1690                 ("%s: can't create (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1691                  errno));
1692         return EIO;
1693     }
1694     vsn.magic = SYSIDMAGIC;
1695     vsn.version = 1;
1696     if ((i = write(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1697         ViceLog(0,
1698                 ("%s: write failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH,
1699                  errno));
1700         return EIO;
1701     }
1702     uuid = FS_HostUUID;
1703     afs_htonuuid(&uuid);
1704     if ((i =
1705          write(fd, (char *)&uuid,
1706                sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1707         ViceLog(0,
1708                 ("%s: write of uuid failed (%d)\n",
1709                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1710         return EIO;
1711     }
1712     if ((i =
1713          write(fd, (char *)&FS_HostAddr_cnt,
1714                sizeof(afs_int32))) != sizeof(afs_int32)) {
1715         ViceLog(0,
1716                 ("%s: write of # of entries failed (%d)\n",
1717                  AFSDIR_SERVER_SYSID_FILEPATH, errno));
1718         return EIO;
1719     }
1720     for (i = 0; i < FS_HostAddr_cnt; i++) {
1721         if (write(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) !=
1722             sizeof(afs_int32)) {
1723             ViceLog(0,
1724                     ("%s: write of addresses failed (%d)\n",
1725                      AFSDIR_SERVER_SYSID_FILEPATH, errno));
1726             return EIO;
1727         }
1728     }
1729     close(fd);
1730     return 0;
1731 }
1732
1733 /*
1734  * defect 10966 
1735  * This routine sets up the buffers for the VL_RegisterAddrs RPC. All addresses
1736  * in FS_HostAddrs[] are in NBO, while the RPC treats them as a "blob" of data
1737  * and so we need to convert each of them into HBO which is what the extra 
1738  * array called FS_HostAddrs_HBO is used here.
1739  */
1740 afs_int32
1741 Do_VLRegisterRPC()
1742 {
1743     register int code;
1744     bulkaddrs addrs;
1745     extern int VL_RegisterAddrs();
1746     afs_uint32 FS_HostAddrs_HBO[ADDRSPERSITE];
1747     int i = 0;
1748
1749     for (i = 0; i < FS_HostAddr_cnt; i++)
1750         FS_HostAddrs_HBO[i] = ntohl(FS_HostAddrs[i]);
1751     addrs.bulkaddrs_len = FS_HostAddr_cnt;
1752     addrs.bulkaddrs_val = (afs_uint32 *) FS_HostAddrs_HBO;
1753     code = ubik_Call(VL_RegisterAddrs, cstruct, 0, &FS_HostUUID, 0, &addrs);
1754     if (code) {
1755         if (code == VL_MULTIPADDR) {
1756             ViceLog(0,
1757                     ("VL_RegisterAddrs rpc failed; The IP address exists on a different server; repair it\n"));
1758             ViceLog(0,
1759                     ("VL_RegisterAddrs rpc failed; See VLLog for details\n"));
1760             return code;
1761         } else if (code == RXGEN_OPCODE) {
1762             ViceLog(0,
1763                     ("vlserver doesn't support VL_RegisterAddrs rpc; ignored\n"));
1764             FS_registered = 2;  /* So we don't have to retry in the gc daemon */
1765         } else {
1766             ViceLog(0,
1767                     ("VL_RegisterAddrs rpc failed; will retry periodically (code=%d, err=%d)\n",
1768                      code, errno));
1769         }
1770     } else {
1771         FS_registered = 2;      /* So we don't have to retry in the gc daemon */
1772         WriteSysIdFile();
1773     }
1774
1775     return 0;
1776 }
1777
1778 afs_int32
1779 InitVL()
1780 {
1781     afs_int32 code;
1782
1783     /*
1784      * If this fails, it's because something major is wrong, and is not
1785      * likely to be time dependent.
1786      */
1787     code = vl_Initialize(AFSDIR_SERVER_ETC_DIRPATH);
1788     if (code != 0) {
1789         ViceLog(0,
1790                 ("Couldn't initialize protection library; code=%d.\n", code));
1791         return code;
1792     }
1793
1794     /* Read or create the sysid file and register the fileserver's
1795      * IP addresses with the vlserver.
1796      */
1797     code = ReadSysIdFile();
1798     if (code) {
1799         /* Need to create the file */
1800         ViceLog(0, ("Creating new SysID file\n"));
1801         if ((code = afs_uuid_create(&FS_HostUUID))) {
1802             ViceLog(0, ("Failed to create new uuid: %d\n", code));
1803             exit(1);
1804         }
1805     }
1806     /* A good sysid file exists; inform the vlserver. If any conflicts,
1807      * we always use the latest interface available as the real truth.
1808      */
1809 #ifndef AFS_NT40_ENV
1810     if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) {
1811         /*
1812          * Find addresses we are supposed to register as per the netrestrict 
1813          * and netinfo files (/usr/afs/local/NetInfo and 
1814          * /usr/afs/local/NetRestict)
1815          */
1816         char reason[1024];
1817         afs_int32 code = parseNetFiles(FS_HostAddrs, NULL, NULL,
1818                                        ADDRSPERSITE, reason,
1819                                        AFSDIR_SERVER_NETINFO_FILEPATH,
1820                                        AFSDIR_SERVER_NETRESTRICT_FILEPATH);
1821         if (code < 0) {
1822             ViceLog(0, ("Can't register any valid addresses: %s\n", reason));
1823             exit(1);
1824         }
1825         FS_HostAddr_cnt = (afs_uint32) code;
1826     } else
1827 #endif
1828     {
1829         FS_HostAddr_cnt = rx_getAllAddr(FS_HostAddrs, ADDRSPERSITE);
1830     }
1831
1832     FS_registered = 1;
1833     code = Do_VLRegisterRPC();
1834     return code;
1835 }
1836
1837 int
1838 main(int argc, char *argv[])
1839 {
1840     afs_int32 code;
1841     char tbuffer[32];
1842     struct rx_securityClass *sc[4];
1843     struct rx_service *tservice;
1844 #ifdef AFS_PTHREAD_ENV
1845     pthread_t serverPid;
1846     pthread_attr_t tattr;
1847 #else /* AFS_PTHREAD_ENV */
1848     PROCESS parentPid, serverPid;
1849 #endif /* AFS_PTHREAD_ENV */
1850     struct hostent *he;
1851     int minVnodesRequired;      /* min size of vnode cache */
1852 #ifndef AFS_NT40_ENV
1853     struct rlimit rlim;         /* max number of open file descriptors */
1854 #endif
1855     int curLimit;
1856     time_t t;
1857
1858 #ifdef  AFS_AIX32_ENV
1859     struct sigaction nsa;
1860
1861     sigemptyset(&nsa.sa_mask);
1862     nsa.sa_handler = SIG_DFL;
1863     nsa.sa_flags = SA_FULLDUMP;
1864     sigaction(SIGABRT, &nsa, NULL);
1865     sigaction(SIGSEGV, &nsa, NULL);
1866 #endif
1867     osi_audit_init();
1868
1869     /* Initialize dirpaths */
1870     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
1871 #ifdef AFS_NT40_ENV
1872         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
1873 #endif
1874         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
1875                 argv[0]);
1876         exit(2);
1877     }
1878 #ifndef AFS_QUIETFS_ENV
1879     console = afs_fopen("/dev/console", "w");
1880 #endif
1881
1882     if (ParseArgs(argc, argv)) {
1883         FlagMsg();
1884         exit(-1);
1885     }
1886 #ifdef AFS_PTHREAD_ENV
1887     assert(pthread_mutex_init(&fileproc_glock_mutex, NULL) == 0);
1888 #endif /* AFS_PTHREAD_ENV */
1889
1890 #ifdef AFS_SGI_VNODE_GLUE
1891     if (afs_init_kernel_config(-1) < 0) {
1892         printf
1893             ("Can't determine NUMA configuration, not starting fileserver.\n");
1894         exit(1);
1895     }
1896 #endif
1897     confDir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
1898     if (!confDir) {
1899         fprintf(stderr, "Unable to open config directory %s\n",
1900                 AFSDIR_SERVER_ETC_DIRPATH);
1901         exit(-1);
1902     }
1903
1904     NewParms(1);
1905
1906     /* Open FileLog on stdout, stderr, fd 1 and fd2 (for perror), sigh. */
1907 #ifndef AFS_NT40_ENV
1908     serverLogSyslogTag = "fileserver";
1909 #endif
1910     OpenLog(AFSDIR_SERVER_FILELOG_FILEPATH);
1911     SetupLogSignals();
1912
1913     if (SawSpare && SawPctSpare) {
1914         ViceLog(0, ("Both -spare and -pctspare specified, exiting.\n"));
1915         exit(-1);
1916     }
1917 #ifdef AFS_SGI_XFS_IOPS_ENV
1918     ViceLog(0, ("XFS/EFS File server starting\n"));
1919 #else
1920     ViceLog(0, ("File server starting\n"));
1921 #endif
1922
1923 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
1924     /* initialize the pthread soft signal handler thread */
1925     softsig_init();
1926 #endif
1927
1928     /* install signal handlers for controlling the fileserver process */
1929     ResetCheckSignal();         /* set CheckSignal_Signal() sig handler */
1930     ResetCheckDescriptors();    /* set CheckDescriptors_Signal() sig handler */
1931
1932 #if defined(AFS_SGI_ENV)
1933     /* give this guy a non-degrading priority so help busy servers */
1934     schedctl(NDPRI, 0, NDPNORMMAX);
1935     if (SawLock)
1936         plock(PROCLOCK);
1937 #else
1938 #ifndef AFS_NT40_ENV
1939     nice(-5);                   /* TODO: */
1940 #endif
1941 #endif
1942     assert(DInit(buffs) == 0);
1943
1944 #ifdef AFS_NT40_ENV
1945     if (afs_winsockInit() < 0) {
1946         ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
1947         ViceLog(0, ("File server failed to intialize winsock.\n"));
1948         exit(1);
1949     }
1950 #endif
1951     CheckAdminName();
1952
1953     /* if we support more than 16 threads, then we better have the ability 
1954      ** to keep open a large number of files simultaneously 
1955      */
1956 #if     defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV)
1957     curLimit = OPEN_MAX;        /* for pre AIX 4.2 systems */
1958 #elif defined(AFS_NT40_ENV)
1959     curLimit = NT_OPEN_MAX;     /* open file descriptor limit on NT */
1960 #else
1961
1962     curLimit = 0;               /* the number of open file descriptors */
1963     code = getrlimit(RLIMIT_NOFILE, &rlim);
1964     if (code == 0) {
1965         curLimit = rlim.rlim_cur;
1966         rlim.rlim_cur = rlim.rlim_max;
1967         code = setrlimit(RLIMIT_NOFILE, &rlim);
1968         if (code == 0)
1969             curLimit = rlim.rlim_max;
1970     }
1971     if (code != 0)
1972         ViceLog(0, ("Failed to increase open file limit, using default\n"));
1973
1974 #endif /* defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV) */
1975
1976     curLimit -= 32;             /* leave a slack of 32 file descriptors */
1977     if (lwps > curLimit) {
1978         if (curLimit > 0)
1979             lwps = curLimit;
1980         else if (lwps > 16)
1981             lwps = 16;          /* default to a maximum of 16 threads */
1982         ViceLog(0,
1983                 ("The system supports a max of %d open files and we are starting %d threads\n",
1984                  curLimit, lwps));
1985     }
1986 #ifndef AFS_PTHREAD_ENV
1987     assert(LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid) ==
1988            LWP_SUCCESS);
1989 #endif /* !AFS_PTHREAD_ENV */
1990
1991     /* Initialize volume support */
1992     if (!novbc) {
1993         V_BreakVolumeCallbacks = BreakVolumeCallBacksLater;
1994     }
1995
1996 #ifdef AFS_PTHREAD_ENV
1997     SetLogThreadNumProgram( threadNum );
1998 #endif
1999
2000     /* initialize libacl routines */
2001     acl_Initialize(ACL_VERSION);
2002
2003     /* initialize RX support */
2004 #ifndef AFS_NT40_ENV
2005     rxi_syscallp = viced_syscall;
2006 #endif
2007     rx_extraPackets = rxpackets;
2008     rx_extraQuota = 4;          /* for outgoing prserver calls from R threads */
2009     rx_SetBusyThreshold(busy_threshold, VBUSY);
2010     rx_SetCallAbortThreshold(abort_threshold);
2011     rx_SetConnAbortThreshold(abort_threshold);
2012     stackSize = lwps * 4000;
2013     if (stackSize < 32000)
2014         stackSize = 32000;
2015     else if (stackSize > 44000)
2016         stackSize = 44000;
2017 #if    defined(AFS_HPUX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_SGI51_ENV)
2018     rx_SetStackSize(1, stackSize);
2019 #endif
2020     if (udpBufSize)
2021         rx_SetUdpBufSize(udpBufSize);   /* set the UDP buffer size for receive */
2022     if (rx_Init((int)htons(7000)) < 0) {
2023         ViceLog(0, ("Cannot initialize RX\n"));
2024         exit(1);
2025     }
2026     if (!rxJumbograms) {
2027         /* Don't send and don't allow 3.4 clients to send jumbograms. */
2028         rx_SetNoJumbo();
2029     }
2030     if (rxMaxMTU != -1) {
2031         rx_SetMaxMTU(rxMaxMTU);
2032     }
2033     rx_GetIFInfo();
2034     rx_SetRxDeadTime(30);
2035     sc[0] = rxnull_NewServerSecurityObject();
2036     sc[1] = 0;                  /* rxvab_NewServerSecurityObject(key1, 0) */
2037     sc[2] = rxkad_NewServerSecurityObject(rxkad_clear, NULL, get_key, NULL);
2038     sc[3] = rxkad_NewServerSecurityObject(rxkad_crypt, NULL, get_key, NULL);
2039     tservice = rx_NewService( /* port */ 0, /* service id */ 1, /*service name */
2040                              "AFS",
2041                                                         /* security classes */ sc,
2042                                                         /* numb sec classes */
2043                              4, RXAFS_ExecuteRequest);
2044     if (!tservice) {
2045         ViceLog(0,
2046                 ("Failed to initialize RX, probably two servers running.\n"));
2047         exit(-1);
2048     }
2049     rx_SetDestroyConnProc(tservice, (void (*)())h_FreeConnection);
2050     rx_SetMinProcs(tservice, 3);
2051     rx_SetMaxProcs(tservice, lwps);
2052     rx_SetCheckReach(tservice, 1);
2053
2054     tservice =
2055         rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", sc, 4,
2056                       RXSTATS_ExecuteRequest);
2057     if (!tservice) {
2058         ViceLog(0, ("Failed to initialize rpc stat service.\n"));
2059         exit(-1);
2060     }
2061     rx_SetMinProcs(tservice, 2);
2062     rx_SetMaxProcs(tservice, 4);
2063
2064     /*
2065      * Enable RX hot threads, which allows the listener thread to trade
2066      * places with an idle thread and moves the context switch from listener
2067      * to worker out of the critical path.
2068      */
2069     rx_EnableHotThread();
2070
2071     /* Some rx debugging */
2072     if (rxlog || eventlog) {
2073         debugFile = afs_fopen("rx_dbg", "w");
2074         if (rxlog)
2075             rx_debugFile = debugFile;
2076         if (eventlog)
2077             rxevent_debugFile = debugFile;
2078     }
2079
2080     init_sys_error_to_et();     /* Set up error table translation */
2081     h_InitHostPackage();        /* set up local cellname and realmname */
2082     InitCallBack(numberofcbs);
2083     ClearXStatValues();
2084
2085     code = InitVL();
2086     if (code) {
2087         ViceLog(0, ("Fatal error in library initialization, exiting!!\n"));
2088         exit(1);
2089     }
2090
2091     code = InitPR();
2092     if (code) {
2093         ViceLog(0, ("Fatal error in protection initialization, exiting!!\n"));
2094         exit(1);
2095     }
2096
2097     /* allow super users to manage RX statistics */
2098     rx_SetRxStatUserOk(fs_rxstat_userok);
2099
2100     rx_StartServer(0);          /* now start handling requests */
2101
2102     /* we ensure that there is enough space in the vnode buffer to satisfy
2103      ** requests from all concurrent threads. 
2104      ** the maximum number of vnodes used by a single thread at any one time
2105      ** is three ( "link" uses three vnodes simultaneously, one vLarge and
2106      ** two vSmall for linking files and two vLarge and one vSmall for linking
2107      ** files  ) : dhruba 
2108      */
2109     minVnodesRequired = 2 * lwps + 1;
2110     if (minVnodesRequired > nSmallVns) {
2111         nSmallVns = minVnodesRequired;
2112         ViceLog(0,
2113                 ("Overriding -s command line parameter with %d\n",
2114                  nSmallVns));
2115     }
2116     if (minVnodesRequired > large) {
2117         large = minVnodesRequired;
2118         ViceLog(0, ("Overriding -l command line parameter with %d\n", large));
2119     }
2120
2121     /* We now do this after getting the listener up and running, so that client
2122      * connections don't timeout (maybe) if a file server is restarted, since it
2123      * will be available "real soon now".  Worry about whether we can satisfy the 
2124      * calls in the volume package itself.
2125      */
2126     if (VInitVolumePackage(fileServer, large, nSmallVns, 0, volcache)) {
2127         ViceLog(0,
2128                 ("Shutting down: errors encountered initializing volume package\n"));
2129         VShutdown();
2130         exit(1);
2131     }
2132
2133 #ifdef AFS_DEMAND_ATTACH_FS
2134     if (fs_state.options.fs_state_restore) {
2135         /*
2136          * demand attach fs
2137          * restore fileserver state */
2138         fs_stateRestore();
2139     }
2140 #endif /* AFS_DEMAND_ATTACH_FS */
2141
2142     /*
2143      * We are done calling fopen/fdopen. It is safe to use a large
2144      * of the file descriptor cache.
2145      */
2146     ih_UseLargeCache();
2147
2148 #ifdef AFS_PTHREAD_ENV
2149     ViceLog(5, ("Starting pthreads\n"));
2150     assert(pthread_attr_init(&tattr) == 0);
2151     assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
2152
2153     assert(pthread_create
2154            (&serverPid, &tattr, (void *)FiveMinuteCheckLWP,
2155             &fiveminutes) == 0);
2156     assert(pthread_create
2157            (&serverPid, &tattr, (void *)HostCheckLWP, &fiveminutes) == 0);
2158     assert(pthread_create
2159            (&serverPid, &tattr, (void *)FsyncCheckLWP, &fiveminutes) == 0);
2160 #else /* AFS_PTHREAD_ENV */
2161     ViceLog(5, ("Starting LWP\n"));
2162     assert(LWP_CreateProcess
2163            (FiveMinuteCheckLWP, stack * 1024, LWP_MAX_PRIORITY - 2,
2164             (void *)&fiveminutes, "FiveMinuteChecks",
2165             &serverPid) == LWP_SUCCESS);
2166
2167     assert(LWP_CreateProcess
2168            (HostCheckLWP, stack * 1024, LWP_MAX_PRIORITY - 2,
2169             (void *)&fiveminutes, "HostCheck", &serverPid) == LWP_SUCCESS);
2170     assert(LWP_CreateProcess
2171            (FsyncCheckLWP, stack * 1024, LWP_MAX_PRIORITY - 2,
2172             (void *)&fiveminutes, "FsyncCheck", &serverPid) == LWP_SUCCESS);
2173 #endif /* AFS_PTHREAD_ENV */
2174
2175     TM_GetTimeOfDay(&tp, 0);
2176
2177 #ifndef AFS_QUIETFS_ENV
2178     if (console != NULL) { 
2179         time_t t = tp.tv_sec;
2180         fprintf(console, "File server has started at %s\r",
2181                 afs_ctime(&t, tbuffer, sizeof(tbuffer)));
2182     }
2183 #endif
2184
2185     /*
2186      * Figure out the FileServer's name and primary address.
2187      */
2188     ViceLog(0, ("Getting FileServer name...\n"));
2189     code = gethostname(FS_HostName, 64);
2190     if (code) {
2191         ViceLog(0, ("gethostname() failed\n"));
2192     }
2193     ViceLog(0, ("FileServer host name is '%s'\n", FS_HostName));
2194
2195     ViceLog(0, ("Getting FileServer address...\n"));
2196     he = gethostbyname(FS_HostName);
2197     if (!he) {
2198         ViceLog(0, ("Can't find address for FileServer '%s'\n", FS_HostName));
2199     } else {
2200         char hoststr[16];
2201         memcpy(&FS_HostAddr_NBO, he->h_addr, 4);
2202         (void)afs_inet_ntoa_r(FS_HostAddr_NBO, hoststr);
2203         FS_HostAddr_HBO = ntohl(FS_HostAddr_NBO);
2204         ViceLog(0,
2205                 ("FileServer %s has address %s (0x%x or 0x%x in host byte order)\n",
2206                  FS_HostName, hoststr, FS_HostAddr_NBO, FS_HostAddr_HBO));
2207     }
2208
2209     /* Install handler to catch the shutdown signal;
2210      * bosserver assumes SIGQUIT shutdown
2211      */
2212 #if defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
2213     softsig_signal(SIGQUIT, ShutDown_Signal);
2214 #else
2215     (void)signal(SIGQUIT, ShutDown_Signal);
2216 #endif
2217
2218     t = tp.tv_sec;
2219     ViceLog(0,
2220             ("File Server started %s",
2221              afs_ctime(&t, tbuffer, sizeof(tbuffer))));
2222 #if FS_STATS_DETAILED
2223     afs_FullPerfStats.det.epoch.tv_sec = StartTime = tp.tv_sec;
2224 #endif
2225 #ifdef AFS_PTHREAD_ENV
2226     while (1) {
2227         sleep(1000);            /* long time */
2228     }
2229 #else /* AFS_PTHREAD_ENV */
2230     assert(LWP_WaitProcess(&parentPid) == LWP_SUCCESS);
2231 #endif /* AFS_PTHREAD_ENV */
2232 }