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