opr: Assert opr_cv_timedwait return codes
[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 <pthread.h>
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 /*
33  * Exported variables.
34  */
35 int fsprobe_numServers;         /*Num servers connected */
36 struct fsprobe_ConnectionInfo *fsprobe_ConnInfo;        /*Ptr to connection array */
37 struct fsprobe_ProbeResults fsprobe_Results;    /*Latest probe results */
38 int fsprobe_ProbeFreqInSecs;    /*Probe freq. in seconds */
39
40 /*
41  * Private globals.
42  */
43 static int fsprobe_initflag = 0;        /*Was init routine called? */
44 static int fsprobe_debug = 0;   /*Debugging output enabled? */
45 static int (*fsprobe_Handler) (void);   /*Probe handler routine */
46 static pthread_t fsprobe_thread;        /*Probe thread */
47 static int fsprobe_statsBytes;  /*Num bytes in stats block */
48 static int fsprobe_probeOKBytes;        /*Num bytes in probeOK block */
49 static opr_mutex_t fsprobe_force_lock;  /*Lock to force probe */
50 static opr_cv_t fsprobe_force_cv;       /*Condvar to force probe */
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 thread 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     struct timespec wait;       /*Time to wait */
222     int conn_idx;               /*Connection index */
223     struct fsprobe_ConnectionInfo *curr_conn;   /*Current connection */
224     struct ProbeViceStatistics *curr_stats;     /*Current stats region */
225     int *curr_probeOK;          /*Current probeOK field */
226     ViceStatistics64 stats64;      /*Current stats region */
227     stats64.ViceStatistics64_val = malloc(STATS64_VERSION *
228                                           sizeof(afs_uint64));
229     while (1) {                 /*Service loop */
230         /*
231          * Iterate through the server connections, gathering data.
232          * Don't forget to bump the probe count and zero the statistics
233          * areas before calling the servers.
234          */
235         if (fsprobe_debug)
236             fprintf(stderr,
237                     "[%s] Waking up, collecting data from %d connected servers\n",
238                     rn, fsprobe_numServers);
239         curr_conn = fsprobe_ConnInfo;
240         curr_stats = fsprobe_Results.stats;
241         curr_probeOK = fsprobe_Results.probeOK;
242         fsprobe_Results.probeNum++;
243         memset(fsprobe_Results.stats, 0, fsprobe_statsBytes);
244         memset(fsprobe_Results.probeOK, 0, fsprobe_probeOKBytes);
245
246         for (conn_idx = 0; conn_idx < fsprobe_numServers; conn_idx++) {
247             /*
248              * Grab the statistics for the current FileServer, if the
249              * connection is valid.
250              */
251             if (fsprobe_debug)
252                 fprintf(stderr, "[%s] Contacting server %s\n", rn,
253                         curr_conn->hostName);
254             if (curr_conn->rxconn != (struct rx_connection *)0) {
255                 if (fsprobe_debug)
256                     fprintf(stderr,
257                             "[%s] Connection valid, calling RXAFS_GetStatistics\n",
258                             rn);
259                 *curr_probeOK =
260                     RXAFS_GetStatistics64(curr_conn->rxconn, STATS64_VERSION, &stats64);
261                 if (*curr_probeOK == RXGEN_OPCODE)
262                     *curr_probeOK =
263                         RXAFS_GetStatistics(curr_conn->rxconn, (ViceStatistics *)curr_stats);
264                 else if (*curr_probeOK == 0) {
265                     curr_stats->CurrentTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_CURRENTTIME]);
266                     curr_stats->BootTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_BOOTTIME]);
267                     curr_stats->StartTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_STARTTIME]);
268                     curr_stats->CurrentConnections = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_CURRENTCONNECTIONS]);
269                     curr_stats->TotalFetchs = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_TOTALFETCHES]);
270                     curr_stats->TotalStores = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_TOTALSTORES]);
271                     curr_stats->WorkStations = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_WORKSTATIONS]);
272                 }
273             }
274
275             /*Valid Rx connection */
276             /*
277              * Call the Volume Server too to get additional stats
278              */
279             if (fsprobe_debug)
280                 fprintf(stderr, "[%s] Contacting volume server %s\n", rn,
281                         curr_conn->hostName);
282             if (curr_conn->rxVolconn != (struct rx_connection *)0) {
283                 int i, code;
284                 char pname[10];
285                 struct diskPartition partition;
286                 struct diskPartition64 *partition64p =
287                     malloc(sizeof(struct diskPartition64));
288
289                 if (fsprobe_debug)
290                     fprintf(stderr,
291                             "[%s] Connection valid, calling RXAFS_GetStatistics\n",
292                             rn);
293                 for (i = 0; i < curr_conn->partCnt; i++) {
294                     if (curr_conn->partList.partFlags[i] & PARTVALID) {
295                         MapPartIdIntoName(curr_conn->partList.partId[i],
296                                           pname);
297                         code =
298                             AFSVolPartitionInfo64(curr_conn->rxVolconn, pname,
299                                                   partition64p);
300
301                         if (!code) {
302                             curr_stats->Disk[i].BlocksAvailable =
303                                 RoundInt64ToInt31(partition64p->free);
304                             curr_stats->Disk[i].TotalBlocks =
305                                 RoundInt64ToInt31(partition64p->minFree);
306                             strcpy(curr_stats->Disk[i].Name, pname);
307                         }
308                         if (code == RXGEN_OPCODE) {
309                             code =
310                                 AFSVolPartitionInfo(curr_conn->rxVolconn,
311                                                     pname, &partition);
312                             if (!code) {
313                                 curr_stats->Disk[i].BlocksAvailable =
314                                     partition.free;
315                                 curr_stats->Disk[i].TotalBlocks =
316                                     partition.minFree;
317                                 strcpy(curr_stats->Disk[i].Name, pname);
318                             }
319                         }
320                         if (code) {
321                             fprintf(stderr,
322                                     "Could not get information on server %s partition %s\n",
323                                     curr_conn->hostName, pname);
324                         }
325                     }
326                 }
327                 free(partition64p);
328             }
329
330
331             /*
332              * Advance the fsprobe connection pointer & stats pointer.
333              */
334             curr_conn++;
335             curr_stats++;
336             curr_probeOK++;
337
338         }                       /*For each fsprobe connection */
339
340         /*
341          * All (valid) connections have been probed.  Now, call the
342          * associated handler function.  The handler does not take
343          * any explicit parameters, rather gets to the goodies via
344          * some of the objects exported by this module.
345          */
346         if (fsprobe_debug)
347             fprintf(stderr,
348                     "[%s] Polling complete, calling associated handler routine.\n",
349                     rn);
350         code = fsprobe_Handler();
351         if (code)
352             fprintf(stderr, "[%s] Handler routine returned error code %d\n",
353                     rn, code);
354
355         /*
356          * Fall asleep for the prescribed number of seconds or wakeup
357          * sooner if forced.
358          */
359         gettimeofday(&tv, NULL);
360         wait.tv_sec = tv.tv_sec + fsprobe_ProbeFreqInSecs;
361         wait.tv_nsec = tv.tv_usec * 1000;
362         opr_mutex_enter(&fsprobe_force_lock);
363         code = opr_cv_timedwait(&fsprobe_force_cv, &fsprobe_force_lock, &wait);
364         opr_mutex_exit(&fsprobe_force_lock);
365     }                           /*Service loop */
366     AFS_UNREACHED(free(stats64.ViceStatistics64_val));
367     AFS_UNREACHED(return(NULL));
368 }                               /*fsprobe_LWP */
369
370 /*list all the partitions on <aserver> */
371 static int newvolserver = 0;
372
373 int
374 XListPartitions(struct rx_connection *aconn, struct partList *ptrPartList,
375                 afs_int32 *cntp)
376 {
377     struct pIDs partIds;
378     struct partEntries partEnts;
379     int i, j = 0, code;
380
381     *cntp = 0;
382     if (newvolserver == 1) {
383         for (i = 0; i < 26; i++)
384             partIds.partIds[i] = -1;
385       tryold:
386         code = AFSVolListPartitions(aconn, &partIds);
387         if (!code) {
388             for (i = 0; i < 26; i++) {
389                 if ((partIds.partIds[i]) != -1) {
390                     ptrPartList->partId[j] = partIds.partIds[i];
391                     ptrPartList->partFlags[j] = PARTVALID;
392                     j++;
393                 } else
394                     ptrPartList->partFlags[i] = 0;
395             }
396             *cntp = j;
397         }
398         goto out;
399     }
400     partEnts.partEntries_len = 0;
401     partEnts.partEntries_val = NULL;
402     code = AFSVolXListPartitions(aconn, &partEnts);
403     if (!newvolserver) {
404         if (code == RXGEN_OPCODE) {
405             newvolserver = 1;   /* Doesn't support new interface */
406             goto tryold;
407         } else if (!code) {
408             newvolserver = 2;
409         }
410     }
411     if (!code) {
412         *cntp = partEnts.partEntries_len;
413         if (*cntp > VOLMAXPARTS) {
414             fprintf(stderr,
415                     "Warning: number of partitions on the server too high %d (process only %d)\n",
416                     *cntp, VOLMAXPARTS);
417             *cntp = VOLMAXPARTS;
418         }
419         for (i = 0; i < *cntp; i++) {
420             ptrPartList->partId[i] = partEnts.partEntries_val[i];
421             ptrPartList->partFlags[i] = PARTVALID;
422         }
423         free(partEnts.partEntries_val);
424     }
425   out:
426     if (code)
427         fprintf(stderr,
428                 "Could not fetch the list of partitions from the server\n");
429     return code;
430 }
431
432
433 /*------------------------------------------------------------------------
434  * [exported] fsprobe_Init
435  *
436  * Description:
437  *      Initialize the fsprobe module: set up Rx connections to the
438  *      given set of servers, start up the probe and callback threads,
439  *      and associate the routine to be called when a probe completes.
440  *
441  * Arguments:
442  *      int a_numServers                  : Num. servers to connect to.
443  *      struct sockaddr_in *a_socketArray : Array of server sockets.
444  *      int a_ProbeFreqInSecs             : Probe frequency in seconds.
445  *      int (*a_ProbeHandler)()           : Ptr to probe handler fcn.
446  *      int a_debug;                      : Turn debugging output on?
447  *
448  * Returns:
449  *      0 on success,
450  *      -2 for (at least one) connection error,
451  *      thread process creation code, if it failed,
452  *      -1 for other fatal errors.
453  *
454  * Environment:
455  *      *** MUST BE THE FIRST ROUTINE CALLED FROM THIS PACKAGE ***
456  *      Also, the server security object CBsecobj MUST be a static,
457  *      since it has to stick around after this routine exits.
458  *
459  * Side Effects:
460  *      Sets up just about everything.
461  *------------------------------------------------------------------------*/
462
463 int
464 fsprobe_Init(int a_numServers, struct sockaddr_in *a_socketArray,
465              int a_ProbeFreqInSecs, int (*a_ProbeHandler)(void),
466              int a_debug)
467 {                               /*fsprobe_Init */
468
469     static char rn[] = "fsprobe_Init";  /*Routine name */
470     afs_int32 code;     /*Return value */
471     static struct rx_securityClass *CBsecobj;   /*Callback security object */
472     struct rx_securityClass *secobj;    /*Client security object */
473     struct rx_service *rxsrv_afsserver; /*Server for AFS */
474     int arg_errfound;           /*Argument error found? */
475     int curr_srv;               /*Current server idx */
476     struct fsprobe_ConnectionInfo *curr_conn;   /*Ptr to current conn */
477     char *hostNameFound;        /*Ptr to returned host name */
478     int conn_err;               /*Connection error? */
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     opr_mutex_init(&fsprobe_force_lock);
491     opr_cv_init(&fsprobe_force_cv);
492
493     /*
494      * Check the parameters for bogosities.
495      */
496     arg_errfound = 0;
497     if (a_numServers <= 0) {
498         fprintf(stderr, "[%s] Illegal number of servers: %d\n", rn,
499                 a_numServers);
500         arg_errfound = 1;
501     }
502     if (a_socketArray == (struct sockaddr_in *)0) {
503         fprintf(stderr, "[%s] Null server socket array argument\n", rn);
504         arg_errfound = 1;
505     }
506     if (a_ProbeFreqInSecs <= 0) {
507         fprintf(stderr, "[%s] Illegal probe frequency: %d\n", rn,
508                 a_ProbeFreqInSecs);
509         arg_errfound = 1;
510     }
511     if (a_ProbeHandler == NULL) {
512         fprintf(stderr, "[%s] Null probe handler function argument\n", rn);
513         arg_errfound = 1;
514     }
515     if (arg_errfound)
516         return (-1);
517
518     /*
519      * Record our passed-in info.
520      */
521     fsprobe_debug = a_debug;
522     fsprobe_numServers = a_numServers;
523     fsprobe_Handler = a_ProbeHandler;
524     fsprobe_ProbeFreqInSecs = a_ProbeFreqInSecs;
525
526     /*
527      * Get ready in case we have to do a cleanup - basically, zero
528      * everything out.
529      */
530     fsprobe_CleanupInit();
531
532     /*
533      * Allocate the necessary data structures and initialize everything
534      * else.
535      */
536     fsprobe_ConnInfo = (struct fsprobe_ConnectionInfo *)
537         malloc(a_numServers * sizeof(struct fsprobe_ConnectionInfo));
538     if (fsprobe_ConnInfo == (struct fsprobe_ConnectionInfo *)0) {
539         fprintf(stderr,
540                 "[%s] Can't allocate %d connection info structs (%"AFS_SIZET_FMT" bytes)\n",
541                 rn, a_numServers,
542                 (a_numServers * sizeof(struct fsprobe_ConnectionInfo)));
543         return (-1);            /*No cleanup needs to be done yet */
544     }
545
546     fsprobe_statsBytes = a_numServers * sizeof(struct ProbeViceStatistics);
547     fsprobe_Results.stats = (struct ProbeViceStatistics *)
548         malloc(fsprobe_statsBytes);
549     if (fsprobe_Results.stats == NULL) {
550         fprintf(stderr,
551                 "[%s] Can't allocate %d statistics structs (%d bytes)\n", rn,
552                 a_numServers, fsprobe_statsBytes);
553         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
554         return (-1);
555     } else if (fsprobe_debug)
556         fprintf(stderr, "[%s] fsprobe_Results.stats allocated (%d bytes)\n",
557                 rn, fsprobe_statsBytes);
558
559     fsprobe_probeOKBytes = a_numServers * sizeof(int);
560     fsprobe_Results.probeOK = malloc(fsprobe_probeOKBytes);
561     if (fsprobe_Results.probeOK == (int *)0) {
562         fprintf(stderr,
563                 "[%s] Can't allocate %d probeOK array entries (%d bytes)\n",
564                 rn, a_numServers, fsprobe_probeOKBytes);
565         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
566         return (-1);
567     } else if (fsprobe_debug)
568         fprintf(stderr, "[%s] fsprobe_Results.probeOK allocated (%d bytes)\n",
569                 rn, fsprobe_probeOKBytes);
570
571     fsprobe_Results.probeNum = 0;
572     fsprobe_Results.probeTime = 0;
573     memset(fsprobe_Results.stats, 0,
574            (a_numServers * sizeof(struct ProbeViceStatistics)));
575
576     /*
577      * Initialize the Rx subsystem, just in case nobody's done it.
578      */
579     if (fsprobe_debug)
580         fprintf(stderr, "[%s] Initializing Rx\n", rn);
581     code = rx_Init(0);
582     if (code) {
583         fprintf(stderr, "[%s] Fatal error in rx_Init()\n", rn);
584         return (-1);
585     }
586     if (fsprobe_debug)
587         fprintf(stderr, "[%s] Rx initialized.\n", rn);
588
589     /*
590      * Create a null Rx server security object, to be used by the
591      * Callback listener.
592      */
593     CBsecobj = rxnull_NewServerSecurityObject();
594     if (CBsecobj == (struct rx_securityClass *)0) {
595         fprintf(stderr,
596                 "[%s] Can't create null security object for the callback listener.\n",
597                 rn);
598         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
599         return (-1);
600     }
601     if (fsprobe_debug)
602         fprintf(stderr, "[%s] Callback server security object created\n", rn);
603
604     /*
605      * Create a null Rx client security object, to be used by the
606      * probe thread.
607      */
608     secobj = rxnull_NewClientSecurityObject();
609     if (secobj == (struct rx_securityClass *)0) {
610         fprintf(stderr,
611                 "[%s] Can't create client security object for probe thread.\n",
612                 rn);
613         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
614         return (-1);
615     }
616     if (fsprobe_debug)
617         fprintf(stderr, "[%s] Probe thread client security object created\n",
618                 rn);
619
620     curr_conn = fsprobe_ConnInfo;
621     conn_err = 0;
622     for (curr_srv = 0; curr_srv < a_numServers; curr_srv++) {
623         /*
624          * Copy in the socket info for the current server, resolve its
625          * printable name if possible.
626          */
627         if (fsprobe_debug) {
628             fprintf(stderr, "[%s] Copying in the following socket info:\n",
629                     rn);
630             fprintf(stderr, "[%s] IP addr 0x%x, port %d\n", rn,
631                     (a_socketArray + curr_srv)->sin_addr.s_addr,
632                     (a_socketArray + curr_srv)->sin_port);
633         }
634         memcpy(&(curr_conn->skt), a_socketArray + curr_srv,
635                sizeof(struct sockaddr_in));
636
637         hostNameFound =
638             hostutil_GetNameByINet(curr_conn->skt.sin_addr.s_addr);
639         if (hostNameFound == NULL) {
640             fprintf(stderr,
641                     "[%s] Can't map Internet address %u to a string name\n",
642                     rn, curr_conn->skt.sin_addr.s_addr);
643             curr_conn->hostName[0] = '\0';
644         } else {
645             strcpy(curr_conn->hostName, hostNameFound);
646             if (fsprobe_debug)
647                 fprintf(stderr, "[%s] Host name for server index %d is %s\n",
648                         rn, curr_srv, curr_conn->hostName);
649         }
650
651         /*
652          * Make an Rx connection to the current server.
653          */
654         if (fsprobe_debug)
655             fprintf(stderr,
656                     "[%s] Connecting to srv idx %d, IP addr 0x%x, port %d, service 1\n",
657                     rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
658                     curr_conn->skt.sin_port);
659         curr_conn->rxconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr,    /*Server addr */
660                                              curr_conn->skt.sin_port,   /*Server port */
661                                              1, /*AFS service num */
662                                              secobj,    /*Security object */
663                                              0);        /*Number of above */
664         if (curr_conn->rxconn == (struct rx_connection *)0) {
665             fprintf(stderr,
666                     "[%s] Can't create Rx connection to server %s (%u)\n",
667                     rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
668             conn_err = 1;
669         }
670         if (fsprobe_debug)
671             fprintf(stderr, "[%s] New connection at %p\n", rn,
672                     curr_conn->rxconn);
673
674         /*
675          * Make an Rx connection to the current volume server.
676          */
677         if (fsprobe_debug)
678             fprintf(stderr,
679                     "[%s] Connecting to srv idx %d, IP addr 0x%x, port %d, service 1\n",
680                     rn, curr_srv, curr_conn->skt.sin_addr.s_addr,
681                     htons(7005));
682         curr_conn->rxVolconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr, /*Server addr */
683                                                 htons(AFSCONF_VOLUMEPORT),      /*Volume Server port */
684                                                 VOLSERVICE_ID,  /*AFS service num */
685                                                 secobj, /*Security object */
686                                                 0);     /*Number of above */
687         if (curr_conn->rxVolconn == (struct rx_connection *)0) {
688             fprintf(stderr,
689                     "[%s] Can't create Rx connection to volume server %s (%u)\n",
690                     rn, curr_conn->hostName, curr_conn->skt.sin_addr.s_addr);
691             conn_err = 1;
692         } else {
693             int i, cnt;
694
695             memset(&curr_conn->partList, 0, sizeof(struct partList));
696             curr_conn->partCnt = 0;
697             i = XListPartitions(curr_conn->rxVolconn, &curr_conn->partList,
698                                 &cnt);
699             if (!i) {
700                 curr_conn->partCnt = cnt;
701             }
702         }
703         if (fsprobe_debug)
704             fprintf(stderr, "[%s] New connection at %p\n", rn,
705                     curr_conn->rxVolconn);
706
707
708         /*
709          * Bump the current fsprobe connection to set up.
710          */
711         curr_conn++;
712
713     }                           /*for curr_srv */
714
715     /*
716      * Create the AFS callback service (listener).
717      */
718     if (fsprobe_debug)
719         fprintf(stderr, "[%s] Creating AFS callback listener\n", rn);
720     rxsrv_afsserver = rx_NewService(0,  /*Use default port */
721                                     1,  /*Service ID */
722                                     "afs",      /*Service name */
723                                     &CBsecobj,  /*Ptr to security object(s) */
724                                     1,  /*Number of security objects */
725                                     RXAFSCB_ExecuteRequest);    /*Dispatcher */
726     if (rxsrv_afsserver == (struct rx_service *)0) {
727         fprintf(stderr, "[%s] Can't create callback Rx service/listener\n",
728                 rn);
729         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
730         return (-1);
731     }
732     if (fsprobe_debug)
733         fprintf(stderr, "[%s] Callback listener created\n", rn);
734
735     /*
736      * Start up the AFS callback service.
737      */
738     if (fsprobe_debug)
739         fprintf(stderr, "[%s] Starting up callback listener.\n", rn);
740     rx_StartServer(0 /*Don't donate yourself to thread pool */ );
741
742     /*
743      * Start up the probe thread.
744      */
745     if (fsprobe_debug)
746         fprintf(stderr, "[%s] Creating the probe thread\n", rn);
747     code = pthread_create(&fsprobe_thread, NULL, fsprobe_LWP, NULL);
748     if (code) {
749         fprintf(stderr, "[%s] Can't create fsprobe thread!  Error is %d\n", rn,
750                 code);
751         fsprobe_Cleanup(1);     /*Delete already-malloc'ed areas */
752         return (code);
753     }
754
755     /*
756      * Return the final results.
757      */
758     if (conn_err)
759         return (-2);
760     else
761         return (0);
762
763 }                               /*fsprobe_Init */
764
765
766 /*------------------------------------------------------------------------
767  * [exported] fsprobe_ForceProbeNow
768  *
769  * Description:
770  *      Wake up the probe thread, forcing it to execute a probe immediately.
771  *
772  * Arguments:
773  *      None.
774  *
775  * Returns:
776  *      0 on success,
777  *      Error value otherwise.
778  *
779  * Environment:
780  *      The module must have been initialized.
781  *
782  * Side Effects:
783  *      As advertised.
784  *------------------------------------------------------------------------*/
785
786 int
787 fsprobe_ForceProbeNow(void)
788 {                               /*fsprobe_ForceProbeNow */
789
790     static char rn[] = "fsprobe_ForceProbeNow"; /*Routine name */
791
792     /*
793      * There isn't a prayer unless we've been initialized.
794      */
795     if (!fsprobe_initflag) {
796         fprintf(stderr, "[%s] Must call fsprobe_Init first!\n", rn);
797         return (-1);
798     }
799
800     /*
801      * Kick the sucker in the side.
802      */
803     opr_mutex_enter(&fsprobe_force_lock);
804     opr_cv_signal(&fsprobe_force_cv);
805     opr_mutex_exit(&fsprobe_force_lock);
806
807     /*
808      * We did it, so report the happy news.
809      */
810     return (0);
811
812 }                               /*fsprobe_ForceProbeNow */
813
814 /*------------------------------------------------------------------------
815  * [exported] fsprobe_Wait
816  *
817  * Description:
818  *      Wait for the collection to complete.
819  *
820  * Arguments:
821  *    int sleep_secs : time to wait in seconds. 0 means sleep forever.
822  *
823  * Returns:
824  *      0 on success,
825  *      Error value otherwise.
826  *
827  * Environment:
828  *      The module must have been initialized.
829  *
830  * Side Effects:
831  *      As advertised.
832  *------------------------------------------------------------------------*/
833 int
834 fsprobe_Wait(int sleep_secs)
835 {
836     int code;
837     struct timeval tv;
838
839     if (sleep_secs == 0) {
840         while (1) {
841             tv.tv_sec = 30;
842             tv.tv_usec = 0;
843             code = select(0, 0, 0, 0, &tv);
844             if (code < 0)
845                 break;
846         }
847     } else {
848         tv.tv_sec = sleep_secs;
849         tv.tv_usec = 0;
850         code = select(0, 0, 0, 0, &tv);
851     }
852     return code;
853 }