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