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