2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /* viced.c - File Server main loop */
14 /* Function - This routine has the initialization code for */
17 /* ********************************************************************** */
19 #include <afsconfig.h>
20 #include <afs/param.h>
27 #include <sys/types.h>
28 #include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
34 #include <WINNT/afsevent.h>
37 #include <netinet/in.h>
39 #include <unistd.h> /* sysconf() */
51 #endif /* ITIMER_REAL */
52 #include <sys/resource.h>
53 #endif /* AFS_NT40_ENV */
58 #ifdef AFS_PTHREAD_ENV
60 #else /* AFS_PTHREAD_ENV */
61 #include <afs/assert.h>
62 #endif /* AFS_PTHREAD_ENV */
65 #include <afs/ptclient.h>
66 #include <afs/afsint.h>
67 #include <afs/vldbint.h>
68 #include <afs/errors.h>
69 #include <afs/ihandle.h>
70 #include <afs/vnode.h>
71 #include <afs/volume.h>
73 #include <afs/cellconfig.h>
75 #include <afs/prs_fs.h>
79 #include <afs/afs_args.h>
80 #include <afs/vlserver.h>
81 #include <afs/afsutil.h>
82 #include <afs/fileutil.h>
84 #include <afs/netutils.h>
88 #if defined(AFS_SGI_ENV)
89 #include "sys/schedctl.h"
92 #include <rx/rx_globals.h>
95 extern int BreakVolumeCallBacks(), InitCallBack();
96 extern int LogLevel, etext;
97 extern afs_int32 BlocksSpare, PctSpare;
100 static void ClearXStatValues(), NewParms(), PrintCounters();
101 static void ResetCheckDescriptors(void), ResetCheckSignal(void);
102 static int CheckSignal();
103 static int FiveMinuteCheckLWP(), HostCheckLWP();
104 extern int GetKeysFromToken();
105 extern int RXAFS_ExecuteRequest();
106 extern int RXSTATS_ExecuteRequest();
108 int eventlog = 0, rxlog = 0;
110 FILE * console = NULL;
113 #define AFS_QUIETFS_ENV 1
114 #define NT_OPEN_MAX 1024 /* This is an arbitrary no. we came up with for
115 * now. We hope this will be replaced by a more
116 * intelligent estimate later. */
119 int SystemId; /* ViceID of "Administrators"*/
120 int SystemAnyUser; /* Viceid of "System:AnyUser" */
121 prlist SystemAnyUserCPS; /* CPS for "system:AnyUser */
122 int AnonymousID = 0; /* ViceId of "Anonymous"*/
123 prlist AnonCPS; /* CPS for "Anonymous"*/
125 struct afsconf_dir *confDir; /* Configuration dir object */
127 int restartMode = RESTART_ORDINARY;
129 int Testing = 0; /* for ListViceInodes */
132 * Home for the performance statistics.
134 struct afs_PerfStats afs_perfstats;
137 extern int Statistics;
144 int rxJumbograms = 1; /* default is to send and receive jumbograms. */
145 afs_int32 implicitAdminRights = PRSFS_LOOKUP; /* The ADMINISTER right is
149 int stackSize = 24000;
150 int fiveminutes = 300; /* 5 minutes. Change this for debugging only */
151 int CurrentConnections = 0;
152 int hostaclRefresh = 7200; /* refresh host clients' acls every 2 hrs */
153 #if defined(AFS_SGI_ENV)
158 int rxpackets = 150; /* 100 */
159 int nSmallVns = 400; /* 200 */
160 int large = 400; /* 200 */
161 int volcache = 400; /* 400 */
162 int numberofcbs = 60000; /* 60000 */
163 int lwps = 9; /* 6 */
164 int buffs = 90; /* 70 */
165 int novbc = 0; /* Enable Volume Break calls */
166 int busy_threshold = 600;
167 int udpBufSize = 0; /* UDP buffer size for receive*/
172 * FileServer's name and IP address, both network byte order and
175 #define ADDRSPERSITE 16 /* Same global is in rx/rx_user.c */
177 char FS_HostName[128] = "localhost";
178 afs_uint32 FS_HostAddr_NBO;
179 afs_uint32 FS_HostAddr_HBO;
180 afs_uint32 FS_HostAddrs[ADDRSPERSITE], FS_HostAddr_cnt = 0, FS_registered=0;
181 /* All addresses in FS_HostAddrs are in NBO */
188 * Home for the performance statistics.
192 static CheckDescriptors()
196 register int tsize = getdtablesize();
198 for (i = 0; i<tsize; i++) {
199 if (fstat(i, &status) != -1) {
200 printf("%d: dev %x, inode %u, length %u, type/mode %x\n",
201 i, status.st_dev, status.st_ino,
202 status.st_size, status.st_mode);
206 ResetCheckDescriptors();
208 } /*CheckDescriptors*/
211 #ifdef AFS_PTHREAD_ENV
212 void CheckSignal_Signal(x) {CheckSignal(0);}
213 void ShutDown_Signal(x) {ShutDown(0);}
214 void CheckDescriptors_Signal(x) {CheckDescriptors(0);}
215 #else /* AFS_PTHREAD_ENV */
216 void CheckSignal_Signal(x) {IOMGR_SoftSig(CheckSignal, 0);}
217 void ShutDown_Signal(x) {IOMGR_SoftSig(ShutDown, 0);}
218 void CheckDescriptors_Signal(x) {IOMGR_SoftSig(CheckDescriptors, 0);}
219 #endif /* AFS_PTHREAD_ENV */
221 /* check whether caller is authorized to manage RX statistics */
222 int fs_rxstat_userok(call)
223 struct rx_call *call;
225 return afsconf_SuperUser(confDir, call, NULL);
228 static void ResetCheckSignal(void)
231 signal(SIGPOLL, CheckSignal_Signal);
234 signal(SIGUSR2, CheckSignal_Signal);
236 signal(SIGXCPU, CheckSignal_Signal);
241 static void ResetCheckDescriptors(void)
244 signal(SIGTERM, CheckDescriptors_Signal);
249 /* proc called by rxkad module to get a key */
250 static int get_key(arock, akvno, akey)
253 register afs_int32 akvno;
257 static struct afsconf_key tkey;
258 register afs_int32 code;
261 ViceLog(0, ("conf dir not open\n"));
264 code = afsconf_GetKey(confDir, akvno, tkey.key);
267 memcpy(akey, tkey.key, sizeof(tkey.key));
273 int viced_syscall(a3, a4, a5)
280 #ifndef AFS_LINUX20_ENV
281 old = (void (*)())signal(SIGSYS, SIG_IGN);
283 rcode = syscall (AFS_SYSCALL, 28 /* AFSCALL_CALL */, a3, a4, a5);
284 #ifndef AFS_LINUX20_ENV
292 #if !defined(AFS_NT40_ENV)
293 #include "AFS_component_version_number.c"
294 #endif /* !AFS_NT40_ENV */
305 struct rx_securityClass *sc[4];
306 struct rx_service *tservice;
307 #ifdef AFS_PTHREAD_ENV
308 pthread_t parentPid, serverPid;
309 pthread_attr_t tattr;
311 #else /* AFS_PTHREAD_ENV */
312 PROCESS parentPid, serverPid;
313 #endif /* AFS_PTHREAD_ENV */
315 int minVnodesRequired; /* min size of vnode cache */
317 struct rlimit rlim; /* max number of open file descriptors */
322 struct sigaction nsa;
324 sigemptyset(&nsa.sa_mask);
325 nsa.sa_handler = SIG_DFL;
326 nsa.sa_flags = SA_FULLDUMP;
327 sigaction(SIGABRT, &nsa, NULL);
328 sigaction(SIGSEGV, &nsa, NULL);
331 /* Initialize dirpaths */
332 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
334 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0],0);
336 fprintf(stderr,"%s: Unable to obtain AFS server directory.\n", argv[0]);
340 #ifndef AFS_QUIETFS_ENV
341 console = fopen("/dev/console","w");
344 if(ParseArgs(argc,argv)) {
349 #ifdef AFS_PTHREAD_ENV
350 assert(pthread_mutex_init(&fileproc_glock_mutex, NULL) == 0);
351 #endif /* AFS_PTHREAD_ENV */
353 #ifdef AFS_SGI_VNODE_GLUE
354 if (afs_init_kernel_config(-1) <0) {
355 printf("Can't determine NUMA configuration, not starting fileserver.\n");
359 confDir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
361 fprintf(stderr, "Unable to open config directory %s\n",
362 AFSDIR_SERVER_ETC_DIRPATH);
368 /* Open FileLog on stdout, stderr, fd 1 and fd2 (for perror), sigh. */
369 OpenLog(AFSDIR_SERVER_FILELOG_FILEPATH);
372 if (SawSpare && SawPctSpare) {
373 ViceLog(0, ("Both -spare and -pctspare specified, exiting.\n"));
377 #ifdef AFS_SGI_XFS_IOPS_ENV
378 ViceLog(0, ("XFS/EFS File server starting\n"));
380 ViceLog(0, ("File server starting\n"));
383 /* install signal handlers for controlling the fileserver process */
384 ResetCheckSignal(); /* set CheckSignal_Signal() sig handler */
385 ResetCheckDescriptors(); /* set CheckDescriptors_Signal() sig handler */
387 #if defined(AFS_SGI_ENV)
388 /* give this guy a non-degrading priority so help busy servers */
389 schedctl(NDPRI, 0, NDPNORMMAX);
394 nice(-5); /* TODO: */
397 assert(DInit(buffs) == 0);
400 if (afs_winsockInit()<0) {
401 ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
402 ViceLog(0, ("File server failed to intialize winsock.\n"));
408 /* if we support more than 16 threads, then we better have the ability
409 ** to keep open a large number of files simultaneously
411 #if defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV)
412 curLimit = OPEN_MAX; /* for pre AIX 4.2 systems */
413 #elif defined(AFS_NT40_ENV)
414 curLimit = NT_OPEN_MAX; /* open file descriptor limit on NT */
417 curLimit = 0; /* the number of open file descriptors */
418 code = getrlimit(RLIMIT_NOFILE, &rlim);
420 curLimit = rlim.rlim_cur;
421 rlim.rlim_cur = rlim.rlim_max;
422 code = setrlimit(RLIMIT_NOFILE, &rlim);
424 curLimit = rlim.rlim_max;
427 ViceLog(0, ("Failed to increase open file limit, using default\n"));
429 #endif /* defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV) */
431 curLimit -= 32; /* leave a slack of 32 file descriptors */
432 if ( lwps > curLimit ) {
435 else if ( lwps > 16 )
436 lwps = 16; /* default to a maximum of 16 threads */
437 ViceLog(0, ("The system supports a max of %d open files and we are starting %d threads\n", curLimit, lwps));
441 #ifndef AFS_PTHREAD_ENV
442 assert(LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid) == LWP_SUCCESS);
443 #endif /* !AFS_PTHREAD_ENV */
445 /* Initialize volume support */
447 V_BreakVolumeCallbacks = BreakVolumeCallBacks;
450 /* initialize libacl routines */
451 acl_Initialize(ACL_VERSION);
453 /* initialize RX support */
455 rxi_syscallp = viced_syscall;
457 rx_extraPackets = rxpackets;
458 rx_extraQuota = 4; /* for outgoing prserver calls from R threads */
459 rx_SetBusyThreshold(busy_threshold, VBUSY);
460 rx_SetCallAbortThreshold(10);
461 rx_SetConnAbortThreshold(10);
462 stackSize = lwps * 4000;
463 if (stackSize < 32000)
465 else if (stackSize > 44000)
467 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_SGI51_ENV)
468 rx_SetStackSize(1, stackSize);
471 rx_SetUdpBufSize(udpBufSize);/* set the UDP buffer size for receive */
472 if (rx_Init((int)htons(7000))<0) {
473 ViceLog(0, ("Cannot initialize RX\n"));
477 /* Don't send and don't allow 3.4 clients to send jumbograms. */
481 rx_SetRxDeadTime(30);
482 sc[0] = rxnull_NewServerSecurityObject();
483 sc[1] = 0; /* rxvab_NewServerSecurityObject(key1, 0) */
484 sc[2] = rxkad_NewServerSecurityObject (rxkad_clear, NULL,
486 sc[3] = rxkad_NewServerSecurityObject (rxkad_crypt, NULL,
488 tservice = rx_NewService
489 (/* port */ 0, /* service id */ 1, /*service name */ "AFS",
490 /* security classes */ sc, /* numb sec classes */ 4,
491 RXAFS_ExecuteRequest);
493 ViceLog(0, ("Failed to initialize RX, probably two servers running.\n"));
496 rx_SetDestroyConnProc(tservice, h_FreeConnection);
497 rx_SetMinProcs(tservice, 3);
498 rx_SetMaxProcs(tservice, lwps);
499 rx_SetCheckReach(tservice, 1);
501 tservice = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", sc, 4, RXSTATS_ExecuteRequest);
503 ViceLog(0, ("Failed to initialize rpc stat service.\n"));
506 rx_SetMinProcs(tservice, 2);
507 rx_SetMaxProcs(tservice, 4);
510 * Enable RX hot threads, which allows the listener thread to trade
511 * places with an idle thread and moves the context switch from listener
512 * to worker out of the critical path.
514 rx_EnableHotThread();
516 /* Some rx debugging */
517 if (rxlog || eventlog) {
518 debugFile = fopen("rx_dbg", "w");
519 if (rxlog) rx_debugFile = debugFile;
520 if (eventlog) rxevent_debugFile = debugFile;
523 h_InitHostPackage(); /* set up local cellname and realmname */
524 InitCallBack(numberofcbs);
529 ViceLog(0,("Fatal error in library initialization, exiting!!\n"));
535 ViceLog(0,("Fatal error in protection initialization, exiting!!\n"));
539 /* allow super users to manage RX statistics */
540 rx_SetRxStatUserOk(fs_rxstat_userok);
542 rx_StartServer(0); /* now start handling requests */
544 /* we ensure that there is enough space in the vnode buffer to satisfy
545 ** requests from all concurrent threads.
546 ** the maximum number of vnodes used by a single thread at any one time
547 ** is three ( "link" uses three vnodes simultaneously, one vLarge and
548 ** two vSmall for linking files and two vLarge and one vSmall for linking
551 minVnodesRequired = 2 * lwps + 1;
552 if ( minVnodesRequired > nSmallVns ) {
553 nSmallVns = minVnodesRequired;
554 ViceLog(0, ("Overriding -s command line parameter with %d\n",
557 if ( minVnodesRequired > large ) {
558 large = minVnodesRequired;
559 ViceLog(0, ("Overriding -l command line parameter with %d\n", large));
562 /* We now do this after getting the listener up and running, so that client
563 connections don't timeout (maybe) if a file server is restarted, since it
564 will be available "real soon now". Worry about whether we can satisfy the
565 calls in the volume package itself.
567 if (VInitVolumePackage(fileServer,large,nSmallVns,0, volcache)) {
568 ViceLog(0, ("Shutting down: errors encountered initializing volume package\n"));
574 * We are done calling fopen/fdopen. It is safe to use a large
575 * of the file descriptor cache.
579 #ifdef AFS_PTHREAD_ENV
580 assert(pthread_attr_init(&tattr) == 0);
581 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
582 /* Block signals in the threads */
584 assert(pthread_create(&serverPid, &tattr, (void *)FiveMinuteCheckLWP, &fiveminutes) == 0);
585 assert(pthread_create(&serverPid, &tattr, (void *)HostCheckLWP, &fiveminutes) == 0);
586 AFS_SIGSET_RESTORE();
587 #else /* AFS_PTHREAD_ENV */
588 assert(LWP_CreateProcess(FiveMinuteCheckLWP, stack*1024, LWP_MAX_PRIORITY - 2,
589 &fiveminutes, "FiveMinuteChecks", &serverPid) == LWP_SUCCESS);
591 assert(LWP_CreateProcess(HostCheckLWP, stack*1024, LWP_MAX_PRIORITY - 2,
592 &fiveminutes, "HostCheck", &serverPid) == LWP_SUCCESS);
593 #endif /* AFS_PTHREAD_ENV */
595 TM_GetTimeOfDay(&tp, 0);
597 #ifndef AFS_QUIETFS_ENV
598 if (console != NULL) {
599 fprintf(console, "File server has started at %s\r",
600 afs_ctime(&tp.tv_sec, tbuffer, sizeof(tbuffer)));
605 * Figure out the FileServer's name and primary address.
607 ViceLog(0, ("Getting FileServer name...\n"));
608 code = gethostname(FS_HostName, 64);
610 ViceLog(0, ("gethostname() failed\n"));
612 ViceLog(0, ("FileServer host name is '%s'\n", FS_HostName));
614 ViceLog(0, ("Getting FileServer address...\n"));
615 he = gethostbyname(FS_HostName);
617 ViceLog(0, ("Can't find address for FileServer '%s'\n", FS_HostName));
621 memcpy(&FS_HostAddr_NBO, he->h_addr, 4);
622 afs_inet_ntoa_r(FS_HostAddr_NBO, hoststr);
623 FS_HostAddr_HBO = ntohl(FS_HostAddr_NBO);
624 ViceLog(0,("FileServer %s has address %s (0x%x or 0x%x in host byte order)\n",
625 FS_HostName, hoststr, FS_HostAddr_NBO, FS_HostAddr_HBO));
628 /* Install handler to catch the shutdown signal */
629 signal(SIGQUIT, ShutDown_Signal); /* bosserver assumes SIGQUIT shutdown */
631 ViceLog(0,("File Server started %s",
632 afs_ctime(&tp.tv_sec, tbuffer, sizeof(tbuffer))));
633 #if FS_STATS_DETAILED
634 afs_FullPerfStats.det.epoch.tv_sec = StartTime = tp.tv_sec;
636 #ifdef AFS_PTHREAD_ENV
638 sleep(1000); /* long time */
640 #else /* AFS_PTHREAD_ENV */
641 assert(LWP_WaitProcess(&parentPid) == LWP_SUCCESS);
642 #endif /* AFS_PTHREAD_ENV */
646 /* This LWP does things roughly every 5 minutes */
647 static FiveMinuteCheckLWP()
653 ViceLog(1, ("Starting five minute check process\n"));
655 #ifdef AFS_PTHREAD_ENV
657 #else /* AFS_PTHREAD_ENV */
658 IOMGR_Sleep(fiveminutes);
659 #endif /* AFS_PTHREAD_ENV */
661 /* close the log so it can be removed */
662 ReOpenLog(AFSDIR_SERVER_FILELOG_FILEPATH); /* don't trunc, just append */
663 ViceLog(2, ("Cleaning up timed out callbacks\n"));
664 if(CleanupTimedOutCallBacks())
665 ViceLog(5,("Timed out callbacks deleted\n"));
666 ViceLog(2, ("Set disk usage statistics\n"));
668 if (FS_registered == 1) Do_VLRegisterRPC();
669 if(printBanner && (++msg&1)) { /* Every 10 minutes */
670 time_t now = FT_ApproxTime();
671 if (console != NULL) {
672 #ifndef AFS_QUIETFS_ENV
673 fprintf(console,"File server is running at %s\r",
674 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
675 #endif /* AFS_QUIETFS_ENV */
676 ViceLog(2, ("File server is running at %s\n",
677 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
681 } /*FiveMinuteCheckLWP*/
684 /* This LWP does host checks every 5 minutes: it should not be used for
685 * other 5 minute activities because it may be delayed by timeouts when
686 * it probes the workstations
688 static HostCheckLWP()
691 ViceLog(1, ("Starting Host check process\n"));
693 #ifdef AFS_PTHREAD_ENV
695 #else /* AFS_PTHREAD_ENV */
696 IOMGR_Sleep(fiveminutes);
697 #endif /* AFS_PTHREAD_ENV */
698 ViceLog(2, ("Checking for dead venii & clients\n"));
704 #define MAXADMINNAME 64
705 char adminName[MAXADMINNAME];
713 if ((stat("/AdminName", &status)) || /* if file does not exist */
714 (status.st_size <= 0) || /* or it is too short */
715 (status.st_size >= (MAXADMINNAME)) || /* or it is too long */
716 !(fd = open("/AdminName", O_RDONLY, 0))) { /* or the open fails */
717 strcpy(adminName, "System:Administrators"); /* use the default name */
720 read(fd, adminName, status.st_size); /* use name from the file */
723 close(fd); /* close fd if it was opened */
728 /*------------------------------------------------------------------------
729 * PRIVATE ClearXStatValues
732 * Initialize all of the values collected via the xstat
742 * Must be called during File Server initialization.
746 *------------------------------------------------------------------------*/
748 static void ClearXStatValues()
750 { /*ClearXStatValues*/
752 struct fs_stats_opTimingData *opTimeP; /*Ptr to timing struct*/
753 struct fs_stats_xferData *opXferP; /*Ptr to xfer struct*/
754 int i; /*Loop counter*/
757 * Zero all xstat-related structures.
759 memset((char *)(&afs_perfstats), 0, sizeof(struct afs_PerfStats));
760 #if FS_STATS_DETAILED
761 memset((char *)(&afs_FullPerfStats), 0, sizeof(struct fs_stats_FullPerfStats));
764 * That's not enough. We have to set reasonable minima for
765 * time and xfer values in the detailed stats.
767 opTimeP = &(afs_FullPerfStats.det.rpcOpTimes[0]);
768 for (i = 0; i < FS_STATS_NUM_RPC_OPS; i++, opTimeP++)
769 opTimeP->minTime.tv_sec = 999999;
771 opXferP = &(afs_FullPerfStats.det.xferOpTimes[0]);
772 for (i = 0; i < FS_STATS_NUM_XFER_OPS; i++, opXferP++) {
773 opXferP->minTime.tv_sec = 999999;
774 opXferP->minBytes = 999999999;
778 * There's more. We have to set our unique system identifier, as
779 * declared in param.h. If such a thing is not defined, we bitch
780 * and declare ourselves to be an unknown system type.
783 afs_perfstats.sysname_ID = SYS_NAME_ID;
786 ViceLog(0, ("Sys name ID constant not defined in param.h!!\n"));
787 ViceLog(0, ("[Choosing ``undefined'' sys name ID.\n"));
789 afs_perfstats.sysname_ID = SYS_NAME_ID_UNDEFINED;
790 #endif /* SYS_NAME_ID */
793 } /*ClearXStatValues*/
796 static void PrintCounters()
799 int dirbuff, dircall, dirio;
801 int workstations, activeworkstations, delworkstations;
805 TM_GetTimeOfDay(&tpl, 0);
807 ViceLog(0, ("Vice was last started at %s\n",
808 afs_ctime(&StartTime, tbuffer, sizeof(tbuffer))));
812 DStat(&dirbuff, &dircall, &dirio);
813 ViceLog(0,("With %d directory buffers; %d reads resulted in %d read I/Os\n",
814 dirbuff, dircall, dirio));
815 rx_PrintStats(stderr);
817 PrintCallBackStats();
819 processSize = -1; /* TODO: */
821 processSize = (int)((long) sbrk(0) >> 10);
823 ViceLog(0,("There are %d connections, process size %d\n", CurrentConnections, processSize));
824 h_GetWorkStats(&workstations, &activeworkstations, &delworkstations,
827 ("There are %d workstations, %d are active (req in < 15 mins), %d marked \"down\"\n",
828 workstations, activeworkstations, delworkstations));
838 if (FS_registered > 0) {
840 * We have proper ip addresses; tell the vlserver what we got; the following
841 * routine will do the proper reporting for us
853 void ShutDownAndCore(dopanic)
856 time_t now = time(0);
860 ViceLog(0, ("Shutting down file server at %s",
861 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
863 ViceLog(0, ("ABNORMAL SHUTDOWN, see core file.\n"));
864 #ifndef AFS_QUIETFS_ENV
865 if (console != NULL) {
866 fprintf(console,"File server restart/shutdown received at %s\r",
867 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
873 /* do not allows new reqests to be served from now on, all new requests
874 are returned with an error code of RX_RESTARTING ( transient failure ) */
875 rx_SetRxTranquil(); /* dhruba */
879 rx_PrintStats(debugFile);
882 if (console != NULL) {
885 #ifndef AFS_QUIETFS_ENV
886 fprintf(console, "File server has terminated abnormally at %s\r",
887 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
889 ViceLog(0, ("File server has terminated abnormally at %s\n",
890 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
892 #ifndef AFS_QUIETFS_ENV
893 fprintf(console, "File server has terminated normally at %s\r",
894 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
896 ViceLog(0, ("File server has terminated normally at %s\n",
897 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
905 void ShutDown() /* backward compatibility */
907 ShutDownAndCore(DONTPANIC);
916 /* default supports help flag */
918 strcpy(buffer, "Usage: fileserver ");
919 strcat(buffer, "[-d <debug level>] ");
920 strcat(buffer, "[-p <number of processes>] ");
921 strcat(buffer, "[-spare <number of spare blocks>] ");
922 strcat(buffer, "[-pctspare <percentage spare>] ");
923 strcat(buffer, "[-b <buffers>] ");
924 strcat(buffer, "[-l <large vnodes>] ");
925 strcat(buffer, "[-s <small vnodes>] ");
926 strcat(buffer, "[-vc <volume cachesize>] ");
927 strcat(buffer, "[-w <call back wait interval>] ");
928 strcat(buffer, "[-cb <number of call backs>] ");
929 strcat(buffer, "[-banner (print banner every 10 minutes)] ");
930 strcat(buffer, "[-novbc (whole volume cbs disabled)] ");
931 strcat(buffer, "[-implicit <admin mode bits: rlidwka>] ");
932 strcat(buffer, "[-hr <number of hours between refreshing the host cps>] ");
933 strcat(buffer, "[-busyat <redirect clients when queue > n>] ");
934 strcat(buffer, "[-rxpck <number of rx extra packets>] ");
935 strcat(buffer, "[-rxdbg (enable rx debugging)] ");
936 strcat(buffer, "[-rxdbge (enable rxevent debugging)] ");
938 strcat(buffer, "[-m <min percentage spare in partition>] ");
940 #if defined(AFS_SGI_ENV)
941 strcat(buffer, "[-lock (keep fileserver from swapping)] ");
943 strcat(buffer, "[-L (large server conf)] ");
944 strcat(buffer, "[-S (small server conf)] ");
945 strcat(buffer, "[-k <stack size>] ");
946 strcat(buffer, "[-realm <Kerberos realm name>] ");
947 strcat(buffer, "[-udpsize <size of socket buffer in bytes>] ");
948 /* strcat(buffer, "[-enable_peer_stats] "); */
949 /* strcat(buffer, "[-enable_process_stats] "); */
950 strcat(buffer, "[-help]\n");
952 ViceLog(0, ("%s", buffer));
961 static afs_int32 ParseRights(arights)
968 if (!arights || !strcmp(arights, "")) {
969 printf("Missing list of mode bits on -implicit option\n");
972 if (!strcmp(arights, "none"))
974 else if (!strcmp(arights, "read"))
975 mode = PRSFS_READ | PRSFS_LOOKUP;
976 else if (!strcmp(arights, "write"))
977 mode = PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT |
978 PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK;
979 else if (!strcmp(arights, "all"))
980 mode = PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT |
981 PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
983 len = strlen(arights);
986 if (tc == 'r') mode |= PRSFS_READ;
987 else if (tc == 'l') mode |= PRSFS_LOOKUP;
988 else if (tc == 'i') mode |= PRSFS_INSERT;
989 else if (tc == 'd') mode |= PRSFS_DELETE;
990 else if (tc == 'w') mode |= PRSFS_WRITE;
991 else if (tc == 'k') mode |= PRSFS_LOCK;
992 else if (tc == 'a') mode |= PRSFS_ADMINISTER;
993 else if (tc == 'A') mode |= PRSFS_USR0;
994 else if (tc == 'B') mode |= PRSFS_USR1;
995 else if (tc == 'C') mode |= PRSFS_USR2;
996 else if (tc == 'D') mode |= PRSFS_USR3;
997 else if (tc == 'E') mode |= PRSFS_USR4;
998 else if (tc == 'F') mode |= PRSFS_USR5;
999 else if (tc == 'G') mode |= PRSFS_USR6;
1000 else if (tc == 'H') mode |= PRSFS_USR7;
1002 printf("Illegal -implicit rights character '%c'.\n", tc);
1011 * Limit MAX_FILESERVER_THREAD by the system limit on the number of
1012 * pthreads (sysconf(_SC_THREAD_THREADS_MAX)), if applicable and
1015 * AIX: sysconf() limit is real
1016 * HP-UX: sysconf() limit is real
1017 * IRIX: sysconf() limit is apparently NOT real -- too small
1018 * DUX: sysconf() limit is apparently NOT real -- too big
1019 * Linux: sysconf() limit is apparently NOT real -- too big
1020 * Solaris: no sysconf() limit
1023 max_fileserver_thread(void)
1025 #if defined(AFS_PTHREAD_ENV)
1026 #if defined(AFS_AIX_ENV) || defined(AFS_HPUX_ENV)
1029 ans = sysconf(_SC_THREAD_THREADS_MAX);
1030 if (0 < ans && ans < MAX_FILESERVER_THREAD)
1033 #endif /* defined(AFS_PTHREAD_ENV) */
1034 return MAX_FILESERVER_THREAD;
1037 static ParseArgs(argc, argv)
1042 int SawL=0, SawS=0, SawVC=0;
1043 int Sawrxpck = 0, Sawsmall=0, Sawlarge=0, Sawcbs=0, Sawlwps=0, Sawbufs=0;
1046 int bufSize = 0; /* temp variable to read in udp socket buf size*/
1048 for (i = 1; i < argc; i++) {
1049 if (!strcmp(argv[i], "-d")) {
1050 debuglevel = atoi(argv[++i]);
1051 LogLevel = debuglevel;
1054 if (!strcmp(argv[i], "-banner")) {
1057 if (!strcmp(argv[i], "-implicit")) {
1058 implicitAdminRights = ParseRights(argv[++i]);
1059 if (implicitAdminRights < 0) return implicitAdminRights;
1061 if (!strcmp(argv[i], "-L")) {
1064 if (!strcmp(argv[i], "-S")) {
1068 if (!strcmp(argv[i], "-p")) {
1069 int lwps_max = max_fileserver_thread() - FILESERVER_HELPER_THREADS;
1071 lwps = atoi(argv[++i]);
1072 if (lwps > lwps_max)
1078 if (!strcmp(argv[i], "-b")) {
1080 buffs = atoi(argv[++i]);
1083 if (!strcmp(argv[i], "-l")) {
1085 large = atoi(argv[++i]);
1088 if (!strcmp(argv[i], "-vc")) {
1090 volcache = atoi(argv[++i]);
1093 if (!strcmp(argv[i], "-novbc")) {
1097 if (!strcmp(argv[i], "-rxpck")) {
1099 rxpackets = atoi(argv[++i]);
1102 if (!strcmp(argv[i], "-s")) {
1104 nSmallVns = atoi(argv[++i]);
1107 if (!strcmp(argv[i], "-k"))
1108 stack = atoi(argv[++i]);
1109 #if defined(AFS_SGI_ENV)
1111 if (!strcmp(argv[i], "-lock")) {
1116 if (!strcmp(argv[i], "-spare")) {
1117 BlocksSpare = atoi(argv[++i]);
1121 if (!strcmp(argv[i], "-pctspare")) {
1122 PctSpare = atoi(argv[++i]);
1123 BlocksSpare = 0; /* has non-zero default */
1127 if (!strcmp(argv[i], "-w"))
1128 fiveminutes = atoi(argv[++i]);
1130 if (!strcmp(argv[i], "-hr")) {
1131 int hr = atoi(argv[++i]);
1132 if ((hr < 1) || (hr > 36)) {
1133 printf("host acl refresh interval of %d hours is invalid; hours must be between 1 and 36\n\n",
1137 hostaclRefresh = hr*60*60;
1139 if (!strcmp(argv[i], "-rxdbg"))
1142 if (!strcmp(argv[i], "-rxdbge"))
1145 if (!strcmp(argv[i], "-cb")) {
1147 numberofcbs = atoi(argv[++i]);
1148 if ((numberofcbs < 10000) || (numberofcbs > 65535)) {
1149 printf("number of cbs %d invalid; must be between 10000 and 65535\n",
1155 if (!strcmp(argv[i], "-busyat")) {
1157 busy_threshold = atoi(argv[++i]);
1158 if (busy_threshold < 10) {
1159 printf("Busy threshold %d is too low, will compute default.\n",
1164 #ifdef AFS_AIX32_ENV
1166 if (!strcmp(argv[i], "-m")) {
1167 extern int aixlow_water;
1168 aixlow_water = atoi(argv[++i]);
1169 if ((aixlow_water < 0) || (aixlow_water > 30)) {
1170 printf("space reserved %d% invalid; must be between 0-30%\n", aixlow_water);
1176 if (!strcmp(argv[i], "-nojumbo")) {
1180 if (!strcmp(argv[i], "-realm")) {
1181 extern char local_realm[AFS_REALM_SZ];
1182 if (strlen(argv[++i]) >= AFS_REALM_SZ) {
1183 printf("-realm argument must contain fewer than %d characters.\n",AFS_REALM_SZ);
1186 strncpy (local_realm, argv[i], AFS_REALM_SZ);
1189 if ( !strcmp(argv[i], "-udpsize")) {
1190 if ( (i+1) >= argc ) {
1191 printf("You have to specify -udpsize <integer value>\n");
1194 bufSize = atoi(argv[++i]);
1195 if ( bufSize < rx_GetMinUdpBufSize() )
1196 printf("Warning:udpsize %d is less than minimum %d; ignoring\n",
1197 bufSize, rx_GetMinUdpBufSize() );
1199 udpBufSize = bufSize;
1202 if (!strcmp(argv[i], "-enable_peer_stats")) {
1203 rx_enablePeerRPCStats();
1206 if (!strcmp(argv[i], "-enable_process_stats")) {
1207 rx_enableProcessRPCStats();
1209 #ifndef AFS_NT40_ENV
1211 if (strcmp(argv[i], "-syslog")==0) {
1212 /* set syslog logging flag */
1213 serverLogSyslog = 1;
1216 if (strncmp(argv[i], "-syslog=", 8)==0) {
1217 serverLogSyslog = 1;
1218 serverLogSyslogFacility = atoi(argv[i]+8);
1226 printf("Only one of -L, or -S must be specified\n");
1230 if (!Sawrxpck) rxpackets = 100;
1231 if (!Sawsmall) nSmallVns = 200;
1232 if (!Sawlarge) large = 200;
1233 if (!Sawcbs) numberofcbs = 20000;
1234 if (!Sawlwps) lwps = 6;
1235 if (!Sawbufs) buffs = 70;
1236 if (!SawVC) volcache = 200;
1239 if (!Sawrxpck) rxpackets = 200;
1240 if (!Sawsmall) nSmallVns = 600;
1241 if (!Sawlarge) large = 600;
1242 if (!Sawcbs) numberofcbs = 64000;
1243 if (!Sawlwps) lwps = 12;
1244 if (!Sawbufs) buffs = 120;
1245 if (!SawVC) volcache = 600;
1248 busy_threshold = 3*rxpackets/2;
1257 static void NewParms(initializing)
1261 static struct stat sbuf;
1264 char *argv[MAXPARMS];
1267 if (!(stat("/vice/file/parms",&sbuf))) {
1268 parms = (char *)malloc(sbuf.st_size);
1270 fd = open("parms", O_RDONLY, 0666);
1272 ViceLog(0, ("Open for parms failed with errno = %d\n", errno));
1276 i = read(fd, parms, sbuf.st_size);
1278 if(i != sbuf.st_size) {
1280 ViceLog(0, ("Read on parms failed with errno = %d\n", errno));
1283 ("Read on parms failed; expected %d bytes but read %d\n",
1290 for (i = 0;i < MAXPARMS; argv[i++] = 0 );
1292 for (argc = i = 0; i < sbuf.st_size; i++) {
1293 if ((*(parms + i) != ' ') && (*(parms + i) != '\n')){
1294 if(argv[argc] == 0) argv[argc] = (parms+i);
1297 *(parms + i) = '\0';
1298 if(argv[argc] != 0) {
1299 if(++argc == MAXPARMS) break;
1301 while ((*(parms + i + 1) == ' ') || (*(parms + i + 1) == '\n'))
1305 if(ParseArgs(argc, argv) == 0) {
1306 ViceLog(0, ("Change parameters to:"));
1308 ViceLog(0, ("Invalid parameter in:"));
1310 for(i = 0; i < argc; i++) {
1311 ViceLog(0, (" %s", argv[i]));
1318 ViceLog(0, ("Received request to change parms but no parms file exists\n"));
1323 /* Miscellaneous routines */
1328 ViceLog (0,("%s\n", msg));
1340 * If this fails, it's because something major is wrong, and is not
1341 * likely to be time dependent.
1343 code = pr_Initialize(2, AFSDIR_SERVER_ETC_DIRPATH, 0);
1345 ViceLog(0, ("Couldn't initialize protection library; code=%d.\n", code));
1348 SystemId = SYSADMINID;
1349 SystemAnyUser = ANYUSERID;
1350 SystemAnyUserCPS.prlist_len = 0;
1351 SystemAnyUserCPS.prlist_val = NULL;
1352 AnonCPS.prlist_len = 0;
1353 AnonCPS.prlist_val = NULL;
1355 code = pr_GetCPS(SystemAnyUser, &SystemAnyUserCPS);
1358 ("Couldn't get CPS for AnyUser, will try again in 30 seconds; code=%d.\n",
1362 code = pr_GetCPS(ANONYMOUSID,&AnonCPS);
1364 ViceLog(0,("Couldn't get Anonymous CPS, exiting; code=%d.\n", code));
1367 AnonymousID = ANONYMOUSID;
1370 #ifdef AFS_PTHREAD_ENV
1372 #else /* AFS_PTHREAD_ENV */
1374 #endif /* AFS_PTHREAD_ENV */
1378 struct rx_connection *serverconns[MAXSERVERS];
1379 struct ubik_client *cstruct;
1380 afs_int32 vl_Initialize(confDir)
1382 { afs_int32 code, scIndex = 0, i;
1383 struct afsconf_dir *tdir;
1384 struct rx_securityClass *sc;
1385 struct afsconf_cell info;
1387 tdir = afsconf_Open(confDir);
1389 ViceLog(0, ("Could not open configuration directory (%s).\n", confDir));
1392 code = afsconf_ClientAuth(tdir, &sc, &scIndex);
1394 ViceLog(0, ("Could not get security object for localAuth\n"));
1397 code = afsconf_GetCellInfo(tdir,NULL, AFSCONF_VLDBSERVICE, &info);
1398 if (info.numServers > MAXSERVERS) {
1399 ViceLog(0, ("vl_Initialize: info.numServers=%d (> MAXSERVERS=%d)\n",info.numServers, MAXSERVERS));
1402 for (i = 0;i<info.numServers;i++)
1403 serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port,
1404 USER_SERVICE_ID, sc, scIndex);
1405 code = ubik_ClientInit(serverconns, &cstruct);
1407 ViceLog(0, ("vl_Initialize: ubik client init failed.\n"));
1413 #define SYSIDMAGIC 0x88aabbcc
1414 #define SYSIDVERSION 1
1417 afs_int32 fd, nentries, i;
1418 struct versionStamp vsn;
1422 if ((stat(AFSDIR_SERVER_SYSID_FILEPATH, &status)) || (status.st_size <= 0)) {
1423 ViceLog(0, ("%s: doesn't exist\n", AFSDIR_SERVER_SYSID_FILEPATH));
1426 if (!(fd = open(AFSDIR_SERVER_SYSID_FILEPATH, O_RDONLY, 0))) {
1427 ViceLog(0, ("%s: can't open (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1430 if ((i = read(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1431 ViceLog(0, ("%s: Read failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1434 if (vsn.magic != SYSIDMAGIC) {
1435 ViceLog(0, ("%s: wrong magic %x (we support %x)\n", AFSDIR_SERVER_SYSID_FILEPATH, vsn.magic, SYSIDMAGIC));
1438 if (vsn.version != SYSIDVERSION) {
1439 ViceLog(0, ("%s: wrong version %d (we support %d)\n", AFSDIR_SERVER_SYSID_FILEPATH, vsn.version, SYSIDVERSION));
1442 if ((i = read(fd, (char *)&uuid, sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1443 ViceLog(0, ("%s: read of uuid failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1446 afs_ntohuuid(&uuid);
1448 if ((i = read(fd, (char *)&nentries, sizeof(afs_int32))) != sizeof(afs_int32)) {
1449 ViceLog(0, ("%s: Read of entries failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1452 if (nentries <= 0 || nentries > ADDRSPERSITE) {
1453 ViceLog(0, ("%s: invalid num of interfaces: %d\n", AFSDIR_SERVER_SYSID_FILEPATH, nentries));
1456 FS_HostAddr_cnt = nentries;
1457 for (i = 0; i < nentries; i++) {
1458 if (read(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) != sizeof(afs_int32)) {
1459 ViceLog(0, ("%s: Read of addresses failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1460 FS_HostAddr_cnt = 0; /* reset it */
1469 afs_int32 fd, nentries, i;
1470 struct versionStamp vsn;
1474 if (!stat(AFSDIR_SERVER_SYSID_FILEPATH, &status)) {
1476 * File exists; keep the old one around
1478 renamefile(AFSDIR_SERVER_SYSID_FILEPATH, AFSDIR_SERVER_OLDSYSID_FILEPATH);
1480 fd = open(AFSDIR_SERVER_SYSID_FILEPATH, O_WRONLY|O_TRUNC|O_CREAT, 0666);
1482 ViceLog(0, ("%s: can't create (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1485 vsn.magic = SYSIDMAGIC;
1487 if ((i = write(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1488 ViceLog(0, ("%s: write failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1492 afs_htonuuid(&uuid);
1493 if ((i = write(fd, (char *)&uuid, sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1494 ViceLog(0, ("%s: write of uuid failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1497 if ((i = write(fd, (char *)&FS_HostAddr_cnt, sizeof(afs_int32))) != sizeof(afs_int32)) {
1498 ViceLog(0, ("%s: write of # of entries failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1501 for (i = 0; i < FS_HostAddr_cnt; i++) {
1502 if (write(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) != sizeof(afs_int32)) {
1503 ViceLog(0, ("%s: write of addresses failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1513 * This routine sets up the buffers for the VL_RegisterAddrs RPC. All addresses
1514 * in FS_HostAddrs[] are in NBO, while the RPC treats them as a "blob" of data
1515 * and so we need to convert each of them into HBO which is what the extra
1516 * array called FS_HostAddrs_HBO is used here.
1518 Do_VLRegisterRPC() {
1521 extern int VL_RegisterAddrs();
1522 afs_uint32 FS_HostAddrs_HBO[ADDRSPERSITE];
1525 for (i=0; i < FS_HostAddr_cnt ; i++)
1526 FS_HostAddrs_HBO[i]=ntohl(FS_HostAddrs[i]);
1527 addrs.bulkaddrs_len = FS_HostAddr_cnt;
1528 addrs.bulkaddrs_val = (afs_uint32 *)FS_HostAddrs_HBO;
1529 code = ubik_Call(VL_RegisterAddrs, cstruct, 0, &FS_HostUUID, 0, &addrs);
1531 if (code == VL_MULTIPADDR) {
1532 ViceLog(0, ("VL_RegisterAddrs rpc failed; The ethernet address exist on a different server; repair it\n"));
1533 ViceLog(0, ("VL_RegisterAddrs rpc failed; See VLLog for details\n"));
1535 } else if (code == RXGEN_OPCODE) {
1536 ViceLog(0, ("vlserver doesn't support VL_RegisterAddrs rpc; ignored\n"));
1537 FS_registered = 2; /* So we don't have to retry in the gc daemon */
1539 ViceLog(0, ("VL_RegisterAddrs rpc failed; will retry periodically (code=%d, err=%d)\n",
1543 FS_registered = 2; /* So we don't have to retry in the gc daemon */
1551 static int AddrsEqual(cnt, addr1, addr2)
1553 afs_int32 *addr1, *addr2;
1557 for (i = 0; i < cnt; i++) {
1558 for (j = 0; j < cnt; j++) {
1559 if (addr1[i] == addr2[j]) break;
1561 if (j == cnt) return 0;
1571 extern int rxi_numNetAddrs;
1572 extern afs_uint32 rxi_NetAddrs[];
1575 * If this fails, it's because something major is wrong, and is not
1576 * likely to be time dependent.
1578 code = vl_Initialize(AFSDIR_SERVER_ETC_DIRPATH);
1580 ViceLog(0, ("Couldn't initialize protection library; code=%d.\n", code));
1584 /* Read or create the sysid file and register the fileserver's
1585 * IP addresses with the vlserver.
1587 code = ReadSysIdFile();
1589 /* Need to create the file */
1590 ViceLog(0, ("Creating new SysID file\n"));
1591 if ((code = afs_uuid_create(&FS_HostUUID))) {
1592 ViceLog(0, ("Failed to create new uuid: %d\n", code));
1596 /* A good sysid file exists; inform the vlserver. If any conflicts,
1597 * we always use the latest interface available as the real truth.
1599 #ifndef AFS_NT40_ENV
1600 if(AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) {
1602 * Find addresses we are supposed to register as per the netrestrict
1603 * and netinfo files (/usr/afs/local/NetInfo and
1604 * /usr/afs/local/NetRestict)
1607 afs_int32 code = parseNetFiles(FS_HostAddrs,NULL, NULL,
1608 ADDRSPERSITE, reason,
1609 AFSDIR_SERVER_NETINFO_FILEPATH,
1610 AFSDIR_SERVER_NETRESTRICT_FILEPATH);
1612 ViceLog(0,("Can't register any valid addresses: %s\n",reason));
1615 FS_HostAddr_cnt = (afs_uint32) code;
1620 FS_HostAddr_cnt = rx_getAllAddr(FS_HostAddrs, ADDRSPERSITE);
1624 code = Do_VLRegisterRPC();