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 <sys/resource.h>
40 #include <unistd.h> /* sysconf() */
43 #endif /* ITIMER_REAL */
44 #endif /* AFS_NT40_ENV */
49 #ifdef AFS_PTHREAD_ENV
51 #else /* AFS_PTHREAD_ENV */
52 #include <afs/assert.h>
53 #endif /* AFS_PTHREAD_ENV */
56 #include <afs/ptclient.h>
57 #include <afs/afsint.h>
58 #include <afs/vldbint.h>
59 #include <afs/errors.h>
60 #include <afs/ihandle.h>
61 #include <afs/vnode.h>
62 #include <afs/volume.h>
64 #include <afs/cellconfig.h>
66 #include <afs/prs_fs.h>
70 #include <afs/afs_args.h>
71 #include <afs/vlserver.h>
72 #include <afs/afsutil.h>
73 #include <afs/fileutil.h>
75 #include <afs/netutils.h>
79 #if defined(AFS_SGI_ENV)
80 #include "sys/schedctl.h"
83 #include <rx/rx_globals.h>
86 extern int BreakVolumeCallBacks(), InitCallBack();
87 extern int LogLevel, etext;
88 extern afs_int32 BlocksSpare, PctSpare;
91 static void ClearXStatValues(), NewParms(), PrintCounters();
92 static void ResetCheckDescriptors(void), ResetCheckSignal(void);
93 static int CheckSignal();
94 static int FiveMinuteCheckLWP(), HostCheckLWP();
95 extern int GetKeysFromToken();
96 extern struct rx_securityClass *rxnull_NewServerSecurityObject();
97 extern int RXAFS_ExecuteRequest();
98 extern int RXSTATS_ExecuteRequest();
100 int eventlog = 0, rxlog = 0;
102 FILE * console = NULL;
105 #define AFS_QUIETFS_ENV 1
106 #define NT_OPEN_MAX 1024 /* This is an arbitrary no. we came up with for
107 * now. We hope this will be replaced by a more
108 * intelligent estimate later. */
111 int SystemId; /* ViceID of "Administrators"*/
112 int SystemAnyUser; /* Viceid of "System:AnyUser" */
113 prlist SystemAnyUserCPS; /* CPS for "system:AnyUser */
114 int AnonymousID = 0; /* ViceId of "Anonymous"*/
115 prlist AnonCPS; /* CPS for "Anonymous"*/
117 struct afsconf_dir *confDir; /* Configuration dir object */
119 int restartMode = RESTART_ORDINARY;
121 int Testing = 0; /* for ListViceInodes */
124 * Home for the performance statistics.
126 struct afs_PerfStats afs_perfstats;
129 extern int Statistics;
136 int rxJumbograms = 1; /* default is to send and receive jumbograms. */
137 afs_int32 implicitAdminRights = PRSFS_LOOKUP; /* The ADMINISTER right is
141 int stackSize = 24000;
142 int fiveminutes = 300; /* 5 minutes. Change this for debugging only */
143 int CurrentConnections = 0;
144 int hostaclRefresh = 7200; /* refresh host clients' acls every 2 hrs */
145 #if defined(AFS_SGI_ENV)
150 int rxpackets = 150; /* 100 */
151 int nSmallVns = 400; /* 200 */
152 int large = 400; /* 200 */
153 int volcache = 400; /* 400 */
154 int numberofcbs = 60000; /* 60000 */
155 int lwps = 9; /* 6 */
156 int buffs = 90; /* 70 */
157 int novbc = 0; /* Enable Volume Break calls */
158 int busy_threshold = 600;
159 int udpBufSize = 0; /* UDP buffer size for receive*/
164 * FileServer's name and IP address, both network byte order and
167 #define ADDRSPERSITE 16 /* Same global is in rx/rx_user.c */
169 char FS_HostName[128] = "localhost";
170 afs_uint32 FS_HostAddr_NBO;
171 afs_uint32 FS_HostAddr_HBO;
172 afs_uint32 FS_HostAddrs[ADDRSPERSITE], FS_HostAddr_cnt = 0, FS_registered=0;
173 /* All addresses in FS_HostAddrs are in NBO */
180 * Home for the performance statistics.
184 static CheckDescriptors()
188 register int tsize = getdtablesize();
190 for (i = 0; i<tsize; i++) {
191 if (fstat(i, &status) != -1) {
192 printf("%d: dev %x, inode %u, length %u, type/mode %x\n",
193 i, status.st_dev, status.st_ino,
194 status.st_size, status.st_mode);
198 ResetCheckDescriptors();
200 } /*CheckDescriptors*/
203 #ifdef AFS_PTHREAD_ENV
204 void CheckSignal_Signal(x) {CheckSignal(0);}
205 void ShutDown_Signal(x) {ShutDown(0);}
206 void CheckDescriptors_Signal(x) {CheckDescriptors(0);}
207 #else /* AFS_PTHREAD_ENV */
208 void CheckSignal_Signal(x) {IOMGR_SoftSig(CheckSignal, 0);}
209 void ShutDown_Signal(x) {IOMGR_SoftSig(ShutDown, 0);}
210 void CheckDescriptors_Signal(x) {IOMGR_SoftSig(CheckDescriptors, 0);}
211 #endif /* AFS_PTHREAD_ENV */
213 /* check whether caller is authorized to manage RX statistics */
214 int fs_rxstat_userok(call)
215 struct rx_call *call;
217 return afsconf_SuperUser(confDir, call, (char *)0);
220 static void ResetCheckSignal(void)
223 signal(SIGPOLL, CheckSignal_Signal);
226 signal(SIGUSR2, CheckSignal_Signal);
228 signal(SIGXCPU, CheckSignal_Signal);
233 static void ResetCheckDescriptors(void)
236 signal(SIGTERM, CheckDescriptors_Signal);
241 /* proc called by rxkad module to get a key */
242 static int get_key(arock, akvno, akey)
245 register afs_int32 akvno;
249 static struct afsconf_key tkey;
250 register afs_int32 code;
253 ViceLog(0, ("conf dir not open\n"));
256 code = afsconf_GetKey(confDir, akvno, tkey.key);
259 memcpy(akey, tkey.key, sizeof(tkey.key));
265 int viced_syscall(a3, a4, a5)
272 #ifndef AFS_LINUX20_ENV
273 old = (void (*)())signal(SIGSYS, SIG_IGN);
275 rcode = syscall (AFS_SYSCALL, 28 /* AFSCALL_CALL */, a3, a4, a5);
276 #ifndef AFS_LINUX20_ENV
284 #if !defined(AFS_NT40_ENV)
285 #include "AFS_component_version_number.c"
286 #endif /* !AFS_NT40_ENV */
297 struct rx_securityClass *sc[4];
298 struct rx_service *tservice;
299 #ifdef AFS_PTHREAD_ENV
300 pthread_t parentPid, serverPid;
301 pthread_attr_t tattr;
303 #else /* AFS_PTHREAD_ENV */
304 PROCESS parentPid, serverPid;
305 #endif /* AFS_PTHREAD_ENV */
307 int minVnodesRequired; /* min size of vnode cache */
309 struct rlimit rlim; /* max number of open file descriptors */
314 struct sigaction nsa;
316 sigemptyset(&nsa.sa_mask);
317 nsa.sa_handler = SIG_DFL;
318 nsa.sa_flags = SA_FULLDUMP;
319 sigaction(SIGABRT, &nsa, NULL);
320 sigaction(SIGSEGV, &nsa, NULL);
323 /* Initialize dirpaths */
324 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
326 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0],0);
328 fprintf(stderr,"%s: Unable to obtain AFS server directory.\n", argv[0]);
332 #ifndef AFS_QUIETFS_ENV
333 console = fopen("/dev/console","w");
336 if(ParseArgs(argc,argv)) {
341 #ifdef AFS_PTHREAD_ENV
342 assert(pthread_mutex_init(&fileproc_glock_mutex, NULL) == 0);
343 #endif /* AFS_PTHREAD_ENV */
345 #ifdef AFS_SGI_VNODE_GLUE
346 if (afs_init_kernel_config(-1) <0) {
347 printf("Can't determine NUMA configuration, not starting fileserver.\n");
351 confDir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
353 fprintf(stderr, "Unable to open config directory %s\n",
354 AFSDIR_SERVER_ETC_DIRPATH);
360 /* Open FileLog on stdout, stderr, fd 1 and fd2 (for perror), sigh. */
361 OpenLog(AFSDIR_SERVER_FILELOG_FILEPATH);
364 if (SawSpare && SawPctSpare) {
365 ViceLog(0, ("Both -spare and -pctspare specified, exiting.\n"));
369 #ifdef AFS_SGI_XFS_IOPS_ENV
370 ViceLog(0, ("XFS/EFS File server starting\n"));
372 ViceLog(0, ("File server starting\n"));
375 /* install signal handlers for controlling the fileserver process */
376 ResetCheckSignal(); /* set CheckSignal_Signal() sig handler */
377 ResetCheckDescriptors(); /* set CheckDescriptors_Signal() sig handler */
379 #if defined(AFS_SGI_ENV)
380 /* give this guy a non-degrading priority so help busy servers */
381 schedctl(NDPRI, 0, NDPNORMMAX);
386 nice(-5); /* TODO: */
389 assert(DInit(buffs) == 0);
392 if (afs_winsockInit()<0) {
393 ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
394 ViceLog(0, ("File server failed to intialize winsock.\n"));
400 /* if we support more than 16 threads, then we better have the ability
401 ** to keep open a large number of files simultaneously
403 #if defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV)
404 curLimit = OPEN_MAX; /* for pre AIX 4.2 systems */
405 #elif defined(AFS_NT40_ENV)
406 curLimit = NT_OPEN_MAX; /* open file descriptor limit on NT */
409 curLimit = 0; /* the number of open file descriptors */
410 code = getrlimit(RLIMIT_NOFILE, &rlim);
412 curLimit = rlim.rlim_cur;
413 rlim.rlim_cur = rlim.rlim_max;
414 code = setrlimit(RLIMIT_NOFILE, &rlim);
416 curLimit = rlim.rlim_max;
419 ViceLog(0, ("Failed to increase open file limit, using default\n"));
421 #endif /* defined(AFS_AIX_ENV) && !defined(AFS_AIX42_ENV) */
423 curLimit -= 32; /* leave a slack of 32 file descriptors */
424 if ( lwps > curLimit ) {
427 else if ( lwps > 16 )
428 lwps = 16; /* default to a maximum of 16 threads */
429 ViceLog(0, ("The system supports a max of %d open files and we are starting %d threads\n", curLimit, lwps));
433 #ifndef AFS_PTHREAD_ENV
434 assert(LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid) == LWP_SUCCESS);
435 #endif /* !AFS_PTHREAD_ENV */
437 /* Initialize volume support */
439 V_BreakVolumeCallbacks = BreakVolumeCallBacks;
442 /* initialize libacl routines */
443 acl_Initialize(ACL_VERSION);
445 /* initialize RX support */
447 rxi_syscallp = viced_syscall;
449 rx_extraPackets = rxpackets;
450 rx_extraQuota = 4; /* for outgoing prserver calls from R threads */
451 rx_SetBusyThreshold(busy_threshold, VBUSY);
452 rx_SetCallAbortThreshold(10);
453 rx_SetConnAbortThreshold(10);
454 stackSize = lwps * 4000;
455 if (stackSize < 32000)
457 else if (stackSize > 44000)
459 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_SGI51_ENV)
460 rx_SetStackSize(1, stackSize);
463 rx_SetUdpBufSize(udpBufSize);/* set the UDP buffer size for receive */
464 if (rx_Init((int)htons(7000))<0) {
465 ViceLog(0, ("Cannot initialize RX\n"));
469 /* Don't send and don't allow 3.4 clients to send jumbograms. */
473 rx_SetRxDeadTime(30);
474 sc[0] = rxnull_NewServerSecurityObject();
475 sc[1] = 0; /* rxvab_NewServerSecurityObject(key1, 0) */
476 sc[2] = rxkad_NewServerSecurityObject (rxkad_clear, (char *) 0,
477 get_key, (char *) 0);
478 sc[3] = rxkad_NewServerSecurityObject (rxkad_crypt, (char *) 0,
479 get_key, (char *) 0);
480 tservice = rx_NewService
481 (/* port */ 0, /* service id */ 1, /*service name */ "AFS",
482 /* security classes */ sc, /* numb sec classes */ 4,
483 RXAFS_ExecuteRequest);
485 ViceLog(0, ("Failed to initialize RX, probably two servers running.\n"));
488 rx_SetDestroyConnProc(tservice, (char (*)()) h_FreeConnection);
489 rx_SetMinProcs(tservice, 3);
490 rx_SetMaxProcs(tservice, lwps);
492 tservice = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", sc, 4, RXSTATS_ExecuteRequest);
494 ViceLog(0, ("Failed to initialize rpc stat service.\n"));
497 rx_SetMinProcs(tservice, 2);
498 rx_SetMaxProcs(tservice, 4);
501 * Enable RX hot threads, which allows the listener thread to trade
502 * places with an idle thread and moves the context switch from listener
503 * to worker out of the critical path.
505 rx_EnableHotThread();
507 /* Some rx debugging */
508 if (rxlog || eventlog) {
509 debugFile = fopen("rx_dbg", "w");
510 if (rxlog) rx_debugFile = debugFile;
511 if (eventlog) rxevent_debugFile = debugFile;
514 h_InitHostPackage(); /* set up local cellname and realmname */
515 InitCallBack(numberofcbs);
520 ViceLog(0,("Fatal error in library initialization, exiting!!\n"));
526 ViceLog(0,("Fatal error in protection initialization, exiting!!\n"));
530 /* allow super users to manage RX statistics */
531 rx_SetRxStatUserOk(fs_rxstat_userok);
533 rx_StartServer(0); /* now start handling requests */
535 /* we ensure that there is enough space in the vnode buffer to satisfy
536 ** requests from all concurrent threads.
537 ** the maximum number of vnodes used by a single thread at any one time
538 ** is three ( "link" uses three vnodes simultaneously, one vLarge and
539 ** two vSmall for linking files and two vLarge and one vSmall for linking
542 minVnodesRequired = 2 * lwps + 1;
543 if ( minVnodesRequired > nSmallVns ) {
544 nSmallVns = minVnodesRequired;
545 ViceLog(0, ("Overriding -s command line parameter with %d\n",
548 if ( minVnodesRequired > large ) {
549 large = minVnodesRequired;
550 ViceLog(0, ("Overriding -l command line parameter with %d\n", large));
553 /* We now do this after getting the listener up and running, so that client
554 connections don't timeout (maybe) if a file server is restarted, since it
555 will be available "real soon now". Worry about whether we can satisfy the
556 calls in the volume package itself.
558 if (VInitVolumePackage(fileServer,large,nSmallVns,0, volcache)) {
559 ViceLog(0, ("Shutting down: errors encountered initializing volume package\n"));
565 * We are done calling fopen/fdopen. It is safe to use a large
566 * of the file descriptor cache.
570 #ifdef AFS_PTHREAD_ENV
571 assert(pthread_attr_init(&tattr) == 0);
572 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
573 /* Block signals in the threads */
575 assert(pthread_create(&serverPid, &tattr, (void *)FiveMinuteCheckLWP, &fiveminutes) == 0);
576 assert(pthread_create(&serverPid, &tattr, (void *)HostCheckLWP, &fiveminutes) == 0);
577 AFS_SIGSET_RESTORE();
578 #else /* AFS_PTHREAD_ENV */
579 assert(LWP_CreateProcess(FiveMinuteCheckLWP, stack*1024, LWP_MAX_PRIORITY - 2,
580 &fiveminutes, "FiveMinuteChecks", &serverPid) == LWP_SUCCESS);
582 assert(LWP_CreateProcess(HostCheckLWP, stack*1024, LWP_MAX_PRIORITY - 2,
583 &fiveminutes, "HostCheck", &serverPid) == LWP_SUCCESS);
584 #endif /* AFS_PTHREAD_ENV */
586 TM_GetTimeOfDay(&tp, 0);
588 #ifndef AFS_QUIETFS_ENV
589 if (console != NULL) {
590 fprintf(console, "File server has started at %s\r",
591 afs_ctime(&tp.tv_sec, tbuffer, sizeof(tbuffer)));
596 * Figure out the FileServer's name and primary address.
598 ViceLog(0, ("Getting FileServer name...\n"));
599 code = gethostname(FS_HostName, 64);
601 ViceLog(0, ("gethostname() failed\n"));
603 ViceLog(0, ("FileServer host name is '%s'\n", FS_HostName));
605 ViceLog(0, ("Getting FileServer address...\n"));
606 he = gethostbyname(FS_HostName);
608 ViceLog(0, ("Can't find address for FileServer '%s'\n", FS_HostName));
612 memcpy(&FS_HostAddr_NBO, he->h_addr, 4);
613 afs_inet_ntoa_r(FS_HostAddr_NBO, hoststr);
614 FS_HostAddr_HBO = ntohl(FS_HostAddr_NBO);
615 ViceLog(0,("FileServer %s has address %s (0x%x or 0x%x in host byte order)\n",
616 FS_HostName, hoststr, FS_HostAddr_NBO, FS_HostAddr_HBO));
619 /* Install handler to catch the shutdown signal */
620 signal(SIGQUIT, ShutDown_Signal); /* bosserver assumes SIGQUIT shutdown */
622 ViceLog(0,("File Server started %s",
623 afs_ctime(&tp.tv_sec, tbuffer, sizeof(tbuffer))));
624 #if FS_STATS_DETAILED
625 afs_FullPerfStats.det.epoch.tv_sec = StartTime = tp.tv_sec;
627 #ifdef AFS_PTHREAD_ENV
629 sleep(1000); /* long time */
631 #else /* AFS_PTHREAD_ENV */
632 assert(LWP_WaitProcess(&parentPid) == LWP_SUCCESS);
633 #endif /* AFS_PTHREAD_ENV */
637 /* This LWP does things roughly every 5 minutes */
638 static FiveMinuteCheckLWP()
644 ViceLog(1, ("Starting five minute check process\n"));
646 #ifdef AFS_PTHREAD_ENV
648 #else /* AFS_PTHREAD_ENV */
649 IOMGR_Sleep(fiveminutes);
650 #endif /* AFS_PTHREAD_ENV */
652 /* close the log so it can be removed */
653 ReOpenLog(AFSDIR_SERVER_FILELOG_FILEPATH); /* don't trunc, just append */
654 ViceLog(2, ("Cleaning up timed out callbacks\n"));
655 if(CleanupTimedOutCallBacks())
656 ViceLog(5,("Timed out callbacks deleted\n"));
657 ViceLog(2, ("Set disk usage statistics\n"));
659 if (FS_registered == 1) Do_VLRegisterRPC();
660 if(printBanner && (++msg&1)) { /* Every 10 minutes */
661 time_t now = FT_ApproxTime();
662 if (console != NULL) {
663 #ifndef AFS_QUIETFS_ENV
664 fprintf(console,"File server is running at %s\r",
665 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
666 #endif /* AFS_QUIETFS_ENV */
667 ViceLog(2, ("File server is running at %s\n",
668 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
672 } /*FiveMinuteCheckLWP*/
675 /* This LWP does host checks every 5 minutes: it should not be used for
676 * other 5 minute activities because it may be delayed by timeouts when
677 * it probes the workstations
679 static HostCheckLWP()
682 ViceLog(1, ("Starting Host check process\n"));
684 #ifdef AFS_PTHREAD_ENV
686 #else /* AFS_PTHREAD_ENV */
687 IOMGR_Sleep(fiveminutes);
688 #endif /* AFS_PTHREAD_ENV */
689 ViceLog(2, ("Checking for dead venii & clients\n"));
695 #define MAXADMINNAME 64
696 char adminName[MAXADMINNAME];
704 if ((stat("/AdminName", &status)) || /* if file does not exist */
705 (status.st_size <= 0) || /* or it is too short */
706 (status.st_size >= (MAXADMINNAME)) || /* or it is too long */
707 !(fd = open("/AdminName", O_RDONLY, 0))) { /* or the open fails */
708 strcpy(adminName, "System:Administrators"); /* use the default name */
711 read(fd, adminName, status.st_size); /* use name from the file */
714 close(fd); /* close fd if it was opened */
719 /*------------------------------------------------------------------------
720 * PRIVATE ClearXStatValues
723 * Initialize all of the values collected via the xstat
733 * Must be called during File Server initialization.
737 *------------------------------------------------------------------------*/
739 static void ClearXStatValues()
741 { /*ClearXStatValues*/
743 struct fs_stats_opTimingData *opTimeP; /*Ptr to timing struct*/
744 struct fs_stats_xferData *opXferP; /*Ptr to xfer struct*/
745 int i; /*Loop counter*/
748 * Zero all xstat-related structures.
750 memset((char *)(&afs_perfstats), 0, sizeof(struct afs_PerfStats));
751 #if FS_STATS_DETAILED
752 memset((char *)(&afs_FullPerfStats), 0, sizeof(struct fs_stats_FullPerfStats));
755 * That's not enough. We have to set reasonable minima for
756 * time and xfer values in the detailed stats.
758 opTimeP = &(afs_FullPerfStats.det.rpcOpTimes[0]);
759 for (i = 0; i < FS_STATS_NUM_RPC_OPS; i++, opTimeP++)
760 opTimeP->minTime.tv_sec = 999999;
762 opXferP = &(afs_FullPerfStats.det.xferOpTimes[0]);
763 for (i = 0; i < FS_STATS_NUM_XFER_OPS; i++, opXferP++) {
764 opXferP->minTime.tv_sec = 999999;
765 opXferP->minBytes = 999999999;
769 * There's more. We have to set our unique system identifier, as
770 * declared in param.h. If such a thing is not defined, we bitch
771 * and declare ourselves to be an unknown system type.
774 afs_perfstats.sysname_ID = SYS_NAME_ID;
777 ViceLog(0, ("Sys name ID constant not defined in param.h!!\n"));
778 ViceLog(0, ("[Choosing ``undefined'' sys name ID.\n"));
780 afs_perfstats.sysname_ID = SYS_NAME_ID_UNDEFINED;
781 #endif /* SYS_NAME_ID */
784 } /*ClearXStatValues*/
787 static void PrintCounters()
790 int dirbuff, dircall, dirio;
792 int workstations, activeworkstations, delworkstations;
796 TM_GetTimeOfDay(&tpl, 0);
798 ViceLog(0, ("Vice was last started at %s\n",
799 afs_ctime(&StartTime, tbuffer, sizeof(tbuffer))));
803 DStat(&dirbuff, &dircall, &dirio);
804 ViceLog(0,("With %d directory buffers; %d reads resulted in %d read I/Os\n",
805 dirbuff, dircall, dirio));
806 rx_PrintStats(stderr);
808 PrintCallBackStats();
810 processSize = -1; /* TODO: */
812 processSize = (int)((long) sbrk(0) >> 10);
814 ViceLog(0,("There are %d connections, process size %d\n", CurrentConnections, processSize));
815 h_GetWorkStats(&workstations, &activeworkstations, &delworkstations,
818 ("There are %d workstations, %d are active (req in < 15 mins), %d marked \"down\"\n",
819 workstations, activeworkstations, delworkstations));
829 if (FS_registered > 0) {
831 * We have proper ip addresses; tell the vlserver what we got; the following
832 * routine will do the proper reporting for us
844 void ShutDownAndCore(dopanic)
847 time_t now = time(0);
851 ViceLog(0, ("Shutting down file server at %s",
852 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
854 ViceLog(0, ("ABNORMAL SHUTDOWN, see core file.\n"));
855 #ifndef AFS_QUIETFS_ENV
856 if (console != NULL) {
857 fprintf(console,"File server restart/shutdown received at %s\r",
858 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
864 /* do not allows new reqests to be served from now on, all new requests
865 are returned with an error code of RX_RESTARTING ( transient failure ) */
866 rx_SetRxTranquil(); /* dhruba */
870 rx_PrintStats(debugFile);
873 if (console != NULL) {
876 #ifndef AFS_QUIETFS_ENV
877 fprintf(console, "File server has terminated abnormally at %s\r",
878 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
880 ViceLog(0, ("File server has terminated abnormally at %s\n",
881 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
883 #ifndef AFS_QUIETFS_ENV
884 fprintf(console, "File server has terminated normally at %s\r",
885 afs_ctime(&now, tbuffer, sizeof(tbuffer)));
887 ViceLog(0, ("File server has terminated normally at %s\n",
888 afs_ctime(&now, tbuffer, sizeof(tbuffer))));
896 void ShutDown() /* backward compatibility */
898 ShutDownAndCore(DONTPANIC);
907 /* default supports help flag */
909 strcpy(buffer, "Usage: fileserver ");
910 strcat(buffer, "[-d <debug level>] ");
911 strcat(buffer, "[-p <number of processes>] ");
912 strcat(buffer, "[-spare <number of spare blocks>] ");
913 strcat(buffer, "[-pctspare <percentage spare>] ");
914 strcat(buffer, "[-b <buffers>] ");
915 strcat(buffer, "[-l <large vnodes>] ");
916 strcat(buffer, "[-s <small vnodes>] ");
917 strcat(buffer, "[-vc <volume cachesize>] ");
918 strcat(buffer, "[-w <call back wait interval>] ");
919 strcat(buffer, "[-cb <number of call backs>] ");
920 strcat(buffer, "[-banner (print banner every 10 minutes)] ");
921 strcat(buffer, "[-novbc (whole volume cbs disabled)] ");
922 strcat(buffer, "[-implicit <admin mode bits: rlidwka>] ");
923 strcat(buffer, "[-hr <number of hours between refreshing the host cps>] ");
924 strcat(buffer, "[-busyat <redirect clients when queue > n>] ");
925 strcat(buffer, "[-rxpck <number of rx extra packets>] ");
926 strcat(buffer, "[-rxdbg (enable rx debugging)] ");
927 strcat(buffer, "[-rxdbge (enable rxevent debugging)] ");
929 strcat(buffer, "[-m <min percentage spare in partition>] ");
931 #if defined(AFS_SGI_ENV)
932 strcat(buffer, "[-lock (keep fileserver from swapping)] ");
934 strcat(buffer, "[-L (large server conf)] ");
935 strcat(buffer, "[-S (small server conf)] ");
936 strcat(buffer, "[-k <stack size>] ");
937 strcat(buffer, "[-realm <Kerberos realm name>] ");
938 strcat(buffer, "[-udpsize <size of socket buffer in bytes>] ");
939 /* strcat(buffer, "[-enable_peer_stats] "); */
940 /* strcat(buffer, "[-enable_process_stats] "); */
941 strcat(buffer, "[-help]\n");
943 ViceLog(0, ("%s", buffer));
952 static afs_int32 ParseRights(arights)
959 if (!arights || !strcmp(arights, "")) {
960 printf("Missing list of mode bits on -implicit option\n");
963 if (!strcmp(arights, "none"))
965 else if (!strcmp(arights, "read"))
966 mode = PRSFS_READ | PRSFS_LOOKUP;
967 else if (!strcmp(arights, "write"))
968 mode = PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT |
969 PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK;
970 else if (!strcmp(arights, "all"))
971 mode = PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT |
972 PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER;
974 len = strlen(arights);
977 if (tc == 'r') mode |= PRSFS_READ;
978 else if (tc == 'l') mode |= PRSFS_LOOKUP;
979 else if (tc == 'i') mode |= PRSFS_INSERT;
980 else if (tc == 'd') mode |= PRSFS_DELETE;
981 else if (tc == 'w') mode |= PRSFS_WRITE;
982 else if (tc == 'k') mode |= PRSFS_LOCK;
983 else if (tc == 'a') mode |= PRSFS_ADMINISTER;
984 else if (tc == 'A') mode |= PRSFS_USR0;
985 else if (tc == 'B') mode |= PRSFS_USR1;
986 else if (tc == 'C') mode |= PRSFS_USR2;
987 else if (tc == 'D') mode |= PRSFS_USR3;
988 else if (tc == 'E') mode |= PRSFS_USR4;
989 else if (tc == 'F') mode |= PRSFS_USR5;
990 else if (tc == 'G') mode |= PRSFS_USR6;
991 else if (tc == 'H') mode |= PRSFS_USR7;
993 printf("Illegal -implicit rights character '%c'.\n", tc);
1002 * Limit MAX_FILESERVER_THREAD by the system limit on the number of
1003 * pthreads (sysconf(_SC_THREAD_THREADS_MAX)), if applicable and
1006 * AIX: sysconf() limit is real
1007 * HP-UX: sysconf() limit is real
1008 * IRIX: sysconf() limit is apparently NOT real -- too small
1009 * DUX: sysconf() limit is apparently NOT real -- too big
1010 * Linux: sysconf() limit is apparently NOT real -- too big
1011 * Solaris: no sysconf() limit
1014 max_fileserver_thread(void)
1016 #if defined(AFS_PTHREAD_ENV)
1017 #if defined(AFS_AIX_ENV) || defined(AFS_HPUX_ENV)
1020 ans = sysconf(_SC_THREAD_THREADS_MAX);
1021 if (0 < ans && ans < MAX_FILESERVER_THREAD)
1024 #endif /* defined(AFS_PTHREAD_ENV) */
1025 return MAX_FILESERVER_THREAD;
1028 static ParseArgs(argc, argv)
1033 int SawL=0, SawS=0, SawVC=0;
1034 int Sawrxpck = 0, Sawsmall=0, Sawlarge=0, Sawcbs=0, Sawlwps=0, Sawbufs=0;
1037 int bufSize = 0; /* temp variable to read in udp socket buf size*/
1039 for (i = 1; i < argc; i++) {
1040 if (!strcmp(argv[i], "-d")) {
1041 debuglevel = atoi(argv[++i]);
1042 LogLevel = debuglevel;
1045 if (!strcmp(argv[i], "-banner")) {
1048 if (!strcmp(argv[i], "-implicit")) {
1049 implicitAdminRights = ParseRights(argv[++i]);
1050 if (implicitAdminRights < 0) return implicitAdminRights;
1052 if (!strcmp(argv[i], "-L")) {
1055 if (!strcmp(argv[i], "-S")) {
1059 if (!strcmp(argv[i], "-p")) {
1060 int lwps_max = max_fileserver_thread() - FILESERVER_HELPER_THREADS;
1062 lwps = atoi(argv[++i]);
1063 if (lwps > lwps_max)
1069 if (!strcmp(argv[i], "-b")) {
1071 buffs = atoi(argv[++i]);
1074 if (!strcmp(argv[i], "-l")) {
1076 large = atoi(argv[++i]);
1079 if (!strcmp(argv[i], "-vc")) {
1081 volcache = atoi(argv[++i]);
1084 if (!strcmp(argv[i], "-novbc")) {
1088 if (!strcmp(argv[i], "-rxpck")) {
1090 rxpackets = atoi(argv[++i]);
1093 if (!strcmp(argv[i], "-s")) {
1095 nSmallVns = atoi(argv[++i]);
1098 if (!strcmp(argv[i], "-k"))
1099 stack = atoi(argv[++i]);
1100 #if defined(AFS_SGI_ENV)
1102 if (!strcmp(argv[i], "-lock")) {
1107 if (!strcmp(argv[i], "-spare")) {
1108 BlocksSpare = atoi(argv[++i]);
1112 if (!strcmp(argv[i], "-pctspare")) {
1113 PctSpare = atoi(argv[++i]);
1114 BlocksSpare = 0; /* has non-zero default */
1118 if (!strcmp(argv[i], "-w"))
1119 fiveminutes = atoi(argv[++i]);
1121 if (!strcmp(argv[i], "-hr")) {
1122 int hr = atoi(argv[++i]);
1123 if ((hr < 1) || (hr > 36)) {
1124 printf("host acl refresh interval of %d hours is invalid; hours must be between 1 and 36\n\n",
1128 hostaclRefresh = hr*60*60;
1130 if (!strcmp(argv[i], "-rxdbg"))
1133 if (!strcmp(argv[i], "-rxdbge"))
1136 if (!strcmp(argv[i], "-cb")) {
1138 numberofcbs = atoi(argv[++i]);
1139 if ((numberofcbs < 10000) || (numberofcbs > 65535)) {
1140 printf("number of cbs %d invalid; must be between 10000 and 65535\n",
1146 if (!strcmp(argv[i], "-busyat")) {
1148 busy_threshold = atoi(argv[++i]);
1149 if (busy_threshold < 10) {
1150 printf("Busy threshold %d is too low, will compute default.\n",
1155 #ifdef AFS_AIX32_ENV
1157 if (!strcmp(argv[i], "-m")) {
1158 extern int aixlow_water;
1159 aixlow_water = atoi(argv[++i]);
1160 if ((aixlow_water < 0) || (aixlow_water > 30)) {
1161 printf("space reserved %d% invalid; must be between 0-30%\n", aixlow_water);
1167 if (!strcmp(argv[i], "-nojumbo")) {
1171 if (!strcmp(argv[i], "-realm")) {
1172 extern char local_realm[AFS_REALM_SZ];
1173 if (strlen(argv[++i]) >= AFS_REALM_SZ) {
1174 printf("-realm argument must contain fewer than %d characters.\n",AFS_REALM_SZ);
1177 strncpy (local_realm, argv[i], AFS_REALM_SZ);
1180 if ( !strcmp(argv[i], "-udpsize")) {
1181 if ( (i+1) >= argc ) {
1182 printf("You have to specify -udpsize <integer value>\n");
1185 bufSize = atoi(argv[++i]);
1186 if ( bufSize < rx_GetMinUdpBufSize() )
1187 printf("Warning:udpsize %d is less than minimum %d; ignoring\n",
1188 bufSize, rx_GetMinUdpBufSize() );
1190 udpBufSize = bufSize;
1193 if (!strcmp(argv[i], "-enable_peer_stats")) {
1194 rx_enablePeerRPCStats();
1197 if (!strcmp(argv[i], "-enable_process_stats")) {
1198 rx_enableProcessRPCStats();
1200 #ifndef AFS_NT40_ENV
1202 if (strcmp(argv[i], "-syslog")==0) {
1203 /* set syslog logging flag */
1204 serverLogSyslog = 1;
1207 if (strncmp(argv[i], "-syslog=", 8)==0) {
1208 serverLogSyslog = 1;
1209 serverLogSyslogFacility = atoi(argv[i]+8);
1217 printf("Only one of -L, or -S must be specified\n");
1221 if (!Sawrxpck) rxpackets = 100;
1222 if (!Sawsmall) nSmallVns = 200;
1223 if (!Sawlarge) large = 200;
1224 if (!Sawcbs) numberofcbs = 20000;
1225 if (!Sawlwps) lwps = 6;
1226 if (!Sawbufs) buffs = 70;
1227 if (!SawVC) volcache = 200;
1230 if (!Sawrxpck) rxpackets = 200;
1231 if (!Sawsmall) nSmallVns = 600;
1232 if (!Sawlarge) large = 600;
1233 if (!Sawcbs) numberofcbs = 64000;
1234 if (!Sawlwps) lwps = 12;
1235 if (!Sawbufs) buffs = 120;
1236 if (!SawVC) volcache = 600;
1239 busy_threshold = 3*rxpackets/2;
1248 static void NewParms(initializing)
1252 static struct stat sbuf;
1255 char *argv[MAXPARMS];
1258 if (!(stat("/vice/file/parms",&sbuf))) {
1259 parms = (char *)malloc(sbuf.st_size);
1260 if(parms <= (char *)0) return;
1261 fd = open("parms", O_RDONLY, 0666);
1263 ViceLog(0, ("Open for parms failed with errno = %d\n", errno));
1267 i = read(fd, parms, sbuf.st_size);
1269 if(i != sbuf.st_size) {
1271 ViceLog(0, ("Read on parms failed with errno = %d\n", errno));
1274 ("Read on parms failed; expected %d bytes but read %d\n",
1280 for (i = 0;i < MAXPARMS; argv[i++] = 0 );
1282 for (argc = i = 0; i < sbuf.st_size; i++) {
1283 if ((*(parms + i) != ' ') && (*(parms + i) != '\n')){
1284 if(argv[argc] == 0) argv[argc] = (parms+i);
1287 *(parms + i) = '\0';
1288 if(argv[argc] != 0) {
1289 if(++argc == MAXPARMS) break;
1291 while ((*(parms + i + 1) == ' ') || (*(parms + i + 1) == '\n'))
1295 if(ParseArgs(argc, argv) == 0)
1296 ViceLog(0, ("Change parameters to:"));
1298 ViceLog(0, ("Invalid parameter in:"));
1299 for(i = 0; i < argc; i++) {
1300 ViceLog(0, (" %s", argv[i]));
1307 ViceLog(0, ("Received request to change parms but no parms file exists\n"));
1312 /* Miscellaneous routines */
1317 ViceLog (0,("%s\n", msg));
1329 * If this fails, it's because something major is wrong, and is not
1330 * likely to be time dependent.
1332 code = pr_Initialize(2, AFSDIR_SERVER_ETC_DIRPATH, 0);
1334 ViceLog(0, ("Couldn't initialize protection library; code=%d.\n", code));
1337 SystemId = SYSADMINID;
1338 SystemAnyUser = ANYUSERID;
1339 SystemAnyUserCPS.prlist_len = 0;
1340 SystemAnyUserCPS.prlist_val = (afs_int32 *)0;
1341 AnonCPS.prlist_len = 0;
1342 AnonCPS.prlist_val = (afs_int32 *)0;
1344 code = pr_GetCPS(SystemAnyUser, &SystemAnyUserCPS);
1347 ("Couldn't get CPS for AnyUser, will try again in 30 seconds; code=%d.\n",
1351 code = pr_GetCPS(ANONYMOUSID,&AnonCPS);
1353 ViceLog(0,("Couldn't get Anonymous CPS, exiting; code=%d.\n", code));
1356 AnonymousID = ANONYMOUSID;
1359 #ifdef AFS_PTHREAD_ENV
1361 #else /* AFS_PTHREAD_ENV */
1363 #endif /* AFS_PTHREAD_ENV */
1367 struct rx_connection *serverconns[MAXSERVERS];
1368 struct ubik_client *cstruct;
1369 afs_int32 vl_Initialize(confDir)
1371 { afs_int32 code, scIndex = 0, i;
1372 struct afsconf_dir *tdir;
1373 struct rx_securityClass *sc;
1374 struct afsconf_cell info;
1376 tdir = afsconf_Open(confDir);
1378 ViceLog(0, ("Could not open configuration directory (%s).\n", confDir));
1381 code = afsconf_ClientAuth(tdir, &sc, &scIndex);
1383 ViceLog(0, ("Could not get security object for localAuth\n"));
1386 code = afsconf_GetCellInfo(tdir,(char *)0, AFSCONF_VLDBSERVICE, &info);
1387 if (info.numServers > MAXSERVERS) {
1388 ViceLog(0, ("vl_Initialize: info.numServers=%d (> MAXSERVERS=%d)\n",info.numServers, MAXSERVERS));
1391 for (i = 0;i<info.numServers;i++)
1392 serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port,
1393 USER_SERVICE_ID, sc, scIndex);
1394 code = ubik_ClientInit(serverconns, &cstruct);
1396 ViceLog(0, ("vl_Initialize: ubik client init failed.\n"));
1402 #define SYSIDMAGIC 0x88aabbcc
1403 #define SYSIDVERSION 1
1406 afs_int32 fd, nentries, i;
1407 struct versionStamp vsn;
1411 if ((stat(AFSDIR_SERVER_SYSID_FILEPATH, &status)) || (status.st_size <= 0)) {
1412 ViceLog(0, ("%s: doesn't exist\n", AFSDIR_SERVER_SYSID_FILEPATH));
1415 if (!(fd = open(AFSDIR_SERVER_SYSID_FILEPATH, O_RDONLY, 0))) {
1416 ViceLog(0, ("%s: can't open (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1419 if ((i = read(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1420 ViceLog(0, ("%s: Read failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1423 if (vsn.magic != SYSIDMAGIC) {
1424 ViceLog(0, ("%s: wrong magic %x (we support %x)\n", AFSDIR_SERVER_SYSID_FILEPATH, vsn.magic, SYSIDMAGIC));
1427 if (vsn.version != SYSIDVERSION) {
1428 ViceLog(0, ("%s: wrong version %d (we support %d)\n", AFSDIR_SERVER_SYSID_FILEPATH, vsn.version, SYSIDVERSION));
1431 if ((i = read(fd, (char *)&uuid, sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1432 ViceLog(0, ("%s: read of uuid failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1435 afs_ntohuuid(&uuid);
1437 if ((i = read(fd, (char *)&nentries, sizeof(afs_int32))) != sizeof(afs_int32)) {
1438 ViceLog(0, ("%s: Read of entries failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1441 if (nentries <= 0 || nentries > ADDRSPERSITE) {
1442 ViceLog(0, ("%s: invalid num of interfaces: %d\n", AFSDIR_SERVER_SYSID_FILEPATH, nentries));
1445 FS_HostAddr_cnt = nentries;
1446 for (i = 0; i < nentries; i++) {
1447 if (read(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) != sizeof(afs_int32)) {
1448 ViceLog(0, ("%s: Read of addresses failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1449 FS_HostAddr_cnt = 0; /* reset it */
1458 afs_int32 fd, nentries, i;
1459 struct versionStamp vsn;
1463 if (!stat(AFSDIR_SERVER_SYSID_FILEPATH, &status)) {
1465 * File exists; keep the old one around
1467 renamefile(AFSDIR_SERVER_SYSID_FILEPATH, AFSDIR_SERVER_OLDSYSID_FILEPATH);
1469 fd = open(AFSDIR_SERVER_SYSID_FILEPATH, O_WRONLY|O_TRUNC|O_CREAT, 0666);
1471 ViceLog(0, ("%s: can't create (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1474 vsn.magic = SYSIDMAGIC;
1476 if ((i = write(fd, (char *)&vsn, sizeof(vsn))) != sizeof(vsn)) {
1477 ViceLog(0, ("%s: write failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1481 afs_htonuuid(&uuid);
1482 if ((i = write(fd, (char *)&uuid, sizeof(struct afsUUID))) != sizeof(struct afsUUID)) {
1483 ViceLog(0, ("%s: write of uuid failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1486 if ((i = write(fd, (char *)&FS_HostAddr_cnt, sizeof(afs_int32))) != sizeof(afs_int32)) {
1487 ViceLog(0, ("%s: write of # of entries failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1490 for (i = 0; i < FS_HostAddr_cnt; i++) {
1491 if (write(fd, (char *)&FS_HostAddrs[i], sizeof(afs_int32)) != sizeof(afs_int32)) {
1492 ViceLog(0, ("%s: write of addresses failed (%d)\n", AFSDIR_SERVER_SYSID_FILEPATH, errno));
1502 * This routine sets up the buffers for the VL_RegisterAddrs RPC. All addresses
1503 * in FS_HostAddrs[] are in NBO, while the RPC treats them as a "blob" of data
1504 * and so we need to convert each of them into HBO which is what the extra
1505 * array called FS_HostAddrs_HBO is used here.
1507 Do_VLRegisterRPC() {
1510 extern int VL_RegisterAddrs();
1511 afs_uint32 FS_HostAddrs_HBO[ADDRSPERSITE];
1514 for (i=0; i < FS_HostAddr_cnt ; i++)
1515 FS_HostAddrs_HBO[i]=ntohl(FS_HostAddrs[i]);
1516 addrs.bulkaddrs_len = FS_HostAddr_cnt;
1517 addrs.bulkaddrs_val = (afs_uint32 *)FS_HostAddrs_HBO;
1518 code = ubik_Call(VL_RegisterAddrs, cstruct, 0, &FS_HostUUID, 0, &addrs);
1520 if (code == VL_MULTIPADDR) {
1521 ViceLog(0, ("VL_RegisterAddrs rpc failed; The ethernet address exist on a different server; repair it\n"));
1522 ViceLog(0, ("VL_RegisterAddrs rpc failed; See VLLog for details\n"));
1524 } else if (code == RXGEN_OPCODE) {
1525 ViceLog(0, ("vlserver doesn't support VL_RegisterAddrs rpc; ignored\n"));
1526 FS_registered = 2; /* So we don't have to retry in the gc daemon */
1528 ViceLog(0, ("VL_RegisterAddrs rpc failed; will retry periodically (code=%d, err=%d)\n",
1532 FS_registered = 2; /* So we don't have to retry in the gc daemon */
1539 AddrsEqual(cnt, addr1, addr2)
1541 afs_int32 *addr1, *addr2;
1545 for (i = 0; i < cnt; i++) {
1546 for (j = 0; j < cnt; j++) {
1547 if (addr1[i] == addr2[j]) break;
1549 if (j == cnt) return 0;
1558 extern int rxi_numNetAddrs;
1559 extern afs_uint32 rxi_NetAddrs[];
1562 * If this fails, it's because something major is wrong, and is not
1563 * likely to be time dependent.
1565 code = vl_Initialize(AFSDIR_SERVER_ETC_DIRPATH);
1567 ViceLog(0, ("Couldn't initialize protection library; code=%d.\n", code));
1571 /* Read or create the sysid file and register the fileserver's
1572 * IP addresses with the vlserver.
1574 code = ReadSysIdFile();
1576 /* Need to create the file */
1577 ViceLog(0, ("Creating new SysID file\n"));
1578 if (code = afs_uuid_create(&FS_HostUUID)) {
1579 ViceLog(0, ("Failed to create new uuid: %d\n", code));
1583 /* A good sysid file exists; inform the vlserver. If any conflicts,
1584 * we always use the latest interface available as the real truth.
1586 #ifndef AFS_NT40_ENV
1587 if(AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) {
1589 * Find addresses we are supposed to register as per the netrestrict
1590 * and netinfo files (/usr/afs/local/NetInfo and
1591 * /usr/afs/local/NetRestict)
1594 afs_int32 code = parseNetFiles(FS_HostAddrs,NULL, NULL,
1595 ADDRSPERSITE, reason,
1596 AFSDIR_SERVER_NETINFO_FILEPATH,
1597 AFSDIR_SERVER_NETRESTRICT_FILEPATH);
1599 ViceLog(0,("Can't register any valid addresses: %s\n",reason));
1602 FS_HostAddr_cnt = (afs_uint32) code;
1607 FS_HostAddr_cnt = rx_getAllAddr(FS_HostAddrs, ADDRSPERSITE);
1611 code = Do_VLRegisterRPC();