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