Add proper per-file copyright notices/licenses and top-level license.
[bluesky.git] / TBBT / trace_play / sfs_3_ops.c.org
1 #ifndef lint
2 static char sfs_3_opsSid[] = "@(#)sfs_3_ops.c   2.1     97/10/23";
3 #endif
4
5 /*
6  *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
7  *      All rights reserved.
8  *              Standard Performance Evaluation Corporation (SPEC)
9  *              6585 Merchant Place, Suite 100
10  *              Warrenton, VA 20187
11  *
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.
15  *
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.
19  *
20  *      The source code is provided to the user or company under the license
21  *      agreement for the SPEC Benchmark Suite for this product.
22  */
23
24 /*****************************************************************
25  *                                                               *
26  *      Copyright 1991,1992  Legato Systems, Inc.                *
27  *      Copyright 1991,1992  Auspex Systems, Inc.                *
28  *      Copyright 1991,1992  Data General Corporation            *
29  *      Copyright 1991,1992  Digital Equipment Corporation       *
30  *      Copyright 1991,1992  Interphase Corporation              *
31  *      Copyright 1991,1992  Sun Microsystems, Inc.              *
32  *                                                               *
33  *****************************************************************/
34
35 /*
36  * ---------------------- sfs_3_ops.c ---------------------
37  *
38  *      RPC routines to implement the NFS protocol.
39  *
40  *.Local Routines
41  *      int op_null(void)
42  *      int op_getattr(void)
43  *      int op_setattr(int)
44  *      int op_lookup(void)
45  *      int op_access(void)
46  *      int op_readlink(void)
47  *      int op_read(int)
48  *      int op_write(int, int, stable_how)
49  *      int op_create(void)
50  *      int op_mkdir(void);
51  *      int op_symlink(void);
52  *      int op_mknod(void);
53  *      int op_remove(void);
54  *      int op_rmdir(void);
55  *      int op_rename(void);
56  *      int op_link(void);
57  *      int op_readdir(void);
58  *      int op_readdirplus(void);
59  *      int op_fsstat(void);
60  *      int op_fsinfo(void);
61  *      int op_pathconf(void);
62  *      int op_commit(void);
63  *
64  *.Revision_History
65  *      30-Jun-94       ChakChung Ng    Created.
66  */
67
68
69 /*
70  * -------------------------  Include Files  -------------------------
71  */
72
73 /*
74  * ANSI C headers
75  */
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include <errno.h>
80
81 #include <sys/types.h>
82 #include <sys/stat.h>
83
84 #include <unistd.h>
85
86 #include "sfs_c_def.h"
87
88 /*
89  * --------------------  Local NFS ops function --------------------
90  */
91 static int op_null(void);
92 static int op_getattr(void);
93 static int op_setattr(int);
94 static int op_lookup(void);
95 static int op_access(void);
96 static int op_readlink(void);
97 static int op_read(int);
98 static int op_write(int, int, stable_how);
99 static int op_create(void);
100 static int op_mkdir(void);
101 static int op_symlink(void);
102 static int op_mknod(void);
103 static int op_remove(void);
104 static int op_rmdir(void);
105 static int op_rename(void);
106 static int op_link(void);
107 static int op_readdir(void);
108 static int op_readdirplus(void);
109 static int op_fsstat(void);
110 static int op_fsinfo(void);
111 static int op_pathconf(void);
112 static int op_commit(void);
113 static int op_nosys(void);
114 static char *nfs3_strerror(int);
115
116
117 /*
118  * --------------------  NFS ops vector --------------------
119  */
120 /*
121  * per operation information
122  */
123 static sfs_op_type nfsv3_Ops[] = {
124
125 /* name        mix   function         op    call  no  req  req  req  results */
126 /*             pcnt                  class  targ call pcnt cnt  targ         */
127
128  { "null",        0, op_null,        Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
129  { "getattr",    11, op_getattr,     Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
130  { "setattr",     1, op_setattr,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
131  { "root",        0, op_nosys,       Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
132  { "lookup",     27, op_lookup,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
133  { "readlink",    7, op_readlink,    Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
134  { "read",       18, op_read,        Read,    0,  0,  0.0,  0,   0,  { 0, }},
135  { "wrcache",     0, op_nosys,       Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
136  { "write",       9, op_write,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
137  { "create",      1, op_create,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
138  { "remove",      1, op_remove,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
139  { "rename",      0, op_rename,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
140  { "link",        0, op_link,        Write,   0,  0,  0.0,  0,   0,  { 0, }},
141  { "symlink",     0, op_symlink,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
142  { "mkdir",       0, op_mkdir,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
143  { "rmdir",       0, op_rmdir,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
144  { "readdir",     2, op_readdir,     Read,    0,  0,  0.0,  0,   0,  { 0, }},
145  { "fsstat",      1, op_fsstat,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
146  { "access",      7, op_access,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
147  { "commit",      5, op_commit,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
148  { "fsinfo",      1, op_fsinfo,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
149  { "mknod",       0, op_mknod,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
150  { "pathconf",    0, op_pathconf,    Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
151  { "readdirplus", 9, op_readdirplus, Read,   0,  0,  0.0,  0,   0,  { 0, }},
152  { "TOTAL",     100, 0,              Lookup,  0,  0,  0.0,  0,   0,  { 0, }}
153 };
154
155 sfs_op_type *Ops;
156
157 /*
158  * --------------------  RPC routines for NFS protocol --------------------
159  */
160
161 void
162 init_ops(void)
163 {
164     Ops = nfsv3_Ops;
165     nfs_version = NFS_V3;
166 }
167
168 /*
169  * The routines below attempt to do over-the-wire operations.
170  * Each op tries to cause one or more of a particular
171  * NFS operation to go over the wire.  OPs return the success
172  * of their NFS call(s).  Each OP records how many calls it
173  * actually made in global data.
174  *
175  * An array of file information is kept for files existing in
176  * the test directory.  File handles, attributes, names, etc
177  * are stored in this array.
178  *
179  */
180
181 /*
182  * Generic catch all for operations not covered by this protocol.
183  */
184 static int
185 op_nosys(void)
186 {
187     Ops[TOTAL].results.bad_calls++;
188     return(0);
189 }
190
191 static int
192 op_null(void)
193 {
194     sfs_op_type         *op_ptr;        /* per operation info */
195     enum clnt_stat      rpc_stat;       /* result from RPC call */
196     struct ladtime      start;
197     struct ladtime      stop;
198     int                 ret;            /* ret val == call success */
199
200     op_ptr = &Ops[NULLCALL];
201     ret = 0;
202
203     /* make the call */
204     sfs_gettime(&start);
205     rpc_stat = clnt_call(NFS_client, NFSPROC3_NULL,
206                         xdr_void, (char *)0, xdr_void, (char *)0,
207                         (Current_test_phase < Warmup_phase)
208                                  ? Nfs_timers[Init]
209                                  : Nfs_timers[op_ptr->call_class]);
210     sfs_gettime(&stop);
211     Cur_time = stop;
212
213     if (rpc_stat == RPC_SUCCESS) {
214         sfs_elapsedtime(op_ptr, &start, &stop);
215         op_ptr->results.good_calls++;
216         Ops[TOTAL].results.good_calls++;
217         ret++;
218     } else {
219         if (DEBUG_CHILD_ERROR) {
220              (void) fprintf(stderr, "%s: null_op call RPC error %d\n",
221                                                 sfs_Myname, rpc_stat);
222         }
223         op_ptr->results.bad_calls++;
224         Ops[TOTAL].results.bad_calls++;
225     }
226     return(ret);
227
228 } /* op_null */
229
230
231 static int
232 op_getattr(void)
233 {
234     sfs_op_type         *op_ptr;        /* per operation info */
235     GETATTR3args        args;           /* fh to do op on */
236     GETATTR3res         reply;          /* the reply */
237     enum clnt_stat      rpc_stat;       /* result from RPC call */
238     struct ladtime      start;
239     struct ladtime      stop;
240     int                 ret;            /* ret val == call success */
241
242     op_ptr = &Ops[GETATTR];
243     ret = 0;
244
245     /* set up the arguments */
246     (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
247                                                         sizeof (nfs_fh3));
248
249     /* make the call */
250     sfs_gettime(&start);
251     rpc_stat = clnt_call(NFS_client, NFSPROC3_GETATTR,
252                         xdr_GETATTR3args, (char *) &args,
253                         xdr_GETATTR3res, (char *) &reply,
254                         (Current_test_phase < Warmup_phase)
255                                  ? Nfs_timers[Init]
256                                  : Nfs_timers[op_ptr->call_class]);
257     sfs_gettime(&stop);
258     Cur_time = stop;
259
260     if (rpc_stat == RPC_SUCCESS) {
261         if (reply.status == NFS3_OK) {
262             (void) memmove((char *) &Cur_file_ptr->attributes3,
263                                 (char *) &reply.resok.obj_attributes,
264                                 sizeof (Cur_file_ptr->attributes3));
265             Cur_file_ptr->size = fh_size(Cur_file_ptr);
266         } else {
267             if (DEBUG_CHILD_ERROR) {
268                  (void) fprintf(stderr,
269                         "%s: getattr call NFS error %s on file %d\n",
270                         sfs_Myname, nfs3_strerror(reply.status),
271                         Cur_file_ptr->unique_num);
272             }
273         }
274         sfs_elapsedtime(op_ptr, &start, &stop);
275         op_ptr->results.good_calls++;
276         Ops[TOTAL].results.good_calls++;
277         ret++;
278     } else {
279         if (DEBUG_CHILD_ERROR) {
280              (void) fprintf(stderr,
281                         "%s: getattr call RPC error %d on file %d\n",
282                         sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
283         }
284         op_ptr->results.bad_calls++;
285         Ops[TOTAL].results.bad_calls++;
286     }
287     return(ret);
288
289 } /* op_getattr */
290
291
292 /*
293  * perform an RPC setattr operation.  If 'truncate_size' is non-negative,
294  * truncate the file to that size.
295  */
296 static int
297 op_setattr(
298     int         truncate_size)
299 {
300     sfs_op_type         *op_ptr;        /* per operation info */
301     SETATTR3args        args;
302     SETATTR3res         reply;          /* the reply */
303     enum clnt_stat      rpc_stat;       /* result from RPC call */
304     struct ladtime      start;
305     struct ladtime      stop;
306     int                 ret;            /* ret val == call success */
307
308     op_ptr = &Ops[SETATTR];
309     ret = 0;
310
311     /* set up the arguments */
312     (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
313                                                         sizeof (nfs_fh3));
314     args.new_attributes.mode.set_it = TRUE;
315     args.new_attributes.mode.mode = (uint32_t) 0666;
316     args.new_attributes.uid.set_it = FALSE;
317     args.new_attributes.uid.uid = (uint32_t) -1;
318     args.new_attributes.gid.set_it = FALSE;
319     args.new_attributes.gid.gid = (uint32_t) -1;
320     args.new_attributes.size.set_it = FALSE;
321     args.new_attributes.size.size._p._u = (uint32_t) ~0;
322     args.new_attributes.size.size._p._l = (uint32_t) -1;
323     args.new_attributes.atime.set_it = TRUE;
324     args.new_attributes.atime.atime.seconds = Cur_time.esec;
325     args.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
326     args.new_attributes.mtime.set_it = TRUE;
327     args.new_attributes.mtime.mtime.seconds = Cur_time.esec;
328     args.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
329     args.guard.check = FALSE;
330
331     /* handle file truncations */
332     if (truncate_size >= 0) {
333         args.new_attributes.size.set_it = TRUE;
334         args.new_attributes.size.size._p._u = (uint32_t) 0;
335         if (truncate_size > Cur_file_ptr->attributes3.size._p._l)
336             args.new_attributes.size.size._p._l = (uint32_t) 0;
337         else
338             args.new_attributes.size.size._p._l =
339                 (uint32_t) Cur_file_ptr->attributes3.size._p._l -
340                                                                 truncate_size;
341     }
342
343     /* make the call */
344     sfs_gettime(&start);
345     rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR,
346                         xdr_SETATTR3args, (char *) &args,
347                         xdr_SETATTR3res, (char *) &reply,
348                         (Current_test_phase < Warmup_phase)
349                                  ? Nfs_timers[Init]
350                                  : Nfs_timers[op_ptr->call_class]);
351
352     sfs_gettime(&stop);
353     Cur_time = stop;
354
355     if (rpc_stat == RPC_SUCCESS) {
356         if (reply.status == NFS3_OK) {
357             (void) memmove((char *) &Cur_file_ptr->attributes3,
358                                 (char *) &reply.resok.obj_wcc.after.attr,
359                                 sizeof (Cur_file_ptr->attributes3));
360             Cur_file_ptr->size = fh_size(Cur_file_ptr);
361         } else {
362             if (DEBUG_CHILD_ERROR) {
363                  (void) fprintf(stderr,
364                         "%s: setattr call NFS error %s on file %d\n",
365                         sfs_Myname, nfs3_strerror(reply.status),
366                         Cur_file_ptr->unique_num);
367             }
368         }
369         sfs_elapsedtime(op_ptr, &start, &stop);
370         op_ptr->results.good_calls++;
371         Ops[TOTAL].results.good_calls++;
372         ret++;
373     } else {
374         if (DEBUG_CHILD_ERROR) {
375              (void) fprintf(stderr,
376                         "%s: setattr call RPC error %d on file %d\n",
377                         sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
378         }
379         op_ptr->results.bad_calls++;
380         Ops[TOTAL].results.bad_calls++;
381     }
382     return(ret);
383
384 } /* op_setattr */
385
386
387 static int
388 op_lookup(void)
389 {
390     sfs_op_type         *op_ptr;        /* per operation info */
391     LOOKUP3args         args;
392     LOOKUP3res          reply;          /* the reply */
393     enum clnt_stat      rpc_stat;       /* result from RPC call */
394     struct ladtime      start;
395     struct ladtime      stop;
396     int                 ret;            /* ret val == call success */
397
398     op_ptr = &Ops[LOOKUP];
399     ret = 0;
400
401     /* set up the arguments */
402     (void) memmove((char *) &args.what.dir, (char *) &Cur_file_ptr->dir->fh3,
403                                                         sizeof (nfs_fh3));
404     args.what.name = Cur_filename;
405     (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
406
407     /* make the call */
408     sfs_gettime(&start);
409     rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
410                         xdr_LOOKUP3args, (char *) &args,
411                         xdr_LOOKUP3res, (char *) &reply,
412                         (Current_test_phase < Warmup_phase)
413                                  ? Nfs_timers[Init]
414                                  : Nfs_timers[op_ptr->call_class]);
415     sfs_gettime(&stop);
416     Cur_time = stop;
417
418     if (rpc_stat == RPC_SUCCESS) {
419         if (reply.status == NFS3_OK) {
420             Cur_file_ptr->state = Exists;
421             (void) memmove((char *) &Cur_file_ptr->fh3,
422                         (char *) &reply.resok.object,
423                         sizeof (nfs_fh3));
424             (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
425             (void) memmove((char *) &Cur_file_ptr->attributes3,
426                                 (char *) &reply.resok.obj_attributes.attr,
427                                 sizeof (Cur_file_ptr->attributes3));
428             Cur_file_ptr->size = fh_size(Cur_file_ptr);
429         } else {
430             /* We do lookup Nonexistent and this is not an error */
431             if (reply.status != NFS3ERR_NOENT ||
432                         Cur_file_ptr->state != Nonexistent) {
433                 if (DEBUG_CHILD_ERROR) {
434                      (void) fprintf(stderr,
435                         "%s: lookup call NFS error %s on file %d\n",
436                         sfs_Myname, nfs3_strerror(reply.status),
437                         Cur_file_ptr->unique_num);
438                 }
439             }
440         }
441         sfs_elapsedtime(op_ptr, &start, &stop);
442         op_ptr->results.good_calls++;
443         Ops[TOTAL].results.good_calls++;
444         ret++;
445     } else {
446         if (DEBUG_CHILD_ERROR) {
447              (void) fprintf(stderr, "%s: lookup call RPC error %d on file %d\n",
448                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
449         }
450         op_ptr->results.bad_calls++;
451         Ops[TOTAL].results.bad_calls++;
452     }
453     return(ret);
454
455 } /* op_lookup */
456
457
458 static int
459 op_access(void)
460 {
461     sfs_op_type         *op_ptr;        /* per operation info */
462     ACCESS3args         args;
463     ACCESS3res          reply;          /* the reply */
464     enum clnt_stat      rpc_stat;       /* result from RPC call */
465     struct ladtime      start;
466     struct ladtime      stop;
467     int                 ret;            /* ret val == call success */
468
469     op_ptr = &Ops[ACCESS];
470     ret = 0;
471
472     /* set up the arguments */
473     (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->dir->fh3,
474                                 sizeof (nfs_fh3));
475     args.access = ACCESS3_MODIFY;
476
477     /* make the call */
478     sfs_gettime(&start);
479     rpc_stat = clnt_call(NFS_client, NFSPROC3_ACCESS,
480                         xdr_ACCESS3args, (char *) &args,
481                         xdr_ACCESS3res, (char *) &reply,
482                         (Current_test_phase < Warmup_phase)
483                                  ? Nfs_timers[Init]
484                                  : Nfs_timers[op_ptr->call_class]);
485     sfs_gettime(&stop);
486     Cur_time = stop;
487
488     if (rpc_stat == RPC_SUCCESS) {
489         if (reply.status == NFS3_OK) {
490             Cur_file_ptr->state = Exists;
491             (void) memmove((char *) &Cur_file_ptr->attributes3,
492                                 (char *) &reply.resok.obj_attributes.attr,
493                                 sizeof (Cur_file_ptr->attributes3));
494             Cur_file_ptr->size = fh_size(Cur_file_ptr);
495         } else {
496             if (DEBUG_CHILD_ERROR) {
497                  (void) fprintf(stderr,
498                         "%s: access call NFS error %s on file %d\n",
499                         sfs_Myname, nfs3_strerror(reply.status),
500                         Cur_file_ptr->unique_num);
501             }
502         }
503         sfs_elapsedtime(op_ptr, &start, &stop);
504         op_ptr->results.good_calls++;
505         Ops[TOTAL].results.good_calls++;
506         ret++;
507     } else {
508         if (DEBUG_CHILD_ERROR) {
509              (void) fprintf(stderr, "%s: access call RPC error %d on file %d\n",
510                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
511         }
512         op_ptr->results.bad_calls++;
513         Ops[TOTAL].results.bad_calls++;
514     }
515     return(ret);
516
517 } /* op_access */
518
519
520 static int
521 op_readlink(void)
522 {
523     sfs_op_type         *op_ptr;                /* per operation info */
524     READLINK3args       args;                   /* the args */
525     READLINK3res        reply;                  /* the reply */
526     char                sym_data[NFS_MAXPATHLEN];
527     enum clnt_stat      rpc_stat;               /* result from RPC call */
528     struct ladtime      start;
529     struct ladtime      stop;
530     int                 ret;                    /* ret val == call success */
531
532     op_ptr = &Ops[READLINK];
533     ret = 0;
534
535     /* set up the arguments */
536     /*
537      * Note: this symlink may be bogus because SYMLINK does
538      * not return a symlink ... only a status.  So unless we have
539      * done a LOOKUP on this guy, the symlink will probably be bad.
540      * If it is bad it shows up as a symlink error in the results.
541      */
542     (void) memmove((char *) &args.symlink,
543                         (char *) &Cur_file_ptr->fh3,
544                         sizeof (nfs_fh3));
545
546     /* Have lower layers fill in the data directly. */
547     reply.resok.data = sym_data;
548
549     /* make the call now */
550     sfs_gettime(&start);
551     rpc_stat = clnt_call(NFS_client, NFSPROC3_READLINK,
552                         xdr_READLINK3args, (char *) &args,
553                         xdr_READLINK3res, (char *) &reply,
554                         (Current_test_phase < Warmup_phase)
555                                  ? Nfs_timers[Init]
556                                  : Nfs_timers[op_ptr->call_class]);
557     sfs_gettime(&stop);
558     Cur_time = stop;
559
560     if (rpc_stat == RPC_SUCCESS) {
561         if (reply.status == NFS3_OK) {
562             if (DEBUG_CHILD_RPC) {
563                 (void) fprintf(stderr, "%s: READLINK on %s returned %s\n",
564                                     sfs_Myname, Cur_filename, sym_data);
565                 (void) fflush(stderr);
566             }
567         } else {
568             if (DEBUG_CHILD_ERROR) {
569                  (void) fprintf(stderr,
570                         "%s: readlink call NFS error %s on file %d\n",
571                         sfs_Myname, nfs3_strerror(reply.status),
572                         Cur_file_ptr->unique_num);
573             }
574         }
575         sfs_elapsedtime(op_ptr, &start, &stop);
576         op_ptr->results.good_calls++;
577         Ops[TOTAL].results.good_calls++;
578         ret++;
579     } else {
580         if (DEBUG_CHILD_ERROR) {
581              (void) fprintf(stderr,
582                         "%s: readlink call RPC error %d on file %d\n",
583                         sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
584         }
585         op_ptr->results.bad_calls++;
586         Ops[TOTAL].results.bad_calls++;
587     }
588     return(ret);
589
590 } /* op_readlink */
591
592
593 /*
594  * perform an RPC read operation of length 'xfer_size'
595  */
596 static int
597 op_read(
598     int                         xfer_size)
599 {
600     sfs_op_type                 *op_ptr;        /* per operation info */
601     int                         cur_cnt;
602     int                         max_cnt;        /* packet ctrs */
603     char                        buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
604     READ3args                   args;
605     READ3res                    reply;          /* the reply */
606     enum clnt_stat              rpc_stat;       /* result from RPC call */
607     struct ladtime              start;
608     struct ladtime              stop;
609     int                         size;
610     int                         j;
611     int                         ret;            /* ret val == call success */
612
613     op_ptr = &Ops[READ];
614     ret = 0;
615
616     /* set up the arguments */
617     (void) memmove((char *) &args.file,
618                         (char *) &Cur_file_ptr->fh3,
619                         sizeof (nfs_fh3));
620
621     /*
622      * Don't allow a read of less than one block size
623      */
624     if (xfer_size < Bytes_per_block)
625         xfer_size = Bytes_per_block;
626
627     /*
628      * randomly choose an offset that is a multiple of the block size
629      * and constrained by making the transfer fit within the file
630      */
631     args.offset._p._u = 0;
632     if (Cur_file_ptr->attributes3.size._p._l > xfer_size)
633         args.offset._p._l = Bytes_per_block * (sfs_random() %
634                         (((Cur_file_ptr->attributes3.size._p._l - xfer_size)
635                         / Bytes_per_block) + 1));
636     else
637         args.offset._p._l = 0;
638
639     /* Have lower layers fill in the data directly.  */
640     reply.resok.data.data_len = 0;
641     reply.resok.data.data_val = buf;
642
643     /* first read the whole buffers, then the fragment */
644     for (j = 0; j < 2; j++) {
645
646         if (j == 0) {
647             size = Bytes_per_block;
648             max_cnt = xfer_size / Bytes_per_block;
649         } else {
650             /* 1KB - (Kb_per_block -1) KB fragment */
651             size = xfer_size % Bytes_per_block;
652             max_cnt = 1;
653         }
654         if (size == 0)
655             continue;
656
657         /* check our stats to see if this would overflow */
658         if (!Timed_run) {
659             if (op_ptr->target_calls > 0) {
660                 if ((op_ptr->results.good_calls + max_cnt)
661                      > op_ptr->target_calls) {
662                     max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
663                 }
664             }
665         }
666
667         args.count = size;
668
669         if (DEBUG_CHILD_RPC) {
670             (void) fprintf(stderr, "read: %d buffers\n", max_cnt);
671             (void) fflush(stderr);
672         }
673
674         /* make the call(s) now */
675         for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
676
677             /* capture length for possible dump */
678             Dump_length = fh_size(Cur_file_ptr);
679  
680             sfs_gettime(&start);
681             rpc_stat = clnt_call(NFS_client, NFSPROC3_READ,
682                                 xdr_READ3args, (char *) &args,
683                                 xdr_READ3res, (char *) &reply,
684                                 (Current_test_phase < Warmup_phase)
685                                      ? Nfs_timers[Init]
686                                      : Nfs_timers[op_ptr->call_class]);
687             sfs_gettime(&stop);
688             Cur_time = stop;
689
690             /* capture count and offset for possible dump */
691             Dump_count = (rpc_stat == RPC_SUCCESS && reply.status == NFS3_OK)
692                             ? reply.resok.data.data_len : 0;
693             Dump_offset = args.offset._p._l;
694
695             if (rpc_stat == RPC_SUCCESS) {
696                 if (reply.status == NFS3_OK) {
697                     Cur_file_ptr->state = Exists;
698                     (void) memmove((char *) &Cur_file_ptr->attributes3,
699                                 (char *) &reply.resok.file_attributes.attr,
700                                 sizeof (Cur_file_ptr->attributes3));
701                     Cur_file_ptr->size = fh_size(Cur_file_ptr);
702                     size = reply.resok.data.data_len;
703
704                     if (DEBUG_CHILD_RPC) {
705                         (void) fprintf(stderr, "%s: READ %s %d bytes\n",
706                                            sfs_Myname, Cur_filename, size);
707                         (void) fflush(stderr);
708                     }
709                     args.offset._p._l += size;
710                 } else {
711                     if (DEBUG_CHILD_ERROR) {
712                          (void) fprintf(stderr,
713                                 "%s: read call NFS error %s on file %d\n",
714                                         sfs_Myname,
715                                         nfs3_strerror(reply.status),
716                                         Cur_file_ptr->unique_num);
717                     }
718                 }
719                 sfs_elapsedtime(op_ptr, &start, &stop);
720                 op_ptr->results.good_calls++;
721                 Ops[TOTAL].results.good_calls++;
722                 ret++;
723             } else {
724                 if (DEBUG_CHILD_ERROR) {
725                      (void) fprintf(stderr,
726                                 "%s: read call RPC error %d on file %d\n",
727                             sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
728                 }
729                 op_ptr->results.bad_calls++;
730                 Ops[TOTAL].results.bad_calls++;
731             }
732         } /* for reading max_cnt packets */
733     } /* for buffers and fragments */
734     return(ret);
735
736 } /* op_read */
737
738 char *
739 init_write_buffer(
740     void)
741 {
742     uint32_t *bp;
743     static uint32_t write_buf[DEFAULT_MAX_BUFSIZE / sizeof(uint32_t)];
744     uint32_t *be  = write_buf + (sizeof(write_buf) /
745                                                         sizeof(uint32_t));
746
747     if (write_buf[0] != (uint32_t)0xdeadbeef) {
748         for (bp = write_buf; bp < be; bp++)
749             *bp = (uint32_t)0xdeadbeef;
750     }
751     return (char *)write_buf;
752 }
753
754
755 /*
756  * Perform and RPC write operation of length 'xfer_size'.  If 'append_flag'
757  * is true, then write the data to the end of the file.
758  *
759  * If the stab_flag is set to UNSTABLE we issue the requests and then
760  * issue a op_commit to sync the data.
761  */
762 static int
763 op_write(
764     int                 xfer_size,
765     int                 append_flag,
766     stable_how          stab_flag)
767 {
768     sfs_op_type                 *op_ptr;        /* per operation info */
769     static char                 *buf = NULL;    /* the data buffer */
770     unsigned int                size;           /* size of data write */
771     int                         cur_cnt;        /* controls # NFS calls */
772     int                         max_cnt;
773     WRITE3args                  args;
774     WRITE3res                   reply;          /* the reply */
775     enum clnt_stat              rpc_stat;       /* result from RPC call */
776     struct ladtime              start;
777     struct ladtime              stop;
778     int                         j;
779     int                         ret;            /* ret val == call success */
780
781     /*
782      * For now we treat DATA_SYNC to be the same as FILE_SYNC.
783      */
784     if (stab_flag == DATA_SYNC)
785         stab_flag = FILE_SYNC;
786
787     /*
788      * Initialize write buffer to known value
789      */
790     if (buf == NULL) {
791         buf = init_write_buffer();
792     }
793
794     op_ptr = &Ops[WRITE];
795     ret = 0;
796
797     /* set up the arguments */
798     (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
799                 sizeof (nfs_fh3));
800     args.offset._p._u = 0;
801     if (append_flag == 1) {
802         args.offset._p._l = Cur_file_ptr->attributes3.size._p._l;
803     } else {
804         /*
805          * randomly choose an offset that is a multiple of the block size
806          * and constrained by making the transfer fit within the file
807          */
808         if (Cur_file_ptr->attributes3.size._p._l > xfer_size) {
809             args.offset._p._l = Bytes_per_block * (sfs_random() %
810                             (((Cur_file_ptr->attributes3.size._p._l - xfer_size)
811                             / Bytes_per_block) + 1));
812         } else
813             args.offset._p._l = 0;
814     }
815
816     /* stab_flag has to be set in op() in sfs_3_chd.c */
817     args.stable = stab_flag;
818
819     /* first write the whole buffers, then the fragment */
820     for (j = 0; j < 2; j++) {
821
822         if (j == 0) {
823             size = Bytes_per_block;
824             max_cnt = xfer_size / Bytes_per_block;
825         } else {
826             /* 1KB - (Kb_per_block - 1) KB fragment */
827             size = xfer_size % Bytes_per_block;
828             max_cnt = 1;
829         }
830         if (size == 0)
831             continue;
832
833         args.count = size;
834         args.data.data_len = size;
835         args.data.data_val = buf;
836
837         /* check our stats to see if this would overflow */
838         if (!Timed_run) {
839             if (op_ptr->target_calls > 0) {
840                 if ((op_ptr->results.good_calls + max_cnt)
841                      > op_ptr->target_calls) {
842                     max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
843                 }
844             }
845         }
846
847         if (DEBUG_CHILD_RPC) {
848             (void) fprintf(stderr, "write: %d buffers\n", max_cnt);
849             (void) fflush(stderr);
850         }
851
852         /* make the call(s) now */
853         for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
854
855             if (DEBUG_CHILD_RPC) {
856 (void) fprintf(stderr, "%s: WRITE %s offset %u count %lu stable %d\n",
857 sfs_Myname, Cur_filename, args.offset._p._l, args.count, args.stable);
858                 (void) fflush(stderr);
859             }
860
861             /* capture length for possible dump */
862             Dump_length = fh_size(Cur_file_ptr);
863  
864             sfs_gettime(&start);
865             rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE,
866                                 xdr_WRITE3args, (char *) &args,
867                                 xdr_WRITE3res, (char *) &reply,
868                                 (Current_test_phase < Warmup_phase)
869                                      ? Nfs_timers[Init]
870                                      : Nfs_timers[op_ptr->call_class]);
871             sfs_gettime(&stop);
872             Cur_time = stop;
873
874             /* capture count and offset for possible dump */
875             Dump_count = args.data.data_len;
876             Dump_offset = args.offset._p._l;
877
878             if (rpc_stat == RPC_SUCCESS) {
879                 if (reply.status == NFS3_OK) {
880                     Cur_file_ptr->state = Exists;
881                     (void) memmove((char *) &Cur_file_ptr->attributes3,
882                                 (char *) &reply.resok.file_wcc.after.attr,
883                                 sizeof (Cur_file_ptr->attributes3));
884                     Cur_file_ptr->size = fh_size(Cur_file_ptr);
885                     args.offset._p._l += size;
886
887                     if (DEBUG_CHILD_RPC) {
888                         (void) fprintf(stderr, "%s: WRITE %s %d bytes\n",
889                                            sfs_Myname, Cur_filename, size);
890                         (void) fflush(stderr);
891                     }
892                 } else {
893                     if (DEBUG_CHILD_ERROR) {
894                          (void) fprintf(stderr,
895                                 "%s: write call NFS error %s on file %d\n",
896                                 sfs_Myname, nfs3_strerror(reply.status),
897                                 Cur_file_ptr->unique_num);
898                     }
899                 }
900                 sfs_elapsedtime(op_ptr, &start, &stop);
901                 op_ptr->results.good_calls++;
902                 Ops[TOTAL].results.good_calls++;
903                 ret++;
904             } else {
905                 if (DEBUG_CHILD_ERROR) {
906                      (void) fprintf(stderr,
907                                 "%s: write call RPC error %d on file %d\n",
908                             sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
909                 }
910                 op_ptr->results.bad_calls++;
911                 Ops[TOTAL].results.bad_calls++;
912             }
913         } /* for writing max_cnt packets */
914     } /* for buffers and fragments */
915
916     /*
917      * If we have not gotten an error and we were asked for an async write
918      * send a commit operation.
919      */
920     if (ret && stab_flag != FILE_SYNC)
921         ret += op_commit();
922
923     return(ret);
924
925 } /* op_write */
926
927
928 static int
929 op_create(void)
930 {
931     sfs_op_type         *op_ptr;                /* per operation info */
932     CREATE3args         args;
933     CREATE3res          reply;                  /* the reply */
934     enum clnt_stat      rpc_stat;               /* result from RPC call */
935     struct ladtime      start;
936     struct ladtime      stop;
937     int                 ret;                    /* ret val == call success */
938
939     op_ptr = &Ops[CREATE];
940     ret = 0;
941
942     /* set up the arguments */
943     (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
944                 sizeof (nfs_fh3));
945     args.where.name = Cur_filename;
946     args.how.mode = UNCHECKED;
947     args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
948     args.how.createhow3_u.obj_attributes.mode.mode = (NFSMODE_REG | 0666);
949     args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
950     args.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
951     args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
952     args.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
953     args.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
954     args.how.createhow3_u.obj_attributes.atime.atime.seconds = Cur_time.esec;
955     args.how.createhow3_u.obj_attributes.atime.atime.nseconds =
956                                                 Cur_time.usec * 1000;
957     args.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
958     args.how.createhow3_u.obj_attributes.mtime.mtime.seconds = Cur_time.esec;
959     args.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
960                                                 Cur_time.usec * 1000;
961     args.how.createhow3_u.obj_attributes.size.set_it = TRUE;
962     args.how.createhow3_u.obj_attributes.size.size._p._u = (uint32_t) 0;
963     args.how.createhow3_u.obj_attributes.size.size._p._l = (uint32_t) 0;
964
965     /* make the call now */
966     sfs_gettime(&start);
967     rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE,
968                         xdr_CREATE3args, (char *) &args,
969                         xdr_CREATE3res, (char *) &reply,
970                         (Current_test_phase < Warmup_phase)
971                                  ? Nfs_timers[Init]
972                                  : Nfs_timers[op_ptr->call_class]);
973     sfs_gettime(&stop);
974     Cur_time = stop;
975
976     if (rpc_stat == RPC_SUCCESS) {
977         if (reply.status == NFS3_OK) {
978             Cur_file_ptr->state = Exists;
979             (void) memmove((char *) &Cur_file_ptr->fh3,
980                         (char *) &reply.resok.obj.handle,
981                         sizeof (nfs_fh3));
982             (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
983             (void) memmove((char *) &Cur_file_ptr->attributes3,
984                         (char *) &reply.resok.obj_attributes.attr,
985                         sizeof(Cur_file_ptr->attributes3));
986             Cur_file_ptr->size = fh_size(Cur_file_ptr);
987         } else {
988             if (DEBUG_CHILD_ERROR) {
989                  (void) fprintf(stderr,
990                         "%s: create call NFS error %s on file %d\n",
991                         sfs_Myname, nfs3_strerror(reply.status),
992                         Cur_file_ptr->unique_num);
993             }
994         }
995         sfs_elapsedtime(op_ptr, &start, &stop);
996         op_ptr->results.good_calls++;
997         Ops[TOTAL].results.good_calls++;
998         ret++;
999     } else {
1000         if (DEBUG_CHILD_ERROR) {
1001              (void) fprintf(stderr, "%s: create call RPC error %d on file %d\n",
1002                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1003         }
1004         op_ptr->results.bad_calls++;
1005         Ops[TOTAL].results.bad_calls++;
1006     }
1007     return(ret);
1008
1009 } /* op_create */
1010
1011
1012 static int
1013 op_mkdir(void)
1014 {
1015     sfs_op_type         *op_ptr;                /* per operation info */
1016     MKDIR3args          args;
1017     MKDIR3res           reply;                  /* the reply */
1018     enum clnt_stat      rpc_stat;               /* result from RPC call */
1019     struct ladtime      start;
1020     struct ladtime      stop;
1021     int                 ret;                    /* ret val == call success */
1022
1023     op_ptr = &Ops[MKDIR];
1024     ret = 0;
1025
1026     /* set up the arguments */
1027     (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
1028                 sizeof (nfs_fh3));
1029     args.where.name = Cur_filename;
1030     args.attributes.mode.set_it = TRUE;
1031     args.attributes.mode.mode = (NFSMODE_DIR | 0777);
1032     args.attributes.uid.set_it = TRUE;
1033     args.attributes.uid.uid = Cur_uid;
1034     args.attributes.gid.set_it = TRUE;
1035     args.attributes.gid.gid = Cur_gid;
1036     args.attributes.size.set_it = TRUE;
1037     args.attributes.size.size._p._u = 0;
1038     args.attributes.size.size._p._l = 512;
1039     args.attributes.atime.set_it = TRUE;
1040     args.attributes.atime.atime.seconds = Cur_time.esec;
1041     args.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
1042     args.attributes.mtime.set_it = TRUE;
1043     args.attributes.mtime.mtime.seconds = Cur_time.esec;
1044     args.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
1045
1046     /* make the call now */
1047     sfs_gettime(&start);
1048     rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR,
1049                         xdr_MKDIR3args, (char *) &args,
1050                         xdr_MKDIR3res, (char *) &reply,
1051                         (Current_test_phase < Warmup_phase)
1052                                  ? Nfs_timers[Init]
1053                                  : Nfs_timers[op_ptr->call_class]);
1054     sfs_gettime(&stop);
1055     Cur_time = stop;
1056
1057     if (rpc_stat == RPC_SUCCESS) {
1058         if (reply.status == NFS3_OK) {
1059             Cur_file_ptr->state = Empty_dir;
1060             (void) memmove((char *) &Cur_file_ptr->fh3,
1061                         (char *) &reply.resok.obj.handle,
1062                         sizeof (nfs_fh3));
1063             (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
1064             (void) memmove((char *) &Cur_file_ptr->attributes3,
1065                         (char *) &reply.resok.obj_attributes.attr,
1066                         sizeof(Cur_file_ptr->attributes3));
1067             Cur_file_ptr->size = fh_size(Cur_file_ptr);
1068         } else {
1069             if (DEBUG_CHILD_ERROR) {
1070                  (void) fprintf(stderr,
1071                         "%s: mkdir call NFS error %s on file %d\n",
1072                         sfs_Myname, nfs3_strerror(reply.status),
1073                         Cur_file_ptr->unique_num);
1074             }
1075         }
1076         sfs_elapsedtime(op_ptr, &start, &stop);
1077         op_ptr->results.good_calls++;
1078         Ops[TOTAL].results.good_calls++;
1079         ret++;
1080     } else {
1081         if (DEBUG_CHILD_ERROR) {
1082              (void) fprintf(stderr, "%s: mkdir call RPC error %d on file %d\n",
1083                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1084         }
1085         op_ptr->results.bad_calls++;
1086         Ops[TOTAL].results.bad_calls++;
1087     }
1088     return(ret);
1089
1090 } /* op_mkdir */
1091
1092
1093 static int
1094 op_symlink(void)
1095 {
1096     sfs_op_type         *op_ptr;                /* per operation info */
1097     sfs_fh_type         *target_fileinfo_ptr;   /* target file */
1098     SYMLINK3args        args;
1099     SYMLINK3res         reply;                  /* the reply */
1100     char                sym_data[NFS_MAXPATHLEN];       /* symlink data */
1101     enum clnt_stat      rpc_stat;               /* result from RPC call */
1102     struct ladtime      start;
1103     struct ladtime      stop;
1104     int                 ret;                    /* ret val == call success */
1105
1106     op_ptr = &Ops[SYMLINK];
1107     ret = 0;
1108
1109     /* set up the arguments */
1110     target_fileinfo_ptr = randfh(SYMLINK, 0, 0, Exists, Sfs_non_io_file);
1111     (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
1112                 sizeof (nfs_fh3));
1113     args.where.name = Cur_filename;
1114
1115     (void) strcpy(sym_data, "./");
1116     (void) strcat(sym_data, target_fileinfo_ptr->file_name);
1117     args.symlink.symlink_attributes.size.set_it = TRUE;
1118     args.symlink.symlink_attributes.size.size._p._u = (uint32_t) 0;
1119     args.symlink.symlink_attributes.size.size._p._l = strlen(sym_data);
1120     args.symlink.symlink_data = sym_data;
1121
1122     args.symlink.symlink_attributes.mode.set_it = TRUE;
1123     args.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
1124     args.symlink.symlink_attributes.uid.set_it = TRUE;
1125     args.symlink.symlink_attributes.uid.uid = Cur_uid;
1126     args.symlink.symlink_attributes.gid.set_it = TRUE;
1127     args.symlink.symlink_attributes.gid.gid = Cur_gid;
1128     args.symlink.symlink_attributes.atime.set_it = TRUE;
1129     args.symlink.symlink_attributes.atime.atime.seconds = Cur_time.esec;
1130     args.symlink.symlink_attributes.atime.atime.nseconds =
1131                                                 Cur_time.usec * 1000;
1132     args.symlink.symlink_attributes.mtime.set_it = TRUE;
1133     args.symlink.symlink_attributes.mtime.mtime.seconds = Cur_time.esec;
1134     args.symlink.symlink_attributes.mtime.mtime.nseconds =
1135                                                 Cur_time.usec * 1000;
1136
1137     /* make the call now */
1138     sfs_gettime(&start);
1139     rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK,
1140                         xdr_SYMLINK3args, (char *) &args,
1141                         xdr_SYMLINK3res, (char *) &reply,
1142                         ((int)Current_test_phase < (int)Warmup_phase)
1143                                  ? Nfs_timers[Init]
1144                                  : Nfs_timers[op_ptr->call_class]);
1145     sfs_gettime(&stop);
1146     Cur_time = stop;
1147
1148     if (rpc_stat == RPC_SUCCESS) {
1149         if (reply.status == NFS3_OK) {
1150             /*
1151              * SYMLINK doesn't return a fh. If we try to access this symlink
1152              * (eg, remove(), readlink()) before we do a lookup, we won't have
1153              * a fh to use. So, we do a lookup call here. If it fails, we fill
1154              * in what we can.
1155              */
1156             Cur_file_ptr->state = Exists;
1157             if (op_lookup() == 0) {
1158                 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
1159                 Cur_file_ptr->attributes3.type = NF3LNK;
1160                 Cur_file_ptr->attributes3.mode = (NFSMODE_LNK|0777);
1161                 Cur_file_ptr->attributes3.uid = Cur_uid;
1162                 Cur_file_ptr->attributes3.gid = Cur_gid;
1163                 Cur_file_ptr->attributes3.atime.seconds = Cur_time.esec;
1164                 Cur_file_ptr->attributes3.atime.nseconds =
1165                                                         Cur_time.usec * 1000;
1166                 Cur_file_ptr->attributes3.mtime =
1167                         Cur_file_ptr->attributes3.atime;
1168             } else
1169                 ret++;
1170         } else {
1171             if (DEBUG_CHILD_ERROR) {
1172                  (void) fprintf(stderr,
1173                         "%s: symlink call NFS error %s on file %d\n",
1174                         sfs_Myname, nfs3_strerror(reply.status),
1175                         Cur_file_ptr->unique_num);
1176             }
1177         }
1178         sfs_elapsedtime(op_ptr, &start, &stop);
1179         op_ptr->results.good_calls++;
1180         Ops[TOTAL].results.good_calls++;
1181         ret++;
1182     } else {
1183         if (DEBUG_CHILD_ERROR) {
1184              (void) fprintf(stderr,
1185                         "%s: symlink call RPC error %d on file %d\n",
1186                         sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1187         }
1188         op_ptr->results.bad_calls++;
1189         Ops[TOTAL].results.bad_calls++;
1190     }
1191     return(ret);
1192
1193 } /* op_symlink */
1194
1195
1196 static int
1197 op_mknod(void)
1198 {
1199     sfs_op_type         *op_ptr;                /* per operation info */
1200     MKNOD3args          args;
1201     MKNOD3res           reply;
1202     enum clnt_stat      rpc_stat;               /* result from RPC call */
1203     struct ladtime      start;
1204     struct ladtime      stop;
1205     int                 ret;                    /* ret val == call success */
1206
1207     op_ptr = &Ops[MKNOD];
1208     ret = 0;
1209
1210     /* set up the arguments */
1211     (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
1212                 sizeof (nfs_fh3));
1213     args.where.name = Cur_filename;
1214     args.what.type = NF3FIFO;
1215     args.what.mknoddata3_u.pipe_attributes.mode.set_it = TRUE;
1216     args.what.mknoddata3_u.pipe_attributes.mode.mode = (NFSMODE_FIFO | 0777);
1217     args.what.mknoddata3_u.pipe_attributes.uid.set_it = TRUE;
1218     args.what.mknoddata3_u.pipe_attributes.uid.uid = Cur_uid;
1219     args.what.mknoddata3_u.pipe_attributes.gid.set_it = TRUE;
1220     args.what.mknoddata3_u.pipe_attributes.gid.gid = Cur_gid;
1221     args.what.mknoddata3_u.pipe_attributes.size.set_it = TRUE;
1222     args.what.mknoddata3_u.pipe_attributes.size.size._p._u = (uint32_t) 0;
1223     args.what.mknoddata3_u.pipe_attributes.size.size._p._l =
1224                                                         (uint32_t) 512;
1225     args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
1226     args.what.mknoddata3_u.pipe_attributes.atime.atime.seconds =
1227                                                         Cur_time.esec;
1228     args.what.mknoddata3_u.pipe_attributes.atime.atime.nseconds =
1229                                                         Cur_time.usec * 1000;
1230     args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
1231     args.what.mknoddata3_u.pipe_attributes.mtime.mtime.seconds =
1232                                                                 Cur_time.esec;
1233     args.what.mknoddata3_u.pipe_attributes.mtime.mtime.nseconds =
1234                                                         Cur_time.usec * 1000;
1235
1236     /* make the call now */
1237     sfs_gettime(&start);
1238     rpc_stat = clnt_call(NFS_client, NFSPROC3_MKNOD,
1239                         xdr_MKNOD3args, (char *) &args,
1240                         xdr_MKNOD3res, (char *) &reply,
1241                         (Current_test_phase < Warmup_phase)
1242                                  ? Nfs_timers[Init]
1243                                  : Nfs_timers[op_ptr->call_class]);
1244     sfs_gettime(&stop);
1245     Cur_time = stop;
1246
1247     if (rpc_stat == RPC_SUCCESS) {
1248         if (reply.status == NFS3_OK) {
1249             Cur_file_ptr->state = Exists;
1250             (void) memmove((char *) &Cur_file_ptr->fh3,
1251                         (char *) &reply.resok.obj.handle,
1252                         sizeof (nfs_fh3));
1253             (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
1254             (void) memmove((char *) &Cur_file_ptr->attributes3,
1255                         (char *) &reply.resok.obj_attributes.attr,
1256                         sizeof(Cur_file_ptr->attributes3));
1257             Cur_file_ptr->size = fh_size(Cur_file_ptr);
1258         } else {
1259             if (DEBUG_CHILD_ERROR) {
1260                  (void) fprintf(stderr,
1261                         "%s: mknod call NFS error %s on file %d\n",
1262                         sfs_Myname, nfs3_strerror(reply.status),
1263                         Cur_file_ptr->unique_num);
1264             }
1265         }
1266         sfs_elapsedtime(op_ptr, &start, &stop);
1267         op_ptr->results.good_calls++;
1268         Ops[TOTAL].results.good_calls++;
1269         ret++;
1270     } else {
1271         if (DEBUG_CHILD_ERROR) {
1272              (void) fprintf(stderr, "%s: mknod call RPC error %d on file %d\n",
1273                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1274         }
1275         op_ptr->results.bad_calls++;
1276         Ops[TOTAL].results.bad_calls++;
1277     }
1278     return(ret);
1279
1280 } /* op_mknod */
1281
1282
1283 static int
1284 op_remove(void)
1285 {
1286     sfs_op_type         *op_ptr;        /* per operation info */
1287     REMOVE3args         args;
1288     REMOVE3res          reply;          /* the reply */
1289     enum clnt_stat      rpc_stat;       /* result from RPC call */
1290     struct ladtime      start;
1291     struct ladtime      stop;
1292     int                 ret;            /* ret val == call success */
1293
1294     op_ptr = &Ops[REMOVE];
1295     ret = 0;
1296
1297     /* set up the arguments */
1298     args.object.name = Cur_filename;
1299     (void) memmove((char *) &args.object.dir,(char *) &Cur_file_ptr->dir->fh3,
1300                 sizeof (nfs_fh3));
1301
1302     /* make the call now */
1303     sfs_gettime(&start);
1304     rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE,
1305                         xdr_REMOVE3args, (char *) &args,
1306                         xdr_REMOVE3res, (char *) &reply,
1307                         (Current_test_phase < Warmup_phase)
1308                                  ? Nfs_timers[Init]
1309                                  : Nfs_timers[op_ptr->call_class]);
1310     sfs_gettime(&stop);
1311     Cur_time = stop;
1312
1313     if (rpc_stat == RPC_SUCCESS) {
1314         if (reply.status == NFS3_OK) {
1315             Cur_file_ptr->state = Nonexistent;
1316         } else {
1317             if (DEBUG_CHILD_ERROR) {
1318                  (void) fprintf(stderr,
1319                                 "%s: remove call NFS error %s on file %d\n",
1320                                 sfs_Myname, nfs3_strerror(reply.status),
1321                                 Cur_file_ptr->unique_num);
1322             }
1323         }
1324         sfs_elapsedtime(op_ptr, &start, &stop);
1325         op_ptr->results.good_calls++;
1326         Ops[TOTAL].results.good_calls++;
1327         ret++;
1328     } else {
1329         if (DEBUG_CHILD_ERROR) {
1330              (void) fprintf(stderr, "%s: remove call RPC error %d on file %d\n",
1331                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1332         }
1333         op_ptr->results.bad_calls++;
1334         Ops[TOTAL].results.bad_calls++;
1335     }
1336     return(ret);
1337
1338 } /* op_remove */
1339
1340
1341 static int
1342 op_rmdir(void)
1343 {
1344     sfs_op_type         *op_ptr;        /* per operation info */
1345     RMDIR3args          args;
1346     RMDIR3res           reply;          /* the reply */
1347     enum clnt_stat      rpc_stat;       /* result from RPC call */
1348     struct ladtime      start;
1349     struct ladtime      stop;
1350     int                 ret;            /* ret val == call success */
1351
1352     op_ptr = &Ops[RMDIR];
1353     ret = 0;
1354
1355     /* set up the arguments */
1356     (void) memmove((char *) &args.object.dir, (char *) &Cur_file_ptr->dir->fh3,
1357                 sizeof (nfs_fh3));
1358     args.object.name = Cur_file_ptr->file_name;
1359
1360     /* make the call now */
1361     sfs_gettime(&start);
1362     rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR,
1363                         xdr_RMDIR3args, (char *) &args,
1364                         xdr_RMDIR3res, (char *) &reply,
1365                         (Current_test_phase < Warmup_phase)
1366                                  ? Nfs_timers[Init]
1367                                  : Nfs_timers[op_ptr->call_class]);
1368     sfs_gettime(&stop);
1369     Cur_time = stop;
1370
1371     if (rpc_stat == RPC_SUCCESS) {
1372         if (reply.status == NFS3_OK) {
1373             Cur_file_ptr->state = Nonexistent;
1374         } else {
1375             if (DEBUG_CHILD_ERROR) {
1376                  (void) fprintf(stderr,
1377                                 "%s: rmdir call NFS error %s on file %d\n",
1378                                 sfs_Myname, nfs3_strerror(reply.status),
1379                                 Cur_file_ptr->unique_num);
1380             }
1381         }
1382         sfs_elapsedtime(op_ptr, &start, &stop);
1383         op_ptr->results.good_calls++;
1384         Ops[TOTAL].results.good_calls++;
1385         ret++;
1386     } else {
1387         if (DEBUG_CHILD_ERROR) {
1388              (void) fprintf(stderr, "%s: rmdir call RPC error %d on file %d\n",
1389                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1390         }
1391         op_ptr->results.bad_calls++;
1392         Ops[TOTAL].results.bad_calls++;
1393     }
1394     return(ret);
1395
1396 } /* op_rmdir */
1397
1398
1399 static int
1400 op_rename(void)
1401 {
1402     sfs_op_type         *op_ptr;                /* per operation info */
1403     sfs_fh_type         *target_fileinfo_ptr;   /* target name */
1404     RENAME3args         args;
1405     RENAME3res          reply;                  /* the reply */
1406     enum clnt_stat      rpc_stat;               /* result from RPC call */
1407     struct ladtime      start;
1408     struct ladtime      stop;
1409     int                 ret;                    /* ret val == call success */
1410
1411     op_ptr = &Ops[RENAME];
1412     ret = 0;
1413
1414     /* set up the arguments */
1415     (void) memmove((char *) &args.from.dir, (char *) &Cur_file_ptr->dir->fh3,
1416                 sizeof (nfs_fh3));
1417     (void) memmove((char *) &args.to.dir, (char *) &Cur_file_ptr->dir->fh3,
1418                 sizeof (nfs_fh3));
1419
1420     target_fileinfo_ptr = randfh(RENAME, 0, 0, Nonexistent,
1421                                  Sfs_non_io_file);
1422
1423     args.from.name = Cur_file_ptr->file_name;
1424     (void) sprintf(target_fileinfo_ptr->file_name, Filespec,
1425                    target_fileinfo_ptr->unique_num);
1426     args.to.name = target_fileinfo_ptr->file_name;
1427
1428     /* make the call now */
1429     sfs_gettime(&start);
1430     rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
1431                         xdr_RENAME3args, (char *) &args,
1432                         xdr_RENAME3res, (char *) &reply,
1433                         (Current_test_phase < Warmup_phase)
1434                                  ? Nfs_timers[Init]
1435                                  : Nfs_timers[op_ptr->call_class]);
1436     sfs_gettime(&stop);
1437     Cur_time = stop;
1438
1439     if (rpc_stat == RPC_SUCCESS) {
1440         if (reply.status == NFS3_OK) {
1441             target_fileinfo_ptr->state = Exists;
1442             (void) memmove((char *) &target_fileinfo_ptr->fh3,
1443                         (char *) &Cur_file_ptr->fh3,
1444                         sizeof (nfs_fh3));
1445             target_fileinfo_ptr->attributes3 = Cur_file_ptr->attributes3;
1446             target_fileinfo_ptr->size = fh_size(Cur_file_ptr);
1447             Cur_file_ptr->state = Nonexistent;
1448         } else {
1449             if (DEBUG_CHILD_ERROR) {
1450                  (void) fprintf(stderr,
1451                         "%s: rename call NFS error %s on file %d\n",
1452                         sfs_Myname, nfs3_strerror(reply.status),
1453                         Cur_file_ptr->unique_num);
1454             }
1455         }
1456         sfs_elapsedtime(op_ptr, &start, &stop);
1457         op_ptr->results.good_calls++;
1458         Ops[TOTAL].results.good_calls++;
1459         ret++;
1460     } else {
1461         if (DEBUG_CHILD_ERROR) {
1462              (void) fprintf(stderr, "%s: rename call RPC error %d on file %d\n",
1463                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1464         }
1465         op_ptr->results.bad_calls++;
1466         Ops[TOTAL].results.bad_calls++;
1467     }
1468     return(ret);
1469
1470 } /* op_rename */
1471
1472
1473 static int
1474 op_link(void)
1475 {
1476     sfs_op_type         *op_ptr;                /* per operation info */
1477     sfs_fh_type         *target_fileinfo_ptr;   /* target */
1478     LINK3args           args;
1479     LINK3res            reply;                  /* the reply */
1480     enum clnt_stat      rpc_stat;               /* result from RPC call */
1481     struct ladtime      start;
1482     struct ladtime      stop;
1483     int                 ret;                    /* ret val == call success */
1484
1485     op_ptr = &Ops[LINK];
1486     ret = 0;
1487
1488     /* set up the arguments */
1489     target_fileinfo_ptr = randfh(LINK, 0, 0, Exists, Sfs_non_io_file);
1490     (void) memmove((char *) &args.file, (char *) &target_fileinfo_ptr->fh3,
1491                 sizeof (nfs_fh3));
1492     (void) memmove((char *) &args.link.dir, (char *) &Cur_file_ptr->dir->fh3,
1493                 sizeof (nfs_fh3));
1494     args.link.name = Cur_filename;
1495
1496     /* make the call now */
1497     sfs_gettime(&start);
1498     rpc_stat = clnt_call(NFS_client, NFSPROC3_LINK,
1499                         xdr_LINK3args, (char *) &args,
1500                         xdr_LINK3res, (char *) &reply,
1501                         (Current_test_phase < Warmup_phase)
1502                                  ? Nfs_timers[Init]
1503                                  : Nfs_timers[op_ptr->call_class]);
1504     sfs_gettime(&stop);
1505     Cur_time = stop;
1506
1507     if (rpc_stat == RPC_SUCCESS) {
1508         if (reply.status == NFS3_OK) {
1509             Cur_file_ptr->state = Exists;
1510             (void) memmove((char *) &Cur_file_ptr->fh3,
1511                         (char *) &target_fileinfo_ptr->fh3,
1512                         sizeof (nfs_fh3));
1513             (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
1514             target_fileinfo_ptr->attributes3.nlink++;
1515             Cur_file_ptr->attributes3 = target_fileinfo_ptr->attributes3;
1516             Cur_file_ptr->size = fh_size(Cur_file_ptr);
1517         } else {
1518             if (DEBUG_CHILD_ERROR) {
1519                  (void) fprintf(stderr,
1520                         "%s: link call NFS error %s on file %d\n",
1521                         sfs_Myname, nfs3_strerror(reply.status),
1522                         Cur_file_ptr->unique_num);
1523             }
1524         }
1525         sfs_elapsedtime(op_ptr, &start, &stop);
1526         op_ptr->results.good_calls++;
1527         Ops[TOTAL].results.good_calls++;
1528         ret++;
1529     } else {
1530         if (DEBUG_CHILD_ERROR) {
1531              (void) fprintf(stderr, "%s: link call RPC error %d on file %d\n",
1532                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1533         }
1534         op_ptr->results.bad_calls++;
1535         Ops[TOTAL].results.bad_calls++;
1536     }
1537     return(ret);
1538
1539 } /* op_link */
1540
1541
1542 static int
1543 op_readdir(void)
1544 {
1545     sfs_op_type         *op_ptr;                /* per operation info */
1546     READDIR3args        args;
1547     READDIR3res         reply;                  /* the reply */
1548     enum clnt_stat      rpc_stat;               /* result from RPC call */
1549     int                 i;
1550     struct ladtime      start;
1551     struct ladtime      stop;
1552     int                 ret;                    /* ret val == call success */
1553     bool_t              hit_eof;
1554         /* array of entries */
1555     entry3              entry_stream[SFS_MAXDIRENTS];
1556     entry3              *entries;               /* ptr to the dir entry */
1557
1558     op_ptr = &Ops[READDIR];
1559     ret = 0;
1560
1561     /* set up the arguments */
1562     (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
1563                 sizeof (nfs_fh3));
1564     args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
1565     (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
1566     args.count = DEFAULT_MAX_BUFSIZE;
1567
1568     /* Have lower layers fill in the data directly.  */
1569     (void) memset((char *) &reply, '\0', sizeof (reply));
1570     (void) memset((char *) entry_stream, '\0',
1571                                         sizeof (entry3) * SFS_MAXDIRENTS);
1572     reply.resok.count = SFS_MAXDIRENTS;
1573     reply.resok.reply.entries = entry_stream;
1574
1575     /* make the call now */
1576     sfs_gettime(&start);
1577     rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIR,
1578                         xdr_READDIR3args, (char *) &args,
1579                         xdr_READDIR3res, (char *) &reply,
1580                         (Current_test_phase < Warmup_phase)
1581                                  ? Nfs_timers[Init]
1582                                  : Nfs_timers[op_ptr->call_class]);
1583     sfs_gettime(&stop);
1584     Cur_time = stop;
1585
1586     if (rpc_stat == RPC_SUCCESS) {
1587         if (reply.status == NFS3_OK) {
1588
1589             if (DEBUG_CHILD_RPC) {
1590                 hit_eof = reply.resok.reply.eof;
1591                 entries = reply.resok.reply.entries;
1592                 for (i = 0; i < reply.resok.count; i++) {
1593                     (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
1594                                     sfs_Myname, hit_eof, entries[i].name);
1595                 }
1596                 (void) fflush(stderr);
1597             }
1598         } else {
1599             if (DEBUG_CHILD_ERROR) {
1600                  (void) fprintf(stderr,
1601                         "%s: readdir call NFS error %s on file %d\n",
1602                         sfs_Myname, nfs3_strerror(reply.status),
1603                         Cur_file_ptr->unique_num);
1604             }
1605         }
1606         sfs_elapsedtime(op_ptr, &start, &stop);
1607         op_ptr->results.good_calls++;
1608         Ops[TOTAL].results.good_calls++;
1609         ret++;
1610     } else {
1611         if (DEBUG_CHILD_ERROR) {
1612              (void) fprintf(stderr,
1613                                 "%s: readdir call RPC error %d on file %d\n",
1614                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1615         }
1616         op_ptr->results.bad_calls++;
1617         Ops[TOTAL].results.bad_calls++;
1618     }
1619     return(ret);
1620
1621 } /* op_readdir */
1622
1623
1624 static int
1625 op_readdirplus(void)
1626 {
1627     sfs_op_type         *op_ptr;                /* per operation info */
1628     READDIRPLUS3args    args;
1629     READDIRPLUS3res     reply;                  /* the reply */
1630     enum clnt_stat      rpc_stat;               /* result from RPC call */
1631     int                 i;
1632     struct ladtime      start;
1633     struct ladtime      stop;
1634     int                 ret;                    /* ret val == call success */
1635     bool_t              hit_eof;
1636         /* array of entries */
1637     entryplus3          entry_stream[SFS_MAXDIRENTS];
1638     entryplus3          *entries;
1639
1640     op_ptr = &Ops[READDIRPLUS];
1641     ret = 0;
1642
1643     /* set up the arguments */
1644     (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
1645                 sizeof (nfs_fh3));
1646     args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
1647     (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
1648     (void) memset((char *) entry_stream, '\0',
1649                                 sizeof (entryplus3) * SFS_MAXDIRENTS);
1650     args.dircount = DEFAULT_MAX_BUFSIZE;
1651     args.maxcount = DEFAULT_MAX_BUFSIZE;
1652
1653     /* Have lower layers fill in the data directly.  */
1654     reply.resok.count = SFS_MAXDIRENTS;
1655     reply.resok.reply.entries = entry_stream;
1656
1657     /* make the call now */
1658     sfs_gettime(&start);
1659     rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIRPLUS,
1660                         xdr_READDIRPLUS3args, (char *) &args,
1661                         xdr_READDIRPLUS3res, (char *) &reply,
1662                         (Current_test_phase < Warmup_phase)
1663                                  ? Nfs_timers[Init]
1664                                  : Nfs_timers[op_ptr->call_class]);
1665     sfs_gettime(&stop);
1666     Cur_time = stop;
1667
1668     if (rpc_stat == RPC_SUCCESS) {
1669         if (reply.status == NFS3_OK) {
1670
1671             if (DEBUG_CHILD_RPC) {
1672                 hit_eof = reply.resok.reply.eof;
1673                 entries = reply.resok.reply.entries;
1674                 for (i = 0; i < reply.resok.count; i++) {
1675                     (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
1676                                     sfs_Myname, hit_eof, entries[i].name);
1677                 }
1678                 (void) fflush(stderr);
1679             }
1680         } else {
1681             if (DEBUG_CHILD_ERROR) {
1682                  (void) fprintf(stderr,
1683                         "%s: readdir call NFS error %s on file %d\n",
1684                         sfs_Myname, nfs3_strerror(reply.status),
1685                         Cur_file_ptr->unique_num);
1686             }
1687         }
1688         sfs_elapsedtime(op_ptr, &start, &stop);
1689         op_ptr->results.good_calls++;
1690         Ops[TOTAL].results.good_calls++;
1691         ret++;
1692     } else {
1693         if (DEBUG_CHILD_ERROR) {
1694              (void) fprintf(stderr,
1695                                 "%s: readdir call RPC error %d on file %d\n",
1696                     sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1697         }
1698         op_ptr->results.bad_calls++;
1699         Ops[TOTAL].results.bad_calls++;
1700     }
1701     return(ret);
1702
1703 } /* op_readdirplus */
1704
1705
1706 static int
1707 op_fsstat(void)
1708 {
1709     sfs_op_type         *op_ptr;        /* per operation info */
1710     FSSTAT3args         args;
1711     FSSTAT3res          reply;          /* the reply */
1712     enum clnt_stat      rpc_stat;       /* result from RPC call */
1713     struct ladtime      start;
1714     struct ladtime      stop;
1715     int                 ret;            /* ret val == call success */
1716
1717     op_ptr = &Ops[FSSTAT];
1718     ret = 0;
1719
1720     /* set up the arguments */
1721     (void) memmove((char *) &args.fsroot, (char *) &Cur_file_ptr->dir->fh3,
1722                 sizeof (nfs_fh3));
1723
1724     /* make the call */
1725     sfs_gettime(&start);
1726     rpc_stat = clnt_call(NFS_client, NFSPROC3_FSSTAT,
1727                         xdr_FSSTAT3args, (char *) &args,
1728                         xdr_FSSTAT3args, (char *) &reply,
1729                         (Current_test_phase < Warmup_phase)
1730                                  ? Nfs_timers[Init]
1731                                  : Nfs_timers[op_ptr->call_class]);
1732     sfs_gettime(&stop);
1733     Cur_time = stop;
1734
1735     if (rpc_stat == RPC_SUCCESS) {
1736         sfs_elapsedtime(op_ptr, &start, &stop);
1737         op_ptr->results.good_calls++;
1738         Ops[TOTAL].results.good_calls++;
1739         ret++;
1740     } else {
1741         if (DEBUG_CHILD_ERROR) {
1742              (void) fprintf(stderr, "%s: fsstat call RPC error %d\n",
1743                                                 sfs_Myname, rpc_stat);
1744         }
1745         op_ptr->results.bad_calls++;
1746         Ops[TOTAL].results.bad_calls++;
1747     }
1748     return(ret);
1749
1750 } /* op_fsstat */
1751
1752
1753 static int
1754 op_fsinfo(void)
1755 {
1756     sfs_op_type         *op_ptr;        /* per operation info */
1757     FSINFO3args         args;
1758     FSINFO3res          reply;          /* the reply */
1759     enum clnt_stat      rpc_stat;       /* result from RPC call */
1760     struct ladtime      start;
1761     struct ladtime      stop;
1762     int                 ret;            /* ret val == call success */
1763
1764     op_ptr = &Ops[FSINFO];
1765     ret = 0;
1766
1767     /* set up the arguments */
1768     (void) memmove((char *) &args.fsroot, (char *) &Cur_file_ptr->dir->fh3,
1769                 sizeof (nfs_fh3));
1770
1771     /* make the call */
1772     sfs_gettime(&start);
1773     rpc_stat = clnt_call(NFS_client, NFSPROC3_FSINFO,
1774                         xdr_FSINFO3args, (char *) &args,
1775                         xdr_FSINFO3args, (char *) &reply,
1776                         (Current_test_phase < Warmup_phase)
1777                                  ? Nfs_timers[Init]
1778                                  : Nfs_timers[op_ptr->call_class]);
1779     sfs_gettime(&stop);
1780     Cur_time = stop;
1781
1782     if (rpc_stat == RPC_SUCCESS) {
1783         sfs_elapsedtime(op_ptr, &start, &stop);
1784         op_ptr->results.good_calls++;
1785         Ops[TOTAL].results.good_calls++;
1786         ret++;
1787     } else {
1788         if (DEBUG_CHILD_ERROR) {
1789              (void) fprintf(stderr, "%s: fsinfo call RPC error %d\n",
1790                                                 sfs_Myname, rpc_stat);
1791         }
1792         op_ptr->results.bad_calls++;
1793         Ops[TOTAL].results.bad_calls++;
1794     }
1795     return(ret);
1796
1797 } /* op_fsinfo */
1798
1799
1800 static int
1801 op_pathconf(void)
1802 {
1803     sfs_op_type         *op_ptr;        /* per operation info */
1804     PATHCONF3args       args;
1805     PATHCONF3res        reply;          /* the reply */
1806     enum clnt_stat      rpc_stat;       /* result from RPC call */
1807     struct ladtime      start;
1808     struct ladtime      stop;
1809     int                 ret;            /* ret val == call success */
1810
1811     op_ptr = &Ops[PATHCONF];
1812     ret = 0;
1813
1814     /* set up the arguments */
1815     (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
1816                 sizeof (nfs_fh3));
1817
1818     /* make the call */
1819     sfs_gettime(&start);
1820     rpc_stat = clnt_call(NFS_client, NFSPROC3_PATHCONF,
1821                         xdr_PATHCONF3args, (char *) &args,
1822                         xdr_PATHCONF3args, (char *) &reply,
1823                         (Current_test_phase < Warmup_phase)
1824                                  ? Nfs_timers[Init]
1825                                  : Nfs_timers[op_ptr->call_class]);
1826     sfs_gettime(&stop);
1827     Cur_time = stop;
1828
1829     if (rpc_stat == RPC_SUCCESS) {
1830         sfs_elapsedtime(op_ptr, &start, &stop);
1831         op_ptr->results.good_calls++;
1832         Ops[TOTAL].results.good_calls++;
1833         ret++;
1834     } else {
1835         if (DEBUG_CHILD_ERROR) {
1836              (void) fprintf(stderr,
1837                         "%s: pathconf call RPC error %d on file %d\n",
1838                         sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1839         }
1840         op_ptr->results.bad_calls++;
1841         Ops[TOTAL].results.bad_calls++;
1842     }
1843     return(ret);
1844
1845 } /* op_pathconf */
1846
1847
1848 static int
1849 op_commit(void)
1850 {
1851     sfs_op_type                 *op_ptr;        /* per operation info */
1852     int32_t                     size;           /* size of data write */
1853     COMMIT3args                 args;
1854     COMMIT3res                  reply;          /* the reply */
1855     enum clnt_stat              rpc_stat;       /* result from RPC call */
1856     struct ladtime              start;
1857     struct ladtime              stop;
1858     int                         ret;            /* ret val == call success */
1859
1860     op_ptr = &Ops[COMMIT];
1861     ret = 0;
1862
1863     /* set up the arguments */
1864     (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
1865                 sizeof (nfs_fh3));
1866     args.offset._p._u = args.offset._p._l = (uint32_t) 0;
1867     args.count = Cur_file_ptr->attributes3.size._p._l;
1868     size = args.count;
1869
1870     sfs_gettime(&start);
1871     rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT,
1872                                 xdr_COMMIT3args, (char *) &args,
1873                                 xdr_COMMIT3res, (char *) &reply,
1874                                 (Current_test_phase < Warmup_phase)
1875                                      ? Nfs_timers[Init]
1876                                      : Nfs_timers[op_ptr->call_class]);
1877     sfs_gettime(&stop);
1878     Cur_time = stop;
1879
1880     if (rpc_stat == RPC_SUCCESS) {
1881         if (reply.status == NFS3_OK) {
1882             Cur_file_ptr->state = Exists;
1883             (void) memmove((char *) &Cur_file_ptr->attributes3,
1884                         (char *) &reply.resok.file_wcc.after.attr,
1885                         sizeof(Cur_file_ptr->attributes3));
1886             Cur_file_ptr->size = fh_size(Cur_file_ptr);
1887
1888             if (DEBUG_CHILD_RPC) {
1889                 (void) fprintf(stderr, "%s: WRITE %s %ld bytes\n",
1890                                            sfs_Myname, Cur_filename, size);
1891                 (void) fflush(stderr);
1892             }
1893         } else {
1894             if (DEBUG_CHILD_ERROR) {
1895                  (void) fprintf(stderr,
1896                         "%s: write call NFS error %s on file %d\n",
1897                         sfs_Myname, nfs3_strerror(reply.status),
1898                         Cur_file_ptr->unique_num);
1899             }
1900         }
1901         sfs_elapsedtime(op_ptr, &start, &stop);
1902         op_ptr->results.good_calls++;
1903         Ops[TOTAL].results.good_calls++;
1904         ret++;
1905     } else {
1906         if (DEBUG_CHILD_ERROR) {
1907              (void) fprintf(stderr, "%s: write call RPC error %d on file %d\n",
1908                             sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1909         }
1910         op_ptr->results.bad_calls++;
1911         Ops[TOTAL].results.bad_calls++;
1912     }
1913
1914     return(ret);
1915
1916 } /* op_commit */
1917
1918
1919 #define LAD_RETRIABLE(stat) (((stat) == RPC_TIMEDOUT) || ((stat) == RPC_CANTDECODERES))
1920
1921 /*
1922  * Reliably lookup a file in the current directory
1923  * Return:
1924  *      -1      RPC error
1925  *      1       File doesn't exist
1926  *      0       File exists
1927  */
1928 int
1929 lad_lookup(sfs_fh_type *file_ptr, char *name)
1930 {
1931     LOOKUP3args         args;
1932     LOOKUP3res          reply;          /* the reply */
1933     enum clnt_stat      rpc_stat;       /* result from RPC call */
1934
1935     if (DEBUG_CHILD_RPC) {
1936         (void) fprintf(stderr, "%s:lad_lookup: %lx[%lx] %s\n", sfs_Myname,
1937                         (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
1938         (void) fflush(stderr);
1939     }
1940
1941     /* CONSTCOND */
1942     while (1) {
1943         /* set up the arguments */
1944         (void) memmove((char *) &args.what.dir, (char *) &file_ptr->dir->fh3,
1945                                                         sizeof (nfs_fh3));
1946         args.what.name = name;
1947         (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
1948
1949         /* make the call */
1950         rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
1951                         xdr_LOOKUP3args, (char *) &args,
1952                         xdr_LOOKUP3res, (char *) &reply,
1953                         Nfs_timers[Init]);
1954
1955         if (rpc_stat == RPC_SUCCESS) 
1956                 break;
1957         if (rpc_stat != RPC_TIMEDOUT) {
1958                 (void) fprintf(stderr, "lad_lookup(%s) RPC call failed : %s\n",
1959                                 name, clnt_sperrno(rpc_stat));
1960         }
1961         if (!LAD_RETRIABLE(rpc_stat)) {
1962                 return(-1);
1963         }
1964     }
1965
1966     if (reply.status == NFS3ERR_NOENT) {
1967         return(1);
1968     }
1969
1970     if (reply.status != NFS3_OK) {
1971         (void) fprintf(stderr, "lad_lookup(%s) NFS call failed : %s\n",
1972                         name, nfs3_strerror(reply.status));
1973         return(-1);
1974     }
1975
1976     file_ptr->state = Exists;
1977     (void) memmove((char *) &file_ptr->fh3,
1978                         (char *) &reply.resok.object,
1979                         sizeof (nfs_fh3));
1980     (void) strcpy(file_ptr->file_name, name);
1981     (void) memmove((char *) &file_ptr->attributes3,
1982                                 (char *) &reply.resok.obj_attributes.attr,
1983                                 sizeof (file_ptr->attributes3));
1984     file_ptr->size = fh_size(file_ptr);
1985     return(0);
1986 }
1987
1988 /*
1989  * Reliably remove a file in the current directory
1990  */
1991 int
1992 lad_remove(sfs_fh_type *file_ptr, char *name)
1993 {
1994     REMOVE3args         args;
1995     REMOVE3res          reply;          /* the reply */
1996     enum clnt_stat      rpc_stat;       /* result from RPC call */
1997     int                 retried = 0;
1998
1999     /*
2000      * This function presumes that the file name does exist
2001      */
2002     if (file_ptr->attributes3.type == NF3DIR)
2003         return (lad_rmdir(file_ptr, name));
2004
2005     if (DEBUG_CHILD_RPC) {
2006         (void) fprintf(stderr, "%s:lad_remove: %lx[%lx] %s\n", sfs_Myname,
2007                         (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
2008         (void) fflush(stderr);
2009     }
2010
2011     /* CONSTCOND */
2012     while (1) {
2013         /* set up the arguments */
2014         args.object.name = name;
2015         (void) memmove((char *) &args.object.dir, (char *) &file_ptr->dir->fh3,
2016                         sizeof(nfs_fh3));
2017
2018         /* make the call now */
2019         rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE,
2020                         xdr_REMOVE3args, (char *) &args,
2021                         xdr_REMOVE3res, (char *) &reply,
2022                         Nfs_timers[Init]);
2023
2024         if (rpc_stat == RPC_SUCCESS) 
2025                 break;
2026         if (rpc_stat != RPC_TIMEDOUT) {
2027                 (void) fprintf(stderr, "lad_remove(%s) RPC call failed : %s\n",
2028                                 name, clnt_sperrno(rpc_stat));
2029         }
2030         if (!LAD_RETRIABLE(rpc_stat)) {
2031                 return(-1);
2032         }
2033         retried++;
2034     }
2035
2036     if (reply.status != NFS3_OK) {
2037         if (reply.status != NFS3ERR_NOENT || !retried) {
2038             (void) fprintf(stderr, "lad_remove(%s) NFS call failed : %s\n",
2039                         name, nfs3_strerror(reply.status));
2040             return(-1);
2041         }
2042     }
2043
2044     file_ptr->state = Nonexistent;
2045
2046     return(0);
2047 }
2048
2049 /*
2050  * Reliably remove a directory in the current directory
2051  */
2052 int
2053 lad_rmdir(sfs_fh_type *file_ptr, char *name)
2054 {
2055     RMDIR3args          args;
2056     RMDIR3res           reply;          /* the reply */
2057     enum clnt_stat      rpc_stat;       /* result from RPC call */
2058     int                 retried = 0;
2059
2060     /*
2061      * This function presumes that the file name does exist and is empty
2062      */
2063     if (file_ptr->attributes3.type != NF3DIR)
2064         return (lad_remove(file_ptr, name));
2065
2066     if (DEBUG_CHILD_RPC) {
2067         (void) fprintf(stderr, "%s:lad_rmdir: %lx[%lx] %s\n", sfs_Myname,
2068                         (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
2069         (void) fflush(stderr);
2070     }
2071
2072     /* CONSTCOND */
2073     while (1) {
2074         /* set up the arguments */
2075         args.object.name = name;
2076         (void) memmove((char *) &args.object.dir, (char *) &file_ptr->dir->fh3,
2077                 sizeof (nfs_fh3));
2078
2079         /* make the call now */
2080         rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR,
2081                         xdr_RMDIR3args, (char *) &args,
2082                         xdr_RMDIR3res, (char *) &reply,
2083                         Nfs_timers[Init]);
2084
2085         if (rpc_stat == RPC_SUCCESS) 
2086                 break;
2087         if (rpc_stat != RPC_TIMEDOUT) {
2088                 (void) fprintf(stderr, "lad_rmdir(%s) RPC call failed : %s\n",
2089                                 name, clnt_sperrno(rpc_stat));
2090         }
2091         if (!LAD_RETRIABLE(rpc_stat)) {
2092                 return(-1);
2093         }
2094         retried++;
2095     }
2096
2097     if (reply.status != NFS3_OK) {
2098         if (reply.status != NFS3ERR_NOENT || !retried) {
2099             (void) fprintf(stderr, "lad_rmdir(%s) NFS call failed : %s\n",
2100                         name, nfs3_strerror(reply.status));
2101             return(-1);
2102         }
2103     }
2104
2105     file_ptr->state = Nonexistent;
2106
2107     return(0);
2108 }
2109
2110 /*
2111  * Reliably create a symlink in the current directory
2112  */
2113 int
2114 lad_symlink(sfs_fh_type *file_ptr, char *target, char *name)
2115 {
2116     SYMLINK3args        args;
2117     SYMLINK3res         reply;                  /* the reply */
2118     char                sym_data[NFS_MAXPATHLEN];       /* symlink data */
2119     enum clnt_stat      rpc_stat;               /* result from RPC call */
2120     int                 retried = 0;
2121
2122     /*
2123      * This function presumes that the file name does not already exist
2124      */
2125     if (DEBUG_CHILD_RPC) {
2126         (void) fprintf(stderr, "%s:lad_symlink: %lx[%lx] %s -> %s\n", sfs_Myname,
2127                         (int32_t) file_ptr, (int32_t) file_ptr->dir, name, target);
2128         (void) fflush(stderr);
2129     }
2130
2131     /* CONSTCOND */
2132     while (1) {
2133         /* set up the arguments */
2134          (void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
2135                 sizeof (nfs_fh3));
2136          args.where.name = name;
2137
2138         (void) strcpy(sym_data, "./");
2139         (void) strcat(sym_data, target);
2140         args.symlink.symlink_attributes.size.set_it = TRUE;
2141         args.symlink.symlink_attributes.size.size._p._u = (uint32_t) 0;
2142         args.symlink.symlink_attributes.size.size._p._l = strlen(sym_data);
2143         args.symlink.symlink_data = sym_data;
2144
2145         args.symlink.symlink_attributes.mode.set_it = TRUE;
2146         args.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
2147         args.symlink.symlink_attributes.uid.set_it = TRUE;
2148         args.symlink.symlink_attributes.uid.uid = Cur_uid;
2149         args.symlink.symlink_attributes.gid.set_it = TRUE;
2150         args.symlink.symlink_attributes.gid.gid = Cur_gid;
2151         args.symlink.symlink_attributes.atime.set_it = TRUE;
2152         args.symlink.symlink_attributes.atime.atime.seconds = Cur_time.esec;
2153         args.symlink.symlink_attributes.atime.atime.nseconds =
2154                                                 Cur_time.usec * 1000;
2155         args.symlink.symlink_attributes.mtime.set_it = TRUE;
2156         args.symlink.symlink_attributes.mtime.mtime.seconds = Cur_time.esec;
2157         args.symlink.symlink_attributes.mtime.mtime.nseconds =
2158                                                 Cur_time.usec * 1000;
2159
2160
2161         /* make the call now */
2162         rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK,
2163                         xdr_SYMLINK3args, (char *) &args,
2164                         xdr_SYMLINK3res, (char *) &reply,
2165                         Nfs_timers[Init]);
2166         if (rpc_stat == RPC_SUCCESS) 
2167                 break;
2168         if (rpc_stat != RPC_TIMEDOUT) {
2169                 (void) fprintf(stderr, "lad_symlink(%s) RPC call failed : %s\n",
2170                                 name, clnt_sperrno(rpc_stat));
2171         }
2172         if (!LAD_RETRIABLE(rpc_stat)) {
2173                 return(-1);
2174         }
2175         retried++;
2176     }
2177
2178     if (reply.status != NFS3_OK) {
2179         if (reply.status != NFS3ERR_EXIST || !retried) {
2180             (void) fprintf(stderr, "lad_symlink(%s, %s) NFS call failed : %s\n",
2181                         target, name, nfs3_strerror(reply.status));
2182             return(-1);
2183         }
2184     }
2185
2186     /*
2187      * SYMLINK may not return a fh. If we try to
2188      * access this symlink (eg, remove(), readlink())
2189      * before we do a lookup, we won't have a fh to use.
2190      * So, we do a lookup call here.
2191      * If it fails, we fill in what we can.
2192      */  
2193     return (lad_lookup(file_ptr, name));
2194 }
2195
2196 /*
2197  * Reliably create a directory in the current directory
2198  */
2199 int
2200 lad_mkdir(sfs_fh_type *file_ptr, char *name)
2201 {
2202     MKDIR3args          args;
2203     MKDIR3res           reply;                  /* the reply */
2204     enum clnt_stat      rpc_stat;               /* result from RPC call */
2205     int                 retried = 0;
2206
2207     /*
2208      * This function presumes that the file name does not already exist
2209      */
2210     if (DEBUG_CHILD_RPC) {
2211         (void) fprintf(stderr, "%s:lad_mkdir: %lx[%lx] %s\n", sfs_Myname,
2212                         (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
2213         (void) fflush(stderr);
2214     }
2215
2216     /* CONSTCOND */
2217     while (1) {
2218         /* set up the arguments */
2219         (void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
2220                 sizeof (nfs_fh3));
2221         args.where.name = name;
2222         args.attributes.mode.set_it = TRUE;
2223         args.attributes.mode.mode = (NFSMODE_DIR | 0777);
2224         args.attributes.uid.set_it = TRUE;
2225         args.attributes.uid.uid = Cur_uid;
2226         args.attributes.gid.set_it = TRUE;
2227         args.attributes.gid.gid = Cur_gid;
2228         args.attributes.size.set_it = TRUE;
2229         args.attributes.size.size._p._u = 0;
2230         args.attributes.size.size._p._l = 512;
2231         args.attributes.atime.set_it = TRUE;
2232         args.attributes.atime.atime.seconds = Cur_time.esec;
2233         args.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
2234         args.attributes.mtime.set_it = TRUE;
2235         args.attributes.mtime.mtime.seconds = Cur_time.esec;
2236         args.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
2237
2238         /* make the call now */
2239         rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR,
2240                         xdr_MKDIR3args, (char *) &args,
2241                         xdr_MKDIR3res, (char *) &reply,
2242                         Nfs_timers[Init]);
2243
2244         if (rpc_stat == RPC_SUCCESS) 
2245                 break;
2246         if (rpc_stat != RPC_TIMEDOUT) {
2247                 (void) fprintf(stderr, "lad_mkdir(%s) RPC call failed : %s\n",
2248                                 name, clnt_sperrno(rpc_stat));
2249         }
2250         if (!LAD_RETRIABLE(rpc_stat)) {
2251                 return(-1);
2252         }
2253         retried++;
2254     }
2255
2256     if (!retried && reply.status == NFS3ERR_EXIST)
2257         return(1);
2258
2259     if (reply.status != NFS3_OK) {
2260         if (reply.status != NFS3ERR_EXIST || !retried) {
2261             (void) fprintf(stderr, "lad_mkdir(%s) NFS call failed : %s\n",
2262                         name, nfs3_strerror(reply.status));
2263             return(-1);
2264         }
2265         /*
2266          * If the first mkdir suceeded but the reply as dropped and
2267          * was retransmitted, we still need to lookup the attributes
2268          */
2269         if (lad_lookup(file_ptr, name))
2270            return (-1);
2271     } else {
2272         (void) memmove((char *) &file_ptr->fh3,
2273                    (char *) &reply.resok.obj.handle,
2274                    sizeof (nfs_fh3));
2275         (void) strcpy(file_ptr->file_name, name);
2276         (void) memmove((char *) &file_ptr->attributes3,
2277                    (char *) &reply.resok.obj_attributes.attr,
2278                    sizeof(file_ptr->attributes3));
2279         file_ptr->size = fh_size(file_ptr);
2280     }
2281     file_ptr->state = Empty_dir;
2282
2283     return(0);
2284 }
2285
2286 /*
2287  * Reliably commit a file
2288  */
2289 static int
2290 lad_commit(sfs_fh_type *file_ptr)
2291 {
2292     COMMIT3args                 args;
2293     COMMIT3res                  reply;          /* the reply */
2294     enum clnt_stat              rpc_stat;       /* result from RPC call */
2295
2296     if (DEBUG_CHILD_RPC) {
2297         (void) fprintf(stderr, "%s:lad_commit: %lx[%lx]\n",
2298                         sfs_Myname,
2299                         (int32_t) file_ptr, (int32_t) file_ptr->dir);
2300         (void) fflush(stderr);
2301     }
2302
2303     /* set up the arguments */
2304     (void) memmove((char *) &args.file, (char *) &file_ptr->fh3,
2305                 sizeof (nfs_fh3));
2306     args.offset._p._u = args.offset._p._l = (uint32_t) 0;
2307     args.count = file_ptr->attributes3.size._p._l;
2308
2309     /* CONSTCOND */
2310     while (1) {
2311         rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT,
2312                                 xdr_COMMIT3args, (char *) &args,
2313                                 xdr_COMMIT3res, (char *) &reply,
2314                                 Nfs_timers[Init]);
2315         if (rpc_stat == RPC_SUCCESS) 
2316             break;
2317         if (rpc_stat != RPC_TIMEDOUT) {
2318             (void) fprintf(stderr, "lad_commit() RPC call failed : %s\n",
2319                                 clnt_sperrno(rpc_stat));
2320         }
2321         if (!LAD_RETRIABLE(rpc_stat)) {
2322                 return(-1);
2323         }
2324     }
2325
2326     return(0);
2327 }
2328
2329 /*
2330  * Reliably write a file in the current directory
2331  */
2332 int
2333 lad_write(sfs_fh_type *file_ptr, int32_t offset, int32_t length)
2334 {
2335     static char                 *buf = NULL;    /* the data buffer */
2336     int32_t                     size;           /* size of data write */
2337     int32_t                     cur_cnt;
2338     WRITE3args                  args;
2339     WRITE3res                   reply;          /* the reply */
2340     enum clnt_stat              rpc_stat;       /* result from RPC call */
2341     int                         async = 1;
2342
2343     if (DEBUG_CHILD_RPC) {
2344         (void) fprintf(stderr, "%s:lad_write: %lx[%lx] %ld %ld\n",
2345                         sfs_Myname,
2346                         (int32_t) file_ptr, (int32_t) file_ptr->dir, offset, length);
2347         (void) fflush(stderr);
2348     }
2349
2350     /*
2351      * This function presumes that the file name does exist
2352      * Initialize write buffer to known value
2353      */
2354     if (buf == NULL) {
2355         buf = init_write_buffer();
2356     }
2357
2358     /*
2359      * If a short file write don't bother with the commit, just write sync.
2360      */
2361     if (length <= Bytes_per_block)
2362         async = 0;
2363
2364     /* set up the arguments */
2365     (void) memmove((char *) &args.file, (char *) &file_ptr->fh3,
2366                 sizeof (nfs_fh3));
2367     args.offset._p._u = 0;
2368     args.offset._p._l = offset;
2369     if (async)
2370             args.stable = UNSTABLE;
2371     else
2372             args.stable = FILE_SYNC;
2373
2374     size = Bytes_per_block;
2375     for (cur_cnt = 0; cur_cnt < length; cur_cnt += size) {
2376         if ((cur_cnt + size) > length)
2377                 size = length - cur_cnt;
2378
2379         if (size == 0)
2380             break;
2381
2382         args.count = size;
2383         args.data.data_len = size;
2384         args.data.data_val = buf;
2385
2386         /* make the call now */
2387         /* CONSTCOND */
2388         while (1) {
2389             rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE,
2390                                 xdr_WRITE3args, (char *) &args,
2391                                 xdr_WRITE3res, (char *) &reply,
2392                                 Nfs_timers[Init]);
2393
2394             if (rpc_stat == RPC_SUCCESS) 
2395                 break;
2396             if (rpc_stat != RPC_TIMEDOUT) {
2397                 (void) fprintf(stderr, "lad_write() RPC call failed : %s\n",
2398                                 clnt_sperrno(rpc_stat));
2399             }
2400             if (!LAD_RETRIABLE(rpc_stat)) {
2401                 return(-1);
2402             }
2403         }
2404         if (reply.status != NFS3_OK) {
2405             (void) fprintf(stderr, "lad_write() NFS call failed : %s\n",
2406                         nfs3_strerror(reply.status));
2407             return(-1);
2408         }
2409         file_ptr->state = Exists;
2410         (void) memmove((char *) &file_ptr->attributes3,
2411                                 (char *) &reply.resok.file_wcc.after.attr,
2412                                 sizeof (file_ptr->attributes3));
2413         file_ptr->size = fh_size(file_ptr);
2414
2415         args.offset._p._l += size;
2416     }
2417
2418     if (async)
2419         (void) lad_commit(file_ptr);
2420     return(0);
2421 }
2422
2423 /*
2424  * Reliably create a file in the current directory
2425  */
2426 int
2427 lad_create(sfs_fh_type *file_ptr, char *name)
2428 {
2429     CREATE3args         args;
2430     CREATE3res          reply;                  /* the reply */
2431     enum clnt_stat      rpc_stat;               /* result from RPC call */
2432     int                 retried = 0;
2433
2434     /*
2435      * This function presumes that the file name does not already exist
2436      */
2437     if (DEBUG_CHILD_RPC) {
2438         (void) fprintf(stderr, "%s:lad_create: %lx[%lx] %s\n", sfs_Myname,
2439                         (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
2440         (void) fflush(stderr);
2441     }
2442
2443     /* CONSTCOND */
2444     while (1) {
2445         /* set up the arguments */
2446         (void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
2447                 sizeof (nfs_fh3));
2448         args.where.name = name;
2449         args.how.mode = UNCHECKED;
2450         args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
2451         args.how.createhow3_u.obj_attributes.mode.mode = (NFSMODE_REG | 0666);
2452         args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
2453         args.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
2454         args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
2455         args.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
2456         args.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
2457         args.how.createhow3_u.obj_attributes.atime.atime.seconds =
2458                                                 Cur_time.esec;
2459         args.how.createhow3_u.obj_attributes.atime.atime.nseconds =
2460                                                 Cur_time.usec * 1000;
2461         args.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
2462         args.how.createhow3_u.obj_attributes.mtime.mtime.seconds =
2463                                                 Cur_time.esec;
2464         args.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
2465                                                 Cur_time.usec * 1000;
2466         args.how.createhow3_u.obj_attributes.size.set_it = TRUE;
2467         args.how.createhow3_u.obj_attributes.size.size._p._u =
2468                                                 (uint32_t) 0;
2469         args.how.createhow3_u.obj_attributes.size.size._p._l =
2470                                                 (uint32_t) 0;
2471
2472         /* make the call now */
2473         rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE,
2474                         xdr_CREATE3args, (char *) &args,
2475                         xdr_CREATE3res, (char *) &reply,
2476                         Nfs_timers[Init]);
2477
2478         if (rpc_stat == RPC_SUCCESS) 
2479                 break;
2480         if (rpc_stat != RPC_TIMEDOUT) {
2481                 (void) fprintf(stderr, "lad_create(%s) RPC call failed : %s\n",
2482                                 name, clnt_sperrno(rpc_stat));
2483         }
2484         if (!LAD_RETRIABLE(rpc_stat)) {
2485                 return(-1);
2486         }
2487         retried++;
2488     }
2489
2490     if (!retried && reply.status == NFS3ERR_EXIST) {
2491         return(1);
2492     }
2493
2494     if (reply.status != NFS3_OK) {
2495         if (reply.status != NFS3ERR_EXIST || !retried) {
2496             (void) fprintf(stderr, "lad_create(%s) NFS call failed : %s\n",
2497                         name, nfs3_strerror(reply.status));
2498             return(-1);
2499         }
2500         /*
2501          * If the first create suceeded but the reply as dropped and
2502          * was retransmitted, we still need to lookup the attributes
2503          */
2504         if (lad_lookup(file_ptr, name))
2505            return (-1);
2506     } else {
2507         (void) memmove((char *) &file_ptr->fh3,
2508                    (char *) &reply.resok.obj.handle,
2509                    sizeof (nfs_fh3));
2510         (void) strcpy(file_ptr->file_name, name);
2511         (void) memmove((char *) &file_ptr->attributes3,
2512                    (char *) &reply.resok.obj_attributes.attr,
2513                    sizeof(file_ptr->attributes3));
2514         file_ptr->size = fh_size(file_ptr);
2515     }
2516
2517     file_ptr->state = Exists;
2518     /*
2519      * Directories are created as Empty_dir, when a file is created it
2520      * becomes an Exists.
2521      */
2522     file_ptr->dir->state = Exists;
2523
2524     return(0);
2525 }
2526
2527 /*
2528  * Reliably set the size of a file in the current directory
2529  */
2530 int
2531 lad_truncate(sfs_fh_type *file_ptr, int32_t size)
2532 {
2533     SETATTR3args        args;
2534     SETATTR3res         reply;          /* the reply */
2535     enum clnt_stat      rpc_stat;       /* result from RPC call */
2536
2537     /*
2538      * This function presumes that the file name already exists
2539      */
2540     if (DEBUG_CHILD_RPC) {
2541         (void) fprintf(stderr, "%s:lad_truncate: %lx[%lx] %ld\n", sfs_Myname,
2542                         (int32_t) file_ptr, (int32_t) file_ptr->dir, size);
2543         (void) fflush(stderr);
2544     }
2545
2546     /* CONSTCOND */
2547     while (1) {
2548         /*
2549          * set up the arguments
2550          * Set the mode and times as well
2551          */
2552         (void) memmove((char *) &args.object, (char *) &file_ptr->fh3,
2553                                                         sizeof (nfs_fh3));
2554         args.new_attributes.mode.set_it = TRUE;
2555         args.new_attributes.mode.mode = (uint32_t) 0666;
2556         args.new_attributes.uid.set_it = FALSE;
2557         args.new_attributes.uid.uid = (uint32_t) -1;
2558         args.new_attributes.gid.set_it = FALSE;
2559         args.new_attributes.gid.gid = (uint32_t) -1;
2560         args.new_attributes.size.set_it = TRUE;
2561         args.new_attributes.size.size._p._u = 0;
2562         args.new_attributes.size.size._p._l = size;
2563         args.new_attributes.atime.set_it = TRUE;
2564         args.new_attributes.atime.atime.seconds = Cur_time.esec;
2565         args.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
2566         args.new_attributes.mtime.set_it = TRUE;
2567         args.new_attributes.mtime.mtime.seconds = Cur_time.esec;
2568         args.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
2569         args.guard.check = FALSE;
2570
2571         /* make the call */
2572         rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR,
2573                         xdr_SETATTR3args, (char *) &args,
2574                         xdr_SETATTR3res, (char *) &reply,
2575                         Nfs_timers[Init]);
2576
2577         if (rpc_stat == RPC_SUCCESS) 
2578                 break;
2579         if (rpc_stat != RPC_TIMEDOUT) {
2580                 (void)fprintf(stderr,
2581                                 "lad_truncate(%ld) RPC call failed : %s\n",
2582                                 size, clnt_sperrno(rpc_stat));
2583         }
2584         if (!LAD_RETRIABLE(rpc_stat)) {
2585                 return(-1);
2586         }
2587     }
2588
2589     if (reply.status != NFS3_OK) {
2590         (void) fprintf(stderr, "lad_truncate(%ld) NFS call failed : %s\n",
2591                         size, nfs3_strerror(reply.status));
2592         return(-1);
2593     }
2594     (void) memmove(&file_ptr->attributes3,
2595                    &reply.resok.obj_wcc.after.attr,
2596                    sizeof (file_ptr->attributes3));
2597     file_ptr->size = fh_size(file_ptr);
2598
2599     return(0);
2600 }
2601
2602 static char *
2603 nfs3_strerror(int status)
2604 {
2605     static char str[40];
2606     switch (status) {
2607         case NFS3_OK:
2608             (void) strcpy(str, "no error");
2609             break;
2610         case NFS3ERR_PERM:
2611             (void) strcpy(str, "Not owner");
2612             break;
2613         case NFS3ERR_NOENT:
2614             (void) strcpy(str, "No such file or directory");
2615             break;
2616         case NFS3ERR_IO:
2617             (void) strcpy(str, "I/O error");
2618             break;
2619         case NFS3ERR_NXIO:
2620             (void) strcpy(str, "No such device or address");
2621             break;
2622         case NFS3ERR_ACCES:
2623             (void) strcpy(str, "Permission denied");
2624             break;
2625         case NFS3ERR_EXIST:
2626             (void) strcpy(str, "File exists");
2627             break;
2628         case NFS3ERR_XDEV:
2629             (void) strcpy(str, "Cross-device link");
2630             break;
2631         case NFS3ERR_NODEV:
2632             (void) strcpy(str, "No such device");
2633             break;
2634         case NFS3ERR_NOTDIR:
2635             (void) strcpy(str, "Not a directory");
2636             break;
2637         case NFS3ERR_ISDIR:
2638             (void) strcpy(str, "Is a directory");
2639             break;
2640         case NFS3ERR_INVAL:
2641             (void) strcpy(str, "Invalid argument");
2642             break;
2643         case NFS3ERR_FBIG:
2644             (void) strcpy(str, "File too large");
2645             break;
2646         case NFS3ERR_NOSPC:
2647             (void) strcpy(str, "No space left on device");
2648             break;
2649         case NFS3ERR_ROFS:
2650             (void) strcpy(str, "Read-only file system");
2651             break;
2652         case NFS3ERR_MLINK:
2653             (void) strcpy(str, "Too many links");
2654             break;
2655         case NFS3ERR_NAMETOOLONG:
2656             (void) strcpy(str, "File name too long");
2657             break;
2658         case NFS3ERR_NOTEMPTY:
2659             (void) strcpy(str, "Directory not empty");
2660             break;
2661         case NFS3ERR_DQUOT:
2662             (void) strcpy(str, "Disc quota exceeded");
2663             break;
2664         case NFS3ERR_STALE:
2665             (void) strcpy(str, "Stale NFS file handle");
2666             break;
2667         case NFS3ERR_REMOTE:
2668             (void) strcpy(str, "Object is remote");
2669             break;
2670         case NFS3ERR_BADHANDLE:
2671             (void) strcpy(str, "Bad file handle");
2672             break;
2673         case NFS3ERR_NOT_SYNC:
2674             (void) strcpy(str, "Not sync write");
2675             break;
2676         case NFS3ERR_BAD_COOKIE:
2677             (void) strcpy(str, "Bad cookie");
2678             break;
2679         case NFS3ERR_NOTSUPP:
2680             (void) strcpy(str, "Operation not supported");
2681             break;
2682         case NFS3ERR_TOOSMALL:
2683             (void) strcpy(str, "Value too small");
2684             break;
2685         case NFS3ERR_SERVERFAULT:
2686             (void) strcpy(str, "Server fault");
2687             break;
2688         case NFS3ERR_BADTYPE:
2689             (void) strcpy(str, "Bad type");
2690             break;
2691         case NFS3ERR_JUKEBOX:
2692             (void) strcpy(str, "Jukebox");
2693             break;
2694         default:
2695             (void) sprintf(str, "Unknown status %d", status);
2696             break;
2697     }
2698     return (str);
2699 }
2700
2701 /* sfs_3_ops.c */