2 static char sfs_c_opsSid[] = "@(#)sfs_2_ops.c 2.1 97/10/23";
6 * Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
8 * Standard Performance Evaluation Corporation (SPEC)
9 * 6585 Merchant Place, Suite 100
12 * This product contains benchmarks acquired from several sources who
13 * understand and agree with SPEC's goal of creating fair and objective
14 * benchmarks to measure computer performance.
16 * This copyright notice is placed here only to protect SPEC in the
17 * event the source is misused in any manner that is contrary to the
18 * spirit, the goals and the intent of SPEC.
20 * The source code is provided to the user or company under the license
21 * agreement for the SPEC Benchmark Suite for this product.
24 /*****************************************************************
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. *
33 *****************************************************************/
36 * ---------------------- sfs_c_ops.c ---------------------
38 * RPC routines to implement the NFS protocol.
42 * int op_getattr(void)
46 * int op_readlink(void)
48 * int op_write(int, int, int)
53 * int op_symlink(void)
56 * int op_readdir(void)
60 * 20-Apr-92 Wittle Fix i/o offsets randomization.
61 * 05-Jan-92 Pawlowski Added hooks in for raw data dump.
62 * 04-Dec-91 Keith Define string.h for SYSV/SVR4.
63 * 28-Nov-91 Teelucksingh ANSI C
64 * 01-Aug-91 Santa Wiryaman fix declaration of sfs_srandom()
66 * 25-Jun-91 Santa Wiryaman op_rmdir bug fix: when reply==NFS_OK
67 * Cur_file_ptr->state = Nonexistent
68 * 17-May-90 Richard Bean Created.
73 * ------------------------- Include Files -------------------------
84 #include <sys/types.h>
89 #include "sfs_c_def.h"
92 * -------------------- Local NFS ops function --------------------
94 static int op_null(void);
95 static int op_getattr(void);
96 static int op_setattr(int);
97 static int op_lookup(void);
98 static int op_readlink(void);
99 static int op_read(int);
100 static int op_write(int, int, int);
101 static int op_create(void);
102 static int op_remove(void);
103 static int op_rename(void);
104 static int op_link(void);
105 static int op_symlink(void);
106 static int op_mkdir(void);
107 static int op_rmdir(void);
108 static int op_readdir(void);
109 static int op_fsstat(void);
110 static int op_nosys(void);
111 static char *nfs2_strerror(int);
114 * -------------------- NFS ops vector --------------------
117 * per operation information
119 static sfs_op_type nfsv2_Ops[] = {
121 /* name mix function op call no req req req results */
122 /* pcnt class targ call pcnt cnt targ */
124 { "null", 0, op_null, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
125 { "getattr", 26, op_getattr, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
126 { "setattr", 1, op_setattr, Write, 0, 0, 0.0, 0, 0, { 0, }},
127 { "root", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
128 { "lookup", 36, op_lookup, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
129 { "readlink", 7, op_readlink, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
130 { "read", 14, op_read, Read, 0, 0, 0.0, 0, 0, { 0, }},
131 { "wrcache", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
132 { "write", 7, op_write, Write, 0, 0, 0.0, 0, 0, { 0, }},
133 { "create", 1, op_create, Write, 0, 0, 0.0, 0, 0, { 0, }},
134 { "remove", 1, op_remove, Write, 0, 0, 0.0, 0, 0, { 0, }},
135 { "rename", 0, op_rename, Write, 0, 0, 0.0, 0, 0, { 0, }},
136 { "link", 0, op_link, Write, 0, 0, 0.0, 0, 0, { 0, }},
137 { "symlink", 0, op_symlink, Write, 0, 0, 0.0, 0, 0, { 0, }},
138 { "mkdir", 0, op_mkdir, Write, 0, 0, 0.0, 0, 0, { 0, }},
139 { "rmdir", 0, op_rmdir, Write, 0, 0, 0.0, 0, 0, { 0, }},
140 { "readdir", 6, op_readdir, Read, 0, 0, 0.0, 0, 0, { 0, }},
141 { "fsstat", 1, op_fsstat, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
142 { "access", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
143 { "commit", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
144 { "fsinfo", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
145 { "mknod", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
146 { "pathconf", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
147 { "readdirplus", 0, op_nosys, Lookup, 0, 0, 0.0, 0, 0, { 0, }},
148 { "TOTAL", 100, 0, Lookup, 0, 0, 0.0, 0, 0, { 0, }}
154 * -------------------- RPC routines for NFS protocol --------------------
161 nfs_version = NFS_VERSION;
165 * The routines below attempt to do over-the-wire operations.
166 * Each op tries to cause one or more of a particular
167 * NFS operation to go over the wire. OPs return the success
168 * of their NFS call(s). Each OP records how many calls it
169 * actually made in global data.
171 * An array of file information is kept for files existing in
172 * the test directory. File handles, attributes, names, etc
173 * are stored in this array.
181 * This is a generic catcher for operations that either don't
182 * exist or were never implemented. We will be
183 * kind and simply mark it as a bad call.
185 Ops[TOTAL].results.bad_calls++;
194 sfs_op_type *op_ptr; /* per operation info */
195 enum clnt_stat rpc_stat; /* result from RPC call */
196 struct ladtime start;
198 int ret; /* ret val == call success */
200 op_ptr = &Ops[NULLCALL];
205 rpc_stat = clnt_call(NFS_client, NFSPROC_NULL,
208 (Current_test_phase < Warmup_phase)
210 : Nfs_timers[op_ptr->call_class]);
214 if (rpc_stat == RPC_SUCCESS) {
215 sfs_elapsedtime(op_ptr, &start, &stop);
216 op_ptr->results.good_calls++;
217 Ops[TOTAL].results.good_calls++;
220 if (DEBUG_CHILD_ERROR) {
221 (void) fprintf(stderr,
222 "%s: null_op call RPC error %d on file %d\n",
223 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
225 op_ptr->results.bad_calls++;
226 Ops[TOTAL].results.bad_calls++;
236 sfs_op_type *op_ptr; /* per operation info */
237 fhandle_t fh; /* fh to do op on */
238 attrstat reply; /* the reply */
239 enum clnt_stat rpc_stat; /* result from RPC call */
240 struct ladtime start;
242 int ret; /* ret val == call success */
244 op_ptr = &Ops[GETATTR];
247 /* set up the arguments */
248 (void) memmove((char *) &fh, (char *) &Cur_file_ptr->fh2,
253 rpc_stat = clnt_call(NFS_client, NFSPROC_GETATTR,
254 xdr_getattr, (char *) &fh,
255 xdr_getattr, (char *) &reply,
256 (Current_test_phase < Warmup_phase)
258 : Nfs_timers[op_ptr->call_class]);
262 if (rpc_stat == RPC_SUCCESS) {
263 if (reply.status == NFS_OK) {
264 Cur_file_ptr->attributes2 = reply.attrstat_u.attributes;
265 Cur_file_ptr->size = fh_size(Cur_file_ptr);
267 if (DEBUG_CHILD_ERROR) {
268 (void) fprintf(stderr,
269 "%s: getattr call NFS error %s on file %d\n",
270 sfs_Myname, nfs2_strerror(reply.status),
271 Cur_file_ptr->unique_num);
274 sfs_elapsedtime(op_ptr, &start, &stop);
275 op_ptr->results.good_calls++;
276 Ops[TOTAL].results.good_calls++;
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);
284 op_ptr->results.bad_calls++;
285 Ops[TOTAL].results.bad_calls++;
293 * perform an RPC setattr operation. If 'truncate_size' is non-negative,
294 * truncate the file to that size.
300 sfs_op_type *op_ptr; /* per operation info */
302 attrstat reply; /* the reply */
303 enum clnt_stat rpc_stat; /* result from RPC call */
304 struct ladtime start;
306 int ret; /* ret val == call success */
308 op_ptr = &Ops[SETATTR];
311 /* set up the arguments */
312 args.attributes.mode = 0666;
313 args.attributes.uid = (unsigned int) -1;
314 args.attributes.gid = (unsigned int) -1;
315 args.attributes.size = (unsigned int) -1;
316 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
317 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
318 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
319 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
320 (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh2,
323 /* handle file truncations */
324 if (truncate_size >= 0) {
325 if (truncate_size > Cur_file_ptr->attributes2.size)
326 args.attributes.size = (unsigned int) 0;
328 args.attributes.size = (unsigned int) Cur_file_ptr->attributes2.size
334 rpc_stat = clnt_call(NFS_client, NFSPROC_SETATTR,
335 xdr_setattr, (char *) &args,
336 xdr_setattr, (char *) &reply,
337 (Current_test_phase < Warmup_phase)
339 : Nfs_timers[op_ptr->call_class]);
344 if (rpc_stat == RPC_SUCCESS) {
345 if (reply.status == NFS_OK) {
346 Cur_file_ptr->attributes2 = reply.attrstat_u.attributes;
347 Cur_file_ptr->size = fh_size(Cur_file_ptr);
349 if (DEBUG_CHILD_ERROR) {
350 (void) fprintf(stderr,
351 "%s: setattr call NFS error %s on file %d\n",
352 sfs_Myname, nfs2_strerror(reply.status),
353 Cur_file_ptr->unique_num);
356 sfs_elapsedtime(op_ptr, &start, &stop);
357 op_ptr->results.good_calls++;
358 Ops[TOTAL].results.good_calls++;
361 if (DEBUG_CHILD_ERROR) {
362 (void) fprintf(stderr,
363 "%s: setattr call RPC error %d on file %d\n",
364 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
366 op_ptr->results.bad_calls++;
367 Ops[TOTAL].results.bad_calls++;
377 sfs_op_type *op_ptr; /* per operation info */
379 diropres reply; /* the reply */
380 enum clnt_stat rpc_stat; /* result from RPC call */
381 struct ladtime start;
383 int ret; /* ret val == call success */
385 op_ptr = &Ops[LOOKUP];
388 /* set up the arguments */
389 (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
391 args.name = Cur_filename;
395 rpc_stat = clnt_call(NFS_client, NFSPROC_LOOKUP,
396 xdr_lookup, (char *) &args,
397 xdr_lookup, (char *) &reply,
398 (Current_test_phase < Warmup_phase)
400 : Nfs_timers[op_ptr->call_class]);
404 if (rpc_stat == RPC_SUCCESS) {
405 if (reply.status == NFS_OK) {
406 Cur_file_ptr->state = Exists;
407 (void) memmove((char *) &Cur_file_ptr->fh2,
408 (char *) &reply.diropres_u.diropres.file,
410 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
411 Cur_file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
412 Cur_file_ptr->size = fh_size(Cur_file_ptr);
414 /* We do lookup Nonexistent and this is not an error */
415 if (reply.status != NFSERR_NOENT ||
416 Cur_file_ptr->state != Nonexistent) {
417 if (DEBUG_CHILD_ERROR) {
418 (void) fprintf(stderr,
419 "%s: lookup call NFS error %s on file %d\n",
420 sfs_Myname, nfs2_strerror(reply.status),
421 Cur_file_ptr->unique_num);
426 sfs_elapsedtime(op_ptr, &start, &stop);
427 op_ptr->results.good_calls++;
428 Ops[TOTAL].results.good_calls++;
431 if (DEBUG_CHILD_ERROR) {
432 (void) fprintf(stderr, "%s: lookup call RPC error %d on file %d\n",
433 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
435 op_ptr->results.bad_calls++;
436 Ops[TOTAL].results.bad_calls++;
446 sfs_op_type *op_ptr; /* per operation info */
447 fhandle_t fh; /* fh to do op on */
448 readlinkres reply; /* the reply */
449 char sym_data[NFS_MAXPATHLEN];
450 int len; /* length of symlink data */
451 enum clnt_stat rpc_stat; /* result from RPC call */
452 struct ladtime start;
454 int ret; /* ret val == call success */
456 op_ptr = &Ops[READLINK];
459 /* set up the arguments */
461 * Note: this fh may be bogus because SYMLINK does
462 * not return a fh ... only a status. So unless we have
463 * done a LOOKUP on this guy, the fh will probably be bad.
464 * If it is bad it shows up as a symlink error in the results.
466 (void) memmove((char *) &fh, (char *) &Cur_file_ptr->fh2,
469 /* Have lower layers fill in the data directly. */
470 reply.readlinkres_u.data = sym_data;
473 /* make the call now */
475 rpc_stat = clnt_call(NFS_client, NFSPROC_READLINK,
476 xdr_readlink, (char *) &fh,
477 xdr_readlink, (char *) &reply,
478 (Current_test_phase < Warmup_phase)
480 : Nfs_timers[op_ptr->call_class]);
484 if (rpc_stat == RPC_SUCCESS) {
485 if (reply.status == NFS_OK) {
486 if (DEBUG_CHILD_RPC) {
487 len = reply.readlinkres_u.len;
488 sym_data[len] = '\0';
489 (void) fprintf(stderr, "%s: READLINK on %s returned %s\n",
490 sfs_Myname, Cur_filename, sym_data);
491 (void) fflush(stderr);
494 if (DEBUG_CHILD_ERROR) {
495 (void) fprintf(stderr,
496 "%s: readlink call NFS error %s on file %d\n",
497 sfs_Myname, nfs2_strerror(reply.status),
498 Cur_file_ptr->unique_num);
501 sfs_elapsedtime(op_ptr, &start, &stop);
502 op_ptr->results.good_calls++;
503 Ops[TOTAL].results.good_calls++;
506 if (DEBUG_CHILD_ERROR) {
507 (void) fprintf(stderr,
508 "%s: readlink call RPC error %d on file %d\n",
509 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
511 op_ptr->results.bad_calls++;
512 Ops[TOTAL].results.bad_calls++;
520 * perform an RPC read operation of length 'xfer_size'
526 sfs_op_type *op_ptr; /* per operation info */
528 int max_cnt; /* packet ctrs */
529 char buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
531 readres reply; /* the reply */
532 enum clnt_stat rpc_stat; /* result from RPC call */
533 struct ladtime start;
537 int ret; /* ret val == call success */
542 /* set up the arguments */
543 (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh2,
547 * Don't allow a read of less than one block size
549 if (xfer_size < Bytes_per_block)
550 xfer_size = Bytes_per_block;
553 * randomly choose an offset that is a multiple of the block size
554 * and constrained by making the transfer fit within the file
556 if (Cur_file_ptr->attributes2.size > xfer_size) {
557 args.offset = Bytes_per_block * (sfs_random() %
558 (((Cur_file_ptr->attributes2.size - xfer_size)
559 / Bytes_per_block) + 1));
563 /* first read the whole buffers, then the fragment */
564 for (j = 0; j < 2; j++) {
567 size = Bytes_per_block;
568 max_cnt = xfer_size / Bytes_per_block;
570 /* 1KB - (Kb_per_block -1) KB fragment */
571 size = xfer_size % Bytes_per_block;
577 /* check our stats to see if this would overflow */
579 if (op_ptr->target_calls > 0) {
580 if ((op_ptr->results.good_calls + max_cnt)
581 > op_ptr->target_calls) {
582 max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
588 args.totalcount = size; /* unused */
590 /* Have lower layers fill in the data directly. */
591 reply.readres_u.reply.data.data_val = buf;
593 if (DEBUG_CHILD_RPC) {
594 (void) fprintf(stderr, "read: %d buffers\n", max_cnt);
595 (void) fflush(stderr);
598 /* make the call(s) now */
599 for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
601 /* capture length for possible dump */
602 Dump_length = fh_size(Cur_file_ptr);
605 rpc_stat = clnt_call(NFS_client, NFSPROC_READ,
606 xdr_read, (char *) &args,
607 xdr_read, (char *) &reply,
608 (Current_test_phase < Warmup_phase)
610 : Nfs_timers[op_ptr->call_class]);
614 /* capture count and offset for possible dump */
615 Dump_count = (rpc_stat == RPC_SUCCESS && reply.status == NFS_OK)
616 ? reply.readres_u.reply.data.data_len : 0;
617 Dump_offset = args.offset;
619 if (rpc_stat == RPC_SUCCESS) {
620 if (reply.status == NFS_OK) {
621 Cur_file_ptr->state = Exists;
622 Cur_file_ptr->attributes2 =
623 reply.readres_u.reply.attributes;
624 Cur_file_ptr->size = fh_size(Cur_file_ptr);
625 size = reply.readres_u.reply.data.data_len;
627 if (DEBUG_CHILD_RPC) {
628 (void) fprintf(stderr, "%s: READ %s %d bytes\n",
629 sfs_Myname, Cur_filename, size);
630 (void) fflush(stderr);
634 if (DEBUG_CHILD_ERROR) {
635 (void) fprintf(stderr,
636 "%s: read call NFS error %s on file %d\n",
637 sfs_Myname, nfs2_strerror(reply.status),
638 Cur_file_ptr->unique_num);
641 sfs_elapsedtime(op_ptr, &start, &stop);
642 op_ptr->results.good_calls++;
643 Ops[TOTAL].results.good_calls++;
646 if (DEBUG_CHILD_ERROR) {
647 (void) fprintf(stderr,
648 "%s: read call RPC error %d on file %d\n",
649 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
651 op_ptr->results.bad_calls++;
652 Ops[TOTAL].results.bad_calls++;
654 } /* for reading max_cnt packets */
655 } /* for buffers and fragments */
666 static uint32_t write_buf[DEFAULT_MAX_BUFSIZE / sizeof(uint32_t)];
667 uint32_t *be = write_buf + (sizeof(write_buf) /
670 if (write_buf[0] != (uint32_t)0xdeadbeef) {
671 for (bp = write_buf; bp < be; bp++)
672 *bp = (uint32_t)0xdeadbeef;
674 return (char *)write_buf;
678 * Perform and RPC write operation of length 'xfer_size'. If 'append_flag'
679 * is true, then write the data to the end of the file.
688 sfs_op_type *op_ptr; /* per operation info */
689 static char *buf = NULL; /* the data buffer */
690 int size; /* size of data write */
691 int cur_cnt; /* controls # NFS calls */
694 attrstat reply; /* the reply */
695 enum clnt_stat rpc_stat; /* result from RPC call */
696 struct ladtime start;
699 int ret; /* ret val == call success */
702 * Initialize write buffer to known value
705 buf = init_write_buffer();
707 op_ptr = &Ops[WRITE];
710 /* set up the arguments */
711 (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh2,
713 args.beginoffset = 0; /* unused */
715 if (append_flag == 1) {
716 args.offset = Cur_file_ptr->attributes2.size;
719 * randomly choose an offset that is a multiple of the block size
720 * and constrained by making the transfer fit within the file
722 if (Cur_file_ptr->attributes2.size > xfer_size) {
723 args.offset = Bytes_per_block * (sfs_random() %
724 (((Cur_file_ptr->attributes2.size - xfer_size)
725 / Bytes_per_block) + 1));
730 /* first write the whole buffers, then the fragment */
731 for (j = 0; j < 2; j++) {
734 size = Bytes_per_block;
735 max_cnt = xfer_size / Bytes_per_block;
737 /* 1KB - (Kb_per_block - 1) KB fragment */
738 size = xfer_size % Bytes_per_block;
744 args.totalcount = size; /* unused */
745 args.data.data_len = size;
746 args.data.data_val = buf;
748 /* check our stats to see if this would overflow */
750 if (op_ptr->target_calls > 0) {
751 if ((op_ptr->results.good_calls + max_cnt)
752 > op_ptr->target_calls) {
753 max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
758 if (DEBUG_CHILD_RPC) {
759 (void) fprintf(stderr, "write: %d buffers\n", max_cnt);
760 (void) fflush(stderr);
763 /* make the call(s) now */
764 for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
766 /* capture length for possible dump */
767 Dump_length = fh_size(Cur_file_ptr);
770 rpc_stat = clnt_call(NFS_client, NFSPROC_WRITE,
771 xdr_write, (char *) &args,
772 xdr_write, (char *) &reply,
773 (Current_test_phase < Warmup_phase)
775 : Nfs_timers[op_ptr->call_class]);
779 /* capture count and offset for possible dump */
780 Dump_count = args.data.data_len;
781 Dump_offset = args.offset;
783 if (rpc_stat == RPC_SUCCESS) {
784 if (reply.status == NFS_OK) {
785 Cur_file_ptr->state = Exists;
786 Cur_file_ptr->attributes2 = reply.attrstat_u.attributes;
787 Cur_file_ptr->size = fh_size(Cur_file_ptr);
790 if (DEBUG_CHILD_RPC) {
791 (void) fprintf(stderr, "%s: WRITE %s %d bytes\n",
792 sfs_Myname, Cur_filename, size);
793 (void) fflush(stderr);
796 if (DEBUG_CHILD_ERROR) {
797 (void) fprintf(stderr,
798 "%s: write call NFS error %s on file %d\n",
799 sfs_Myname, nfs2_strerror(reply.status),
800 Cur_file_ptr->unique_num);
803 sfs_elapsedtime(op_ptr, &start, &stop);
804 op_ptr->results.good_calls++;
805 Ops[TOTAL].results.good_calls++;
808 if (DEBUG_CHILD_ERROR) {
809 (void) fprintf(stderr,
810 "%s: write call RPC error %d on file %d\n",
811 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
813 op_ptr->results.bad_calls++;
814 Ops[TOTAL].results.bad_calls++;
816 } /* for writing max_cnt packets */
817 } /* for buffers and fragments */
826 sfs_op_type *op_ptr; /* per operation info */
828 diropres reply; /* the reply */
829 enum clnt_stat rpc_stat; /* result from RPC call */
830 struct ladtime start;
832 int ret; /* ret val == call success */
834 op_ptr = &Ops[CREATE];
837 /* set up the arguments */
838 args.attributes.mode = (0100000 | 0666); /* 666 NFREG file */
839 args.attributes.uid = Cur_uid;
840 args.attributes.gid = Cur_gid;
841 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
842 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
843 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
844 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
845 args.attributes.size = 0;
846 (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh2,
848 args.where.name = Cur_filename;
850 /* make the call now */
852 rpc_stat = clnt_call(NFS_client, NFSPROC_CREATE,
853 xdr_create, (char *) &args,
854 xdr_create, (char *) &reply,
855 (Current_test_phase < Warmup_phase)
857 : Nfs_timers[op_ptr->call_class]);
861 if (rpc_stat == RPC_SUCCESS) {
862 if (reply.status == NFS_OK) {
863 Cur_file_ptr->state = Exists;
864 (void) memmove((char *) &Cur_file_ptr->fh2,
865 (char *) &reply.diropres_u.diropres.file,
867 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
868 Cur_file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
869 Cur_file_ptr->size = fh_size(Cur_file_ptr);
871 if (DEBUG_CHILD_ERROR) {
872 (void) fprintf(stderr,
873 "%s: create call NFS error %s on file %d\n",
874 sfs_Myname, nfs2_strerror(reply.status),
875 Cur_file_ptr->unique_num);
878 sfs_elapsedtime(op_ptr, &start, &stop);
879 op_ptr->results.good_calls++;
880 Ops[TOTAL].results.good_calls++;
883 if (DEBUG_CHILD_ERROR) {
884 (void) fprintf(stderr, "%s: create call RPC error %d on file %d\n",
885 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
887 op_ptr->results.bad_calls++;
888 Ops[TOTAL].results.bad_calls++;
898 sfs_op_type *op_ptr; /* per operation info */
900 nfsstat reply; /* the reply */
901 enum clnt_stat rpc_stat; /* result from RPC call */
902 struct ladtime start;
904 int ret; /* ret val == call success */
906 op_ptr = &Ops[REMOVE];
909 /* set up the arguments */
910 args.name = Cur_filename;
911 (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
914 /* make the call now */
916 rpc_stat = clnt_call(NFS_client, NFSPROC_REMOVE,
917 xdr_remove, (char *) &args,
918 xdr_remove, (char *) &reply,
919 (Current_test_phase < Warmup_phase)
921 : Nfs_timers[op_ptr->call_class]);
925 if (rpc_stat == RPC_SUCCESS) {
926 if (reply == NFS_OK) {
927 Cur_file_ptr->state = Nonexistent;
929 if (DEBUG_CHILD_ERROR) {
930 (void) fprintf(stderr,
931 "%s: remove call NFS error %s on file %d\n",
932 sfs_Myname, nfs2_strerror(reply),
933 Cur_file_ptr->unique_num);
936 sfs_elapsedtime(op_ptr, &start, &stop);
937 op_ptr->results.good_calls++;
938 Ops[TOTAL].results.good_calls++;
941 if (DEBUG_CHILD_ERROR) {
942 (void) fprintf(stderr, "%s: remove call RPC error %d on file %d\n",
943 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
945 op_ptr->results.bad_calls++;
946 Ops[TOTAL].results.bad_calls++;
956 sfs_op_type *op_ptr; /* per operation info */
957 sfs_fh_type *target_fileinfo_ptr; /* target name */
959 nfsstat reply; /* the reply */
960 enum clnt_stat rpc_stat; /* result from RPC call */
961 struct ladtime start;
963 int ret; /* ret val == call success */
965 op_ptr = &Ops[RENAME];
968 /* set up the arguments */
969 (void) memmove((char *) &args.from.dir, (char *) &Cur_file_ptr->dir->fh2,
971 (void) memmove((char *) &args.to.dir, (char *) &Cur_file_ptr->dir->fh2,
974 target_fileinfo_ptr = randfh(RENAME, 0, 0, Nonexistent,
977 args.from.name = Cur_file_ptr->file_name;
978 (void) sprintf(target_fileinfo_ptr->file_name, Filespec,
979 target_fileinfo_ptr->unique_num);
980 args.to.name = target_fileinfo_ptr->file_name;
982 /* make the call now */
984 rpc_stat = clnt_call(NFS_client, NFSPROC_RENAME,
985 xdr_rename, (char *) &args,
986 xdr_rename, (char *) &reply,
987 (Current_test_phase < Warmup_phase)
989 : Nfs_timers[op_ptr->call_class]);
993 if (rpc_stat == RPC_SUCCESS) {
994 if (reply == NFS_OK) {
995 target_fileinfo_ptr->state = Exists;
996 (void) memmove((char *) &target_fileinfo_ptr->fh2,
997 (char *) &Cur_file_ptr->fh2,
999 target_fileinfo_ptr->attributes2 = Cur_file_ptr->attributes2;
1000 target_fileinfo_ptr->size = Cur_file_ptr->size;
1001 Cur_file_ptr->state = Nonexistent;
1003 if (DEBUG_CHILD_ERROR) {
1004 (void) fprintf(stderr,
1005 "%s: rename call NFS error %s on file %d\n",
1006 sfs_Myname, nfs2_strerror(reply),
1007 Cur_file_ptr->unique_num);
1010 sfs_elapsedtime(op_ptr, &start, &stop);
1011 op_ptr->results.good_calls++;
1012 Ops[TOTAL].results.good_calls++;
1015 if (DEBUG_CHILD_ERROR) {
1016 (void) fprintf(stderr, "%s: rename call RPC error %d on file %d\n",
1017 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1019 op_ptr->results.bad_calls++;
1020 Ops[TOTAL].results.bad_calls++;
1030 sfs_op_type *op_ptr; /* per operation info */
1031 sfs_fh_type *target_fileinfo_ptr; /* target */
1033 nfsstat reply; /* the reply */
1034 enum clnt_stat rpc_stat; /* result from RPC call */
1035 struct ladtime start;
1036 struct ladtime stop;
1037 int ret; /* ret val == call success */
1039 op_ptr = &Ops[LINK];
1042 /* set up the arguments */
1043 target_fileinfo_ptr = randfh(LINK, 0, 0, Exists, Sfs_non_io_file);
1044 (void) memmove((char *) &args.from, (char *) &target_fileinfo_ptr->fh2,
1046 (void) memmove((char *) &args.to.dir, (char *) &Cur_file_ptr->dir->fh2,
1048 args.to.name = Cur_filename;
1050 /* make the call now */
1051 sfs_gettime(&start);
1052 rpc_stat = clnt_call(NFS_client, NFSPROC_LINK,
1053 xdr_link, (char *) &args,
1054 xdr_link, (char *) &reply,
1055 (Current_test_phase < Warmup_phase)
1057 : Nfs_timers[op_ptr->call_class]);
1061 if (rpc_stat == RPC_SUCCESS) {
1062 if (reply == NFS_OK) {
1063 Cur_file_ptr->state = Exists;
1064 (void) memmove((char *) &Cur_file_ptr->fh2,
1065 (char *) &target_fileinfo_ptr->fh2, NFS_FHSIZE);
1066 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
1067 target_fileinfo_ptr->attributes2.nlink++;
1068 Cur_file_ptr->attributes2 = target_fileinfo_ptr->attributes2;
1069 Cur_file_ptr->size = fh_size(Cur_file_ptr);
1071 if (DEBUG_CHILD_ERROR) {
1072 (void) fprintf(stderr,
1073 "%s: link call NFS error %s on file %d\n",
1074 sfs_Myname, nfs2_strerror(reply),
1075 Cur_file_ptr->unique_num);
1078 sfs_elapsedtime(op_ptr, &start, &stop);
1079 op_ptr->results.good_calls++;
1080 Ops[TOTAL].results.good_calls++;
1083 if (DEBUG_CHILD_ERROR) {
1084 (void) fprintf(stderr, "%s: link call RPC error %d on file %d\n",
1085 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1087 op_ptr->results.bad_calls++;
1088 Ops[TOTAL].results.bad_calls++;
1098 sfs_op_type *op_ptr; /* per operation info */
1099 sfs_fh_type *target_fileinfo_ptr; /* target file */
1101 nfsstat reply; /* the reply */
1102 char sym_data[NFS_MAXPATHLEN]; /* symlink data */
1103 enum clnt_stat rpc_stat; /* result from RPC call */
1104 struct ladtime start;
1105 struct ladtime stop;
1106 int ret; /* ret val == call success */
1108 op_ptr = &Ops[SYMLINK];
1111 /* set up the arguments */
1112 target_fileinfo_ptr = randfh(SYMLINK, 0, 0, Exists, Sfs_non_io_file);
1113 (void) memmove((char *) &args.from.dir, (char *) &Cur_file_ptr->dir->fh2,
1115 args.from.name = Cur_filename;
1117 (void) strcpy(sym_data, "./");
1118 (void) strcat(sym_data, target_fileinfo_ptr->file_name);
1119 args.attributes.size = strlen(sym_data);
1122 args.attributes.mode = (0120000 | 0777);
1123 args.attributes.uid = Cur_uid;
1124 args.attributes.gid = Cur_gid;
1125 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
1126 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
1127 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
1128 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
1130 /* make the call now */
1131 sfs_gettime(&start);
1132 rpc_stat = clnt_call(NFS_client, NFSPROC_SYMLINK,
1133 xdr_symlink, (char *) &args,
1134 xdr_symlink, (char *) &reply,
1135 ((int)Current_test_phase < (int)Warmup_phase)
1137 : Nfs_timers[op_ptr->call_class]);
1141 if (rpc_stat == RPC_SUCCESS) {
1142 if (reply == NFS_OK) {
1144 * SYMLINK doesn't return a fh. If we try to
1145 * access this symlink (eg, remove(), readlink())
1146 * before we do a lookup, we won't have a fh to use.
1147 * So, we do a lookup call here.
1148 * If it fails, we fill in what we can.
1150 Cur_file_ptr->state = Exists;
1151 if (op_lookup() == 0) {
1152 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
1153 Cur_file_ptr->attributes2.type = NFLNK;
1154 Cur_file_ptr->attributes2.mode = (0120000|0777);
1155 Cur_file_ptr->attributes2.uid = Cur_uid;
1156 Cur_file_ptr->attributes2.gid = Cur_gid;
1157 Cur_file_ptr->attributes2.atime.seconds =(unsigned int)Cur_time.esec;
1158 Cur_file_ptr->attributes2.atime.useconds=(unsigned int)Cur_time.usec;
1159 Cur_file_ptr->attributes2.mtime = Cur_file_ptr->attributes2.atime;
1163 if (DEBUG_CHILD_ERROR) {
1164 (void) fprintf(stderr,
1165 "%s: symlink call NFS error %s on file %d\n",
1166 sfs_Myname, nfs2_strerror(reply),
1167 Cur_file_ptr->unique_num);
1170 sfs_elapsedtime(op_ptr, &start, &stop);
1171 op_ptr->results.good_calls++;
1172 Ops[TOTAL].results.good_calls++;
1175 if (DEBUG_CHILD_ERROR) {
1176 (void) fprintf(stderr, "%s: symlink call RPC error %d on file %d\n",
1177 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1179 op_ptr->results.bad_calls++;
1180 Ops[TOTAL].results.bad_calls++;
1190 sfs_op_type *op_ptr; /* per operation info */
1192 diropres reply; /* the reply */
1193 enum clnt_stat rpc_stat; /* result from RPC call */
1194 struct ladtime start;
1195 struct ladtime stop;
1196 int ret; /* ret val == call success */
1198 op_ptr = &Ops[MKDIR];
1201 /* set up the arguments */
1202 args.attributes.mode = (NFSMODE_DIR | 0777);
1203 args.attributes.uid = Cur_uid;
1204 args.attributes.gid = Cur_gid;
1205 args.attributes.size = (unsigned int) 512;
1206 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
1207 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
1208 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
1209 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
1210 (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh2,
1212 args.where.name = Cur_filename;
1214 /* make the call now */
1215 sfs_gettime(&start);
1216 rpc_stat = clnt_call(NFS_client, NFSPROC_MKDIR,
1217 xdr_mkdir, (char *) &args,
1218 xdr_mkdir, (char *) &reply,
1219 (Current_test_phase < Warmup_phase)
1221 : Nfs_timers[op_ptr->call_class]);
1225 if (rpc_stat == RPC_SUCCESS) {
1226 if (reply.status == NFS_OK) {
1227 Cur_file_ptr->state = Empty_dir;
1228 (void) memmove((char *) &Cur_file_ptr->fh2,
1229 (char *) &reply.diropres_u.diropres.file,
1231 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
1232 Cur_file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
1233 Cur_file_ptr->size = fh_size(Cur_file_ptr);
1235 if (DEBUG_CHILD_ERROR) {
1236 (void) fprintf(stderr,
1237 "%s: mkdir call NFS error %s on file %d\n",
1238 sfs_Myname, nfs2_strerror(reply.status),
1239 Cur_file_ptr->unique_num);
1242 sfs_elapsedtime(op_ptr, &start, &stop);
1243 op_ptr->results.good_calls++;
1244 Ops[TOTAL].results.good_calls++;
1247 if (DEBUG_CHILD_ERROR) {
1248 (void) fprintf(stderr, "%s: mkdir call RPC error %d on file %d\n",
1249 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1251 op_ptr->results.bad_calls++;
1252 Ops[TOTAL].results.bad_calls++;
1262 sfs_op_type *op_ptr; /* per operation info */
1264 nfsstat reply; /* the reply */
1265 enum clnt_stat rpc_stat; /* result from RPC call */
1266 struct ladtime start;
1267 struct ladtime stop;
1268 int ret; /* ret val == call success */
1270 op_ptr = &Ops[RMDIR];
1273 if (Cur_file_ptr->state != Empty_dir) {
1274 (void) fprintf(stderr, "%s: Attempting to remove non-Empty_dir %d\n",
1275 sfs_Myname, Cur_file_ptr->unique_num);
1278 /* set up the arguments */
1279 (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
1281 args.name = Cur_file_ptr->file_name;
1283 /* make the call now */
1284 sfs_gettime(&start);
1285 rpc_stat = clnt_call(NFS_client, NFSPROC_RMDIR,
1286 xdr_rmdir, (char *) &args,
1287 xdr_rmdir, (char *) &reply,
1288 (Current_test_phase < Warmup_phase)
1290 : Nfs_timers[op_ptr->call_class]);
1294 if (rpc_stat == RPC_SUCCESS) {
1295 if (reply == NFS_OK) {
1296 Cur_file_ptr->state = Nonexistent;
1298 if (DEBUG_CHILD_ERROR) {
1299 (void) fprintf(stderr,
1300 "%s: rmdir call NFS error %s on file %d\n",
1301 sfs_Myname, nfs2_strerror(reply),
1302 Cur_file_ptr->unique_num);
1305 sfs_elapsedtime(op_ptr, &start, &stop);
1306 op_ptr->results.good_calls++;
1307 Ops[TOTAL].results.good_calls++;
1310 if (DEBUG_CHILD_ERROR) {
1311 (void) fprintf(stderr, "%s: rmdir call RPC error %d on file %d\n",
1312 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1314 op_ptr->results.bad_calls++;
1315 Ops[TOTAL].results.bad_calls++;
1325 sfs_op_type *op_ptr; /* per operation info */
1327 readdirres reply; /* the reply */
1328 enum clnt_stat rpc_stat; /* result from RPC call */
1330 struct ladtime start;
1331 struct ladtime stop;
1332 int ret; /* ret val == call success */
1335 /* arbitrary fixed ceiling */
1336 int entry_cnt = SFS_MAXDIRENTS;
1337 /* array of entries */
1338 entry entry_stream[SFS_MAXDIRENTS];
1339 entry *entry_ptr; /* ptr to the dir entry */
1341 char name[SFS_MAXNAMLEN];
1342 /* array of dir names */
1343 char name_stream[SFS_MAXDIRENTS * SFS_MAXNAMLEN];
1347 * 1) need some measure of how many entries are in a directory
1348 * currently, we assume SFS_MAXDIRENTS - it should be random
1349 * from 0 to MAX for a large MAX we should pre-allocate a buffer for the
1350 * returned directory names.
1351 * 2) need some measure of how many directory entries to read
1352 * during each readdir() call. Again, we assume SFS_MAXDIRENTS.
1355 op_ptr = &Ops[READDIR];
1358 /* set up the arguments */
1359 (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
1361 (void) memset((char *) args.cookie, '\0', NFS_COOKIESIZE);
1362 args.count = DEFAULT_MAX_BUFSIZE;
1364 /* Have lower layers fill in the data directly. */
1365 reply.readdirres_u.reply.max_entries = entry_cnt;
1366 reply.readdirres_u.reply.entries = entry_stream;
1367 for (i = 0; i < entry_cnt; i++) {
1368 entry_stream[i].name = &name_stream[i * SFS_MAXNAMLEN];
1371 /* make the call now */
1372 sfs_gettime(&start);
1373 rpc_stat = clnt_call(NFS_client, NFSPROC_READDIR,
1374 xdr_readdir, (char *) &args,
1375 xdr_readdir, (char *) &reply,
1376 (Current_test_phase < Warmup_phase)
1378 : Nfs_timers[op_ptr->call_class]);
1382 if (rpc_stat == RPC_SUCCESS) {
1383 if (reply.status == NFS_OK) {
1385 if (DEBUG_CHILD_RPC) {
1386 hit_eof = reply.readdirres_u.reply.eof;
1387 entry_cnt = reply.readdirres_u.reply.max_entries;
1388 entry_ptr = reply.readdirres_u.reply.entries;
1389 for (i = 0; i < entry_cnt; i++) {
1390 entry_ptr->name[entry_ptr->name_len] ='\0';
1391 (void) strcpy(name, entry_ptr->name);
1392 (void) memmove((char *) cookie,
1393 (char *) entry_ptr->cookie,
1395 (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
1396 sfs_Myname, hit_eof, name);
1399 (void) fflush(stderr);
1402 if (DEBUG_CHILD_ERROR) {
1403 (void) fprintf(stderr,
1404 "%s: readdir call NFS error %s on file %d\n",
1405 sfs_Myname, nfs2_strerror(reply.status),
1406 Cur_file_ptr->unique_num);
1409 sfs_elapsedtime(op_ptr, &start, &stop);
1410 op_ptr->results.good_calls++;
1411 Ops[TOTAL].results.good_calls++;
1414 if (DEBUG_CHILD_ERROR) {
1415 (void) fprintf(stderr, "%s: readdir call RPC error %d on file %d\n",
1416 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1418 op_ptr->results.bad_calls++;
1419 Ops[TOTAL].results.bad_calls++;
1426 /* Beware - op_statfs() collides w/ some other name, use op_fsstat() */
1430 sfs_op_type *op_ptr; /* per operation info */
1432 statfsres reply; /* the reply */
1433 enum clnt_stat rpc_stat; /* result from RPC call */
1434 struct ladtime start;
1435 struct ladtime stop;
1436 int ret; /* ret val == call success */
1438 op_ptr = &Ops[FSSTAT];
1441 /* set up the arguments */
1442 (void) memmove((char *) &fh, (char *) &Cur_file_ptr->fh2,
1446 sfs_gettime(&start);
1447 rpc_stat = clnt_call(NFS_client, NFSPROC_STATFS,
1448 xdr_statfs, (char *) &fh,
1449 xdr_statfs, (char *) &reply,
1450 (Current_test_phase < Warmup_phase)
1452 : Nfs_timers[op_ptr->call_class]);
1456 if (rpc_stat == RPC_SUCCESS) {
1457 sfs_elapsedtime(op_ptr, &start, &stop);
1458 op_ptr->results.good_calls++;
1459 Ops[TOTAL].results.good_calls++;
1462 if (DEBUG_CHILD_ERROR) {
1463 (void) fprintf(stderr, "%s: fsstat call RPC error %d on file %d\n",
1464 sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
1466 op_ptr->results.bad_calls++;
1467 Ops[TOTAL].results.bad_calls++;
1475 * These are a set of reliable functions used by the initialization code.
1478 #define LAD_RETRIABLE(stat) (((stat) == RPC_TIMEDOUT) || ((stat) == RPC_CANTDECODERES))
1481 * Reliably lookup a file in the current directory
1484 * 1 File doesn't exist
1488 lad_lookup(sfs_fh_type *file_ptr, char *name)
1491 diropres reply; /* the reply */
1492 enum clnt_stat rpc_stat; /* result from RPC call */
1494 if (DEBUG_CHILD_RPC) {
1495 (void) fprintf(stderr, "%s:lad_lookup: %lx[%lx] %s\n", sfs_Myname,
1496 (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
1497 (void) fflush(stderr);
1502 /* set up the arguments */
1503 (void) memmove((char *) &args.dir, (char *) &file_ptr->dir->fh2,
1508 rpc_stat = clnt_call(NFS_client, NFSPROC_LOOKUP,
1509 xdr_lookup, (char *) &args,
1510 xdr_lookup, (char *) &reply,
1513 if (rpc_stat == RPC_SUCCESS)
1515 if (rpc_stat != RPC_TIMEDOUT) {
1516 (void) fprintf(stderr, "lad_lookup(%s) RPC call failed : %s\n",
1517 name, clnt_sperrno(rpc_stat));
1519 if (!LAD_RETRIABLE(rpc_stat)) {
1524 if (reply.status == NFSERR_NOENT) {
1528 if (reply.status != NFS_OK) {
1529 (void) fprintf(stderr, "lad_lookup(%s) NFS call failed : %s\n",
1530 name, nfs2_strerror(reply.status));
1534 file_ptr->state = Exists;
1535 (void) memmove((char *) &file_ptr->fh2,
1536 (char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
1537 (void) strcpy(file_ptr->file_name, name);
1538 file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
1539 file_ptr->size = fh_size(file_ptr);
1545 * Reliably remove a file in the current directory
1548 lad_remove(sfs_fh_type *file_ptr, char *name)
1551 nfsstat reply; /* the reply */
1552 enum clnt_stat rpc_stat; /* result from RPC call */
1555 if (DEBUG_CHILD_RPC) {
1556 (void) fprintf(stderr, "%s:lad_remove: %lx[%lx] %s\n", sfs_Myname,
1557 (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
1558 (void) fflush(stderr);
1562 * This function presumes that the file name does exist
1564 if (file_ptr->attributes2.type == NFDIR)
1565 return (lad_rmdir(file_ptr, name));
1569 /* set up the arguments */
1571 (void) memmove((char *) &args.dir, (char *) &file_ptr->dir->fh2,
1574 /* make the call now */
1575 rpc_stat = clnt_call(NFS_client, NFSPROC_REMOVE,
1576 xdr_remove, (char *) &args,
1577 xdr_remove, (char *) &reply,
1580 if (rpc_stat == RPC_SUCCESS)
1582 if (rpc_stat != RPC_TIMEDOUT) {
1583 (void) fprintf(stderr, "lad_remove(%s) RPC call failed : %s\n",
1584 name, clnt_sperrno(rpc_stat));
1586 if (!LAD_RETRIABLE(rpc_stat)) {
1592 if (reply != NFS_OK) {
1593 if (reply != NFSERR_NOENT || !retried) {
1594 (void) fprintf(stderr, "lad_remove(%s) NFS call failed : %s\n",
1595 name, nfs2_strerror(reply));
1600 file_ptr->state = Nonexistent;
1606 * Reliably remove a directory in the current directory
1609 lad_rmdir(sfs_fh_type *file_ptr, char *name)
1612 nfsstat reply; /* the reply */
1613 enum clnt_stat rpc_stat; /* result from RPC call */
1616 if (DEBUG_CHILD_RPC) {
1617 (void) fprintf(stderr, "%s: lad_rmdir: %lx[%lx] %s\n", sfs_Myname,
1618 (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
1619 (void) fflush(stderr);
1623 * This function presumes that the file name does exist and the directory
1626 if (file_ptr->attributes2.type != NFDIR)
1627 return (lad_remove(file_ptr, name));
1631 /* set up the arguments */
1633 (void) memmove((char *) &args.dir, (char *) &file_ptr->dir->fh2,
1636 /* make the call now */
1637 rpc_stat = clnt_call(NFS_client, NFSPROC_RMDIR,
1638 xdr_remove, (char *) &args,
1639 xdr_remove, (char *) &reply,
1642 if (rpc_stat == RPC_SUCCESS)
1644 if (rpc_stat != RPC_TIMEDOUT) {
1645 (void) fprintf(stderr, "lad_rmdir(%s) RPC call failed : %s\n",
1646 name, clnt_sperrno(rpc_stat));
1648 if (!LAD_RETRIABLE(rpc_stat)) {
1654 if (reply != NFS_OK) {
1655 if (reply != NFSERR_NOENT || !retried) {
1656 (void) fprintf(stderr, "lad_rmdir(%s) NFS call failed : %s\n",
1657 name, nfs2_strerror(reply));
1662 file_ptr->state = Nonexistent;
1668 * Reliably create a symlink in the current directory
1671 lad_symlink(sfs_fh_type *file_ptr, char *target, char *name)
1674 nfsstat reply; /* the reply */
1675 char sym_data[NFS_MAXPATHLEN]; /* symlink data */
1676 enum clnt_stat rpc_stat; /* result from RPC call */
1679 if (DEBUG_CHILD_RPC) {
1680 (void) fprintf(stderr, "%s:lad_symlink: %lx %s -> %s\n", sfs_Myname,
1681 (int32_t) file_ptr, name, target);
1682 (void) fflush(stderr);
1686 * This function presumes that the file name does not already exist
1690 /* set up the arguments */
1691 (void) memmove((char *) &args.from.dir, (char *) &file_ptr->dir->fh2,
1693 args.from.name = name;
1695 (void) strcpy(sym_data, "./");
1696 (void) strcat(sym_data, target);
1697 args.attributes.size = strlen(sym_data);
1700 args.attributes.mode = (0120000 | 0777);
1701 args.attributes.uid = Cur_uid;
1702 args.attributes.gid = Cur_gid;
1703 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
1704 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
1705 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
1706 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
1708 /* make the call now */
1709 rpc_stat = clnt_call(NFS_client, NFSPROC_SYMLINK,
1710 xdr_symlink, (char *) &args,
1711 xdr_symlink, (char *) &reply,
1713 if (rpc_stat == RPC_SUCCESS)
1715 if (rpc_stat != RPC_TIMEDOUT) {
1716 (void) fprintf(stderr, "lad_symlink(%s) RPC call failed : %s\n",
1717 name, clnt_sperrno(rpc_stat));
1719 if (!LAD_RETRIABLE(rpc_stat)) {
1725 if (reply != NFS_OK) {
1726 if (reply != NFSERR_EXIST || !retried) {
1727 (void) fprintf(stderr, "lad_symlink(%s, %s) NFS call failed : %s\n",
1728 target, name, nfs2_strerror(reply));
1734 * SYMLINK doesn't return a fh. If we try to
1735 * access this symlink (eg, remove(), readlink())
1736 * before we do a lookup, we won't have a fh to use.
1737 * So, we do a lookup call here.
1738 * If it fails, we fill in what we can.
1740 return (lad_lookup(file_ptr, name));
1744 * Reliably create a directory in the current directory
1747 lad_mkdir(sfs_fh_type *file_ptr, char *name)
1750 diropres reply; /* the reply */
1751 enum clnt_stat rpc_stat; /* result from RPC call */
1754 if (DEBUG_CHILD_RPC) {
1755 (void) fprintf(stderr, "%s:lad_mkdir: %lx[%lx] %s\n", sfs_Myname,
1756 (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
1757 (void) fflush(stderr);
1761 * This function presumes that the file name does not already exist
1765 /* set up the arguments */
1766 args.attributes.mode = (NFSMODE_DIR | 0777);
1767 args.attributes.uid = Cur_uid;
1768 args.attributes.gid = Cur_gid;
1769 args.attributes.size = (unsigned int) 512;
1770 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
1771 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
1772 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
1773 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
1774 (void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh2,
1776 args.where.name = name;
1778 /* make the call now */
1779 rpc_stat = clnt_call(NFS_client, NFSPROC_MKDIR,
1780 xdr_mkdir, (char *) &args,
1781 xdr_mkdir, (char *) &reply,
1784 if (rpc_stat == RPC_SUCCESS)
1786 if (rpc_stat != RPC_TIMEDOUT) {
1787 (void) fprintf(stderr, "lad_mkdir(%s) RPC call failed : %s\n",
1788 name, clnt_sperrno(rpc_stat));
1790 if (!LAD_RETRIABLE(rpc_stat)) {
1796 if (!retried && reply.status == NFSERR_EXIST)
1799 if (reply.status != NFS_OK) {
1800 if (reply.status != NFSERR_EXIST || !retried) {
1801 (void) fprintf(stderr, "lad_mkdir(%s) NFS call failed : %s\n",
1802 name, nfs2_strerror(reply.status));
1806 * If the first mkdir suceeded but the reply as dropped and
1807 * was retransmitted, we still need to lookup the attributes
1809 if (lad_lookup(file_ptr, name))
1812 (void) memmove((char *) &file_ptr->fh2,
1813 (char *) &reply.diropres_u.diropres.file,
1815 (void) strcpy(file_ptr->file_name, name);
1816 file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
1817 file_ptr->size = fh_size(file_ptr);
1819 file_ptr->state = Empty_dir;
1825 * Reliably write a file in the current directory
1828 lad_write(sfs_fh_type *file_ptr, int32_t offset, int32_t length)
1830 static char *buf = NULL; /* the data buffer */
1831 int32_t size; /* size of data write */
1834 attrstat reply; /* the reply */
1835 enum clnt_stat rpc_stat; /* result from RPC call */
1837 if (DEBUG_CHILD_RPC) {
1838 (void) fprintf(stderr, "%s:lad_write: %lx[%lx] %ld %ld\n",
1839 sfs_Myname, (int32_t) file_ptr, (int32_t) file_ptr->dir,
1841 (void) fflush(stderr);
1845 * This function presumes that the file name does exist
1846 * Initialize write buffer to known value
1849 buf = init_write_buffer();
1852 /* set up the arguments */
1853 (void) memmove((char *) &args.file, (char *) &file_ptr->fh2,
1855 args.beginoffset = 0; /* unused */
1856 args.offset = offset;
1858 size = Bytes_per_block;
1859 for (cur_cnt = 0; cur_cnt < length; cur_cnt += size) {
1860 if ((cur_cnt + size) > length)
1861 size = length - cur_cnt;
1866 args.totalcount = size; /* unused */
1867 args.data.data_len = size;
1868 args.data.data_val = buf;
1870 /* make the call now */
1873 rpc_stat = clnt_call(NFS_client, NFSPROC_WRITE,
1874 xdr_write, (char *) &args,
1875 xdr_write, (char *) &reply,
1878 if (rpc_stat == RPC_SUCCESS)
1880 if (rpc_stat != RPC_TIMEDOUT) {
1881 (void) fprintf(stderr, "lad_write() RPC call failed : %s\n",
1882 clnt_sperrno(rpc_stat));
1884 if (!LAD_RETRIABLE(rpc_stat)) {
1888 if (reply.status != NFS_OK) {
1889 (void) fprintf(stderr, "lad_write() NFS call failed : %s\n",
1890 nfs2_strerror(reply.status));
1893 file_ptr->state = Exists;
1894 file_ptr->attributes2 = reply.attrstat_u.attributes;
1895 file_ptr->size = fh_size(file_ptr);
1896 args.offset += size;
1902 * Reliably create a file in the current directory
1905 lad_create(sfs_fh_type *file_ptr, char *name)
1908 diropres reply; /* the reply */
1909 enum clnt_stat rpc_stat; /* result from RPC call */
1912 if (DEBUG_CHILD_RPC) {
1913 (void) fprintf(stderr, "%s:lad_create: %lx[%lx] %s\n", sfs_Myname,
1914 (int32_t) file_ptr, (int32_t) file_ptr->dir, name);
1915 (void) fflush(stderr);
1919 * This function presumes that the file name does not already exist
1923 /* set up the arguments */
1924 args.attributes.mode = (0100000 | 0666); /* 666 NFREG file */
1925 args.attributes.uid = Cur_uid;
1926 args.attributes.gid = Cur_gid;
1927 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
1928 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
1929 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
1930 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
1931 args.attributes.size = 0;
1932 (void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh2,
1934 args.where.name = name;
1936 /* make the call now */
1937 rpc_stat = clnt_call(NFS_client, NFSPROC_CREATE,
1938 xdr_create, (char *) &args,
1939 xdr_create, (char *) &reply,
1942 if (rpc_stat == RPC_SUCCESS)
1944 if (rpc_stat != RPC_TIMEDOUT) {
1945 (void) fprintf(stderr, "lad_create(%s) RPC call failed : %s\n",
1946 name, clnt_sperrno(rpc_stat));
1948 if (!LAD_RETRIABLE(rpc_stat)) {
1954 if (!retried && reply.status == NFSERR_EXIST) {
1958 if (reply.status != NFS_OK) {
1959 if (reply.status != NFSERR_EXIST || !retried) {
1960 (void) fprintf(stderr, "lad_create(%s) NFS call failed : %s\n",
1961 name, nfs2_strerror(reply.status));
1965 * If the first create suceeded but the reply as dropped and
1966 * was retransmitted, we still need to lookup the attributes
1968 if (lad_lookup(file_ptr, name))
1971 (void) memmove((char *) &file_ptr->fh2,
1972 (char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
1973 (void) strcpy(file_ptr->file_name, name);
1974 file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
1975 file_ptr->size = fh_size(file_ptr);
1978 file_ptr->state = Exists;
1980 * Directories are created as Empty_dir, when a file is created it
1981 * becomes an Exists.
1983 file_ptr->dir->state = Exists;
1989 * Reliably set the size of a file in the current directory
1992 lad_truncate(sfs_fh_type *file_ptr, int32_t size)
1995 attrstat reply; /* the reply */
1996 enum clnt_stat rpc_stat; /* result from RPC call */
1998 if (DEBUG_CHILD_RPC) {
1999 (void) fprintf(stderr, "%s:lad_truncate: %lx[%lx] %ld\n", sfs_Myname,
2000 (int32_t) file_ptr, (int32_t) file_ptr->dir, size);
2001 (void) fflush(stderr);
2005 * This function presumes that the file name already exists
2010 * set up the arguments
2011 * Set the mode and times as well
2013 args.attributes.mode = 0666;
2014 args.attributes.uid = (unsigned int) -1;
2015 args.attributes.gid = (unsigned int) -1;
2016 args.attributes.size = (unsigned int) -1;
2017 args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
2018 args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
2019 args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
2020 args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
2021 (void) memmove((char *) &args.file, (char *) &file_ptr->fh2,
2023 args.attributes.size = (unsigned int) size;
2026 rpc_stat = clnt_call(NFS_client, NFSPROC_SETATTR,
2027 xdr_setattr, (char *) &args,
2028 xdr_setattr, (char *) &reply,
2031 if (rpc_stat == RPC_SUCCESS)
2033 if (rpc_stat != RPC_TIMEDOUT) {
2034 (void) fprintf(stderr,
2035 "lad_truncate(%ld) RPC call failed : %s\n",
2036 size, clnt_sperrno(rpc_stat));
2038 if (!LAD_RETRIABLE(rpc_stat)) {
2043 if (reply.status != NFS_OK) {
2044 (void) fprintf(stderr, "lad_truncate(%ld) NFS call failed : %s\n",
2045 size, nfs2_strerror(reply.status));
2048 file_ptr->attributes2 = reply.attrstat_u.attributes;
2049 file_ptr->size = fh_size(file_ptr);
2055 nfs2_strerror(int status)
2057 static char str[40];
2060 (void) strcpy(str, "no error");
2063 (void) strcpy(str, "Not owner");
2066 (void) strcpy(str, "No such file or directory");
2069 (void) strcpy(str, "I/O error");
2072 (void) strcpy(str, "No such device or address");
2075 (void) strcpy(str, "Permission denied");
2078 (void) strcpy(str, "File exists");
2081 (void) strcpy(str, "Cross-device link");
2084 (void) strcpy(str, "No such device");
2087 (void) strcpy(str, "Not a directory");
2090 (void) strcpy(str, "Is a directory");
2093 (void) strcpy(str, "Invalid argument");
2096 (void) strcpy(str, "File too large");
2099 (void) strcpy(str, "No space left on device");
2102 (void) strcpy(str, "Read-only file system");
2104 case NFSERR_OPNOTSUPP:
2105 (void) strcpy(str, "Operation not supported");
2107 case NFSERR_NAMETOOLONG:
2108 (void) strcpy(str, "File name too long");
2110 case NFSERR_NOTEMPTY:
2111 (void) strcpy(str, "Directory not empty");
2114 (void) strcpy(str, "Disc quota exceeded");
2117 (void) strcpy(str, "Stale NFS file handle");
2120 (void) strcpy(str, "Object is remote");
2123 (void) strcpy(str, "write cache flushed");
2126 (void) sprintf(str, "Unknown status %d", status);