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