03657eb1a71741d7793a83814f2ee2c8e5ba1985
[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     AFS_UNREACHED(free(stats64.ViceStatistics64_val));
371     AFS_UNREACHED(return(NULL));
372 }                               /*fsprobe_LWP */
373
374 /*list all the partitions on <aserver> */
375 static int newvolserver = 0;
376
377 int
378 XListPartitions(struct rx_connection *aconn, struct partList *ptrPartList,
379                 afs_int32 *cntp)
380 {
381     struct pIDs partIds;
382     struct partEntries partEnts;
383     int i, j = 0, code;
384
385     *cntp = 0;
386     if (newvolserver == 1) {
387         for (i = 0; i < 26; i++)
388             partIds.partIds[i] = -1;
389       tryold:
390         code = AFSVolListPartitions(aconn, &partIds);
391         if (!code) {
392             for (i = 0; i < 26; i++) {
393                 if ((partIds.partIds[i]) != -1) {
394                     ptrPartList->partId[j] = partIds.partIds[i];
395                     ptrPartList->partFlags[j] = PARTVALID;
396                     j++;
397                 } else
398                     ptrPartList->partFlags[i] = 0;
399             }
400             *cntp = j;
401         }
402         goto out;
403     }
404     partEnts.partEntries_len = 0;
405     partEnts.partEntries_val = NULL;
406     code = AFSVolXListPartitions(aconn, &partEnts);
407     if (!newvolserver) {
408         if (code == RXGEN_OPCODE) {
409             newvolserver = 1;   /* Doesn't support new interface */
410             goto tryold;
411         } else if (!code) {
412             newvolserver = 2;
413         }
414     }
415     if (!code) {
416         *cntp = partEnts.partEntries_len;
417         if (*cntp > VOLMAXPARTS) {
418             fprintf(stderr,
419                     "Warning: number of partitions on the server too high %d (process only %d)\n",
420                     *cntp, VOLMAXPARTS);
421             *cntp = VOLMAXPARTS;
422         }
423         for (i = 0; i < *cntp; i++) {
424             ptrPartList->partId[i] = partEnts.partEntries_val[i];
425             ptrPartList->partFlags[i] = PARTVALID;
426         }
427         free(partEnts.partEntries_val);
428     }
429   out:
430     if (code)
431         fprintf(stderr,
432                 "Could not fetch the list of partitions from the server\n");
433     return code;
434 }
435
436
437 /*------------------------------------------------------------------------
438  * [exported] fsprobe_Init
439  *
440  * Description:
441  *      Initialize the fsprobe module: set up Rx connections to the
442  *      given set of servers, start up the probe and callback LWPs,
443  *      and associate the routine to be called when a probe completes.
444  *
445  * Arguments:
446  *      int a_numServers                  : Num. servers to connect to.
447  *      struct sockaddr_in *a_socketArray : Array of server sockets.
448  *      int a_ProbeFreqInSecs             : Probe frequency in seconds.
449  *      int (*a_ProbeHandler)()           : Ptr to probe handler fcn.
450  *      int a_debug;                      : Turn debugging output on?
451  *
452  * Returns:
453  *      0 on success,
454  *      -2 for (at least one) connection error,
455  *      LWP process creation code, if it failed,
456  *      -1 for other fatal errors.
457  *
458  * Environment:
459  *      *** MUST BE THE FIRST ROUTINE CALLED FROM THIS PACKAGE ***
460  *      Also, the server security object CBsecobj MUST be a static,
461  *      since it has to stick around after this routine exits.
462  *
463  * Side Effects:
464  *      Sets up just about everything.
465  *------------------------------------------------------------------------*/
466
467 int
468 fsprobe_Init(int a_numServers, struct sockaddr_in *a_socketArray,
469              int a_ProbeFreqInSecs, int (*a_ProbeHandler)(void),
470              int a_debug)
471 {                               /*fsprobe_Init */
472
473     static char rn[] = "fsprobe_Init";  /*Routine name */
474     afs_int32 code;     /*Return value */
475     static struct rx_securityClass *CBsecobj;   /*Callback security object */
476     struct rx_securityClass *secobj;    /*Client security object */
477     struct rx_service *rxsrv_afsserver; /*Server for AFS */
478     int arg_errfound;           /*Argument error found? */
479     int curr_srv;               /*Current server idx */
480     struct fsprobe_ConnectionInfo *curr_conn;   /*Ptr to current conn */
481     char *hostNameFound;        /*Ptr to returned host name */
482     int conn_err;               /*Connection error? */
483
484     /*
485      * If we've already been called, snicker at the bozo, gently
486      * remind him of his doubtful heritage, and return success.
487      */
488     if (fsprobe_initflag) {
489         fprintf(stderr, "[%s] Called multiple times!\n", rn);
490         return (0);
491     } else
492         fsprobe_initflag = 1;
493
494     /*
495      * Check the parameters for bogosities.
496      */
497     arg_errfound = 0;
498     if (a_numServers <= 0) {
499         fprintf(stderr, "[%s] Illegal number of servers: %d\n", rn,
500                 a_numServers);
501         arg_errfound = 1;
502     }
503     if (a_socketArray == (struct sockaddr_in *)0) {
504         fprintf(stderr, "[%s] Null server socket array argument\n", rn);
505         arg_errfound = 1;
506     }
507     if (a_ProbeFreqInSecs <= 0) {
508         fprintf(stderr, "[%s] Illegal probe frequency: %d\n", rn,
509                 a_ProbeFreqInSecs);
510         arg_errfound = 1;
511     }
512     if (a_ProbeHandler == (int (*)())0) {
513         fprintf(stderr, "[%s] Null probe handler function argument\n", rn);
514         arg_errfound = 1;
515     }
516     if (arg_errfound)
517         return (-1);
518
519     /*
520      * Record our passed-in info.
521      */
522     fsprobe_debug = a_debug;
523     fsprobe_numServers = a_numServers;
524     fsprobe_Handler = a_ProbeHandler;
525     fsprobe_ProbeFreqInSecs = a_ProbeFreqInSecs;
526
527     /*
528      * Get ready in case we have to do a cleanup - basically, zero
529      * everything out.
530      */
531     fsprobe_CleanupInit();
532
533     /*
534      * Allocate the necessary data structures and initialize everything
535      * else.
536      */
537     fsprobe_ConnInfo = (struct fsprobe_ConnectionInfo *)
538         malloc(a_numServers * sizeof(struct fsprobe_ConnectionInfo));
539     if (fsprobe_ConnInfo == (struct fsprobe_ConnectionInfo *)0) {
540         fprintf(stderr,
541                 "[%s] Can't allocate %d connection info structs (%"AFS_SIZET_FMT" bytes)\n",
542                 rn, a_numServers,
543                 (a_numServers * sizeof(struct fsprobe_ConnectionInfo)));
544         return (-1);            /*No cleanup needs to be done yet */
545     }
546 #if 0
547     else
548         fprintf(stderr, "[%s] fsprobe_ConnInfo allocated (%d bytes)\n", rn,
549                 a_numServers * sizeof(struct fsprobe_ConnectionInfo));
550 #endif /* 0 */
551
552     fsprobe_statsBytes = a_numServers * sizeof(struct ProbeViceStatistics);
553     fsprobe_Results.stats = (struct ProbeViceStatistics *)
554         malloc(fsprobe_statsBytes);
555     if (fsprobe_Results.stats == NULL) {
556         fprintf(stderr,
557                 "[%s] Can't allocate %d statistics structs (%d bytes)\n", rn,
558                 a_numServers, fsprobe_statsBytes);
559         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
560         return (-1);
561     } else if (fsprobe_debug)
562         fprintf(stderr, "[%s] fsprobe_Results.stats allocated (%d bytes)\n",
563                 rn, fsprobe_statsBytes);
564
565     fsprobe_probeOKBytes = a_numServers * sizeof(int);
566     fsprobe_Results.probeOK = malloc(fsprobe_probeOKBytes);
567     if (fsprobe_Results.probeOK == (int *)0) {
568         fprintf(stderr,
569                 "[%s] Can't allocate %d probeOK array entries (%d bytes)\n",
570                 rn, a_numServers, fsprobe_probeOKBytes);
571         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
572         return (-1);
573     } else if (fsprobe_debug)
574         fprintf(stderr, "[%s] fsprobe_Results.probeOK allocated (%d bytes)\n",
575                 rn, fsprobe_probeOKBytes);
576
577     fsprobe_Results.probeNum = 0;
578     fsprobe_Results.probeTime = 0;
579     memset(fsprobe_Results.stats, 0,
580            (a_numServers * sizeof(struct ProbeViceStatistics)));
581
582     /*
583      * Initialize the Rx subsystem, just in case nobody's done it.
584      */
585     if (fsprobe_debug)
586         fprintf(stderr, "[%s] Initializing Rx\n", rn);
587     code = rx_Init(0);
588     if (code) {
589         fprintf(stderr, "[%s] Fatal error in rx_Init()\n", rn);
590         return (-1);
591     }
592     if (fsprobe_debug)
593         fprintf(stderr, "[%s] Rx initialized.\n", rn);
594
595     /*
596      * Create a null Rx server security object, to be used by the
597      * Callback listener.
598      */
599     CBsecobj = rxnull_NewServerSecurityObject();
600     if (CBsecobj == (struct rx_securityClass *)0) {
601         fprintf(stderr,
602                 "[%s] Can't create null security object for the callback listener.\n",
603                 rn);
604         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
605         return (-1);
606     }
607     if (fsprobe_debug)
608         fprintf(stderr, "[%s] Callback server security object created\n", rn);
609
610     /*
611      * Create a null Rx client security object, to be used by the
612      * probe LWP.
613      */
614     secobj = rxnull_NewClientSecurityObject();
615     if (secobj == (struct rx_securityClass *)0) {
616         fprintf(stderr,
617                 "[%s] Can't create client security object for probe LWP.\n",
618                 rn);
619         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
620         return (-1);
621     }
622     if (fsprobe_debug)
623         fprintf(stderr, "[%s] Probe LWP client security object created\n",
624                 rn);
625
626     curr_conn = fsprobe_ConnInfo;
627     conn_err = 0;
628     for (curr_srv = 0; curr_srv < a_numServers; curr_srv++) {
629         /*
630          * Copy in the socket info for the current server, resolve its
631          * printable name if possible.
632          */
633         if (fsprobe_debug) {
634             fprintf(stderr, "[%s] Copying in the following socket info:\n",
635                     rn);
636             fprintf(stderr, "[%s] IP addr 0x%x, port %d\n", rn,
637                     (a_socketArray + curr_srv)->sin_addr.s_addr,
638                     (a_socketArray + curr_srv)->sin_port);
639         }
640         memcpy(&(curr_conn->skt), a_socketArray + curr_srv,
641                sizeof(struct sockaddr_in));
642
643         hostNameFound =
644             hostutil_GetNameByINet(curr_conn->skt.sin_addr.s_addr);
645         if (hostNameFound == NULL) {
646             fprintf(stderr,
647                     "[%s] Can't map Internet address %u to a string name\n",
648                     rn, curr_conn->skt.sin_addr.s_addr);
649             curr_conn->hostName[0] = '\0';
650         } else {
651             strcpy(curr_conn->hostName, hostNameFound);
652             if (fsprobe_debug)
653                 fprintf(stderr, "[%s] Host name for server index %d is %s\n",
654                         rn, curr_srv, curr_conn->hostName);
655         }
656
657         /*
658          * Make an Rx connection to the current server.
659          */
660         if (fsprobe_debug)
661             fprintf(stderr,
662                     "[%s] Connecting to srv idx %d, IP addr 0x%x, port %d, service 1\n",
663                     rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
664                     curr_conn->skt.sin_port);
665         curr_conn->rxconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr,    /*Server addr */
666                                              curr_conn->skt.sin_port,   /*Server port */
667                                              1, /*AFS service num */
668                                              secobj,    /*Security object */
669                                              0);        /*Number of above */
670         if (curr_conn->rxconn == (struct rx_connection *)0) {
671             fprintf(stderr,
672                     "[%s] Can't create Rx connection to server %s (%u)\n",
673                     rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
674             conn_err = 1;
675         }
676         if (fsprobe_debug)
677             fprintf(stderr, "[%s] New connection at %p\n", rn,
678                     curr_conn->rxconn);
679
680         /*
681          * Make an Rx connection to the current volume server.
682          */
683         if (fsprobe_debug)
684             fprintf(stderr,
685                     "[%s] Connecting to srv idx %d, IP addr 0x%x, port %d, service 1\n",
686                     rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
687                     htons(7005));
688         curr_conn->rxVolconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr, /*Server addr */
689                                                 htons(AFSCONF_VOLUMEPORT),      /*Volume Server port */
690                                                 VOLSERVICE_ID,  /*AFS service num */
691                                                 secobj, /*Security object */
692                                                 0);     /*Number of above */
693         if (curr_conn->rxVolconn == (struct rx_connection *)0) {
694             fprintf(stderr,
695                     "[%s] Can't create Rx connection to volume server %s (%u)\n",
696                     rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
697             conn_err = 1;
698         } else {
699             int i, cnt;
700
701             memset(&curr_conn->partList, 0, sizeof(struct partList));
702             curr_conn->partCnt = 0;
703             i = XListPartitions(curr_conn->rxVolconn, &curr_conn->partList,
704                                 &cnt);
705             if (!i) {
706                 curr_conn->partCnt = cnt;
707             }
708         }
709         if (fsprobe_debug)
710             fprintf(stderr, "[%s] New connection at %p\n", rn,
711                     curr_conn->rxVolconn);
712
713
714         /*
715          * Bump the current fsprobe connection to set up.
716          */
717         curr_conn++;
718
719     }                           /*for curr_srv */
720
721     /*
722      * Create the AFS callback service (listener).
723      */
724     if (fsprobe_debug)
725         fprintf(stderr, "[%s] Creating AFS callback listener\n", rn);
726     rxsrv_afsserver = rx_NewService(0,  /*Use default port */
727                                     1,  /*Service ID */
728                                     "afs",      /*Service name */
729                                     &CBsecobj,  /*Ptr to security object(s) */
730                                     1,  /*Number of security objects */
731                                     RXAFSCB_ExecuteRequest);    /*Dispatcher */
732     if (rxsrv_afsserver == (struct rx_service *)0) {
733         fprintf(stderr, "[%s] Can't create callback Rx service/listener\n",
734                 rn);
735         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
736         return (-1);
737     }
738     if (fsprobe_debug)
739         fprintf(stderr, "[%s] Callback listener created\n", rn);
740
741     /*
742      * Start up the AFS callback service.
743      */
744     if (fsprobe_debug)
745         fprintf(stderr, "[%s] Starting up callback listener.\n", rn);
746     rx_StartServer(0 /*Don't donate yourself to LWP pool */ );
747
748     /*
749      * Start up the probe LWP.
750      */
751     if (fsprobe_debug)
752         fprintf(stderr, "[%s] Creating the probe LWP\n", rn);
753     code = LWP_CreateProcess(fsprobe_LWP,       /*Function to start up */
754                              LWP_STACK_SIZE,    /*Stack size in bytes */
755                              1, /*Priority */
756                              (void *)0, /*Parameters */
757                              "fsprobe Worker",  /*Name to use */
758                              &probeLWP_ID);     /*Returned LWP process ID */
759     if (code) {
760         fprintf(stderr, "[%s] Can't create fsprobe LWP!  Error is %d\n", rn,
761                 code);
762         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
763         return (code);
764     }
765     if (fsprobe_debug)
766         fprintf(stderr, "[%s] Probe LWP process structure located at %p\n",
767                 rn, probeLWP_ID);
768
769 #if 0
770     /*
771      * Do I need to do this?
772      */
773     if (fsprobe_debug)
774         fprintf(stderr, "[%s] Calling osi_Wakeup()\n", rn);
775     osi_Wakeup(&rxsrv_afsserver);       /*Wake up anyone waiting for it */
776 #endif /* 0 */
777
778     /*
779      * Return the final results.
780      */
781     if (conn_err)
782         return (-2);
783     else
784         return (0);
785
786 }                               /*fsprobe_Init */
787
788
789 /*------------------------------------------------------------------------
790  * [exported] fsprobe_ForceProbeNow
791  *
792  * Description:
793  *      Wake up the probe LWP, forcing it to execute a probe immediately.
794  *
795  * Arguments:
796  *      None.
797  *
798  * Returns:
799  *      0 on success,
800  *      Error value otherwise.
801  *
802  * Environment:
803  *      The module must have been initialized.
804  *
805  * Side Effects:
806  *      As advertised.
807  *------------------------------------------------------------------------*/
808
809 int
810 fsprobe_ForceProbeNow(void)
811 {                               /*fsprobe_ForceProbeNow */
812
813     static char rn[] = "fsprobe_ForceProbeNow"; /*Routine name */
814
815     /*
816      * There isn't a prayer unless we've been initialized.
817      */
818     if (!fsprobe_initflag) {
819         fprintf(stderr, "[%s] Must call fsprobe_Init first!\n", rn);
820         return (-1);
821     }
822
823     /*
824      * Kick the sucker in the side.
825      */
826     IOMGR_Cancel(probeLWP_ID);
827
828     /*
829      * We did it, so report the happy news.
830      */
831     return (0);
832
833 }                               /*fsprobe_ForceProbeNow */