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