2 * Copyright 2000, International Business Machines Corporation and others.
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
12 * Implementation of the AFS FileServer probe facility.
14 *------------------------------------------------------------------------*/
16 #include <afsconfig.h>
17 #include <afs/param.h>
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>
30 #include "fsprobe.h" /*Interface for this module */
32 #define LWP_STACK_SIZE (16 * 1024)
37 int fsprobe_numServers
; /*Num servers connected */
38 struct fsprobe_ConnectionInfo
*fsprobe_ConnInfo
; /*Ptr to connection array */
39 struct fsprobe_ProbeResults fsprobe_Results
; /*Latest probe results */
40 int fsprobe_ProbeFreqInSecs
; /*Probe freq. in seconds */
45 static int fsprobe_initflag
= 0; /*Was init routine called? */
46 static int fsprobe_debug
= 0; /*Debugging output enabled? */
47 static int (*fsprobe_Handler
) (void); /*Probe handler routine */
48 static PROCESS probeLWP_ID
; /*Probe LWP process ID */
49 static int fsprobe_statsBytes
; /*Num bytes in stats block */
50 static int fsprobe_probeOKBytes
; /*Num bytes in probeOK block */
52 /*------------------------------------------------------------------------
53 * [private] fsprobe_CleanupInit
56 * Set up for recovery after an error in initialization (i.e.,
57 * during a call to fsprobe_Init.
64 * Error value otherwise.
67 * This routine is private to the module.
70 * Zeros out basic data structures.
71 *------------------------------------------------------------------------*/
74 fsprobe_CleanupInit(void)
75 { /*fsprobe_CleanupInit */
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 */
83 fsprobe_ConnInfo
= (struct fsprobe_ConnectionInfo
*)0;
84 memset(&fsprobe_Results
, 0, sizeof(struct fsprobe_ProbeResults
));
86 rxcall
= (struct rx_call
*)0;
87 Fids_Array
= (AFSCBFids
*) 0;
88 CallBack_Array
= (AFSCBs
*) 0;
91 code
= SRXAFSCB_CallBack(rxcall
, Fids_Array
, CallBack_Array
);
94 code
= SRXAFSCB_InitCallBackState2(rxcall
, interfaceAddr
);
97 code
= SRXAFSCB_Probe(rxcall
);
100 } /*fsprobe_CleanupInit */
103 /*------------------------------------------------------------------------
104 * [exported] fsprobe_Cleanup
107 * Clean up our memory and connection state.
110 * int a_releaseMem : Should we free up malloc'ed areas?
113 * 0 on total success,
114 * -1 if the module was never initialized, or there was a problem
115 * with the fsprobe connection array.
118 * fsprobe_numServers should be properly set. We don't do anything
119 * unless fsprobe_Init() has already been called.
122 * Shuts down Rx connections gracefully, frees allocated space
124 *------------------------------------------------------------------------*/
127 fsprobe_Cleanup(int a_releaseMem
)
128 { /*fsprobe_Cleanup */
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 */
136 * Assume the best, but check the worst.
138 if (!fsprobe_initflag
) {
139 fprintf(stderr
, "[%s] Refused; module not initialized\n", rn
);
145 * Take care of all Rx connections first. Check to see that the
146 * server count is a legal value.
148 if (fsprobe_numServers
<= 0) {
150 "[%s] Illegal number of servers to clean up (fsprobe_numServers = %d)\n",
151 rn
, fsprobe_numServers
);
154 if (fsprobe_ConnInfo
!= (struct fsprobe_ConnectionInfo
*)0) {
156 * The fsprobe connection structure array exists. Go through it
157 * and close up any Rx connections it holds.
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;
165 if (curr_conn
->rxVolconn
!= (struct rx_connection
*)0) {
166 rx_DestroyConnection(curr_conn
->rxVolconn
);
167 curr_conn
->rxVolconn
= (struct rx_connection
*)0;
170 } /*for each fsprobe connection */
171 } /*fsprobe connection structure exists */
172 } /*Legal number of servers */
175 * Now, release all the space we've allocated, if asked to.
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
);
187 * Return the news, whatever it is.
191 } /*fsprobe_Cleanup */
193 /*------------------------------------------------------------------------
194 * [private] fsprobe_LWP
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.
209 * Started by fsprobe_Init(), uses global sturctures.
213 *------------------------------------------------------------------------*/
215 fsprobe_LWP(void *unused
)
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
*
228 while (1) { /*Service loop */
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.
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
);
245 for (conn_idx
= 0; conn_idx
< fsprobe_numServers
; conn_idx
++) {
247 * Grab the statistics for the current FileServer, if the
248 * connection is valid.
251 fprintf(stderr
, "[%s] Contacting server %s\n", rn
,
252 curr_conn
->hostName
);
253 if (curr_conn
->rxconn
!= (struct rx_connection
*)0) {
256 "[%s] Connection valid, calling RXAFS_GetStatistics\n",
259 RXAFS_GetStatistics64(curr_conn
->rxconn
, STATS64_VERSION
, &stats64
);
260 if (*curr_probeOK
== RXGEN_OPCODE
)
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
]);
274 /*Valid Rx connection */
276 * Call the Volume Server too to get additional stats
279 fprintf(stderr
, "[%s] Contacting volume server %s\n", rn
,
280 curr_conn
->hostName
);
281 if (curr_conn
->rxVolconn
!= (struct rx_connection
*)0) {
284 struct diskPartition partition
;
285 struct diskPartition64
*partition64p
=
286 malloc(sizeof(struct diskPartition64
));
290 "[%s] Connection valid, calling RXAFS_GetStatistics\n",
292 for (i
= 0; i
< curr_conn
->partCnt
; i
++) {
293 if (curr_conn
->partList
.partFlags
[i
] & PARTVALID
) {
294 MapPartIdIntoName(curr_conn
->partList
.partId
[i
],
297 AFSVolPartitionInfo64(curr_conn
->rxVolconn
, pname
,
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
);
307 if (code
== RXGEN_OPCODE
) {
309 AFSVolPartitionInfo(curr_conn
->rxVolconn
,
312 curr_stats
->Disk
[i
].BlocksAvailable
=
314 curr_stats
->Disk
[i
].TotalBlocks
=
316 strcpy(curr_stats
->Disk
[i
].Name
, pname
);
321 "Could not get information on server %s partition %s\n",
322 curr_conn
->hostName
, pname
);
331 * Advance the fsprobe connection pointer & stats pointer.
337 } /*For each fsprobe connection */
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.
347 "[%s] Polling complete, calling associated handler routine.\n",
349 code
= fsprobe_Handler();
351 fprintf(stderr
, "[%s] Handler routine returned error code %d\n",
355 * Fall asleep for the prescribed number of seconds.
357 tv
.tv_sec
= fsprobe_ProbeFreqInSecs
;
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 */
368 fprintf(stderr
, "[%s] IOMGR_Select returned code %d\n", rn
, code
);
370 AFS_UNREACHED(free(stats64
.ViceStatistics64_val
));
371 AFS_UNREACHED(return(NULL
));
374 /*list all the partitions on <aserver> */
375 static int newvolserver
= 0;
378 XListPartitions(struct rx_connection
*aconn
, struct partList
*ptrPartList
,
382 struct partEntries partEnts
;
386 if (newvolserver
== 1) {
387 for (i
= 0; i
< 26; i
++)
388 partIds
.partIds
[i
] = -1;
390 code
= AFSVolListPartitions(aconn
, &partIds
);
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
;
398 ptrPartList
->partFlags
[i
] = 0;
404 partEnts
.partEntries_len
= 0;
405 partEnts
.partEntries_val
= NULL
;
406 code
= AFSVolXListPartitions(aconn
, &partEnts
);
408 if (code
== RXGEN_OPCODE
) {
409 newvolserver
= 1; /* Doesn't support new interface */
416 *cntp
= partEnts
.partEntries_len
;
417 if (*cntp
> VOLMAXPARTS
) {
419 "Warning: number of partitions on the server too high %d (process only %d)\n",
423 for (i
= 0; i
< *cntp
; i
++) {
424 ptrPartList
->partId
[i
] = partEnts
.partEntries_val
[i
];
425 ptrPartList
->partFlags
[i
] = PARTVALID
;
427 free(partEnts
.partEntries_val
);
432 "Could not fetch the list of partitions from the server\n");
437 /*------------------------------------------------------------------------
438 * [exported] fsprobe_Init
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.
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?
454 * -2 for (at least one) connection error,
455 * LWP process creation code, if it failed,
456 * -1 for other fatal errors.
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.
464 * Sets up just about everything.
465 *------------------------------------------------------------------------*/
468 fsprobe_Init(int a_numServers
, struct sockaddr_in
*a_socketArray
,
469 int a_ProbeFreqInSecs
, int (*a_ProbeHandler
)(void),
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? */
485 * If we've already been called, snicker at the bozo, gently
486 * remind him of his doubtful heritage, and return success.
488 if (fsprobe_initflag
) {
489 fprintf(stderr
, "[%s] Called multiple times!\n", rn
);
492 fsprobe_initflag
= 1;
495 * Check the parameters for bogosities.
498 if (a_numServers
<= 0) {
499 fprintf(stderr
, "[%s] Illegal number of servers: %d\n", rn
,
503 if (a_socketArray
== (struct sockaddr_in
*)0) {
504 fprintf(stderr
, "[%s] Null server socket array argument\n", rn
);
507 if (a_ProbeFreqInSecs
<= 0) {
508 fprintf(stderr
, "[%s] Illegal probe frequency: %d\n", rn
,
512 if (a_ProbeHandler
== (int (*)())0) {
513 fprintf(stderr
, "[%s] Null probe handler function argument\n", rn
);
520 * Record our passed-in info.
522 fsprobe_debug
= a_debug
;
523 fsprobe_numServers
= a_numServers
;
524 fsprobe_Handler
= a_ProbeHandler
;
525 fsprobe_ProbeFreqInSecs
= a_ProbeFreqInSecs
;
528 * Get ready in case we have to do a cleanup - basically, zero
531 fsprobe_CleanupInit();
534 * Allocate the necessary data structures and initialize everything
537 fsprobe_ConnInfo
= (struct fsprobe_ConnectionInfo
*)
538 malloc(a_numServers
* sizeof(struct fsprobe_ConnectionInfo
));
539 if (fsprobe_ConnInfo
== (struct fsprobe_ConnectionInfo
*)0) {
541 "[%s] Can't allocate %d connection info structs (%"AFS_SIZET_FMT
" bytes)\n",
543 (a_numServers
* sizeof(struct fsprobe_ConnectionInfo
)));
544 return (-1); /*No cleanup needs to be done yet */
548 fprintf(stderr
, "[%s] fsprobe_ConnInfo allocated (%d bytes)\n", rn
,
549 a_numServers
* sizeof(struct fsprobe_ConnectionInfo
));
552 fsprobe_statsBytes
= a_numServers
* sizeof(struct ProbeViceStatistics
);
553 fsprobe_Results
.stats
= (struct ProbeViceStatistics
*)
554 malloc(fsprobe_statsBytes
);
555 if (fsprobe_Results
.stats
== NULL
) {
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 */
561 } else if (fsprobe_debug
)
562 fprintf(stderr
, "[%s] fsprobe_Results.stats allocated (%d bytes)\n",
563 rn
, fsprobe_statsBytes
);
565 fsprobe_probeOKBytes
= a_numServers
* sizeof(int);
566 fsprobe_Results
.probeOK
= malloc(fsprobe_probeOKBytes
);
567 if (fsprobe_Results
.probeOK
== (int *)0) {
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 */
573 } else if (fsprobe_debug
)
574 fprintf(stderr
, "[%s] fsprobe_Results.probeOK allocated (%d bytes)\n",
575 rn
, fsprobe_probeOKBytes
);
577 fsprobe_Results
.probeNum
= 0;
578 fsprobe_Results
.probeTime
= 0;
579 memset(fsprobe_Results
.stats
, 0,
580 (a_numServers
* sizeof(struct ProbeViceStatistics
)));
583 * Initialize the Rx subsystem, just in case nobody's done it.
586 fprintf(stderr
, "[%s] Initializing Rx\n", rn
);
589 fprintf(stderr
, "[%s] Fatal error in rx_Init()\n", rn
);
593 fprintf(stderr
, "[%s] Rx initialized.\n", rn
);
596 * Create a null Rx server security object, to be used by the
599 CBsecobj
= rxnull_NewServerSecurityObject();
600 if (CBsecobj
== (struct rx_securityClass
*)0) {
602 "[%s] Can't create null security object for the callback listener.\n",
604 fsprobe_Cleanup(1); /*Delete already-malloc'ed areas */
608 fprintf(stderr
, "[%s] Callback server security object created\n", rn
);
611 * Create a null Rx client security object, to be used by the
614 secobj
= rxnull_NewClientSecurityObject();
615 if (secobj
== (struct rx_securityClass
*)0) {
617 "[%s] Can't create client security object for probe LWP.\n",
619 fsprobe_Cleanup(1); /*Delete already-malloc'ed areas */
623 fprintf(stderr
, "[%s] Probe LWP client security object created\n",
626 curr_conn
= fsprobe_ConnInfo
;
628 for (curr_srv
= 0; curr_srv
< a_numServers
; curr_srv
++) {
630 * Copy in the socket info for the current server, resolve its
631 * printable name if possible.
634 fprintf(stderr
, "[%s] Copying in the following socket info:\n",
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
);
640 memcpy(&(curr_conn
->skt
), a_socketArray
+ curr_srv
,
641 sizeof(struct sockaddr_in
));
644 hostutil_GetNameByINet(curr_conn
->skt
.sin_addr
.s_addr
);
645 if (hostNameFound
== NULL
) {
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';
651 strcpy(curr_conn
->hostName
, hostNameFound
);
653 fprintf(stderr
, "[%s] Host name for server index %d is %s\n",
654 rn
, curr_srv
, curr_conn
->hostName
);
658 * Make an Rx connection to the current server.
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) {
672 "[%s] Can't create Rx connection to server %s (%u)\n",
673 rn
, curr_conn
->hostName
, curr_conn
->skt
.sin_addr
.s_addr
);
677 fprintf(stderr
, "[%s] New connection at %p\n", rn
,
681 * Make an Rx connection to the current volume server.
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
,
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) {
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
);
701 memset(&curr_conn
->partList
, 0, sizeof(struct partList
));
702 curr_conn
->partCnt
= 0;
703 i
= XListPartitions(curr_conn
->rxVolconn
, &curr_conn
->partList
,
706 curr_conn
->partCnt
= cnt
;
710 fprintf(stderr
, "[%s] New connection at %p\n", rn
,
711 curr_conn
->rxVolconn
);
715 * Bump the current fsprobe connection to set up.
722 * Create the AFS callback service (listener).
725 fprintf(stderr
, "[%s] Creating AFS callback listener\n", rn
);
726 rxsrv_afsserver
= rx_NewService(0, /*Use default port */
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",
735 fsprobe_Cleanup(1); /*Delete already-malloc'ed areas */
739 fprintf(stderr
, "[%s] Callback listener created\n", rn
);
742 * Start up the AFS callback service.
745 fprintf(stderr
, "[%s] Starting up callback listener.\n", rn
);
746 rx_StartServer(0 /*Don't donate yourself to LWP pool */ );
749 * Start up the probe LWP.
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 */
756 (void *)0, /*Parameters */
757 "fsprobe Worker", /*Name to use */
758 &probeLWP_ID
); /*Returned LWP process ID */
760 fprintf(stderr
, "[%s] Can't create fsprobe LWP! Error is %d\n", rn
,
762 fsprobe_Cleanup(1); /*Delete already-malloc'ed areas */
766 fprintf(stderr
, "[%s] Probe LWP process structure located at %p\n",
771 * Do I need to do this?
774 fprintf(stderr
, "[%s] Calling osi_Wakeup()\n", rn
);
775 osi_Wakeup(&rxsrv_afsserver
); /*Wake up anyone waiting for it */
779 * Return the final results.
789 /*------------------------------------------------------------------------
790 * [exported] fsprobe_ForceProbeNow
793 * Wake up the probe LWP, forcing it to execute a probe immediately.
800 * Error value otherwise.
803 * The module must have been initialized.
807 *------------------------------------------------------------------------*/
810 fsprobe_ForceProbeNow(void)
811 { /*fsprobe_ForceProbeNow */
813 static char rn
[] = "fsprobe_ForceProbeNow"; /*Routine name */
816 * There isn't a prayer unless we've been initialized.
818 if (!fsprobe_initflag
) {
819 fprintf(stderr
, "[%s] Must call fsprobe_Init first!\n", rn
);
824 * Kick the sucker in the side.
826 IOMGR_Cancel(probeLWP_ID
);
829 * We did it, so report the happy news.
833 } /*fsprobe_ForceProbeNow */