2 static char sfs_c_bioSid[] = "@(#)sfs_c_bio.c 2.1 97/10/23";
6 * Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
8 * Standard Performance Evaluation Corporation (SPEC)
9 * 6585 Merchant Place, Suite 100
12 * This product contains benchmarks acquired from several sources who
13 * understand and agree with SPEC's goal of creating fair and objective
14 * benchmarks to measure computer performance.
16 * This copyright notice is placed here only to protect SPEC in the
17 * event the source is misused in any manner that is contrary to the
18 * spirit, the goals and the intent of SPEC.
20 * The source code is provided to the user or company under the license
21 * agreement for the SPEC Benchmark Suite for this product.
25 * ---------------------- sfs_c_bio.c ---------------------
27 * Routines that attempt to simulate biod behavior
29 * The routines contained here model biod behavior. Simply call
30 * biod_init() to replace regular calls to op_read() and op_write()
31 * with calls to op_biod_read() and op_biod_write(). The variables
32 * max_out_writes and max_out_reads control the maximum number of
33 * outstanding writes and reads respectively.
36 * int biod_init(int, int);
37 * void biod_turn_on(void);
38 * void op_biod_write(int, int, int);
39 * void op_biod_read(int);
42 * uint32_t biod_clnt_call(CLIENT *, uint32_t,
44 * struct biod_req *biod_get_reply(CLIENT *, xdrproc_t,
45 * void *, struct timeval *);
46 * int biod_poll_wait(CLIENT *, uint32_t);
50 * History now kept in SCCS
51 * 03-Mar-92 0.1.0 Corbin
56 * ------------------------- Include Files -------------------------
67 #include <sys/types.h>
72 #include "sfs_c_def.h"
75 * Information associated with outstanding read/write requests
78 uint32_t xid; /* RPC transmission ID */
79 bool_t in_use; /* Indicates if the entry is in use */
80 unsigned int count; /* Count saved for Dump routines */
81 unsigned int offset; /* Offset saved for Dump routines */
82 struct ladtime start; /* Time RPC call was made */
83 struct ladtime stop; /* Time RPC reply was received */
84 struct ladtime timeout; /* Time RPC call will time out */
88 * ---------------------- Static Declarations ----------------------
91 static int max_out_writes;
92 static int max_out_reads;
93 static int max_biod_reqs = 0;
94 static struct biod_req *biod_reqp;
96 /* forward definitions for local functions */
97 static uint32_t biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
98 static struct biod_req *biod_get_reply(CLIENT *, xdrproc_t,
99 void *, struct timeval *);
100 static int biod_poll_wait(CLIENT *, uint32_t);
102 static int op_biod_write(int, int, int);
103 static int op_biod_read(int);
106 * ---------------------- BIOD Support Routines ----------------------
112 * This function is called during the initialization phase. It performs
113 * the following tasks:
114 * - Allocate memory to hold outstanding biod request information
116 * Returns 0 for OK, -1 for failure
123 max_out_writes = MAXIMUM(1, out_writes);
124 max_out_reads = MAXIMUM(1, out_reads);
125 max_biod_reqs = MAXIMUM(out_writes, out_reads);
127 biod_reqp = (struct biod_req *) calloc(max_biod_reqs,
128 sizeof (struct biod_req));
129 if (biod_reqp == (struct biod_req *)0) {
130 (void) fprintf(stderr, "%s: biod_init calloc failed.\n", sfs_Myname);
131 (void) fflush(stderr);
140 * - Change the operation functions for reads and writes to use the
141 * biod routines. This step should be done last to allow callers
142 * to still run with the old op functions if the biod initialization
148 Ops[WRITE].funct = op_biod_write;
149 Ops[READ].funct = op_biod_read;
155 * This function is called during the termination phase to free any resources
156 * allocated by the biod_init() routine. It performs the following tasks:
157 * - Frees memory associated with outstanding biod request information
158 * - Frees the biod client handle
169 * Perform and RPC biod style write operation of length 'xfer_size'.
170 * If 'append_flag' is true, then write the data to the end of the file.
178 sfs_op_type *op_ptr; /* per operation info */
179 static char *buf = NULL; /* the data buffer */
180 unsigned int size; /* size of data write */
182 attrstat reply2; /* the reply */
184 WRITE3res reply3; /* the reply */
186 struct ladtime curr_time;
187 struct ladtime tmp_time;
188 struct ladtime call_timeout;
189 struct biod_req *reqp;
190 int ret; /* ret val == call success */
191 int num_out_reqs; /* # of outstanding writes */
195 static int calls = 0;
199 if (nfs_version != NFS_VERSION && nfs_version != NFS_V3)
203 * Initialize write buffer to known value
206 buf = init_write_buffer();
211 * For now we treat DATA_SYNC to be the same as FILE_SYNC.
212 * If it is not a V3 op then it must always be stable
214 if (stab_flag == DATA_SYNC || nfs_version != NFS_V3)
215 stab_flag = FILE_SYNC;
217 op_ptr = &Ops[WRITE];
220 /* set up the arguments */
221 (void) memmove((char *) &args2.file, (char *) &Cur_file_ptr->fh2,
223 (void) memmove((char *) &args3.file, (char *) &Cur_file_ptr->fh3,
226 args2.beginoffset = 0; /* unused */
228 if (append_flag == 1) {
229 args2.offset = Cur_file_ptr->attributes2.size;
230 args3.offset = Cur_file_ptr->attributes3.size;
232 if (fh_size(Cur_file_ptr) > xfer_size) {
233 offset = Bytes_per_block * (sfs_random() %
234 (((fh_size(Cur_file_ptr) - xfer_size)
235 / Bytes_per_block) + 1));
236 args2.offset = offset;
237 args3.offset._p._u = 0;
238 args3.offset._p._l = offset;
241 args3.offset._p._u = args3.offset._p._l = 0;
245 size = Bytes_per_block;
246 args2.totalcount = size; /* unused */
247 args2.data.data_len = size;
248 args2.data.data_val = buf;
249 args3.data.data_len = size;
250 args3.data.data_val = buf;
252 args3.stable = stab_flag;
254 /* Calculate the number of NFS writes required */
255 max_cnt = xfer_size / Bytes_per_block;
256 if ((xfer_size % Bytes_per_block) != 0) {
260 /* check our stats to see if this would overflow */
262 if (op_ptr->target_calls > 0 &&
263 (op_ptr->results.good_calls + max_cnt) > op_ptr->target_calls) {
264 max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
268 if (DEBUG_CHILD_OPS) {
269 (void) fprintf(stderr, "write: %d buffers xfer_size %d\n",
271 (void) fflush(stderr);
274 /* Mark all request slots as not in use */
275 for (reqp = biod_reqp, i = 0; i < max_biod_reqs; i++, reqp++) {
276 reqp->in_use = FALSE;
279 if (Current_test_phase < Warmup_phase) {
280 call_timeout.sec = Nfs_timers[Init].tv_sec;
281 call_timeout.usec = Nfs_timers[Init].tv_usec;
283 call_timeout.sec = Nfs_timers[op_ptr->call_class].tv_sec;
284 call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
287 /* capture length for possible dump */
288 Dump_length = fh_size(Cur_file_ptr);
290 /* make the call(s) now */
292 while (xfer_size > 0 || num_out_reqs > 0) {
294 * Send out calls async until either the maximum number of outstanding
295 * requests has been reached or there are no more requests to make.
297 while (num_out_reqs < max_out_writes && xfer_size > 0) {
299 /* find an empty write request slot */
300 for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
301 if (reqp->in_use == FALSE) {
306 if (xfer_size < size) {
308 args2.data.data_len = xfer_size;
309 args2.totalcount = xfer_size; /* unused */
310 args3.data.data_len = xfer_size;
311 args3.count = xfer_size;
315 sfs_gettime(&reqp->start);
316 if (nfs_version == NFS_V3) {
317 reqp->xid = biod_clnt_call(NFS_client,
318 (uint32_t)NFSPROC3_WRITE,
319 xdr_WRITE3args, (char *) &args3);
320 if (reqp->xid != 0) {
321 /* capture count and offset for possible dump */
322 reqp->count = args3.data.data_len;
323 reqp->offset = args3.offset._p._l;
324 reqp->timeout = reqp->start;
325 ADDTIME(reqp->timeout, call_timeout);
330 if (nfs_version == NFS_VERSION) {
331 reqp->xid = biod_clnt_call(NFS_client,
332 (uint32_t)NFSPROC_WRITE,
333 xdr_write, (char *) &args2);
334 if (reqp->xid != 0) {
335 /* capture count and offset for possible dump */
336 reqp->count = args2.data.data_len;
337 reqp->offset = args2.offset;
338 reqp->timeout = reqp->start;
339 ADDTIME(reqp->timeout, call_timeout);
344 if (DEBUG_CHILD_BIOD) {
345 (void) fprintf (stderr,
346 "[%d]:Biod write started xid %x start (%d.%06d) timeo (%d.%06d)\n",
348 reqp->start.sec, reqp->start.usec,
349 reqp->timeout.sec, reqp->timeout.usec);
352 args2.offset += size;
353 args3.offset._p._l += size;
354 if (biod_poll_wait(NFS_client, 0) > 0) {
357 } /* while can make an async call */
360 * Process replies while there is data on the socket buffer.
361 * Just do polls on the select, no sleeping occurs in this loop.
364 error = biod_poll_wait(NFS_client, 0);
367 if (errno == EINTR) {
371 if (DEBUG_CHILD_BIOD) {
372 (void) fprintf(stderr, "%s:[%d]: biod_poll_wait error\n",
374 (void) fflush(stderr);
383 if (nfs_version == NFS_VERSION)
384 reqp = biod_get_reply(NFS_client, xdr_write,
386 &Nfs_timers[op_ptr->call_class]);
387 if (nfs_version == NFS_V3)
388 reqp = biod_get_reply(NFS_client, xdr_WRITE3res,
390 &Nfs_timers[op_ptr->call_class]);
393 * If biod_get_reply returns NULL then we got an RPC
394 * level error, probably a dropped fragment or the
395 * remains of a previous partial request.
397 if (reqp == (struct biod_req *)NULL) {
403 * We have a valid response, check if procedure completed
406 if ((nfs_version == NFS_VERSION &&
407 reply2.status == NFS_OK) ||
408 (nfs_version == NFS_V3 && reply3.status == NFS3_OK)) {
409 Cur_file_ptr->state = Exists;
411 * In updating attributes we may get replies out
412 * of order. We blindly update the attributes
413 * which may cause old attributes to be stored.
414 * XXX We should check for old attributes.
416 if (nfs_version == NFS_VERSION)
417 Cur_file_ptr->attributes2 =
418 reply2.attrstat_u.attributes;
419 if (nfs_version == NFS_V3)
420 Cur_file_ptr->attributes3 =
421 reply3.res_u.ok.file_wcc.after.attr;
422 if (DEBUG_CHILD_RPC) {
423 (void) fprintf(stderr,
424 "%s: WRITE %s %d bytes offset %d \n",
425 sfs_Myname, Cur_filename,
426 reqp->count, reqp->offset);
427 (void) fflush(stderr);
430 /* capture count and offset for possible dump */
431 Dump_count = reqp->count;
432 Dump_offset = reqp->offset;
433 sfs_elapsedtime(op_ptr, &reqp->start, &reqp->stop);
434 op_ptr->results.good_calls++;
435 Ops[TOTAL].results.good_calls++;
437 reqp->in_use = FALSE;
439 if (DEBUG_CHILD_BIOD) {
440 (void) fprintf (stderr,
441 "[%d]:Biod write succeded xid %x start (%d.%06d) timeo (%d.%06d) stop (%d.%06d)\n",
443 reqp->start.sec, reqp->start.usec,
444 reqp->timeout.sec, reqp->timeout.usec,
445 reqp->stop.sec, reqp->stop.usec);
448 op_ptr->results.bad_calls++;
449 Ops[TOTAL].results.bad_calls++;
450 reqp->in_use = FALSE;
452 if (DEBUG_CHILD_BIOD) {
453 (void) fprintf (stderr,
454 "[%d]:Biod write failed xid %x start (%d.%06d) timeo (%d.%06d)\n",
456 reqp->start.sec, reqp->start.usec,
457 reqp->timeout.sec, reqp->timeout.usec);
459 (void) fprintf(stderr,
460 "[%d]:BIOD WRITE FAILED: xid %x",
463 if (nfs_version == NFS_VERSION)
464 (void) fprintf(stderr, " status %d",
466 if (nfs_version == NFS_V3)
467 (void) fprintf(stderr, " status %d",
469 (void) fprintf(stderr, "\n");
474 } while (error > 0 && num_out_reqs > 0);
476 /* Scan for replies that have timed out */
477 if (num_out_reqs > 0) {
478 sfs_gettime(&curr_time);
479 for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
480 if (reqp->in_use == FALSE) {
483 if (reqp->timeout.sec < curr_time.sec ||
484 (reqp->timeout.sec == curr_time.sec &&
485 reqp->timeout.usec < curr_time.usec)) {
487 op_ptr->results.bad_calls++;
488 Ops[TOTAL].results.bad_calls++;
489 reqp->in_use = FALSE;
491 if (DEBUG_CHILD_BIOD) {
492 (void) fprintf (stderr,
493 "[%d]:Biod write timed out %x start (%d.%06d) timeo (%d.%06d) now (%d.%06d)\n",
495 reqp->start.sec, reqp->start.usec,
496 reqp->timeout.sec, reqp->timeout.usec,
497 curr_time.sec, curr_time.usec);
498 if (biod_poll_wait(NFS_client, 0) > 0) {
499 (void) fprintf(stderr,
500 "[%d]:BIOD WRITE TIMEOUT - data on input queue!\n", calls);
508 * We go to sleep waiting for a reply if all the requests have
509 * been sent and there are outstanding requests, or we cannot
510 * send any more requests.
512 if ((xfer_size <= 0 && num_out_reqs > 0) ||
513 num_out_reqs == max_out_writes) {
515 * Find the next outstanding request that will timeout
516 * and take a time differential to use for the poll timeout.
517 * If the differential is less than zero, then we go to the
518 * top of the loop. Note that we are not picky on errors
519 * returned by select, after the sleep we return to the top
520 * of the loop so extensive error/status checking is not
525 for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
526 if (reqp->in_use == FALSE) {
529 if (tmp_time.sec == 0 ||
530 (reqp->timeout.sec < tmp_time.sec ||
531 (reqp->timeout.sec == tmp_time.sec &&
532 reqp->timeout.usec < tmp_time.usec))) {
534 tmp_time = reqp->timeout;
537 if (tmp_time.sec == 0 && tmp_time.usec == 0)
539 sfs_gettime(&curr_time);
540 SUBTIME(tmp_time, curr_time);
541 (void) biod_poll_wait(NFS_client,
542 tmp_time.sec * 1000000 + tmp_time.usec);
544 } /* while not done */
548 * If we have not gotten an error and we were asked for an async write
549 * send a commit operation.
551 if (ret && stab_flag != FILE_SYNC)
552 ret += (*Ops[COMMIT].funct)();
556 } /* op_biod_write */
560 * perform an RPC read operation of length 'xfer_size'
566 sfs_op_type *op_ptr; /* per operation info */
567 int max_cnt; /* packet ctrs */
568 char buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
570 readres reply2; /* the reply */
572 READ3res reply3; /* the reply */
574 struct ladtime curr_time;
575 struct ladtime call_timeout;
576 struct ladtime tmp_time;
577 struct biod_req *reqp;
578 int ret; /* ret val == call success */
579 int num_out_reqs; /* # of outstanding writes */
583 static int calls = 0;
587 if (nfs_version != NFS_VERSION && nfs_version != NFS_V3)
593 /* set up the arguments */
594 (void) memmove((char *) &args2.file, (char *) &Cur_file_ptr->fh2,
596 (void) memmove((char *) &args3.file, (char *) &Cur_file_ptr->fh3,
600 * Don't allow a read of less than one block size
602 if (xfer_size < Bytes_per_block)
603 xfer_size = Bytes_per_block;
606 /* Calculate the number of NFS reads required */
607 max_cnt = xfer_size / Bytes_per_block;
608 if ((xfer_size % Bytes_per_block) != 0) {
612 /* check our stats to see if this would overflow */
614 if (op_ptr->target_calls > 0 &&
615 (op_ptr->results.good_calls + max_cnt) > op_ptr->target_calls) {
616 max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
621 args3.offset._p._l = args3.offset._p._u = 0;
624 * randomly choose an offset that is a multiple of the block size
625 * and constrained by making the transfer fit within the file
627 if (fh_size(Cur_file_ptr) > xfer_size) {
628 offset = Bytes_per_block * (sfs_random() %
629 (((fh_size(Cur_file_ptr) - xfer_size)
630 / Bytes_per_block) + 1));
631 args2.offset = offset;
632 args3.offset._p._u = 0;
633 args3.offset._p._l = offset;
636 size = Bytes_per_block;
639 args2.totalcount = size; /* unused */
641 /* Have lower layers fill in the data directly. */
642 reply2.readres_u.reply.data.data_val = buf;
643 reply3.res_u.ok.data.data_val = buf;
645 if (DEBUG_CHILD_OPS) {
646 (void) fprintf(stderr, "read: %d buffers xfer_size %d\n",
648 (void) fflush(stderr);
651 /* Mark all request slots as not in use */
652 for (reqp = biod_reqp, i = 0; i < max_biod_reqs; i++, reqp++) {
653 reqp->in_use = FALSE;
656 if (Current_test_phase < Warmup_phase) {
657 call_timeout.sec = Nfs_timers[Init].tv_sec;
658 call_timeout.usec = Nfs_timers[Init].tv_usec;
660 call_timeout.sec = Nfs_timers[op_ptr->call_class].tv_sec;
661 call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
664 /* capture length for possible dump */
665 Dump_length = fh_size(Cur_file_ptr);
667 /* make the call(s) now */
669 while (xfer_size > 0 || num_out_reqs > 0) {
671 * Send out calls async until either the maximum number of outstanding
672 * requests has been reached or there are no more requests to make.
674 while (num_out_reqs < max_out_reads && xfer_size > 0) {
676 /* find an empty read request slot */
677 for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
678 if (reqp->in_use == FALSE) {
683 if (xfer_size < size) {
685 args2.count = xfer_size;
686 args3.count = xfer_size;
687 args2.totalcount = xfer_size; /* unused */
691 sfs_gettime(&reqp->start);
692 if (nfs_version == NFS_VERSION) {
693 reqp->xid = biod_clnt_call(NFS_client,
694 (uint32_t)NFSPROC_READ,
695 xdr_read, (char *) &args2);
696 if (reqp->xid != 0) {
697 /* capture count and offset for possible dump */
698 reqp->count = args2.count;
699 reqp->offset = args2.offset;
700 reqp->timeout = reqp->start;
701 ADDTIME(reqp->timeout, call_timeout);
705 } else if (nfs_version == NFS_V3) {
706 reqp->xid = biod_clnt_call(NFS_client,
707 (uint32_t)NFSPROC3_READ,
708 xdr_READ3args, (char *) &args3);
709 if (reqp->xid != 0) {
710 /* capture count and offset for possible dump */
711 reqp->count = args3.count;
712 reqp->offset = args3.offset._p._l;
713 reqp->timeout = reqp->start;
714 ADDTIME(reqp->timeout, call_timeout);
720 args2.offset += size;
721 args3.offset._p._l += size;
722 if (biod_poll_wait(NFS_client, 0) > 0) {
725 } /* while can make an async call */
728 * Process replies while there is data on the socket buffer.
729 * Just do polls on the select, no sleeping occurs in this loop.
732 error = biod_poll_wait(NFS_client, 0);
735 if (errno == EINTR) {
739 if (DEBUG_CHILD_BIOD) {
740 (void) fprintf(stderr,
741 "%s:[%d]: biod_poll_wait error\n",
743 (void) fflush(stderr);
752 if (nfs_version == NFS_VERSION)
753 reqp = biod_get_reply(NFS_client, xdr_read,
755 &Nfs_timers[op_ptr->call_class]);
756 if (nfs_version == NFS_V3)
757 reqp = biod_get_reply(NFS_client, xdr_READ3res,
759 &Nfs_timers[op_ptr->call_class]);
762 * If biod_get_reply returns NULL then we got an RPC
763 * level error, probably a dropped fragment or the
764 * remains of a previous partial request.
766 if (reqp == (struct biod_req *)NULL) {
772 * We have a valid response, check if procedure completed
775 if ((nfs_version == NFS_VERSION &&
776 reply2.status == NFS_OK) ||
777 (nfs_version == NFS_V3 &&
778 reply3.status == NFS3_OK)) {
779 Cur_file_ptr->state = Exists;
780 if (DEBUG_CHILD_RPC) {
781 (void) fprintf(stderr, "%s: READ %s %d bytes offset %d\n",
782 sfs_Myname, Cur_filename, reqp->count, reqp->offset);
783 (void) fflush(stderr);
786 * In updating attributes we may get replies out
787 * of order. We blindly update the attributes
788 * which may cause old attributes to be stored.
789 * XXX We should check for old attributes.
791 if (nfs_version == NFS_VERSION) {
792 Cur_file_ptr->attributes2 =
793 reply2.readres_u.reply.attributes;
794 /* capture count and offset for possible dump */
795 Dump_count = reply2.readres_u.reply.data.data_len;
797 if (nfs_version == NFS_V3) {
798 Cur_file_ptr->attributes3 =
799 reply3.res_u.ok.file_attributes.attr;
800 /* capture count and offset for possible dump */
801 Dump_count = reply3.res_u.ok.data.data_len;
804 Dump_offset = reqp->offset;
805 sfs_elapsedtime(op_ptr, &reqp->start, &reqp->stop);
806 op_ptr->results.good_calls++;
807 Ops[TOTAL].results.good_calls++;
809 reqp->in_use = FALSE;
812 op_ptr->results.bad_calls++;
813 Ops[TOTAL].results.bad_calls++;
814 reqp->in_use = FALSE;
817 if (DEBUG_CHILD_BIOD) {
818 (void) fprintf(stderr,
819 "[%d]:BIOD READ FAILED: xid %x",
822 if (nfs_version == NFS_VERSION)
823 (void) fprintf(stderr, " status %d",
825 if (nfs_version == NFS_V3)
826 (void) fprintf(stderr, " status %d",
828 (void) fprintf(stderr, "\n");
833 } while (error > 0 && num_out_reqs > 0);
835 /* Scan for replies that have timed out */
836 if (num_out_reqs > 0) {
837 sfs_gettime(&curr_time);
838 for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
839 if (reqp->in_use == FALSE) {
842 if (reqp->timeout.sec < curr_time.sec ||
843 (reqp->timeout.sec == curr_time.sec &&
844 reqp->timeout.usec < curr_time.usec)) {
846 op_ptr->results.bad_calls++;
847 Ops[TOTAL].results.bad_calls++;
848 reqp->in_use = FALSE;
850 if (DEBUG_CHILD_BIOD) {
851 (void) fprintf (stderr,
852 "[%d]:Biod read timed out %x (%d.%06d) now (%d.%06d)\n",
854 reqp->timeout.sec, reqp->timeout.usec,
855 curr_time.sec, curr_time.usec);
856 if (biod_poll_wait(NFS_client, 0) > 0) {
857 (void) fprintf(stderr,
858 "[%d]:BIOD READ TIMEOUT - data on input queue!\n", calls);
866 * We go to sleep waiting for a reply if all the requests have
867 * been sent and there are outstanding requests, or we cannot
868 * send any more requests.
870 if ((xfer_size <= 0 && num_out_reqs > 0) ||
871 num_out_reqs == max_out_reads) {
873 * Find the next outstanding request that will timeout
874 * and take a time differential to use for the poll timeout.
875 * If the differential is less than zero, then we go to the
876 * top of the loop. Note that we are not picky on errors
877 * returned by select, after the sleep we return to the top
878 * of the loop so extensive error/status checking is not
883 for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
884 if (reqp->in_use == FALSE) {
887 if (tmp_time.sec == 0 ||
888 (reqp->timeout.sec < tmp_time.sec ||
889 (reqp->timeout.sec == tmp_time.sec &&
890 reqp->timeout.usec < tmp_time.usec))) {
892 tmp_time = reqp->timeout;
895 if (tmp_time.sec == 0 && tmp_time.usec == 0)
897 sfs_gettime(&curr_time);
898 SUBTIME(tmp_time, curr_time);
899 (void) biod_poll_wait(NFS_client,
900 tmp_time.sec * 1000000 + tmp_time.usec);
902 } /* while not done */
909 * ---------------------- Async RPC Support Routines ----------------------
915 * Returns XID indicating success, 0 indicating failure.
919 CLIENT *clnt_handlep,
924 struct timeval timeout;
928 * Set timeouts to be zero to force message passing semantics.
933 if ((clnt_call(clnt_handlep, proc, xargs, argsp, NULL,
934 &xid, timeout)) != RPC_TIMEDOUT) {
935 clnt_perror(clnt_handlep, "biod_clnt_call failed");
940 } /* biod_clnt_call */
946 * Returns pointer to the biod_req struct entry that a reply was received
947 * for. Returns NULL if an error was detected.
949 * 1) This routine should only be called when it is known that there is
950 * data waiting on the socket.
952 static struct biod_req *
954 CLIENT *clnt_handlep,
963 uint32_t xids[MAX_BIODS];
966 * Load list of valid outstanding xids
968 for (i = 0; i < max_biod_reqs; i++) {
969 if (biod_reqp[i].in_use == TRUE)
970 xids[cnt++] = biod_reqp[i].xid;
976 if ((res = clnt_getreply(clnt_handlep, xresults,
977 resultsp, cnt, xids, &xid, tv)) != RPC_SUCCESS) {
978 if (DEBUG_CHILD_BIOD) {
979 if (res == RPC_CANTDECODERES) {
980 (void) fprintf(stderr, "No xid matched, found %x\n",
988 * Scan to find XID matched in the outstanding request queue.
990 for (i = 0; i < max_biod_reqs; i++) {
991 if (biod_reqp[i].in_use == TRUE && biod_reqp[i].xid == xid) {
992 sfs_gettime(&(biod_reqp[i].stop));
993 return (&biod_reqp[i]);
997 return ((struct biod_req *)0);
998 } /* biod_get_reply */
1004 * Returns -1 on error, 0 for no data available, > 0 to indicate data available
1008 CLIENT *clnt_handlep,
1011 return (clnt_poll(clnt_handlep, usecs));
1012 } /* biod_poll_wait */