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