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