Remove the RCSID macro
[openafs.git] / src / fsprobe / fsprobe.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 /*
11  * Description:
12  *      Implementation of the AFS FileServer probe facility.
13  *
14  *------------------------------------------------------------------------*/
15
16 #include <afsconfig.h>
17 #include <afs/param.h>
18
19
20
21 #include <string.h>
22
23 #include <fsprobe.h>            /*Interface for this module */
24 #include <lwp.h>                /*Lightweight process package */
25 #include <afs/cellconfig.h>
26 #include <afs/afsint.h>
27 #include <afs/afsutil.h>
28     
29 #define LWP_STACK_SIZE  (16 * 1024)
30
31 /*
32  * Routines we need that don't have explicit include file definitions.
33  */
34 extern int RXAFSCB_ExecuteRequest(struct rx_call *);    /*AFS callback dispatcher */
35
36 /*
37  * Help out the linker by explicitly importing the callback routines.
38  */
39 extern afs_int32 SRXAFSCB_CallBack(struct rx_call *, AFSCBFids *, AFSCBs *);
40 extern afs_int32 SRXAFSCB_InitCallBackState2(struct rx_call *, 
41                                              struct interfaceAddr *);
42 extern afs_int32 SRXAFSCB_Probe(struct rx_call *);
43
44 /*
45  * Exported variables.
46  */
47 int fsprobe_numServers;         /*Num servers connected */
48 struct fsprobe_ConnectionInfo *fsprobe_ConnInfo;        /*Ptr to connection array */
49 struct fsprobe_ProbeResults fsprobe_Results;    /*Latest probe results */
50 int fsprobe_ProbeFreqInSecs;    /*Probe freq. in seconds */
51
52 /*
53  * Private globals.
54  */
55 static int fsprobe_initflag = 0;        /*Was init routine called? */
56 static int fsprobe_debug = 0;   /*Debugging output enabled? */
57 static int (*fsprobe_Handler) (void);   /*Probe handler routine */
58 static PROCESS probeLWP_ID;     /*Probe LWP process ID */
59 static int fsprobe_statsBytes;  /*Num bytes in stats block */
60 static int fsprobe_probeOKBytes;        /*Num bytes in probeOK block */
61
62 /*
63  * We have to pass a port to Rx to start up our callback listener
64  * service, but 7001 is already taken up by the Cache Manager.  So,
65  * we make up our own.
66  */
67 #define FSPROBE_CBPORT  7101
68
69
70 /*------------------------------------------------------------------------
71  * [private] fsprobe_CleanupInit
72  *
73  * Description:
74  *      Set up for recovery after an error in initialization (i.e.,
75  *      during a call to fsprobe_Init.
76  *
77  * Arguments:
78  *      None.
79  *
80  * Returns:
81  *      0 on success,
82  *      Error value otherwise.
83  *
84  * Environment:
85  *      This routine is private to the module.
86  *
87  * Side Effects:
88  *      Zeros out basic data structures.
89  *------------------------------------------------------------------------*/
90
91 static int
92 fsprobe_CleanupInit(void)
93 {                               /*fsprobe_CleanupInit */
94
95     afs_int32 code;             /*Return code from callback stubs */
96     struct rx_call *rxcall;     /*Bogus param */
97     AFSCBFids *Fids_Array;      /*Bogus param */
98     AFSCBs *CallBack_Array;     /*Bogus param */
99     struct interfaceAddr *interfaceAddr;        /*Bogus param */
100
101     fsprobe_ConnInfo = (struct fsprobe_ConnectionInfo *)0;
102     memset(&fsprobe_Results, 0, sizeof(struct fsprobe_ProbeResults));
103
104     rxcall = (struct rx_call *)0;
105     Fids_Array = (AFSCBFids *) 0;
106     CallBack_Array = (AFSCBs *) 0;
107     interfaceAddr = NULL;
108
109     code = SRXAFSCB_CallBack(rxcall, Fids_Array, CallBack_Array);
110     if (code)
111         return (code);
112     code = SRXAFSCB_InitCallBackState2(rxcall, interfaceAddr);
113     if (code)
114         return (code);
115     code = SRXAFSCB_Probe(rxcall);
116     return (code);
117
118 }                               /*fsprobe_CleanupInit */
119
120
121 /*------------------------------------------------------------------------
122  * [exported] fsprobe_Cleanup
123  *
124  * Description:
125  *      Clean up our memory and connection state.
126  *
127  * Arguments:
128  *      int a_releaseMem : Should we free up malloc'ed areas?
129  *
130  * Returns:
131  *      0 on total success,
132  *      -1 if the module was never initialized, or there was a problem
133  *              with the fsprobe connection array.
134  *
135  * Environment:
136  *      fsprobe_numServers should be properly set.  We don't do anything
137  *      unless fsprobe_Init() has already been called.
138  *
139  * Side Effects:
140  *      Shuts down Rx connections gracefully, frees allocated space
141  *      (if so directed).
142  *------------------------------------------------------------------------*/
143
144 int
145 fsprobe_Cleanup(int a_releaseMem)
146 {                               /*fsprobe_Cleanup */
147
148     static char rn[] = "fsprobe_Cleanup";       /*Routine name */
149     int code;                   /*Return code */
150     int conn_idx;               /*Current connection index */
151     struct fsprobe_ConnectionInfo *curr_conn;   /*Ptr to fsprobe connection */
152
153     /*
154      * Assume the best, but check the worst.
155      */
156     if (!fsprobe_initflag) {
157         fprintf(stderr, "[%s] Refused; module not initialized\n", rn);
158         return (-1);
159     } else
160         code = 0;
161
162     /*
163      * Take care of all Rx connections first.  Check to see that the
164      * server count is a legal value.
165      */
166     if (fsprobe_numServers <= 0) {
167         fprintf(stderr,
168                 "[%s] Illegal number of servers to clean up (fsprobe_numServers = %d)\n",
169                 rn, fsprobe_numServers);
170         code = -1;
171     } else {
172         if (fsprobe_ConnInfo != (struct fsprobe_ConnectionInfo *)0) {
173             /*
174              * The fsprobe connection structure array exists.  Go through it
175              * and close up any Rx connections it holds.
176              */
177             curr_conn = fsprobe_ConnInfo;
178             for (conn_idx = 0; conn_idx < fsprobe_numServers; conn_idx++) {
179                 if (curr_conn->rxconn != (struct rx_connection *)0) {
180                     rx_DestroyConnection(curr_conn->rxconn);
181                     curr_conn->rxconn = (struct rx_connection *)0;
182                 }
183                 if (curr_conn->rxVolconn != (struct rx_connection *)0) {
184                     rx_DestroyConnection(curr_conn->rxVolconn);
185                     curr_conn->rxVolconn = (struct rx_connection *)0;
186                 }
187                 curr_conn++;
188             }                   /*for each fsprobe connection */
189         }                       /*fsprobe connection structure exists */
190     }                           /*Legal number of servers */
191
192     /*
193      * Now, release all the space we've allocated, if asked to.
194      */
195     if (a_releaseMem) {
196         if (fsprobe_ConnInfo != (struct fsprobe_ConnectionInfo *)0)
197             free(fsprobe_ConnInfo);
198         if (fsprobe_Results.stats != NULL)
199             free(fsprobe_Results.stats);
200         if (fsprobe_Results.probeOK != (int *)0)
201             free(fsprobe_Results.probeOK);
202     }
203
204     /*
205      * Return the news, whatever it is.
206      */
207     return (code);
208
209 }                               /*fsprobe_Cleanup */
210
211 /*------------------------------------------------------------------------
212  * [private] fsprobe_LWP
213  *
214  * Description:
215  *      This LWP iterates over the server connections and gathers up
216  *      the desired statistics from each one on a regular basis.  When
217  *      the sweep is done, the associated handler function is called
218  *      to process the new data.
219  *
220  * Arguments:
221  *      None.
222  *
223  * Returns:
224  *      Nothing.
225  *
226  * Environment:
227  *      Started by fsprobe_Init(), uses global sturctures.
228  *
229  * Side Effects:
230  *      As advertised.
231  *------------------------------------------------------------------------*/
232 static void *
233 fsprobe_LWP(void *unused)
234 {                               /*fsprobe_LWP */
235
236     static char rn[] = "fsprobe_LWP";   /*Routine name */
237     register afs_int32 code;    /*Results of calls */
238     struct timeval tv;          /*Time structure */
239     int conn_idx;               /*Connection index */
240     struct fsprobe_ConnectionInfo *curr_conn;   /*Current connection */
241     struct ProbeViceStatistics *curr_stats;     /*Current stats region */
242     int *curr_probeOK;          /*Current probeOK field */
243     ViceStatistics64 stats64;      /*Current stats region */
244     stats64.ViceStatistics64_val = (afs_uint64 *)malloc(STATS64_VERSION *
245                                                         sizeof(afs_uint64));
246     while (1) {                 /*Service loop */
247         /*
248          * Iterate through the server connections, gathering data.
249          * Don't forget to bump the probe count and zero the statistics
250          * areas before calling the servers.
251          */
252         if (fsprobe_debug)
253             fprintf(stderr,
254                     "[%s] Waking up, collecting data from %d connected servers\n",
255                     rn, fsprobe_numServers);
256         curr_conn = fsprobe_ConnInfo;
257         curr_stats = fsprobe_Results.stats;
258         curr_probeOK = fsprobe_Results.probeOK;
259         fsprobe_Results.probeNum++;
260         memset(fsprobe_Results.stats, 0, fsprobe_statsBytes);
261         memset(fsprobe_Results.probeOK, 0, fsprobe_probeOKBytes);
262
263         for (conn_idx = 0; conn_idx < fsprobe_numServers; conn_idx++) {
264             /*
265              * Grab the statistics for the current FileServer, if the
266              * connection is valid.
267              */
268             if (fsprobe_debug)
269                 fprintf(stderr, "[%s] Contacting server %s\n", rn,
270                         curr_conn->hostName);
271             if (curr_conn->rxconn != (struct rx_connection *)0) {
272                 if (fsprobe_debug)
273                     fprintf(stderr,
274                             "[%s] Connection valid, calling RXAFS_GetStatistics\n",
275                             rn);
276                 *curr_probeOK =
277                     RXAFS_GetStatistics64(curr_conn->rxconn, STATS64_VERSION, &stats64);
278                 if (*curr_probeOK == RXGEN_OPCODE)
279                     *curr_probeOK =
280                         RXAFS_GetStatistics(curr_conn->rxconn, curr_stats);
281                 else if (*curr_probeOK == 0) {
282                     curr_stats->CurrentTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_CURRENTTIME]);
283                     curr_stats->BootTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_BOOTTIME]);
284                     curr_stats->StartTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_STARTTIME]);
285                     curr_stats->CurrentConnections = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_CURRENTCONNECTIONS]);
286                     curr_stats->TotalFetchs = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_TOTALFETCHES]);
287                     curr_stats->TotalStores = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_TOTALSTORES]);
288                     curr_stats->WorkStations = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_WORKSTATIONS]);
289                 }
290             }
291
292             /*Valid Rx connection */
293             /*
294              * Call the Volume Server too to get additional stats
295              */
296             if (fsprobe_debug)
297                 fprintf(stderr, "[%s] Contacting volume server %s\n", rn,
298                         curr_conn->hostName);
299             if (curr_conn->rxVolconn != (struct rx_connection *)0) {
300                 int i, code;
301                 char pname[10];
302                 struct diskPartition partition;
303                 struct diskPartition64 *partition64p =
304                     (struct diskPartition64 *)malloc(sizeof(struct diskPartition64));
305
306                 if (fsprobe_debug)
307                     fprintf(stderr,
308                             "[%s] Connection valid, calling RXAFS_GetStatistics\n",
309                             rn);
310                 for (i = 0; i < curr_conn->partCnt; i++) {
311                     if (curr_conn->partList.partFlags[i] & PARTVALID) {
312                         MapPartIdIntoName(curr_conn->partList.partId[i],
313                                           pname);
314                         code =
315                             AFSVolPartitionInfo64(curr_conn->rxVolconn, pname,
316                                                   partition64p);
317
318                         if (!code) {
319                             curr_stats->Disk[i].BlocksAvailable =
320                                 RoundInt64ToInt31(partition64p->free);
321                             curr_stats->Disk[i].TotalBlocks =
322                                 RoundInt64ToInt31(partition64p->minFree);
323                             strcpy(curr_stats->Disk[i].Name, pname);
324                         }
325                         if (code == RXGEN_OPCODE) {
326                             code = 
327                                 AFSVolPartitionInfo(curr_conn->rxVolconn, 
328                                                     pname, &partition);
329                             if (!code) {
330                                 curr_stats->Disk[i].BlocksAvailable =
331                                     partition.free;
332                                 curr_stats->Disk[i].TotalBlocks =
333                                     partition.minFree;
334                                 strcpy(curr_stats->Disk[i].Name, pname);
335                             }
336                         }
337                         if (code) {
338                             fprintf(stderr,
339                                     "Could not get information on server %s partition %s\n",
340                                     curr_conn->hostName, pname);
341                         }
342                     }
343                 }
344                 free(partition64p);
345             }
346
347
348             /*
349              * Advance the fsprobe connection pointer & stats pointer.
350              */
351             curr_conn++;
352             curr_stats++;
353             curr_probeOK++;
354
355         }                       /*For each fsprobe connection */
356
357         /*
358          * All (valid) connections have been probed.  Now, call the
359          * associated handler function.  The handler does not take
360          * any explicit parameters, rather gets to the goodies via
361          * some of the objects exported by this module.
362          */
363         if (fsprobe_debug)
364             fprintf(stderr,
365                     "[%s] Polling complete, calling associated handler routine.\n",
366                     rn);
367         code = fsprobe_Handler();
368         if (code)
369             fprintf(stderr, "[%s] Handler routine returned error code %d\n",
370                     rn, code);
371
372         /*
373          * Fall asleep for the prescribed number of seconds.
374          */
375         tv.tv_sec = fsprobe_ProbeFreqInSecs;
376         tv.tv_usec = 0;
377         if (fsprobe_debug)
378             fprintf(stderr, "[%s] Falling asleep for %d seconds\n", rn,
379                     fsprobe_ProbeFreqInSecs);
380         code = IOMGR_Select(0,  /*Num fids */
381                             0,  /*Descriptors ready for reading */
382                             0,  /*Descriptors ready for writing */
383                             0,  /*Descriptors w/exceptional conditions */
384                             &tv);       /*Ptr to timeout structure */
385         if (code)
386             fprintf(stderr, "[%s] IOMGR_Select returned code %d\n", rn, code);
387     }                           /*Service loop */
388     free(stats64.ViceStatistics64_val);
389
390     return NULL;
391 }                               /*fsprobe_LWP */
392
393 /*list all the partitions on <aserver> */
394 static int newvolserver = 0;
395
396 int
397 XListPartitions(struct rx_connection *aconn, struct partList *ptrPartList,
398                 afs_int32 *cntp)
399 {
400     struct pIDs partIds;
401     struct partEntries partEnts;
402     register int i, j = 0, code;
403
404     *cntp = 0;
405     if (newvolserver == 1) {
406         for (i = 0; i < 26; i++)
407             partIds.partIds[i] = -1;
408       tryold:
409         code = AFSVolListPartitions(aconn, &partIds);
410         if (!code) {
411             for (i = 0; i < 26; i++) {
412                 if ((partIds.partIds[i]) != -1) {
413                     ptrPartList->partId[j] = partIds.partIds[i];
414                     ptrPartList->partFlags[j] = PARTVALID;
415                     j++;
416                 } else
417                     ptrPartList->partFlags[i] = 0;
418             }
419             *cntp = j;
420         }
421         goto out;
422     }
423     partEnts.partEntries_len = 0;
424     partEnts.partEntries_val = NULL;
425     code = AFSVolXListPartitions(aconn, &partEnts);
426     if (!newvolserver) {
427         if (code == RXGEN_OPCODE) {
428             newvolserver = 1;   /* Doesn't support new interface */
429             goto tryold;
430         } else if (!code) {
431             newvolserver = 2;
432         }
433     }
434     if (!code) {
435         *cntp = partEnts.partEntries_len;
436         if (*cntp > VOLMAXPARTS) {
437             fprintf(stderr,
438                     "Warning: number of partitions on the server too high %d (process only %d)\n",
439                     *cntp, VOLMAXPARTS);
440             *cntp = VOLMAXPARTS;
441         }
442         for (i = 0; i < *cntp; i++) {
443             ptrPartList->partId[i] = partEnts.partEntries_val[i];
444             ptrPartList->partFlags[i] = PARTVALID;
445         }
446         free(partEnts.partEntries_val);
447     }
448   out:
449     if (code)
450         fprintf(stderr,
451                 "Could not fetch the list of partitions from the server\n");
452     return code;
453 }
454
455
456 /*------------------------------------------------------------------------
457  * [exported] fsprobe_Init
458  *
459  * Description:
460  *      Initialize the fsprobe module: set up Rx connections to the
461  *      given set of servers, start up the probe and callback LWPs,
462  *      and associate the routine to be called when a probe completes.
463  *
464  * Arguments:
465  *      int a_numServers                  : Num. servers to connect to.
466  *      struct sockaddr_in *a_socketArray : Array of server sockets.
467  *      int a_ProbeFreqInSecs             : Probe frequency in seconds.
468  *      int (*a_ProbeHandler)()           : Ptr to probe handler fcn.
469  *      int a_debug;                      : Turn debugging output on?
470  *
471  * Returns:
472  *      0 on success,
473  *      -2 for (at least one) connection error,
474  *      LWP process creation code, if it failed,
475  *      -1 for other fatal errors.
476  *
477  * Environment:
478  *      *** MUST BE THE FIRST ROUTINE CALLED FROM THIS PACKAGE ***
479  *      Also, the server security object CBsecobj MUST be a static,
480  *      since it has to stick around after this routine exits.
481  *
482  * Side Effects:
483  *      Sets up just about everything.
484  *------------------------------------------------------------------------*/
485
486 int
487 fsprobe_Init(int a_numServers, struct sockaddr_in *a_socketArray, 
488              int a_ProbeFreqInSecs, int (*a_ProbeHandler)(void),
489              int a_debug)
490 {                               /*fsprobe_Init */
491
492     static char rn[] = "fsprobe_Init";  /*Routine name */
493     register afs_int32 code;    /*Return value */
494     static struct rx_securityClass *CBsecobj;   /*Callback security object */
495     struct rx_securityClass *secobj;    /*Client security object */
496     struct rx_service *rxsrv_afsserver; /*Server for AFS */
497     int arg_errfound;           /*Argument error found? */
498     int curr_srv;               /*Current server idx */
499     struct fsprobe_ConnectionInfo *curr_conn;   /*Ptr to current conn */
500     char *hostNameFound;        /*Ptr to returned host name */
501     int conn_err;               /*Connection error? */
502     int PortToUse;              /*Callback port to use */
503
504     /*
505      * If we've already been called, snicker at the bozo, gently
506      * remind him of his doubtful heritage, and return success.
507      */
508     if (fsprobe_initflag) {
509         fprintf(stderr, "[%s] Called multiple times!\n", rn);
510         return (0);
511     } else
512         fsprobe_initflag = 1;
513
514     /*
515      * Check the parameters for bogosities.
516      */
517     arg_errfound = 0;
518     if (a_numServers <= 0) {
519         fprintf(stderr, "[%s] Illegal number of servers: %d\n", rn,
520                 a_numServers);
521         arg_errfound = 1;
522     }
523     if (a_socketArray == (struct sockaddr_in *)0) {
524         fprintf(stderr, "[%s] Null server socket array argument\n", rn);
525         arg_errfound = 1;
526     }
527     if (a_ProbeFreqInSecs <= 0) {
528         fprintf(stderr, "[%s] Illegal probe frequency: %d\n", rn,
529                 a_ProbeFreqInSecs);
530         arg_errfound = 1;
531     }
532     if (a_ProbeHandler == (int (*)())0) {
533         fprintf(stderr, "[%s] Null probe handler function argument\n", rn);
534         arg_errfound = 1;
535     }
536     if (arg_errfound)
537         return (-1);
538
539     /*
540      * Record our passed-in info.
541      */
542     fsprobe_debug = a_debug;
543     fsprobe_numServers = a_numServers;
544     fsprobe_Handler = a_ProbeHandler;
545     fsprobe_ProbeFreqInSecs = a_ProbeFreqInSecs;
546
547     /*
548      * Get ready in case we have to do a cleanup - basically, zero
549      * everything out.
550      */
551     fsprobe_CleanupInit();
552
553     /*
554      * Allocate the necessary data structures and initialize everything
555      * else.
556      */
557     fsprobe_ConnInfo = (struct fsprobe_ConnectionInfo *)
558         malloc(a_numServers * sizeof(struct fsprobe_ConnectionInfo));
559     if (fsprobe_ConnInfo == (struct fsprobe_ConnectionInfo *)0) {
560         fprintf(stderr,
561                 "[%s] Can't allocate %d connection info structs (%lu bytes)\n",
562                 rn, a_numServers,
563                 (a_numServers * sizeof(struct fsprobe_ConnectionInfo)));
564         return (-1);            /*No cleanup needs to be done yet */
565     }
566 #if 0
567     else
568         fprintf(stderr, "[%s] fsprobe_ConnInfo allocated (%d bytes)\n", rn,
569                 a_numServers * sizeof(struct fsprobe_ConnectionInfo));
570 #endif /* 0 */
571
572     fsprobe_statsBytes = a_numServers * sizeof(struct ProbeViceStatistics);
573     fsprobe_Results.stats = (struct ProbeViceStatistics *)
574         malloc(fsprobe_statsBytes);
575     if (fsprobe_Results.stats == NULL) {
576         fprintf(stderr,
577                 "[%s] Can't allocate %d statistics structs (%d bytes)\n", rn,
578                 a_numServers, fsprobe_statsBytes);
579         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
580         return (-1);
581     } else if (fsprobe_debug)
582         fprintf(stderr, "[%s] fsprobe_Results.stats allocated (%d bytes)\n",
583                 rn, fsprobe_statsBytes);
584
585     fsprobe_probeOKBytes = a_numServers * sizeof(int);
586     fsprobe_Results.probeOK = (int *)malloc(fsprobe_probeOKBytes);
587     if (fsprobe_Results.probeOK == (int *)0) {
588         fprintf(stderr,
589                 "[%s] Can't allocate %d probeOK array entries (%d bytes)\n",
590                 rn, a_numServers, fsprobe_probeOKBytes);
591         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
592         return (-1);
593     } else if (fsprobe_debug)
594         fprintf(stderr, "[%s] fsprobe_Results.probeOK allocated (%d bytes)\n",
595                 rn, fsprobe_probeOKBytes);
596
597     fsprobe_Results.probeNum = 0;
598     fsprobe_Results.probeTime = 0;
599     memset(fsprobe_Results.stats, 0,
600            (a_numServers * sizeof(struct ProbeViceStatistics)));
601
602     /*
603      * Initialize the Rx subsystem, just in case nobody's done it.
604      */
605     if (fsprobe_debug)
606         fprintf(stderr, "[%s] Initializing Rx\n", rn);
607     PortToUse = FSPROBE_CBPORT;
608     do {
609         code = rx_Init(htons(PortToUse));
610         if (code) {
611             if (code == RX_ADDRINUSE) {
612                 if (fsprobe_debug)
613                     fprintf(stderr,
614                             "[%s] Callback port %d in use, advancing\n", rn,
615                             PortToUse);
616                 PortToUse++;
617             } else {
618                 fprintf(stderr, "[%s] Fatal error in rx_Init()\n", rn);
619                 return (-1);
620             }
621         }
622     } while (code);
623     if (fsprobe_debug)
624         fprintf(stderr, "[%s] Rx initialized on port %d\n", rn, PortToUse);
625
626     /*
627      * Create a null Rx server security object, to be used by the
628      * Callback listener.
629      */
630     CBsecobj = rxnull_NewServerSecurityObject();
631     if (CBsecobj == (struct rx_securityClass *)0) {
632         fprintf(stderr,
633                 "[%s] Can't create null security object for the callback listener.\n",
634                 rn);
635         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
636         return (-1);
637     }
638     if (fsprobe_debug)
639         fprintf(stderr, "[%s] Callback server security object created\n", rn);
640
641     /*
642      * Create a null Rx client security object, to be used by the
643      * probe LWP.
644      */
645     secobj = rxnull_NewClientSecurityObject();
646     if (secobj == (struct rx_securityClass *)0) {
647         fprintf(stderr,
648                 "[%s] Can't create client security object for probe LWP.\n",
649                 rn);
650         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
651         return (-1);
652     }
653     if (fsprobe_debug)
654         fprintf(stderr, "[%s] Probe LWP client security object created\n",
655                 rn);
656
657     curr_conn = fsprobe_ConnInfo;
658     conn_err = 0;
659     for (curr_srv = 0; curr_srv < a_numServers; curr_srv++) {
660         /*
661          * Copy in the socket info for the current server, resolve its
662          * printable name if possible.
663          */
664         if (fsprobe_debug) {
665             fprintf(stderr, "[%s] Copying in the following socket info:\n",
666                     rn);
667             fprintf(stderr, "[%s] IP addr 0x%x, port %d\n", rn,
668                     (a_socketArray + curr_srv)->sin_addr.s_addr,
669                     (a_socketArray + curr_srv)->sin_port);
670         }
671         memcpy(&(curr_conn->skt), a_socketArray + curr_srv,
672                sizeof(struct sockaddr_in));
673
674         hostNameFound =
675             hostutil_GetNameByINet(curr_conn->skt.sin_addr.s_addr);
676         if (hostNameFound == NULL) {
677             fprintf(stderr,
678                     "[%s] Can't map Internet address %u to a string name\n",
679                     rn, curr_conn->skt.sin_addr.s_addr);
680             curr_conn->hostName[0] = '\0';
681         } else {
682             strcpy(curr_conn->hostName, hostNameFound);
683             if (fsprobe_debug)
684                 fprintf(stderr, "[%s] Host name for server index %d is %s\n",
685                         rn, curr_srv, curr_conn->hostName);
686         }
687
688         /*
689          * Make an Rx connection to the current server.
690          */
691         if (fsprobe_debug)
692             fprintf(stderr,
693                     "[%s] Connecting to srv idx %d, IP addr 0x%x, port %d, service 1\n",
694                     rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
695                     curr_conn->skt.sin_port);
696         curr_conn->rxconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr,    /*Server addr */
697                                              curr_conn->skt.sin_port,   /*Server port */
698                                              1, /*AFS service num */
699                                              secobj,    /*Security object */
700                                              0);        /*Number of above */
701         if (curr_conn->rxconn == (struct rx_connection *)0) {
702             fprintf(stderr,
703                     "[%s] Can't create Rx connection to server %s (%u)\n",
704                     rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
705             conn_err = 1;
706         }
707         if (fsprobe_debug)
708             fprintf(stderr, "[%s] New connection at %p\n", rn,
709                     curr_conn->rxconn);
710
711         /*
712          * Make an Rx connection to the current volume server.
713          */
714         if (fsprobe_debug)
715             fprintf(stderr,
716                     "[%s] Connecting to srv idx %d, IP addr 0x%x, port %d, service 1\n",
717                     rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
718                     htons(7005));
719         curr_conn->rxVolconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr, /*Server addr */
720                                                 htons(AFSCONF_VOLUMEPORT),      /*Volume Server port */
721                                                 VOLSERVICE_ID,  /*AFS service num */
722                                                 secobj, /*Security object */
723                                                 0);     /*Number of above */
724         if (curr_conn->rxVolconn == (struct rx_connection *)0) {
725             fprintf(stderr,
726                     "[%s] Can't create Rx connection to volume server %s (%u)\n",
727                     rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
728             conn_err = 1;
729         } else {
730             int i, cnt;
731
732             memset(&curr_conn->partList, 0, sizeof(struct partList));
733             curr_conn->partCnt = 0;
734             i = XListPartitions(curr_conn->rxVolconn, &curr_conn->partList,
735                                 &cnt);
736             if (!i) {
737                 curr_conn->partCnt = cnt;
738             }
739         }
740         if (fsprobe_debug)
741             fprintf(stderr, "[%s] New connection at %p\n", rn,
742                     curr_conn->rxVolconn);
743
744
745         /*
746          * Bump the current fsprobe connection to set up.
747          */
748         curr_conn++;
749
750     }                           /*for curr_srv */
751
752     /*
753      * Create the AFS callback service (listener).
754      */
755     if (fsprobe_debug)
756         fprintf(stderr, "[%s] Creating AFS callback listener\n", rn);
757     rxsrv_afsserver = rx_NewService(0,  /*Use default port */
758                                     1,  /*Service ID */
759                                     "afs",      /*Service name */
760                                     &CBsecobj,  /*Ptr to security object(s) */
761                                     1,  /*Number of security objects */
762                                     RXAFSCB_ExecuteRequest);    /*Dispatcher */
763     if (rxsrv_afsserver == (struct rx_service *)0) {
764         fprintf(stderr, "[%s] Can't create callback Rx service/listener\n",
765                 rn);
766         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
767         return (-1);
768     }
769     if (fsprobe_debug)
770         fprintf(stderr, "[%s] Callback listener created\n", rn);
771
772     /*
773      * Start up the AFS callback service.
774      */
775     if (fsprobe_debug)
776         fprintf(stderr, "[%s] Starting up callback listener.\n", rn);
777     rx_StartServer(0 /*Don't donate yourself to LWP pool */ );
778
779     /*
780      * Start up the probe LWP.
781      */
782     if (fsprobe_debug)
783         fprintf(stderr, "[%s] Creating the probe LWP\n", rn);
784     code = LWP_CreateProcess(fsprobe_LWP,       /*Function to start up */
785                              LWP_STACK_SIZE,    /*Stack size in bytes */
786                              1, /*Priority */
787                              (void *)0, /*Parameters */
788                              "fsprobe Worker",  /*Name to use */
789                              &probeLWP_ID);     /*Returned LWP process ID */
790     if (code) {
791         fprintf(stderr, "[%s] Can't create fsprobe LWP!  Error is %d\n", rn,
792                 code);
793         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
794         return (code);
795     }
796     if (fsprobe_debug)
797         fprintf(stderr, "[%s] Probe LWP process structure located at %p\n",
798                 rn, probeLWP_ID);
799
800 #if 0
801     /*
802      * Do I need to do this?
803      */
804     if (fsprobe_debug)
805         fprintf(stderr, "[%s] Calling osi_Wakeup()\n", rn);
806     osi_Wakeup(&rxsrv_afsserver);       /*Wake up anyone waiting for it */
807 #endif /* 0 */
808
809     /*
810      * Return the final results.
811      */
812     if (conn_err)
813         return (-2);
814     else
815         return (0);
816
817 }                               /*fsprobe_Init */
818
819
820 /*------------------------------------------------------------------------
821  * [exported] fsprobe_ForceProbeNow
822  *
823  * Description:
824  *      Wake up the probe LWP, forcing it to execute a probe immediately.
825  *
826  * Arguments:
827  *      None.
828  *
829  * Returns:
830  *      0 on success,
831  *      Error value otherwise.
832  *
833  * Environment:
834  *      The module must have been initialized.
835  *
836  * Side Effects:
837  *      As advertised.
838  *------------------------------------------------------------------------*/
839
840 int
841 fsprobe_ForceProbeNow(void)
842 {                               /*fsprobe_ForceProbeNow */
843
844     static char rn[] = "fsprobe_ForceProbeNow"; /*Routine name */
845
846     /*
847      * There isn't a prayer unless we've been initialized.
848      */
849     if (!fsprobe_initflag) {
850         fprintf(stderr, "[%s] Must call fsprobe_Init first!\n", rn);
851         return (-1);
852     }
853
854     /*
855      * Kick the sucker in the side.
856      */
857     IOMGR_Cancel(probeLWP_ID);
858
859     /*
860      * We did it, so report the happy news.
861      */
862     return (0);
863
864 }                               /*fsprobe_ForceProbeNow */