lwp-protoize-20080310
[openafs.git] / src / xstat / xstat_fs.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 client side of the AFS File Server extended
13  *      statistics facility.
14  *
15  *------------------------------------------------------------------------*/
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20 RCSID
21     ("$Header$");
22
23 #include "xstat_fs.h"           /*Interface for this module */
24 #include <lwp.h>                /*Lightweight process package */
25
26 #include <afs/afsutil.h>
27 #include <string.h>
28
29 #define LWP_STACK_SIZE  (16 * 1024)
30
31 /*
32  * Routines we need that don't have explicit include file definitions.
33  */
34 extern int RXAFSCB_ExecuteRequest();    /*AFS callback dispatcher */
35 extern char *hostutil_GetNameByINet();  /*Host parsing utility */
36
37 /*
38  * Help out the linker by explicitly importing the callback routines
39  * File Servers may be lobbing at us.
40  */
41 extern afs_int32 SRXAFSCB_CallBack();
42 extern afs_int32 SRXAFSCB_InitCallBackState3();
43 extern afs_int32 SRXAFSCB_Probe();
44 extern afs_int32 SRXAFSCB_ProbeUUID();
45 extern afs_int32 SRXAFSCB_GetCE();
46 extern afs_int32 SRXAFSCB_GetLock();
47
48 /*
49  * Exported variables.
50  */
51 int xstat_fs_numServers;        /*Num connected servers */
52 struct xstat_fs_ConnectionInfo
53  *xstat_fs_ConnInfo;            /*Ptr to connection array */
54 int numCollections;             /*Number of data collections */
55 struct xstat_fs_ProbeResults xstat_fs_Results;  /*Latest probe results */
56 char terminationEvent;          /*One-shot termination event */
57
58 afs_int32 xstat_fsData[AFS_MAX_XSTAT_LONGS];    /*Buffer for collected data */
59
60 /*
61  * Private globals.
62  */
63 static int xstat_fs_ProbeFreqInSecs;    /*Probe freq. in seconds */
64 static int xstat_fs_initflag = 0;       /*Was init routine called? */
65 static int xstat_fs_debug = 0;  /*Debugging output enabled? */
66 static int xstat_fs_oneShot = 0;        /*One-shot operation? */
67 static int (*xstat_fs_Handler) ();      /*Probe handler routine */
68 static PROCESS probeLWP_ID;     /*Probe LWP process ID */
69 static int xstat_fs_numCollections;     /*Number of desired collections */
70 static afs_int32 *xstat_fs_collIDP;     /*Ptr to collection IDs desired */
71
72 /*
73  * We have to pass a port to Rx to start up our callback listener
74  * service, but 7001 is already taken up by the Cache Manager.  So,
75  * we make up our own.
76  */
77 #define XSTAT_FS_CBPORT 7101
78
79
80 /*------------------------------------------------------------------------
81  * [private] xstat_fs_CleanupInit
82  *
83  * Description:
84  *      Set up for recovery after an error in initialization (i.e.,
85  *      during a call to xstat_fs_Init.
86  *
87  * Arguments:
88  *      None.
89  *
90  * Returns:
91  *      0 on success,
92  *      Error value otherwise.
93  *
94  * Environment:
95  *      This routine is private to the module.
96  *
97  * Side Effects:
98  *      Zeros out basic data structures.
99  *------------------------------------------------------------------------*/
100
101 static int
102 xstat_fs_CleanupInit()
103 {
104     afs_int32 code;             /*Return code from callback stubs */
105     struct rx_call *rxcall;     /*Bogus param */
106     AFSCBFids *Fids_Array;      /*Bogus param */
107     AFSCBs *CallBack_Array;     /*Bogus param */
108
109     xstat_fs_ConnInfo = (struct xstat_fs_ConnectionInfo *)0;
110     xstat_fs_Results.probeNum = 0;
111     xstat_fs_Results.probeTime = 0;
112     xstat_fs_Results.connP = (struct xstat_fs_ConnectionInfo *)0;
113     xstat_fs_Results.collectionNumber = 0;
114     xstat_fs_Results.data.AFS_CollData_len = AFS_MAX_XSTAT_LONGS;
115     xstat_fs_Results.data.AFS_CollData_val = (afs_int32 *) xstat_fsData;
116     xstat_fs_Results.probeOK = 0;
117
118     rxcall = (struct rx_call *)0;
119     Fids_Array = (AFSCBFids *) 0;
120     CallBack_Array = (AFSCBs *) 0;
121
122     /*
123      * Call each of the callback routines our module provides (in
124      * xstat_fs_callback.c) to make sure they're all there.
125      */
126     code = SRXAFSCB_CallBack(rxcall, Fids_Array, CallBack_Array);
127     if (code)
128         return (code);
129     code = SRXAFSCB_InitCallBackState3(rxcall, (afsUUID *) 0);
130     if (code)
131         return (code);
132     code = SRXAFSCB_Probe(rxcall);
133     return (code);
134 }
135
136
137 /*------------------------------------------------------------------------
138  * [exported] xstat_fs_Cleanup
139  *
140  * Description:
141  *      Clean up our memory and connection state.
142  *
143  * Arguments:
144  *      int a_releaseMem : Should we free up malloc'ed areas?
145  *
146  * Returns:
147  *      0 on total success,
148  *      -1 if the module was never initialized, or there was a problem
149  *              with the xstat_fs connection array.
150  *
151  * Environment:
152  *      xstat_fs_numServers should be properly set.  We don't do anything
153  *      unless xstat_fs_Init() has already been called.
154  *
155  * Side Effects:
156  *      Shuts down Rx connections gracefully, frees allocated space
157  *      (if so directed).
158  *------------------------------------------------------------------------*/
159
160 int
161 xstat_fs_Cleanup(int a_releaseMem)
162 {
163     static char rn[] = "xstat_fs_Cleanup";      /*Routine name */
164     int code;                   /*Return code */
165     int conn_idx;               /*Current connection index */
166     struct xstat_fs_ConnectionInfo *curr_conn;  /*Ptr to xstat_fs connection */
167
168     /*
169      * Assume the best, but check the worst.
170      */
171     if (!xstat_fs_initflag) {
172         fprintf(stderr, "[%s] Refused; module not initialized\n", rn);
173         return (-1);
174     } else
175         code = 0;
176
177     /*
178      * Take care of all Rx connections first.  Check to see that the
179      * server count is a legal value.
180      */
181     if (xstat_fs_numServers <= 0) {
182         fprintf(stderr,
183                 "[%s] Illegal number of servers (xstat_fs_numServers = %d)\n",
184                 rn, xstat_fs_numServers);
185         code = -1;
186     } else {
187         if (xstat_fs_ConnInfo != (struct xstat_fs_ConnectionInfo *)0) {
188             /*
189              * The xstat_fs connection structure array exists.  Go through
190              * it and close up any Rx connections it holds.
191              */
192             curr_conn = xstat_fs_ConnInfo;
193             for (conn_idx = 0; conn_idx < xstat_fs_numServers; conn_idx++) {
194                 if (curr_conn->rxconn != (struct rx_connection *)0) {
195                     rx_DestroyConnection(curr_conn->rxconn);
196                     curr_conn->rxconn = (struct rx_connection *)0;
197                 }
198                 curr_conn++;
199             }                   /*for each xstat_fs connection */
200         }                       /*xstat_fs connection structure exists */
201     }                           /*Legal number of servers */
202
203     /*
204      * If asked to, release the space we've allocated.
205      */
206     if (a_releaseMem) {
207         if (xstat_fs_ConnInfo != (struct xstat_fs_ConnectionInfo *)0)
208             free(xstat_fs_ConnInfo);
209     }
210
211     /*
212      * Return the news, whatever it is.
213      */
214     return (code);
215 }
216
217
218 /*------------------------------------------------------------------------
219  * [private] xstat_fs_LWP
220  *
221  * Description:
222  *      This LWP iterates over the server connections and gathers up
223  *      the desired statistics from each one on a regular basis.  When
224  *      the sweep is done, the associated handler function is called
225  *      to process the new data.
226  *
227  * Arguments:
228  *      None.
229  *
230  * Returns:
231  *      Nothing.
232  *
233  * Environment:
234  *      Started by xstat_fs_Init(), uses global structures and the
235  *      global private xstat_fs_oneShot variable.
236  *
237  * Side Effects:
238  *      Nothing interesting.
239  *------------------------------------------------------------------------*/
240
241 static void *
242 xstat_fs_LWP(void *unused)
243 {
244     static char rn[] = "xstat_fs_LWP";  /*Routine name */
245     register afs_int32 code;    /*Results of calls */
246     int oneShotCode;            /*Result of one-shot signal */
247     struct timeval tv;          /*Time structure */
248     int conn_idx;               /*Connection index */
249     struct xstat_fs_ConnectionInfo *curr_conn;  /*Current connection */
250     afs_int32 srvVersionNumber; /*Xstat version # */
251     afs_int32 clientVersionNumber;      /*Client xstat version */
252     afs_int32 numColls;         /*Number of collections to get */
253     afs_int32 *currCollIDP;     /*Curr collection ID desired */
254
255     static afs_int32 xstat_VersionNumber;       /*Version # of server */
256
257     /*
258      * Set up some numbers we'll need.
259      */
260     clientVersionNumber = AFS_XSTAT_VERSION;
261
262     while (1) {                 /*Service loop */
263         /*
264          * Iterate through the server connections, gathering data.
265          * Don't forget to bump the probe count and zero the statistics
266          * areas before calling the servers.
267          */
268         if (xstat_fs_debug)
269             printf("[%s] Waking up, getting data from %d server(s)\n", rn,
270                    xstat_fs_numServers);
271         curr_conn = xstat_fs_ConnInfo;
272         xstat_fs_Results.probeNum++;
273
274         for (conn_idx = 0; conn_idx < xstat_fs_numServers; conn_idx++) {
275             /*
276              * Grab the statistics for the current File Server, if the
277              * connection is valid.
278              */
279             if (xstat_fs_debug)
280                 printf("[%s] Getting collections from File Server '%s'\n", rn,
281                        curr_conn->hostName);
282             if (curr_conn->rxconn != (struct rx_connection *)0) {
283                 if (xstat_fs_debug)
284                     printf("[%s] Connection OK, calling RXAFS_GetXStats\n",
285                            rn);
286
287                 currCollIDP = xstat_fs_collIDP;
288                 for (numColls = 0; numColls < xstat_fs_numCollections;
289                      numColls++, currCollIDP++) {
290                     /*
291                      * Initialize the per-probe values.
292                      */
293                     if (xstat_fs_debug)
294                         printf("[%s] Asking for data collection %d\n", rn,
295                                *currCollIDP);
296                     xstat_fs_Results.collectionNumber = *currCollIDP;
297                     xstat_fs_Results.data.AFS_CollData_len =
298                         AFS_MAX_XSTAT_LONGS;
299                     memset(xstat_fs_Results.data.AFS_CollData_val, 0,
300                            AFS_MAX_XSTAT_LONGS * 4);
301
302                     xstat_fs_Results.connP = curr_conn;
303
304                     if (xstat_fs_debug) {
305                         printf
306                             ("%s: Calling RXAFS_GetXStats, conn=0x%x, clientVersionNumber=%d, collectionNumber=%d, srvVersionNumberP=0x%x, timeP=0x%x, dataP=0x%x\n",
307                              rn, curr_conn->rxconn, clientVersionNumber,
308                              *currCollIDP, &srvVersionNumber,
309                              &(xstat_fs_Results.probeTime),
310                              &(xstat_fs_Results.data));
311                         printf("%s: [bufflen=%d, buffer at 0x%x]\n", rn,
312                                xstat_fs_Results.data.AFS_CollData_len,
313                                xstat_fs_Results.data.AFS_CollData_val);
314                     }
315
316                     xstat_fs_Results.probeOK =
317                         RXAFS_GetXStats(curr_conn->rxconn,
318                                         clientVersionNumber, *currCollIDP,
319                                         &srvVersionNumber,
320                                         &(xstat_fs_Results.probeTime),
321                                         &(xstat_fs_Results.data));
322
323                     /*
324                      * Now that we (may) have the data for this connection,
325                      * call the associated handler function.  The handler does
326                      * not take any explicit parameters, but rather gets to the
327                      * goodies via some of the objects exported by this module.
328                      */
329                     if (xstat_fs_debug)
330                         printf("[%s] Calling handler routine.\n", rn);
331                     code = xstat_fs_Handler();
332                     if (code)
333                         fprintf(stderr,
334                                 "[%s] Handler returned error code %d\n", rn,
335                                 code);
336
337                 }               /*For each collection */
338             }
339
340             /*Valid Rx connection */
341             /*
342              * Advance the xstat_fs connection pointer.
343              */
344             curr_conn++;
345
346         }                       /*For each xstat_fs connection */
347
348         /*
349          * All (valid) connections have been probed.  Fall asleep for the
350          * prescribed number of seconds, unless we're a one-shot.  In
351          * that case, we need to signal our caller that we're done.
352          */
353         if (xstat_fs_debug)
354             printf("[%s] Polling complete for probe round %d.\n", rn,
355                    xstat_fs_Results.probeNum);
356
357         if (xstat_fs_oneShot) {
358             /*
359              * One-shot execution desired.  Signal our main procedure
360              * that we've finished our collection round.
361              */
362             if (xstat_fs_debug)
363                 printf("[%s] Signalling main process at 0x%x\n", rn,
364                        &terminationEvent);
365             oneShotCode = LWP_SignalProcess(&terminationEvent);
366             if (oneShotCode)
367                 fprintf(stderr, "[%s] Error %d from LWP_SignalProcess()", rn,
368                         oneShotCode);
369             break;              /*from the perpetual while loop */
370         } /*One-shot execution */
371         else {
372             /*
373              * Continuous execution desired.  Sleep for the required
374              * number of seconds.
375              */
376             tv.tv_sec = xstat_fs_ProbeFreqInSecs;
377             tv.tv_usec = 0;
378             if (xstat_fs_debug)
379                 printf("[%s] Falling asleep for %d seconds\n", rn,
380                        xstat_fs_ProbeFreqInSecs);
381             code = IOMGR_Select(0,      /*Num fids */
382                                 0,      /*Descs ready for reading */
383                                 0,      /*Descs ready for writing */
384                                 0,      /*Descs w/exceptional conditions */
385                                 &tv);   /*Ptr to timeout structure */
386             if (code)
387                 fprintf(stderr, "[%s] IOMGR_Select returned code %d\n", rn,
388                         code);
389         }                       /*Continuous execution */
390     }                           /*Service loop */
391     return NULL;
392 }
393
394 /*------------------------------------------------------------------------
395  * [exported] xstat_fs_Init
396  *
397  * Description:
398  *      Initialize the xstat_fs module: set up Rx connections to the
399  *      given set of File Servers, start up the probe and callback LWPs,
400  *      and associate the routine to be called when a probe completes.
401  *      Also, let it know which collections you're interested in.
402  *
403  * Arguments:
404  *      int a_numServers                  : Num. servers to connect to.
405  *      struct sockaddr_in *a_socketArray : Array of server sockets.
406  *      int a_ProbeFreqInSecs             : Probe frequency in seconds.
407  *      int (*a_ProbeHandler)()           : Ptr to probe handler fcn.
408  *      int a_flags                       : Various flags.
409  *      int a_numCollections              : Number of collections desired.
410  *      afs_int32 *a_collIDP                      : Ptr to collection IDs.
411  *
412  * Returns:
413  *      0 on success,
414  *      -2 for (at least one) connection error,
415  *      LWP process creation code, if it failed,
416  *      -1 for other fatal errors.
417  *
418  * Environment:
419  *      *** MUST BE THE FIRST ROUTINE CALLED FROM THIS PACKAGE ***
420  *      Also, the server security object CBsecobj MUST be a static,
421  *      since it has to stick around after this routine exits.
422  *
423  * Side Effects:
424  *      Sets up just about everything.
425  *------------------------------------------------------------------------*/
426
427 int
428 xstat_fs_Init(int a_numServers, struct sockaddr_in *a_socketArray,
429               int a_ProbeFreqInSecs, int (*a_ProbeHandler) (), int a_flags,
430               int a_numCollections, afs_int32 * a_collIDP)
431 {
432     static char rn[] = "xstat_fs_Init"; /*Routine name */
433     register afs_int32 code;    /*Return value */
434     static struct rx_securityClass *CBsecobj;   /*Callback security object */
435     struct rx_securityClass *secobj;    /*Client security object */
436     struct rx_service *rxsrv_afsserver; /*Server for AFS */
437     int arg_errfound;           /*Argument error found? */
438     int curr_srv;               /*Current server idx */
439     struct xstat_fs_ConnectionInfo *curr_conn;  /*Ptr to current conn */
440     char *hostNameFound;        /*Ptr to returned host name */
441     int conn_err;               /*Connection error? */
442     int PortToUse;              /*Callback port to use */
443     int collIDBytes;            /*Num bytes in coll ID array */
444     char hoststr[16];
445
446     /*
447      * If we've already been called, snicker at the bozo, gently
448      * remind him of his doubtful heritage, and return success.
449      */
450     if (xstat_fs_initflag) {
451         fprintf(stderr, "[%s] Called multiple times!\n", rn);
452         return (0);
453     } else
454         xstat_fs_initflag = 1;
455
456     /*
457      * Check the parameters for bogosities.
458      */
459     arg_errfound = 0;
460     if (a_numServers <= 0) {
461         fprintf(stderr, "[%s] Illegal number of servers: %d\n", rn,
462                 a_numServers);
463         arg_errfound = 1;
464     }
465     if (a_socketArray == (struct sockaddr_in *)0) {
466         fprintf(stderr, "[%s] Null server socket array argument\n", rn);
467         arg_errfound = 1;
468     }
469     if (a_ProbeFreqInSecs <= 0) {
470         fprintf(stderr, "[%s] Illegal probe frequency: %d\n", rn,
471                 a_ProbeFreqInSecs);
472         arg_errfound = 1;
473     }
474     if (a_ProbeHandler == (int (*)())0) {
475         fprintf(stderr, "[%s] Null probe handler function argument\n", rn);
476         arg_errfound = 1;
477     }
478     if (a_numCollections <= 0) {
479         fprintf(stderr, "[%s] Illegal collection count argument: %d\n", rn,
480                 a_numServers);
481         arg_errfound = 1;
482     }
483     if (a_collIDP == NULL) {
484         fprintf(stderr, "[%s] Null collection ID array 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     xstat_fs_debug = (a_flags & XSTAT_FS_INITFLAG_DEBUGGING);
494     xstat_fs_oneShot = (a_flags & XSTAT_FS_INITFLAG_ONE_SHOT);
495     xstat_fs_numServers = a_numServers;
496     xstat_fs_Handler = a_ProbeHandler;
497     xstat_fs_ProbeFreqInSecs = a_ProbeFreqInSecs;
498     xstat_fs_numCollections = a_numCollections;
499     collIDBytes = xstat_fs_numCollections * sizeof(afs_int32);
500     xstat_fs_collIDP = (afs_int32 *) (malloc(collIDBytes));
501     memcpy(xstat_fs_collIDP, a_collIDP, collIDBytes);
502     if (xstat_fs_debug) {
503         printf("[%s] Asking for %d collection(s): ", rn,
504                xstat_fs_numCollections);
505         for (curr_srv = 0; curr_srv < xstat_fs_numCollections; curr_srv++)
506             printf("%d ", *(xstat_fs_collIDP + curr_srv));
507         printf("\n");
508     }
509
510     /*
511      * Get ready in case we have to do a cleanup - basically, zero
512      * everything out.
513      */
514     code = xstat_fs_CleanupInit();
515     if (code)
516         return (code);
517
518     /*
519      * Allocate the necessary data structures and initialize everything
520      * else.
521      */
522     xstat_fs_ConnInfo = (struct xstat_fs_ConnectionInfo *)
523         malloc(a_numServers * sizeof(struct xstat_fs_ConnectionInfo));
524     if (xstat_fs_ConnInfo == (struct xstat_fs_ConnectionInfo *)0) {
525         fprintf(stderr,
526                 "[%s] Can't allocate %d connection info structs (%d bytes)\n",
527                 rn, a_numServers,
528                 (a_numServers * sizeof(struct xstat_fs_ConnectionInfo)));
529         return (-1);            /*No cleanup needs to be done yet */
530     }
531
532     /*
533      * Initialize the Rx subsystem, just in case nobody's done it.
534      */
535     if (xstat_fs_debug)
536         printf("[%s] Initializing Rx\n", rn);
537     PortToUse = XSTAT_FS_CBPORT;
538
539     do {
540         code = rx_Init(htons(PortToUse));
541         if (code) {
542             if (code == RX_ADDRINUSE) {
543                 if (xstat_fs_debug)
544                     fprintf(stderr,
545                             "[%s] Callback port %d in use, advancing\n", rn,
546                             PortToUse);
547                 PortToUse++;
548             } else {
549                 fprintf(stderr, "[%s] Fatal error in rx_Init()\n", rn);
550                 return (-1);
551             }
552         }
553     } while (code);
554     if (xstat_fs_debug)
555         printf("[%s] Rx initialized on port %d\n", rn, PortToUse);
556
557     /*
558      * Create a null Rx server security object, to be used by the
559      * Callback listener.
560      */
561     CBsecobj = (struct rx_securityClass *)
562         rxnull_NewServerSecurityObject();
563     if (CBsecobj == (struct rx_securityClass *)0) {
564         fprintf(stderr,
565                 "[%s] Can't create callback listener's security object.\n",
566                 rn);
567         xstat_fs_Cleanup(1);    /*Delete already-malloc'ed areas */
568         return (-1);
569     }
570     if (xstat_fs_debug)
571         printf("[%s] Callback server security object created\n", rn);
572
573     /*
574      * Create a null Rx client security object, to be used by the
575      * probe LWP.
576      */
577     secobj = rxnull_NewClientSecurityObject();
578     if (secobj == (struct rx_securityClass *)0) {
579         fprintf(stderr,
580                 "[%s] Can't create probe LWP client security object.\n", rn);
581         xstat_fs_Cleanup(1);    /*Delete already-malloc'ed areas */
582         return (-1);
583     }
584     if (xstat_fs_debug)
585         printf("[%s] Probe LWP client security object created\n", rn);
586
587     curr_conn = xstat_fs_ConnInfo;
588     conn_err = 0;
589     for (curr_srv = 0; curr_srv < a_numServers; curr_srv++) {
590         /*
591          * Copy in the socket info for the current server, resolve its
592          * printable name if possible.
593          */
594         if (xstat_fs_debug) {
595             char hoststr[16];
596             printf("[%s] Copying in the following socket info:\n", rn);
597             printf("[%s] IP addr %s, port %d\n", rn,
598                    afs_inet_ntoa_r((a_socketArray + curr_srv)->sin_addr.s_addr,hoststr),
599                    ntohs((a_socketArray + curr_srv)->sin_port));
600         }
601         memcpy(&(curr_conn->skt), a_socketArray + curr_srv,
602                sizeof(struct sockaddr_in));
603
604         hostNameFound =
605             hostutil_GetNameByINet(curr_conn->skt.sin_addr.s_addr);
606         if (hostNameFound == NULL) {
607             fprintf(stderr,
608                     "[%s] Can't map Internet address %s to a string name\n",
609                     rn, afs_inet_ntoa_r(curr_conn->skt.sin_addr.s_addr,hoststr));
610             curr_conn->hostName[0] = '\0';
611         } else {
612             strcpy(curr_conn->hostName, hostNameFound);
613             if (xstat_fs_debug)
614                 printf("[%s] Host name for server index %d is %s\n", rn,
615                        curr_srv, curr_conn->hostName);
616         }
617
618         /*
619          * Make an Rx connection to the current server.
620          */
621         if (xstat_fs_debug)
622             printf
623                 ("[%s] Connecting to srv idx %d, IP addr %s, port %d, service 1\n",
624                  rn, curr_srv, afs_inet_ntoa_r(curr_conn->skt.sin_addr.s_addr,hoststr),
625                  ntohs(curr_conn->skt.sin_port));
626
627         curr_conn->rxconn = rx_NewConnection(curr_conn->skt.sin_addr.s_addr,    /*Server addr */
628                                              curr_conn->skt.sin_port,   /*Server port */
629                                              1, /*AFS service # */
630                                              secobj,    /*Security obj */
631                                              0);        /*# of above */
632         if (curr_conn->rxconn == (struct rx_connection *)0) {
633             fprintf(stderr,
634                     "[%s] Can't create Rx connection to server '%s' (%s)\n",
635                     rn, curr_conn->hostName, afs_inet_ntoa_r(curr_conn->skt.sin_addr.s_addr,hoststr));
636             conn_err = 1;
637         }
638         if (xstat_fs_debug)
639             printf("[%s] New connection at 0x%lx\n", rn, curr_conn->rxconn);
640
641         /*
642          * Bump the current xstat_fs connection to set up.
643          */
644         curr_conn++;
645
646     }                           /*for curr_srv */
647
648     /*
649      * Create the AFS callback service (listener).
650      */
651     if (xstat_fs_debug)
652         printf("[%s] Creating AFS callback listener\n", rn);
653     rxsrv_afsserver = rx_NewService(0,  /*Use default port */
654                                     1,  /*Service ID */
655                                     "afs",      /*Service name */
656                                     &CBsecobj,  /*Ptr to security object(s) */
657                                     1,  /*# of security objects */
658                                     RXAFSCB_ExecuteRequest);    /*Dispatcher */
659     if (rxsrv_afsserver == (struct rx_service *)0) {
660         fprintf(stderr, "[%s] Can't create callback Rx service/listener\n",
661                 rn);
662         xstat_fs_Cleanup(1);    /*Delete already-malloc'ed areas */
663         return (-1);
664     }
665     if (xstat_fs_debug)
666         printf("[%s] Callback listener created\n", rn);
667
668     /*
669      * Start up the AFS callback service.
670      */
671     if (xstat_fs_debug)
672         printf("[%s] Starting up callback listener.\n", rn);
673     rx_StartServer(0);          /*Don't donate yourself to LWP pool */
674
675     /*
676      * Start up the probe LWP.
677      */
678     if (xstat_fs_debug)
679         printf("[%s] Creating the probe LWP\n", rn);
680     code = LWP_CreateProcess(xstat_fs_LWP,      /*Function to start up */
681                              LWP_STACK_SIZE,    /*Stack size in bytes */
682                              1, /*Priority */
683                              (void *)0, /*Parameters */
684                              "xstat_fs Worker", /*Name to use */
685                              &probeLWP_ID);     /*Returned LWP process ID */
686     if (code) {
687         fprintf(stderr, "[%s] Can't create xstat_fs LWP!  Error is %d\n", rn,
688                 code);
689         xstat_fs_Cleanup(1);    /*Delete already-malloc'ed areas */
690         return (code);
691     }
692     if (xstat_fs_debug)
693         printf("[%s] Probe LWP process structure located at 0x%x\n", rn,
694                probeLWP_ID);
695
696     /*
697      * Return the final results.
698      */
699     if (conn_err)
700         return (-2);
701     else
702         return (0);
703 }
704
705
706 /*------------------------------------------------------------------------
707  * [exported] xstat_fs_ForceProbeNow
708  *
709  * Description:
710  *      Wake up the probe LWP, forcing it to execute a probe immediately.
711  *
712  * Arguments:
713  *      None.
714  *
715  * Returns:
716  *      0 on success,
717  *      Error value otherwise.
718  *
719  * Environment:
720  *      The module must have been initialized.
721  *
722  * Side Effects:
723  *      As advertised.
724  *------------------------------------------------------------------------*/
725
726 int
727 xstat_fs_ForceProbeNow()
728 {
729     static char rn[] = "xstat_fs_ForceProbeNow";        /*Routine name */
730
731     /*
732      * There isn't a prayer unless we've been initialized.
733      */
734     if (!xstat_fs_initflag) {
735         fprintf(stderr, "[%s] Must call xstat_fs_Init first!\n", rn);
736         return (-1);
737     }
738
739     /*
740      * Kick the sucker in the side.
741      */
742     IOMGR_Cancel(probeLWP_ID);
743
744     /*
745      * We did it, so report the happy news.
746      */
747     return (0);
748 }