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