From adc8816a09e5b6be2e58f4a7c28d2418a74cce9c Mon Sep 17 00:00:00 2001
From: Michael Vrable <mvrable@cs.ucsd.edu>
Date: Fri, 23 Apr 2010 12:48:14 -0700
Subject: [PATCH] Import TBBT (NFS trace replay).

Code downloaded from http://www.ecsl.cs.sunysb.edu/TBBT/.
---
 TBBT/README                            |   50 +
 TBBT/trace_init/EXAMPLES               |  170 ++
 TBBT/trace_init/INSTALL                |   61 +
 TBBT/trace_init/NOTES.TXT              |   17 +
 TBBT/trace_init/commands               |   20 +
 TBBT/trace_init/common.pl              |   61 +
 TBBT/trace_init/counts.pl              |  103 +
 TBBT/trace_init/extract-hierarchy      |    4 +
 TBBT/trace_init/hier.pl                |  715 +++++
 TBBT/trace_init/hier.pl.old            |  550 ++++
 TBBT/trace_init/key.pl                 |  122 +
 TBBT/trace_init/latency.pl             |  159 +
 TBBT/trace_init/nfsdump.pl             |  338 +++
 TBBT/trace_init/nfsscan.pl             |  682 +++++
 TBBT/trace_init/nfsscan.txt            |  230 ++
 TBBT/trace_init/ns_loc2gmt.pl          |  108 +
 TBBT/trace_init/ns_quickview.pl        |  245 ++
 TBBT/trace_init/ns_split.pl            |  153 +
 TBBT/trace_init/ns_timeagg.pl          |  218 ++
 TBBT/trace_init/ns_tsplit.pl           |  219 ++
 TBBT/trace_init/rfs.pl                 |  243 ++
 TBBT/trace_init/rfs.pl.old             |  138 +
 TBBT/trace_init/rfs.stub.pl            |  213 ++
 TBBT/trace_init/test.cnt               |    2 +
 TBBT/trace_init/test.fil               |    1 +
 TBBT/trace_init/userUtils.pl           |   87 +
 TBBT/trace_play/Makefile.org           |  328 ++
 TBBT/trace_play/README                 |   10 +
 TBBT/trace_play/README.old             |  140 +
 TBBT/trace_play/agefs                  |  Bin 0 -> 83979 bytes
 TBBT/trace_play/agefs.log              |   36 +
 TBBT/trace_play/frag_collect           |   15 +
 TBBT/trace_play/frag_collect_cust      |   14 +
 TBBT/trace_play/frag_count             |  Bin 0 -> 26012 bytes
 TBBT/trace_play/frag_count.c           |  311 ++
 TBBT/trace_play/fragment_collect       |   43 +
 TBBT/trace_play/generate_xmgr          |  Bin 0 -> 26083 bytes
 TBBT/trace_play/generate_xmgr.c        |  226 ++
 TBBT/trace_play/generate_xmgr.c.old    |   70 +
 TBBT/trace_play/generic_hash.c         |  230 ++
 TBBT/trace_play/generic_hash.h         |   24 +
 TBBT/trace_play/hash.h                 |   87 +
 TBBT/trace_play/init_holder.c          |   57 +
 TBBT/trace_play/nfsd_nfsfh_cust.h      |  114 +
 TBBT/trace_play/profile.c              |  215 ++
 TBBT/trace_play/profile.h              |   27 +
 TBBT/trace_play/rfs_3_ops.c            |  827 +++++
 TBBT/trace_play/rfs_3_ops.c.old        |  739 +++++
 TBBT/trace_play/rfs_assert.h           |   13 +
 TBBT/trace_play/rfs_c_age.c            | 1393 +++++++++
 TBBT/trace_play/rfs_c_age.c.trace_base |  551 ++++
 TBBT/trace_play/rfs_c_age.c.unit_base  |  915 ++++++
 TBBT/trace_play/rfs_c_age.obsolete.c   |  194 ++
 TBBT/trace_play/rfs_c_dat.c            |  188 ++
 TBBT/trace_play/rfs_c_def.h            |  357 +++
 TBBT/trace_play/rpc/auth.h             |  185 ++
 TBBT/trace_play/rpc/auth_none.c        |  154 +
 TBBT/trace_play/rpc/auth_unix.c        |  345 +++
 TBBT/trace_play/rpc/auth_unix.h        |   95 +
 TBBT/trace_play/rpc/authunix_prot.c    |   86 +
 TBBT/trace_play/rpc/bindresvport.c     |  103 +
 TBBT/trace_play/rpc/clnt.h             |  384 +++
 TBBT/trace_play/rpc/clnt_generic.c     |  133 +
 TBBT/trace_play/rpc/clnt_perror.c      |  316 ++
 TBBT/trace_play/rpc/clnt_simple.c      |  141 +
 TBBT/trace_play/rpc/clnt_tcp.c         |  522 ++++
 TBBT/trace_play/rpc/clnt_udp.c         |  510 ++++
 TBBT/trace_play/rpc/get_myaddress.c    |  169 ++
 TBBT/trace_play/rpc/getrpcent.c        |  250 ++
 TBBT/trace_play/rpc/getrpcport.c       |   77 +
 TBBT/trace_play/rpc/netdb.h            |   63 +
 TBBT/trace_play/rpc/osdep.h            |  218 ++
 TBBT/trace_play/rpc/pmap_clnt.c        |  138 +
 TBBT/trace_play/rpc/pmap_clnt.h        |   97 +
 TBBT/trace_play/rpc/pmap_getmaps.c     |  105 +
 TBBT/trace_play/rpc/pmap_getport.c     |  110 +
 TBBT/trace_play/rpc/pmap_prot.c        |   78 +
 TBBT/trace_play/rpc/pmap_prot.h        |  114 +
 TBBT/trace_play/rpc/pmap_prot2.c       |  138 +
 TBBT/trace_play/rpc/pmap_rmt.c         |  419 +++
 TBBT/trace_play/rpc/pmap_rmt.h         |   74 +
 TBBT/trace_play/rpc/rpc.h              |   93 +
 TBBT/trace_play/rpc/rpc_callmsg.c      |  214 ++
 TBBT/trace_play/rpc/rpc_commondata.c   |   62 +
 TBBT/trace_play/rpc/rpc_dtablesize.c   |  114 +
 TBBT/trace_play/rpc/rpc_msg.h          |  215 ++
 TBBT/trace_play/rpc/rpc_prot.c         |  307 ++
 TBBT/trace_play/rpc/sfs_ctcp.c         |  727 +++++
 TBBT/trace_play/rpc/sfs_cudp.c         |  604 ++++
 TBBT/trace_play/rpc/svc.c              |  479 +++
 TBBT/trace_play/rpc/svc.h              |  314 ++
 TBBT/trace_play/rpc/svc_auth.c         |  136 +
 TBBT/trace_play/rpc/svc_auth.h         |   62 +
 TBBT/trace_play/rpc/svc_auth_unix.c    |  156 +
 TBBT/trace_play/rpc/svc_raw.c          |  196 ++
 TBBT/trace_play/rpc/svc_run.c          |   93 +
 TBBT/trace_play/rpc/svc_simple.c       |  171 ++
 TBBT/trace_play/rpc/svc_tcp.c          |  481 +++
 TBBT/trace_play/rpc/svc_udp.c          |  507 ++++
 TBBT/trace_play/rpc/types.h            |  111 +
 TBBT/trace_play/rpc/xdr.c              |  685 +++++
 TBBT/trace_play/rpc/xdr.h              |  308 ++
 TBBT/trace_play/rpc/xdr_array.c        |  175 ++
 TBBT/trace_play/rpc/xdr_float.c        |  288 ++
 TBBT/trace_play/rpc/xdr_mem.c          |  205 ++
 TBBT/trace_play/rpc/xdr_rec.c          |  608 ++++
 TBBT/trace_play/rpc/xdr_reference.c    |  156 +
 TBBT/trace_play/rpc/xdr_stdio.c        |  210 ++
 TBBT/trace_play/sem.c                  |  149 +
 TBBT/trace_play/sfs.1                  |  842 ++++++
 TBBT/trace_play/sfs3.full_speed        |  Bin 0 -> 1004158 bytes
 TBBT/trace_play/sfs_2_ops.c            | 2131 +++++++++++++
 TBBT/trace_play/sfs_2_vld.c            | 1747 +++++++++++
 TBBT/trace_play/sfs_2_xdr.c            |  735 +++++
 TBBT/trace_play/sfs_3_ops.c            | 2746 +++++++++++++++++
 TBBT/trace_play/sfs_3_ops.c.org        | 2701 +++++++++++++++++
 TBBT/trace_play/sfs_3_vld.c            | 2126 +++++++++++++
 TBBT/trace_play/sfs_3_xdr.c            | 1720 +++++++++++
 TBBT/trace_play/sfs_c_bio.c            | 1023 +++++++
 TBBT/trace_play/sfs_c_bio.org          | 1012 +++++++
 TBBT/trace_play/sfs_c_chd.2thread.c    | 3509 ++++++++++++++++++++++
 TBBT/trace_play/sfs_c_chd.3thread.c    | 3815 ++++++++++++++++++++++++
 TBBT/trace_play/sfs_c_chd.c            |    1 +
 TBBT/trace_play/sfs_c_chd.c.old        | 2457 +++++++++++++++
 TBBT/trace_play/sfs_c_chd.c.old.2      | 2294 ++++++++++++++
 TBBT/trace_play/sfs_c_chd.c.org        | 2866 ++++++++++++++++++
 TBBT/trace_play/sfs_c_chd.work         | 3815 ++++++++++++++++++++++++
 TBBT/trace_play/sfs_c_clk.c            |  309 ++
 TBBT/trace_play/sfs_c_clnt.c           |  108 +
 TBBT/trace_play/sfs_c_dat.c            |  339 +++
 TBBT/trace_play/sfs_c_def.h            |  634 ++++
 TBBT/trace_play/sfs_c_dmp.c            |  298 ++
 TBBT/trace_play/sfs_c_man.c            | 1998 +++++++++++++
 TBBT/trace_play/sfs_c_mnt.c            |  573 ++++
 TBBT/trace_play/sfs_c_nfs.h            | 1470 +++++++++
 TBBT/trace_play/sfs_c_pnt.c            | 1163 ++++++++
 TBBT/trace_play/sfs_c_rnd.c            |  247 ++
 TBBT/trace_play/sfs_c_sig.c            |  170 ++
 TBBT/trace_play/sfs_c_sub.c            |  198 ++
 TBBT/trace_play/sfs_ext_mon            |   58 +
 TBBT/trace_play/sfs_m_def.h            |   59 +
 TBBT/trace_play/sfs_m_msg.c            |  103 +
 TBBT/trace_play/sfs_m_prm.c            | 1545 ++++++++++
 TBBT/trace_play/sfs_m_snc.c            |  456 +++
 TBBT/trace_play/sfs_m_xdr.c            |  103 +
 TBBT/trace_play/sfs_mcr                |  170 ++
 TBBT/trace_play/sfs_mgr                | 1093 +++++++
 TBBT/trace_play/sfs_rc                 |  149 +
 TBBT/trace_play/sfs_suchown            |   71 +
 TBBT/trace_play/sfs_sync.x             |   25 +
 TBBT/trace_play/t                      |  Bin 0 -> 11546 bytes
 TBBT/trace_play/t.c                    |    6 +
 152 files changed, 71768 insertions(+)
 create mode 100644 TBBT/README
 create mode 100755 TBBT/trace_init/EXAMPLES
 create mode 100755 TBBT/trace_init/INSTALL
 create mode 100755 TBBT/trace_init/NOTES.TXT
 create mode 100755 TBBT/trace_init/commands
 create mode 100755 TBBT/trace_init/common.pl
 create mode 100755 TBBT/trace_init/counts.pl
 create mode 100755 TBBT/trace_init/extract-hierarchy
 create mode 100755 TBBT/trace_init/hier.pl
 create mode 100755 TBBT/trace_init/hier.pl.old
 create mode 100755 TBBT/trace_init/key.pl
 create mode 100755 TBBT/trace_init/latency.pl
 create mode 100755 TBBT/trace_init/nfsdump.pl
 create mode 100755 TBBT/trace_init/nfsscan.pl
 create mode 100755 TBBT/trace_init/nfsscan.txt
 create mode 100755 TBBT/trace_init/ns_loc2gmt.pl
 create mode 100755 TBBT/trace_init/ns_quickview.pl
 create mode 100755 TBBT/trace_init/ns_split.pl
 create mode 100755 TBBT/trace_init/ns_timeagg.pl
 create mode 100755 TBBT/trace_init/ns_tsplit.pl
 create mode 100755 TBBT/trace_init/rfs.pl
 create mode 100755 TBBT/trace_init/rfs.pl.old
 create mode 100755 TBBT/trace_init/rfs.stub.pl
 create mode 100644 TBBT/trace_init/test.cnt
 create mode 100755 TBBT/trace_init/test.fil
 create mode 100755 TBBT/trace_init/userUtils.pl
 create mode 100644 TBBT/trace_play/Makefile.org
 create mode 100644 TBBT/trace_play/README
 create mode 100644 TBBT/trace_play/README.old
 create mode 100755 TBBT/trace_play/agefs
 create mode 100644 TBBT/trace_play/agefs.log
 create mode 100755 TBBT/trace_play/frag_collect
 create mode 100755 TBBT/trace_play/frag_collect_cust
 create mode 100755 TBBT/trace_play/frag_count
 create mode 100644 TBBT/trace_play/frag_count.c
 create mode 100755 TBBT/trace_play/fragment_collect
 create mode 100755 TBBT/trace_play/generate_xmgr
 create mode 100644 TBBT/trace_play/generate_xmgr.c
 create mode 100644 TBBT/trace_play/generate_xmgr.c.old
 create mode 100644 TBBT/trace_play/generic_hash.c
 create mode 100644 TBBT/trace_play/generic_hash.h
 create mode 100644 TBBT/trace_play/hash.h
 create mode 100644 TBBT/trace_play/init_holder.c
 create mode 100644 TBBT/trace_play/nfsd_nfsfh_cust.h
 create mode 100755 TBBT/trace_play/profile.c
 create mode 100755 TBBT/trace_play/profile.h
 create mode 100644 TBBT/trace_play/rfs_3_ops.c
 create mode 100644 TBBT/trace_play/rfs_3_ops.c.old
 create mode 100644 TBBT/trace_play/rfs_assert.h
 create mode 100644 TBBT/trace_play/rfs_c_age.c
 create mode 100644 TBBT/trace_play/rfs_c_age.c.trace_base
 create mode 100644 TBBT/trace_play/rfs_c_age.c.unit_base
 create mode 100644 TBBT/trace_play/rfs_c_age.obsolete.c
 create mode 100644 TBBT/trace_play/rfs_c_dat.c
 create mode 100644 TBBT/trace_play/rfs_c_def.h
 create mode 100755 TBBT/trace_play/rpc/auth.h
 create mode 100755 TBBT/trace_play/rpc/auth_none.c
 create mode 100755 TBBT/trace_play/rpc/auth_unix.c
 create mode 100755 TBBT/trace_play/rpc/auth_unix.h
 create mode 100755 TBBT/trace_play/rpc/authunix_prot.c
 create mode 100755 TBBT/trace_play/rpc/bindresvport.c
 create mode 100755 TBBT/trace_play/rpc/clnt.h
 create mode 100755 TBBT/trace_play/rpc/clnt_generic.c
 create mode 100755 TBBT/trace_play/rpc/clnt_perror.c
 create mode 100755 TBBT/trace_play/rpc/clnt_simple.c
 create mode 100755 TBBT/trace_play/rpc/clnt_tcp.c
 create mode 100755 TBBT/trace_play/rpc/clnt_udp.c
 create mode 100755 TBBT/trace_play/rpc/get_myaddress.c
 create mode 100755 TBBT/trace_play/rpc/getrpcent.c
 create mode 100755 TBBT/trace_play/rpc/getrpcport.c
 create mode 100755 TBBT/trace_play/rpc/netdb.h
 create mode 100755 TBBT/trace_play/rpc/osdep.h
 create mode 100755 TBBT/trace_play/rpc/pmap_clnt.c
 create mode 100755 TBBT/trace_play/rpc/pmap_clnt.h
 create mode 100755 TBBT/trace_play/rpc/pmap_getmaps.c
 create mode 100755 TBBT/trace_play/rpc/pmap_getport.c
 create mode 100755 TBBT/trace_play/rpc/pmap_prot.c
 create mode 100755 TBBT/trace_play/rpc/pmap_prot.h
 create mode 100755 TBBT/trace_play/rpc/pmap_prot2.c
 create mode 100755 TBBT/trace_play/rpc/pmap_rmt.c
 create mode 100755 TBBT/trace_play/rpc/pmap_rmt.h
 create mode 100755 TBBT/trace_play/rpc/rpc.h
 create mode 100755 TBBT/trace_play/rpc/rpc_callmsg.c
 create mode 100755 TBBT/trace_play/rpc/rpc_commondata.c
 create mode 100755 TBBT/trace_play/rpc/rpc_dtablesize.c
 create mode 100755 TBBT/trace_play/rpc/rpc_msg.h
 create mode 100755 TBBT/trace_play/rpc/rpc_prot.c
 create mode 100755 TBBT/trace_play/rpc/sfs_ctcp.c
 create mode 100755 TBBT/trace_play/rpc/sfs_cudp.c
 create mode 100755 TBBT/trace_play/rpc/svc.c
 create mode 100755 TBBT/trace_play/rpc/svc.h
 create mode 100755 TBBT/trace_play/rpc/svc_auth.c
 create mode 100755 TBBT/trace_play/rpc/svc_auth.h
 create mode 100755 TBBT/trace_play/rpc/svc_auth_unix.c
 create mode 100755 TBBT/trace_play/rpc/svc_raw.c
 create mode 100755 TBBT/trace_play/rpc/svc_run.c
 create mode 100755 TBBT/trace_play/rpc/svc_simple.c
 create mode 100755 TBBT/trace_play/rpc/svc_tcp.c
 create mode 100755 TBBT/trace_play/rpc/svc_udp.c
 create mode 100755 TBBT/trace_play/rpc/types.h
 create mode 100755 TBBT/trace_play/rpc/xdr.c
 create mode 100755 TBBT/trace_play/rpc/xdr.h
 create mode 100755 TBBT/trace_play/rpc/xdr_array.c
 create mode 100755 TBBT/trace_play/rpc/xdr_float.c
 create mode 100755 TBBT/trace_play/rpc/xdr_mem.c
 create mode 100755 TBBT/trace_play/rpc/xdr_rec.c
 create mode 100755 TBBT/trace_play/rpc/xdr_reference.c
 create mode 100755 TBBT/trace_play/rpc/xdr_stdio.c
 create mode 100644 TBBT/trace_play/sem.c
 create mode 100755 TBBT/trace_play/sfs.1
 create mode 100755 TBBT/trace_play/sfs3.full_speed
 create mode 100644 TBBT/trace_play/sfs_2_ops.c
 create mode 100644 TBBT/trace_play/sfs_2_vld.c
 create mode 100644 TBBT/trace_play/sfs_2_xdr.c
 create mode 100644 TBBT/trace_play/sfs_3_ops.c
 create mode 100644 TBBT/trace_play/sfs_3_ops.c.org
 create mode 100644 TBBT/trace_play/sfs_3_vld.c
 create mode 100644 TBBT/trace_play/sfs_3_xdr.c
 create mode 100644 TBBT/trace_play/sfs_c_bio.c
 create mode 100644 TBBT/trace_play/sfs_c_bio.org
 create mode 100644 TBBT/trace_play/sfs_c_chd.2thread.c
 create mode 100644 TBBT/trace_play/sfs_c_chd.3thread.c
 create mode 120000 TBBT/trace_play/sfs_c_chd.c
 create mode 100644 TBBT/trace_play/sfs_c_chd.c.old
 create mode 100644 TBBT/trace_play/sfs_c_chd.c.old.2
 create mode 100644 TBBT/trace_play/sfs_c_chd.c.org
 create mode 100644 TBBT/trace_play/sfs_c_chd.work
 create mode 100644 TBBT/trace_play/sfs_c_clk.c
 create mode 100644 TBBT/trace_play/sfs_c_clnt.c
 create mode 100644 TBBT/trace_play/sfs_c_dat.c
 create mode 100644 TBBT/trace_play/sfs_c_def.h
 create mode 100644 TBBT/trace_play/sfs_c_dmp.c
 create mode 100644 TBBT/trace_play/sfs_c_man.c
 create mode 100644 TBBT/trace_play/sfs_c_mnt.c
 create mode 100644 TBBT/trace_play/sfs_c_nfs.h
 create mode 100644 TBBT/trace_play/sfs_c_pnt.c
 create mode 100644 TBBT/trace_play/sfs_c_rnd.c
 create mode 100644 TBBT/trace_play/sfs_c_sig.c
 create mode 100644 TBBT/trace_play/sfs_c_sub.c
 create mode 100755 TBBT/trace_play/sfs_ext_mon
 create mode 100644 TBBT/trace_play/sfs_m_def.h
 create mode 100644 TBBT/trace_play/sfs_m_msg.c
 create mode 100644 TBBT/trace_play/sfs_m_prm.c
 create mode 100644 TBBT/trace_play/sfs_m_snc.c
 create mode 100644 TBBT/trace_play/sfs_m_xdr.c
 create mode 100755 TBBT/trace_play/sfs_mcr
 create mode 100755 TBBT/trace_play/sfs_mgr
 create mode 100755 TBBT/trace_play/sfs_rc
 create mode 100755 TBBT/trace_play/sfs_suchown
 create mode 100755 TBBT/trace_play/sfs_sync.x
 create mode 100755 TBBT/trace_play/t
 create mode 100644 TBBT/trace_play/t.c

diff --git a/TBBT/README b/TBBT/README
new file mode 100644
index 0000000..d2886cf
--- /dev/null
+++ b/TBBT/README
@@ -0,0 +1,50 @@
+1. TBBT Directory Structure
+
+# README:	this file. Introduce the TBBT directory and how to use TBBT.
+# trace_init: 	source code for extract file system hierarchy from the trace
+# trace_play: 	source code for trace player
+# test: 	example of play the EECS Oct 21 1 hour trace. It contains the
+#	      	original trace file: 		anon-lair62-011021-0000.txt
+#		file system hierarchy map: 	fh-path-map-play
+#		file system hierarchy:		RFSFS
+#
+
+2. How to use TBBT?
+
+#STEP1: compile the TBBT player, change the executable "sfs3" to be owned
+#       by root 
+
+cd ~nzhu/TBBT/trace_play
+make sfs3
+su - root; chown root:root tplay; exit
+
+#STEP2: copy or link trace file in a directory for trace play
+
+cd TESTDIR
+ln -s ../test/anon-lair62-011021-0000.txt anon-lair62-011021-0000.txt
+
+#STEP3: extract the file system hierarchy from the trace file
+#       There are two outputs: fh-path-map-play and RFSFS
+#	fh-path-map-play is the file system hierarchy map
+#	RFSFS is the actually file system hierarchy, instead of writing
+#       each file to the full length, -S option creates a file system 
+#	hierarchy where all files are of 0 length. This is useful when
+#	for experimental test run or debug run because writing all files
+#	to the full length could be time consuming.
+
+~nzhu/TBBT/trace_init/extract-hierarchy anon-lair62-011021-0000.txt [-S]
+
+#STEP4: copy RFSFS to an exported directory on NFS file server 
+
+scp -r RFSFS server:/export_dir/
+
+#STEP5: pair-up the request and reply packets in the trace. 
+#       The output file name is based on input file with suffix ".pair"
+#       in this example, anon-lair62-011021-0000.txt.pair
+
+sfs3 -pair_trace anon-lair62-011021-0000.txt
+
+
+#STEP6: play the trace against initial file system hierarchy (RFSFS) on server
+
+sfs3 hostname:/export_dir/RFSFS anon-lair62-011021-0000.txt.pair fh-path-map-play 1 0
diff --git a/TBBT/trace_init/EXAMPLES b/TBBT/trace_init/EXAMPLES
new file mode 100755
index 0000000..2ed5187
--- /dev/null
+++ b/TBBT/trace_init/EXAMPLES
@@ -0,0 +1,170 @@
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# $Id: EXAMPLES,v 1.3 2003/07/28 14:27:16 ellard Exp $
+#
+# For nfsscan version 0.10a (dated 7/25/2003).
+
+INTRODUCTION
+
+The usual procedure for analyzing a trace is the following:
+
+	1.  Use nfsscan to produce a tabularized summary of each
+		300-second segment of the trace.  For these examples,
+		we'll call this DEFAULT_TABLE.
+
+		Depending on what you're looking for, the default
+		settings of nfsscan might not provide all the info
+		you're going to want in the next step.  The default is
+		to omit per-client, per-user, per-group, and per-file
+		stats and only tally total operation counts.  [THE
+		DEFAULTS MAY CHANGE IN A FUTURE RELEASE.]
+
+	2.  Use ns_timeagg to create a summary of activity in the
+		entire trace named SUMMARY_TABLE from DEFAULT_TABLE.
+
+		Note that almost anything ns_timeagg and ns_split can
+		do can also be done directly with nfsscan.  However,
+		the implicit goal of ns_timeagg and ns_split is to
+		AVOID re-running nfsscan.  It is much faster to
+		re-process a table created by nfsscan than it is to
+		re-create the table -- the input to nfsscan is
+		typically several million (or billion) lines of trace
+		data, while the output is usually only a few thousand
+		table rows.
+
+	3.  Use ns_quickview to plot interesting aspects of the
+		DEFAULT_TABLE and/or SUMMARY_TABLE.
+
+	4.  [optional] Use ns_split and/or ns_tsplit to isolate
+		interesting parts of DEFAULT_TABLE (such as per-client
+		or per-user counts).  Repeat steps 2 and 3 with the
+		results.
+
+	5.  [optional] If steps 2-4 found anything interesting, re-run
+		nfsscan with new parameters to take a closer look at
+		the trace.
+
+Examples and discussion of these steps and related topics is given
+below.
+
+For these examples, TRACE is a trace file gathered by nfsdump (or
+another tool that creates traces files in the same format), and TABLE.ns
+is a file created by nfsscan from TRACE.  The suffix ".ns" is also
+used to denote files that contain tables created by nfsscan,
+ns_timeagg, ns_split, and ns_tsplit.  Example commandlines always
+begin with "%".
+
+1.  RUNNING NFSSCAN
+
+2.  CREATING A SUMMARY TABLE
+
+	To compute a table contsisting of a single row with counts for
+	each operation tallied by the nfsscan run, aggregate over time
+	with a time length of zero.  (Zero is treated as a special
+	time length that includes the entire input table.)
+
+	% ns_timeagg -t0 TABLE.ns > SUMMARY.ns
+
+	Note that timeagg will always aggregate over every (except
+	time) attribute, so it does not matter whether or not the
+	TABLE.ns contains per-client, per-user, per-group, or per-file
+	data.  The sum will always be the same.
+
+	On the other hand, if you want to prevent ns_timeagg from
+	aggregating over a particular attribute, specify that
+	attribute in the same manner as with nfsscan.  For example, to
+	create a table with a single row containing the operation
+	count per user:
+
+	% ns_timeagg -t0 -BU TABLE.ns > SUMMARY.ns
+
+	Of course, ns_timeagg cannot create data out of thin air.  If
+	TABLE.ns does not contain per-user information then -BU will
+	have no effect.
+
+3.  PLOTTING THE DATA
+
+	To simply plot the total operation count:
+
+	% ns_quickview TABLE.ns
+	% gv qv.ps
+
+WHICH CLIENT REQUESTS THE MOST OPERATIONS?
+
+Method:  use nfsscan to tally the per-client operation counts for the
+	entire trace file (by using -t0), and then sort by the TOTAL
+	op count fields:
+
+	If TABLE contains per-client information, then this is easy:
+
+	% ns_timeagg -t0 -BC TABLE | grep -v '^#' \
+			| awk '{print $7, $3}' | sort -nr
+
+	If TABLE does not contain per-client info, then it's necessary
+	to re-run nfsscan:
+
+	% nfsscan -t0 -BC TRACE | grep -v '^#' \
+			| awk '{print $7, $3}' | sort -nr
+
+	The output from either command is a two-column table.  The
+	first column is the total operation count of each client, and
+	the second column is the ID of each client.
+
+WHICH CLIENT DOES THE MOST READING?
+
+	If we've already got TABLE, and it contains per-client info,
+	then the easiest way is to simply use extract the read count
+	column (instead of the TOTAL column) from TABLE:
+
+	% ns_timeagg -t0 -BC TABLE | grep -v '^#' \
+			| awk '{print $9, $3}' | sort -nr
+
+	Or, we can nfsscan.  Because we're not interested in anything
+	except the read count, we can change the list of operations
+	that nfsscan tabulates so that it only counts reads.  (Of course,
+	the resulting table is useless for anything except answering
+	this particular question, and since nfsscan is expensive to run
+	this is probably wasteful.)
+
+	% nfsscan -t0 -BC -Oread -i TRACE | grep -v '^#' \
+			| awk '{print $7, $3}' | sort -nr
+
+WHICH CLIENT DOES THE MOST FSSTATS?
+
+	fsstat is not ordinarily tabulated by nfsscan.  To tell nfsscan
+	to keep track of it, we can change the list of operations to consist
+	only of fsstat:
+
+	% nfsscan -t0 -BC -Ofsstat -i TRACE | ...
+
+	As mentioned in the previous example, it is often wasteful to
+	run nfsscan just to get one number.  Another approach is to
+	add fsstat to the default list of "interesting" operations, by
+	using "+" at the start of the operation list.  This tells nfsscan
+	to append the given list of operations to the default list:
+
+	% nfsscan -t0 -BC -O+fsstat -i TRACE | ...
+
+	An implication of this is that it's impossible to know what
+	each column in the table represents unless you know what
+	operations were considered "interesting" for each run of
+	nfsscan.  To help with this, nfsscan includes the commandline
+	and column titles at the start of each file it creates.
+
+WHICH USER DOES THE MOST READING?
+
+	This is exactly like the previous example, except that we use
+	-BU instead -BC, to do everything per-user instead of
+	per-client.
+
+WHAT DIRECTORIES ARE HOTTEST?
+
+	Use the -d option to find the cummulative number of operations
+	per directory, then sort the results by operation count.  In
+	order to avoid drowning in data you might choose to print
+	print only the top 100:
+
+	% nfsscan -i TRACE -t0 -d | grep '^D' \
+			| awk '{print $7, $5}' | sort -nr | head -100
+
diff --git a/TBBT/trace_init/INSTALL b/TBBT/trace_init/INSTALL
new file mode 100755
index 0000000..6849497
--- /dev/null
+++ b/TBBT/trace_init/INSTALL
@@ -0,0 +1,61 @@
+# $Id: INSTALL,v 1.4 2003/07/28 14:27:16 ellard Exp $
+
+NFSSCAN INSTALLATION INSTRUCTIONS
+
+This is version 0.10a of nfsscan, dated 7/25/2003.
+
+THIS IS A PRELIMINARY RELEASE OF NEW SOFTWARE:
+
+- THE COMMANDLINE FORMATS MAY EVOLVE RAPIDLY OVER THE NEXT SEVERAL
+	RELEASES.
+
+- DEBUGGING MESSAGES AND WARNINGS MAY APPEAR ON STDERR.  MOST OF THESE
+	ARE MEANINGLESS, BUT IF YOU ENCOUNTER A PROBLEM WITH THE
+	PROGRAM PLEASE INCLUDE THEM IN YOUR BUG REPORT.
+ 
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+System Requirements:
+
+	- You must have PERL 5 (5.005 or later) installed in order to
+		use any of these tools.  (None of these tools have
+		been tested with PERL 6 or later.)
+
+	- If you plan to use ns_quickview, make sure that gnuplot is
+		installed on your system.
+		
+		ns_quickview has been tested with gnuplot 3.7 and
+		should work with later versions.  If you have problems
+		with ns_quickview, please include any diagnostics
+		messages from gnuplot and the version of gnuplot with
+		your bug report.
+
+		If gnuplot is not in your path, you must edit
+		ns_quickview to set GNUPLOT_PATH to the appropriate
+		path after step 2 in the installation instructions.
+
+Installation:
+
+1.  Un-tar the distribution into an empty directory.
+
+2.  Edit the first line of nfsscan and ns_* to point to wherever your
+	favorite version of PERL 5 is installed.  If you don't like
+	looking at debugging messages, remove the -w from the
+	invocation of PERL.
+
+3.  Make sure that nfsscan and ns_* are executable and that
+	all the files are publically readable:
+
+		chmod 444 *
+		chmod 555 nfsscan ns_*
+
+4.  Read NOTES.TXT for last-minute info or errata for this release,
+	and changes from previous releases.
+
+5.  Read nfsscan.txt and EXAMPLES for more information about how to
+	use the tools.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+PLEASE report bugs, problems or suggestions for improvements to
+ellard@eecs.harvard.edu.
diff --git a/TBBT/trace_init/NOTES.TXT b/TBBT/trace_init/NOTES.TXT
new file mode 100755
index 0000000..040500d
--- /dev/null
+++ b/TBBT/trace_init/NOTES.TXT
@@ -0,0 +1,17 @@
+# $Id: NOTES.TXT,v 1.2 2003/07/28 14:27:16 ellard Exp $
+
+NFSSCAN BUGS
+
+Known bugs for version 0.10a:
+
+- Debugging messages and warnings may appear on stderr.  Most of these
+	are meaningless, but if you encounter a problem with any of
+	the programs program please include them in your bug report.
+
+	Remove the -w from the invocation of PERL (on the first line
+	of each script) if you want to get rid of the PERL warnings.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+PLEASE report bugs, problems or suggestions for improvements to
+ellard@eecs.harvard.edu.
diff --git a/TBBT/trace_init/commands b/TBBT/trace_init/commands
new file mode 100755
index 0000000..e71f0b1
--- /dev/null
+++ b/TBBT/trace_init/commands
@@ -0,0 +1,20 @@
+#!/bin/bash -x
+
+# to locate a program
+GUNZIP=`whereis gunzip | gawk '{print $2}'`
+echo $GUNZIP
+
+# to run nfsscan
+gunzip -c traces/* | ./nfsscan -f -t0 -o result-total/test > result-total/output 2>&1
+gunzip -c ~traces/anon-lair62-011130-1100.txt.gz | ../nfsscan.pl > output 2>&1
+
+
+
+# post processing of nfsscan
+gawk '{if ($1=="F") print $2, $3, $5, $6 }' output  > output-filename
+gawk '{if ($3!=".") print $0 }' output-filename  > output-filename-known
+
+echo file#; gawk '{if ($1=="F") print $0}' output-filename-known | wc
+echo dir#; gawk '{if ($1=="D") print $0}' output-filename-known | wc
+echo active#; gawk '{if ($2=="A") print $0}' output-filename-known | wc
+echo dead#; gawk '{if ($2=="D") print $0}' output-filename-known | wc
diff --git a/TBBT/trace_init/common.pl b/TBBT/trace_init/common.pl
new file mode 100755
index 0000000..5959ee1
--- /dev/null
+++ b/TBBT/trace_init/common.pl
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: ns_timeagg,v 1.4 2003/07/10 20:13:31 ellard Exp $
+
+# Allows rounding of the start time, so that minor clock drift doesn't
+# make trace periods appear to begin at funny times (i.e.  one or two
+# seconds after midnight, instead of midnight).
+#
+# This is only meant to help with SMALL amounts of drift.  Trying to
+# use this to correct for anything more than a small fraction of the
+# sample interval is asking for trouble.
+
+require 'timelocal.pl';
+
+sub findStartTime {
+	my ($time, $rounding) = @_;
+
+	my $new_time = int ($time);
+
+	if (defined $rounding && $rounding != 0) {
+		$rounding = int ($rounding);
+
+		my $leftover = $new_time % $rounding;
+
+		if ($leftover > $rounding / 2) {
+			$new_time += $rounding;
+		}
+
+		$new_time -= ($new_time % $rounding);
+	}
+
+	return $new_time;
+}
+
+1;
diff --git a/TBBT/trace_init/counts.pl b/TBBT/trace_init/counts.pl
new file mode 100755
index 0000000..33d7ad9
--- /dev/null
+++ b/TBBT/trace_init/counts.pl
@@ -0,0 +1,103 @@
+#
+# Copyright (c) 2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: counts.pl,v 1.9 2003/07/28 14:27:16 ellard Exp $
+
+package	counts;
+
+@OpList		= ();
+%KeysSeen	= ();
+
+%OpCounts	= ();
+
+sub init {
+	my (@oplist) = @_;
+
+	@OpList = @oplist;
+}
+
+sub printTitle {
+	my ($out) = @_;
+
+	my $str = "#C time client fh euid egid";
+
+	foreach my $op ( @OpList ) {
+		$str .= " $op";
+	}
+	$str .= "\n";
+
+	print $out $str;
+} 
+
+sub printOps {
+	my ($start_time, $out) = @_;
+	my ($k, $str, $op, $nk);
+
+	my @allkeys = sort keys %KeysSeen;
+
+	foreach $k ( @allkeys ) {
+		my $tot = "$k,TOTAL";
+
+		if ($main::OMIT_ZEROS &&
+			(! exists $OpCounts{$tot} || $OpCounts{$tot} == 0)) {
+			next;
+		}
+
+		$str = sprintf ("C %s %s", $start_time, &key::key2str ($k));
+
+		foreach $op ( @OpList ) {
+			$nk = "$k,$op";
+			if (exists $OpCounts{$nk}) {
+				if ($op eq 'readM' || $op eq 'writeM') {
+					$str .= sprintf (" %.3f",
+						$OpCounts{$nk} / (1024 * 1024));
+				}
+				else {
+					$str .= " $OpCounts{$nk}"
+				}
+			}
+			else {
+				$str .= " 0";
+			}
+		}
+		$str .= "\n";
+		print $out $str;
+	}
+}
+
+sub resetOpCounts {
+
+	# Clear the counts on everything we've seen.
+
+	foreach my $op ( keys %OpCounts ) {
+		$OpCounts{$op} = 0;
+	}
+}
+
+1;
+
diff --git a/TBBT/trace_init/extract-hierarchy b/TBBT/trace_init/extract-hierarchy
new file mode 100755
index 0000000..e6b2b9f
--- /dev/null
+++ b/TBBT/trace_init/extract-hierarchy
@@ -0,0 +1,4 @@
+#Usage extract-hierarchy trace_file [-S]
+#nfsscan $1
+echo nfsscan $1
+rfs.pl $2
diff --git a/TBBT/trace_init/hier.pl b/TBBT/trace_init/hier.pl
new file mode 100755
index 0000000..3e2ebfc
--- /dev/null
+++ b/TBBT/trace_init/hier.pl
@@ -0,0 +1,715 @@
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: hier.pl,v 1.14 2003/07/26 20:52:03 ellard Exp $
+#
+# hier.pl - Tools to map out the file system hierarchy.  This is
+# accomplished by snooping out the lookup calls.
+#
+# This is expensive because the hierarchy can require a LOT of space
+# to store for a large system with lots of files (especially if files
+# come and go).  Don't construct the hierarchy unless you want it --
+# and be prepared to prune it from time to time.
+
+package	hier;
+
+# Tables used by the outside world:
+
+%fh2Parent		= ();
+%fh2Name		= ();
+%fh2Attr		= ();
+%fh2AttrOrig		= ();
+%parent2fh		= ();
+
+#RFS: init FS
+%rootsName		= ();
+%discardFHs = ();
+%rootsFHs = ();
+#RFS: dependency table
+%fhCreate = ();
+
+%rfsAllFHs = ();
+%fhType = (); # we use %fhIsDir instead
+$rfsLineNum = 0;
+
+
+
+
+
+
+# Library-private tables and variables.
+
+%pendingCallsXIDnow	= ();
+%pendingCallsXIDfh	= ();
+%pendingCallsXIDname	= ();
+
+$nextPruneTime		= -1;
+$PRUNE_INTERVAL		= 5 * 60;	# Five minutes.
+
+sub processLine {
+	my ($line, $proto, $op, $xid, $client, $now, $response, $fh_type) = @_;
+
+	&addRfsAllFHs($line, $proto, $op, $uxid,
+				$now, $response, $fh_type);
+
+	if ($now > $nextPruneTime) {
+		&prunePending ($now - $PRUNE_INTERVAL);
+		$nextPruneTime = $now + $PRUNE_INTERVAL;
+	}
+
+	my $uxid = "$client-$xid";
+
+	# 'lookup', 'create', 'rename', 'delete',
+	# 'getattr', 'setattr'
+
+	#RFS: add mkdir/rmdir/symlink
+	if ( $op eq 'lookup' || $op eq 'create' || $op eq 'mkdir' || 
+	     ($op eq 'symlink' && ($proto eq 'C3' || $proto eq 'R3' ) ) ) {
+		return (&doLookup ($line, $proto, $op, $uxid,
+				$now, $response, $fh_type));
+	}
+	elsif ($op eq 'rename') {
+	}
+	elsif ($op eq 'remove' || $op eq 'rmdir') {
+		# RFS: why remove these entries? Just let them exist since 
+		# there is generation number available to distinguish btw removed dir/file 
+		# and new dir/file with the same inode number.
+		#return (&doRemove ($line, $proto, $op, $uxid,
+		#		$now, $response, $fh_type));
+	}
+	elsif ($op eq 'getattr' || $op eq 'read' || $op eq 'write'  ||
+	         ($op eq 'readlink' && ($proto eq 'C3' || $proto eq 'R3' ) ) ) {
+		return (&doGetAttr ($line, $proto, $op, $uxid,
+				$now, $response, $fh_type));
+	}
+	elsif ($op eq 'setattr') {
+	}
+}
+
+
+# get time stamp
+
+sub getTimeStamp{
+	my ($line) = @_;
+
+	if (! ($line =~ /^[0-9]/)) {
+		print "getTimeStamp return undef\n";
+		return undef;
+	}
+	else {
+		my @l = split (' ', $line, 2);
+		return $l[0];
+	}
+}
+
+sub addRfsAllFHs {
+	my ($line, $proto, $op, $uxid, $now, $response, $fh_type) = @_;
+
+	my $fh = undef;
+	
+	my $checkfh = undef;
+	$checkfh = nfsd::nfsDumpParseLineField ($line, 'fh');
+	if (defined $checkfh) {
+		$fh = nfsd::nfsDumpCompressFH ($fh_type, $checkfh);
+	}
+	
+	my $fh2 = undef;
+
+	if ($op eq 'rename' || $op eq 'link') {
+		$checkfh = nfsd::nfsDumpParseLineField ($line, 'fh2');
+		if (defined $checkfh) {
+			$fh2 = nfsd::nfsDumpCompressFH ($fh_type, $checkfh);
+		}	
+	}
+
+	if (defined $fh) {
+		# record the first appearance of the fh
+		if ( !exists  $rfsAllFHs{$fh} )  {
+			$rfsAllFHs{$fh} = $rfsLineNum ;
+		}
+	}
+
+	if (defined $fh2) {
+		if ( !exists  $rfsAllFHs{$fh2} ) {
+			$rfsAllFHs{$fh2} = $rfsLineNum;
+		}
+	}
+
+	return ;
+}
+
+
+sub doLookup {
+	my ($line, $proto, $op, $uxid, $now, $response, $fh_type) = @_;
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		my $tag = ($proto eq 'C3') ? 'name' : 'fn';
+		my $name = nfsd::nfsDumpParseLineField ($line, $tag);
+
+		# All directories have (at least) three names:  the
+		# given name, and "." and "..".  We're only interested
+		# in the given name.
+
+		if ($name eq '"."' || $name eq '".."') {
+			return ;
+		}
+
+		my $fh = nfsd::nfsDumpCompressFH ($fh_type,
+			nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+		$pendingCallsXIDnow{$uxid} = $now;
+		$pendingCallsXIDfh{$uxid} = $fh;
+		$pendingCallsXIDname{$uxid} = $name;
+	}
+	elsif ($proto eq 'R3' || $proto eq 'R2') {
+		if (! exists $pendingCallsXIDnow{$uxid}) {
+			return ;
+		}
+
+		my $pfh = $pendingCallsXIDfh{$uxid};
+		my $name = $pendingCallsXIDname{$uxid};
+
+		delete $pendingCallsXIDnow{$uxid};
+		delete $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDname{$uxid};
+
+		if ($response eq 'OK') {
+			my $cfh = nfsd::nfsDumpCompressFH ($fh_type,
+					nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+			my $type = nfsd::nfsDumpParseLineField ($line, 'ftype');
+
+			#if ($type == 2) 
+			{
+				$fhIsDir{$cfh} = $type;
+			}
+
+			# Original code
+			# $fh2Parent{$cfh} = $pfh;
+			# $fh2Name{$cfh} = $name;
+			# $parent2fh{"$pfh,$name"} = $cfh;
+			# RFS code: in case of the rename, we will record the name of the old name
+			$fh2Parent{$cfh} = $pfh;
+			if (! exists   $fh2Name{$cfh}) {
+				$fh2Name{$cfh} = $name;
+				$parent2fh{"$pfh,$name"} = $cfh;
+			} else {
+				# keep the old name in the fh2Name{$cfh}
+				# and we also add the newname and pfh mapping
+				#$fh2Name{$cfh} = $name;
+				$parent2fh{"$pfh,$name"} = $cfh;
+			}
+
+			my ($size, $mode, $atime, $mtime, $ctime, $nlink) =
+					nfsd::nfsDumpParseLineFields ($line,
+					'size', 'mode',
+					'atime', 'mtime', 'ctime', 'nlink');
+			my $ts = getTimeStamp($line);
+
+			# RFS: modify here to get/maintain more file attributes
+			# we can just check the ctime and compare it with trace-start-time
+			# to decide whether to create a file/diretory.
+			# atime - last access time of the file
+			# mtime - last modification time of the file
+			# ctime - last file status change time
+			
+			#$fh2Attr{$cfh} = "$size $mode $atime $mtime $ctime";
+			if  (! exists $fh2AttrOrig{$cfh} ) {
+				$fh2AttrOrig{$cfh} = "$size $mode $op $atime $mtime $ctime $nlink $ts";
+			}
+			$fh2Attr{$cfh} = "$size $mode $op $atime $mtime $ctime $nlink $ts";
+		}
+
+	}
+
+	return ;
+}
+
+sub doRemove {
+	my ($line, $proto, $op, $uxid, $now, $response, $fh_type) = @_;
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		my $tag = ($proto eq 'C3') ? 'name' : 'fn';
+		my $name = nfsd::nfsDumpParseLineField ($line, $tag);
+
+		# All directories have (at least) three names:  the
+		# given name, and "." and "..".  We're only interested
+		# in the given name.
+
+		if ($name eq '"."' || $name eq '".."') {
+			return ;
+		}
+
+		my $pfh = nfsd::nfsDumpCompressFH ($fh_type,
+			nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+		if (! exists $parent2fh{"$pfh,$name"}) {
+			return ;
+		}
+
+		$pendingCallsXIDnow{$uxid} = $now;
+		$pendingCallsXIDfh{$uxid} = $pfh;
+		$pendingCallsXIDname{$uxid} = $name;
+	}
+	elsif ($proto eq 'R3' || $proto eq 'R2') {
+		if (! exists $pendingCallsXIDnow{$uxid}) {
+			return ;
+		}
+
+		my $pfh = $pendingCallsXIDfh{$uxid};
+		my $name = $pendingCallsXIDname{$uxid};
+
+		delete $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDname{$uxid};
+		delete $pendingCallsXIDnow{$uxid};
+
+		if (! exists $parent2fh{"$pfh,$name"}) {
+			return ;
+		}
+
+		my $cfh = $parent2fh{"$pfh,$name"};
+
+		if ($response eq 'OK') {
+			if ($op eq 'remove') {
+				printFileInfo ($cfh, 'D');
+
+				delete $fh2Parent{$cfh};
+				delete $fh2Name{$cfh};
+				delete $fh2Attr{$cfh};
+				delete $fhs2AttrOrig{$cfg};
+				delete $parent2fh{"$pfh,$name"};
+			}
+		}
+	}
+
+	return ;
+}
+
+sub doGetAttr {
+	my ($line, $proto, $op, $uxid, $now, $response, $fh_type) = @_;
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		my $fh = nfsd::nfsDumpCompressFH ($fh_type,
+			nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+		#if (nfsd::nfsDumpParseLineField ($line, 'fh')
+		#		eq '00018961-57570100-d2440000-61890100') {
+		#	printf STDERR "Seen it ($op)\n";
+		#}
+
+		if (! defined $fh) {
+			return ;
+		}
+
+		$pendingCallsXIDnow{$uxid} = $now;
+		$pendingCallsXIDfh{$uxid} = $fh;
+# RFS debug code
+#my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+#if ($fh eq $wantfh) {
+#	print "JIAWU: doGetAttr call $wantfh\n";
+#}
+	}
+	else {
+		if (! exists $pendingCallsXIDnow{$uxid}) {
+			return ;
+		}
+
+		my $fh = $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDnow{$uxid};
+# RFS debug code
+#my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+#if ($fh eq $wantfh) {
+#	print "JIAWU: doGetAttr response $wantfh\n";
+#}
+
+		if ($response ne 'OK') {
+			return ;
+		}
+
+		my ($ftype) = nfsd::nfsDumpParseLineFields ($line, 'ftype');
+		if (!defined $ftype) {
+			print STDERR "BAD $line";
+			return ;
+		}
+
+		#if ($ftype == 2) 
+		{
+			$fhIsDir{$fh} = $ftype;
+		}
+
+		#RFS comment: here if fh is a directory, then it will not be add 
+		# in the two hash table %fh2Attr(%fh2AttrOrig) and %fh2Name
+		# if ($ftype != 1) {
+		#	return ;
+		#}
+		if ($ftype != 1) {
+			#return ;
+		}
+
+
+		my ($mode, $size, $atime, $mtime, $ctime, $nlink) =
+				nfsd::nfsDumpParseLineFields ($line,
+				'mode', 'size', 'atime', 'mtime', 'ctime', 'nlink');
+		my $ts = getTimeStamp($line);
+
+			# RFS: modify here to get/maintain more file attributes
+			# we can just check the ctime and compare it with trace-start-time
+			# to decide whether to create a file/diretory.
+			# atime - last access time of the file
+			# mtime - last modification time of the file
+			# ctime - last file status change time
+
+			# $fh2Attr{$fh} = "$size $mode $atime $mtime $ctime";
+
+			if  (! exists $fh2AttrOrig{$fh} ) {
+				$fh2AttrOrig{$fh} = "$size $mode $op $atime $mtime $ctime $nlink $ts";
+			}
+			$fh2Attr{$fh} = "$size $mode $op $atime $mtime $ctime $nlink $ts";
+	}
+}
+
+# Purge all the pending XID records dated earlier than $when (which is
+# typically at least $PRUNE_INTERVAL seconds ago).  This is important
+# because otherwise missing XID records can pile up, eating a lot of
+# memory. 
+  
+sub prunePending {
+	my ($when) = @_;
+
+	foreach my $uxid ( keys %pendingCallsXIDnow ) {
+		if ($pendingCallsXIDnow{$uxid} < $when) {
+# RFS debug code
+my $fh = $pendingCallsXIDfh{$uxid};
+my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+if ($fh eq $wantfh) {
+	print "JIAWU: prunePending $wantfh\n";
+}
+#enf RFS
+			delete $pendingCallsXIDnow{$uxid};
+		}
+	}
+
+	return ;
+}
+
+# Return as much of the path for the given fh as possible.  It may or
+# may not reach the root (or the mount point of the file system), but
+# right now we don't check.  Usually on busy systems the data is
+# complete enough so that most paths are complete back to the mount
+# point.
+
+sub findPath {
+	my ($fh) = @_;
+	my $isdir = 0;
+	my $cnt = 0;
+	my $MaxPathLen = 40;
+
+	if (exists $fhIsDir{$fh} && $fhIsDir{$fh}==2) {
+		$isdir = 1;
+	}
+
+	my @path = ();
+	while ($fh && exists $fh2Name{$fh}) {
+		unshift (@path, $fh2Name{$fh});
+
+		if ( ($fh2Name{$fh} ne '"RFSNN0"' ) ) {
+			if (! exists $fh2Parent{$fh}) {
+				print STDERR "$fh2Name{$fh} ";
+				if ( ($fh2Name{$fh} eq '"RFSNN0"' ) ) {
+					print STDERR "eq RFSNN0\n";
+				} else {
+					print STDERR "NOT eq RFSNN0\n";
+				}
+			}
+			if ($fh eq $fh2Parent{$fh}) {
+				unshift (@path, '(LOOP)');
+				last;
+			}
+		}
+
+		if ($cnt++ > $MaxPathLen) {
+			print STDERR "findPath: path too long (> $MaxPathLen)\n";
+			unshift (@path, '(TOO-LONG)');
+			last;
+		}
+
+		$fh = $fh2Parent{$fh};
+	}
+
+	# RFS: append the ~user (fh and !exists $fh2Name{$fh} and type is Directory)
+	if ($fh && !exists $fh2Name{$fh} && (exists $fhIsDir{$fh} && $fhIsDir{$fh}==2) ) {
+		if (exists $rootsName{$fh}) {
+			#print "JIAWU: $rootsName{$fh}\n";
+			unshift(@path, $rootsName{$fh});
+		} else {
+			print "JIAWU: WARNING! No rootsName for this fh: $fh\n";
+			unshift(@path, $fh);
+		}
+	} else {
+		if ($fh && !exists $fh2Name{$fh} && (!exists $fhIsDir{$fh} || (exists $fhIsDir{$fh} && $fhIsDir{$fh}!=2)) ) {
+			if (exists $discardFHs{$fh}) {
+				open NOATTRDIR, ">>noattrdirdiscard" || die "open noattrdirdiscard failed\n";
+				print NOATTRDIR "$fh DISCARD\n";
+				close NOATTRDIR;
+			} else {
+				# RFS: if a possible fh without attr and name, then regard it as a special root ~/RFSNN0
+				unshift(@path, '"RFSNN0"');
+				$fhIsDir{$fh}=2;
+				$fh2Name{$fh} = '"RFSNN0"';
+				$rootsName{$fh} = '"RFSNN0"';
+				open NOATTRDIR, ">>noattrdir-root";
+				print NOATTRDIR "$fh /RFSNN0/\n";
+				close NOATTRDIR;
+			}
+		}
+	}
+
+	
+	my $str = '';
+	$cnt = 0;
+	foreach my $p ( @path ) {
+		$p =~ s/^.//;
+		$p =~ s/.$//;
+		$str .= "/$p";
+		$cnt++;
+	}
+
+	if ($isdir) {
+		$str .= '/';
+	}
+
+	if ($cnt == 0) {
+		$str = '.';
+	}
+
+	return ($str, $cnt);
+}
+
+
+$total_unknown_fh = 0;
+$total_known_fh = 0;
+
+sub printAll {
+	my ($start_time, $out) = @_;
+
+	my %allfh = ();
+	my $fh;
+	my $u = 0;
+	my $k = 0;
+
+	# RFS print more information here
+	open (OUT_RFS, ">rfsinfo") ||
+		die "Can't create $OutFileBaseName.rfs.";
+		
+	foreach $fh ( keys %fh2Attr ) {
+		$allfh{$fh} = 1; 
+	}
+	foreach $fh ( keys %fh2Name ) {
+		$allfh{$fh} = 1; 
+	}
+
+	#RFS: before printFileInfo, name those roots' name
+
+	#RFS there are three kind of fh
+	# 1. fh/name paired (fh/attr must)
+	# 2. fh/attr but no fh/name: type file (discard related operations)
+	# 3. fh/attr but no fh/name: type dir (keep as persuedo root)
+	$u = $k = 0;
+	my $sn=1;
+	foreach $fh ( keys %allfh ) {
+		if (exists $fh2Parent{$fh} ) {
+			$k++;
+		}
+		else {
+			$u++;
+			my $type = (exists $fhIsDir{$fh} && $fhIsDir{$fh}==2) ? 'D' : 'F';
+			if ($type eq 'D') {
+				$rootsName{$fh} = sprintf("\"RFSNN%d\"", $sn++);
+				$rootsFHs{$fh} = 2;
+			}
+			else {
+				$discardFHs{$fh} = 1;
+			}
+		}
+	}
+	print OUT_RFS "#stat: fh with parent = $k, fh without parent = $u\n";
+	$u = keys %rootsFHs;
+	print OUT_RFS "#RFS: root fh list($u)\n";
+	foreach $fh (keys %rootsName) {
+		print OUT_RFS "#RFS: $rootsName{$fh} $fh\n";
+	}
+	$u = keys %discardFHs;
+	print OUT_RFS "#RFS: discard fh list($u)\n";
+	print OUT_RFS join("\n", keys %discardFHs, "");
+	
+
+	print $out "#F type state fh path pathcount attrOrig(size,mode,op,atime,mt,ct) attrLast(size,mode,op,at,mt,ct)\n";
+
+	print $out "#T starttime = $start_time\n";
+	foreach $fh ( keys %allfh ) {
+		printFileInfoOutputFile ($fh, 'A', $out);
+	}
+	
+	my $numfh2Name = keys %fh2Name;
+	my $numfh2Attr = keys %fh2Attr;
+	print OUT_RFS "fh2name has $numfh2Name, fh2Attr has $numfh2Attr\n";
+
+	
+	$u = $k = 0;
+	foreach $fh ( keys %allfh ) {
+		if ( exists $fh2Name{$fh} ) {$k++;}
+		else {$u++;}
+	}
+	print OUT_RFS "#stat: total fh with name = $k, without name = $u\n";
+
+	print OUT_RFS "#stat: finally, total known fh = $total_known_fh, unknown = $total_unknown_fh\n";
+
+# Note: fh with name (8303), fh without name (103)
+#          root fh list: 18
+#          discard fh list: 85
+#          known fh (8321): ( fh with name(8303) + root fh list (18) = 8321)
+#          unknown fh (85)
+#
+# All fh from the those data structures: 8321 + 85 = 8303+103
+# Or, in keys %allfh
+#
+# 
+	print OUT_RFS "#RFS\n";
+	close OUT_RFS;	
+
+	open (MISSED, ">missdiscardfh") ||
+			die "Can't create missdiscardfh.";
+	foreach $fh (keys %rfsAllFHs) {
+		if ( !exists $allfh{$fh} && 
+		     ( (defined $fh2Name{$fh}) && ($fh2Name{$fh} ne '"RFSNN0"')) ) {
+			print MISSED "$fh LN: $rfsAllFHs{$fh}\n"
+		}
+	}
+	close MISSED;
+
+# check for a special fh
+#my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+#if ($allfh{$wantfh} == 1) {
+#	print OUT_RFS "JIAWU: found $wantfh\n";
+#} else {
+#	print OUT_RFS "JIAWU: NOT found $wantfh\n";
+#}
+#foreach $fh ( keys %allfh ) {
+#	if ( $fh eq $wantfh ) {
+#		print OUT_RFS "JIAWU: found $wantfh\n";
+#		printFileInfoOutputFile ($fh, 'JIAWU', *OUT_RFS);
+#		last;
+#	}
+#}
+#print OUT_RFS "JIAWU: after \n";
+
+
+}
+
+sub printFileInfoOutputFile {
+	my ($fh, $state, $out) = @_;
+
+	my ($p, $c) = findPath ($fh);
+	
+	if ($c == 0) {$total_unknown_fh++;}
+	else {$total_known_fh++;}
+	
+	#my $type = (exists $fhIsDir{$fh} && $fhIsDir{$fh}==2) ? 'D' : 'F';
+	my $type = $fhIsDir{$fh};
+	if (!defined $type) 
+	{
+		print STDERR "unknown ftype(U) for fh: $fh\n"; 
+		$type = 'U';
+	}
+	my $attr = (exists $fh2Attr{$fh}) ?
+			$fh2Attr{$fh} : "-1 -1 -1 -1 -1 -1 -1 -1";
+	my $attrOrig = (exists $fh2AttrOrig{$fh}) ?
+			$fh2AttrOrig{$fh} : "-1 -1 -1 -1 -1 -1 -1 -1";
+
+	print $out "F $type $state $fh $p $c $attrOrig $attr\n";
+}
+
+sub printFileInfo {
+	my ($fh, $state) = @_;
+
+	my ($p, $c) = findPath ($fh);
+	
+	if ($c == 0) {$total_unknown_fh++;}
+	else {$total_known_fh++;}
+	
+	my $type = (exists $fhIsDir{$fh} && $fhIsDir{$fh}==2) ? 'D' : 'F';
+	my $attr = (exists $fh2Attr{$fh}) ?
+			$fh2Attr{$fh} : "-1 -1 -1 -1 -1 -1 -1 -1";
+	my $attrOrig = (exists $fh2AttrOrig{$fh}) ?
+			$fh2AttrOrig{$fh} : "-1 -1 -1 -1 -1 -1 -1 -1";
+
+	print "F $type $state $fh $p $c $attrOrig $attr\n";
+}
+
+#
+# The flow to create the dependency table
+# 
+# create(dirfh, name, attr) -->newfh, new attr
+# mkdir(dirfh, name, attr) -> newfh, new attr
+#
+# remove(dirfh, name) --> status
+# rmdir(dirfh, name) --> status
+# rename(dirfh, name, todirfh, toname) --> status
+#
+# link(newdirfh, newname, dirfh, name) --> status (newdir/newname=>dir/name)
+# syslink(newdirfh, newname, string) --> status (newdir/newname=>"string")
+# readlink(fh) --> string
+# lookup(dirfh, name) --> fh, attr
+# getattr(fh) --> attr
+# setattr(fh, attr) --> attr
+# read(fh, offset, count) -> attr, data
+# write(fh, offset, count, data) --> attr
+# readdir(dirfh, cookie, count) --> entries
+# statfs(fh) --> status
+#
+#
+#
+#
+# for each line the trace file: 
+# 	if (op == R2 or R3) continue; #skip the response line
+# 	switch (the op)
+# 	{
+#	# CREATION OPs:
+#	case create:
+# 	case remove:
+# 	# DELETE OPs:
+#	case mkdir:
+#	case rmdir:
+# 	# other OPs
+#
+#
+#
+#
+#
+1;
diff --git a/TBBT/trace_init/hier.pl.old b/TBBT/trace_init/hier.pl.old
new file mode 100755
index 0000000..b7f0cf4
--- /dev/null
+++ b/TBBT/trace_init/hier.pl.old
@@ -0,0 +1,550 @@
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: hier.pl,v 1.14 2003/07/26 20:52:03 ellard Exp $
+#
+# hier.pl - Tools to map out the file system hierarchy.  This is
+# accomplished by snooping out the lookup calls.
+#
+# This is expensive because the hierarchy can require a LOT of space
+# to store for a large system with lots of files (especially if files
+# come and go).  Don't construct the hierarchy unless you want it --
+# and be prepared to prune it from time to time.
+
+package	hier;
+
+# Tables used by the outside world:
+
+%fh2Parent		= ();
+%fh2Name		= ();
+%fh2Attr		= ();
+%fh2AttrOrig		= ();
+%parent2fh		= ();
+#RFS
+%rootsName		= ();
+%discardFHs = ();
+%rootsFHs = ();
+
+
+# Library-private tables and variables.
+
+%pendingCallsXIDnow	= ();
+%pendingCallsXIDfh	= ();
+%pendingCallsXIDname	= ();
+
+$nextPruneTime		= -1;
+$PRUNE_INTERVAL		= 5 * 60;	# Five minutes.
+
+sub processLine {
+	my ($line, $proto, $op, $xid, $client, $now, $response, $fh_type) = @_;
+
+	if ($now > $nextPruneTime) {
+		&prunePending ($now - $PRUNE_INTERVAL);
+		$nextPruneTime = $now + $PRUNE_INTERVAL;
+	}
+
+	my $uxid = "$client-$xid";
+
+	# 'lookup', 'create', 'rename', 'delete',
+	# 'getattr', 'setattr'
+
+	#RFS: add mkdir/rmdir
+	if ($op eq 'lookup' || $op eq 'create' || $op eq 'mkdir') {
+		return (&doLookup ($line, $proto, $op, $uxid,
+				$now, $response, $fh_type));
+	}
+	elsif ($op eq 'rename') {
+	}
+	elsif ($op eq 'remove' || $op eq 'rmdir') {
+		# RFS: why remove these entries? Just let them exist since 
+		# there is generation number available to distinguish btw removed dir/file 
+		# and new dir/file with the same inode number.
+		#return (&doRemove ($line, $proto, $op, $uxid,
+		#		$now, $response, $fh_type));
+	}
+	elsif ($op eq 'getattr' || $op eq 'read' || $op eq 'write' ) {
+		return (&doGetAttr ($line, $proto, $op, $uxid,
+				$now, $response, $fh_type));
+	}
+	elsif ($op eq 'setattr') {
+	}
+}
+
+sub doLookup {
+	my ($line, $proto, $op, $uxid, $now, $response, $fh_type) = @_;
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		my $tag = ($proto eq 'C3') ? 'name' : 'fn';
+		my $name = nfsd::nfsDumpParseLineField ($line, $tag);
+
+		# All directories have (at least) three names:  the
+		# given name, and "." and "..".  We're only interested
+		# in the given name.
+
+		if ($name eq '"."' || $name eq '".."') {
+			return ;
+		}
+
+		my $fh = nfsd::nfsDumpCompressFH ($fh_type,
+			nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+		$pendingCallsXIDnow{$uxid} = $now;
+		$pendingCallsXIDfh{$uxid} = $fh;
+		$pendingCallsXIDname{$uxid} = $name;
+	}
+	elsif ($proto eq 'R3' || $proto eq 'R2') {
+		if (! exists $pendingCallsXIDnow{$uxid}) {
+			return ;
+		}
+
+		my $pfh = $pendingCallsXIDfh{$uxid};
+		my $name = $pendingCallsXIDname{$uxid};
+
+		delete $pendingCallsXIDnow{$uxid};
+		delete $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDname{$uxid};
+
+		if ($response eq 'OK') {
+			my $cfh = nfsd::nfsDumpCompressFH ($fh_type,
+					nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+			my $type = nfsd::nfsDumpParseLineField ($line, 'ftype');
+
+			if ($type == 2) {
+				$fhIsDir{$cfh} = 1;
+			}
+
+			$fh2Parent{$cfh} = $pfh;
+			$fh2Name{$cfh} = $name;
+			$parent2fh{"$pfh,$name"} = $cfh;
+
+			my ($size, $mode, $atime, $mtime, $ctime) =
+					nfsd::nfsDumpParseLineFields ($line,
+					'size', 'mode',
+					'atime', 'mtime', 'ctime');
+
+			# RFS: modify here to get/maintain more file attributes
+			# we can just check the ctime and compare it with trace-start-time
+			# to decide whether to create a file/diretory.
+			# atime - last access time of the file
+			# mtime - last modification time of the file
+			# ctime - last file status change time
+			
+			#$fh2Attr{$cfh} = "$size $mode $atime $mtime $ctime";
+			if  (! exists $fh2AttrOrig{$cfh} ) {
+				$fh2AttrOrig{$cfh} = "$size $mode $op $atime $mtime $ctime";
+			}
+			$fh2Attr{$cfh} = "$size $mode $op $atime $mtime $ctime";
+		}
+
+	}
+
+	return ;
+}
+
+sub doRemove {
+	my ($line, $proto, $op, $uxid, $now, $response, $fh_type) = @_;
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		my $tag = ($proto eq 'C3') ? 'name' : 'fn';
+		my $name = nfsd::nfsDumpParseLineField ($line, $tag);
+
+		# All directories have (at least) three names:  the
+		# given name, and "." and "..".  We're only interested
+		# in the given name.
+
+		if ($name eq '"."' || $name eq '".."') {
+			return ;
+		}
+
+		my $pfh = nfsd::nfsDumpCompressFH ($fh_type,
+			nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+		if (! exists $parent2fh{"$pfh,$name"}) {
+			return ;
+		}
+
+		$pendingCallsXIDnow{$uxid} = $now;
+		$pendingCallsXIDfh{$uxid} = $pfh;
+		$pendingCallsXIDname{$uxid} = $name;
+	}
+	elsif ($proto eq 'R3' || $proto eq 'R2') {
+		if (! exists $pendingCallsXIDnow{$uxid}) {
+			return ;
+		}
+
+		my $pfh = $pendingCallsXIDfh{$uxid};
+		my $name = $pendingCallsXIDname{$uxid};
+
+		delete $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDname{$uxid};
+		delete $pendingCallsXIDnow{$uxid};
+
+		if (! exists $parent2fh{"$pfh,$name"}) {
+			return ;
+		}
+
+		my $cfh = $parent2fh{"$pfh,$name"};
+
+		if ($response eq 'OK') {
+			if ($op eq 'remove') {
+				printFileInfo ($cfh, 'D');
+
+				delete $fh2Parent{$cfh};
+				delete $fh2Name{$cfh};
+				delete $fh2Attr{$cfh};
+				delete $fhs2AttrOrig{$cfg};
+				delete $parent2fh{"$pfh,$name"};
+			}
+		}
+	}
+
+	return ;
+}
+
+sub doGetAttr {
+	my ($line, $proto, $op, $uxid, $now, $response, $fh_type) = @_;
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		my $fh = nfsd::nfsDumpCompressFH ($fh_type,
+			nfsd::nfsDumpParseLineField ($line, 'fh'));
+
+		#if (nfsd::nfsDumpParseLineField ($line, 'fh')
+		#		eq '00018961-57570100-d2440000-61890100') {
+		#	printf STDERR "Seen it ($op)\n";
+		#}
+
+		if (! defined $fh) {
+			return ;
+		}
+
+		$pendingCallsXIDnow{$uxid} = $now;
+		$pendingCallsXIDfh{$uxid} = $fh;
+# RFS debug code
+my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+if ($fh eq $wantfh) {
+	print "JIAWU: doGetAttr call $wantfh\n";
+}
+	}
+	else {
+		if (! exists $pendingCallsXIDnow{$uxid}) {
+			return ;
+		}
+
+		my $fh = $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDfh{$uxid};
+		delete $pendingCallsXIDnow{$uxid};
+# RFS debug code
+my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+if ($fh eq $wantfh) {
+	print "JIAWU: doGetAttr response $wantfh\n";
+}
+
+		if ($response ne 'OK') {
+			return ;
+		}
+
+		my ($ftype) = nfsd::nfsDumpParseLineFields ($line, 'ftype');
+		if (!defined $ftype) {
+			print STDERR "BAD $line";
+			return ;
+		}
+
+		if ($ftype == 2) {
+			$fhIsDir{$fh} = 1;
+		}
+
+		#RFS comment: here if fh is a directory, then it will not be add 
+		# in the two hash table %fh2Attr(%fh2AttrOrig) and %fh2Name
+		# if ($ftype != 1) {
+		#	return ;
+		#}
+		if ($ftype != 1) {
+			#return ;
+		}
+
+
+		my ($mode, $size, $atime, $mtime, $ctime) =
+				nfsd::nfsDumpParseLineFields ($line,
+				'mode', 'size', 'atime', 'mtime', 'ctime');
+
+			# RFS: modify here to get/maintain more file attributes
+			# we can just check the ctime and compare it with trace-start-time
+			# to decide whether to create a file/diretory.
+			# atime - last access time of the file
+			# mtime - last modification time of the file
+			# ctime - last file status change time
+
+			# $fh2Attr{$fh} = "$size $mode $atime $mtime $ctime";
+
+			if  (! exists $fh2AttrOrig{$fh} ) {
+				$fh2AttrOrig{$fh} = "$size $mode $op $atime $mtime $ctime";
+			}
+			$fh2Attr{$fh} = "$size $mode $op $atime $mtime $ctime";
+	}
+}
+
+# Purge all the pending XID records dated earlier than $when (which is
+# typically at least $PRUNE_INTERVAL seconds ago).  This is important
+# because otherwise missing XID records can pile up, eating a lot of
+# memory. 
+  
+sub prunePending {
+	my ($when) = @_;
+
+	foreach my $uxid ( keys %pendingCallsXIDnow ) {
+		if ($pendingCallsXIDnow{$uxid} < $when) {
+# RFS debug code
+my $fh = $pendingCallsXIDfh{$uxid};
+my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+if ($fh eq $wantfh) {
+	print "JIAWU: prunePending $wantfh\n";
+}
+#enf RFS
+			delete $pendingCallsXIDnow{$uxid};
+		}
+	}
+
+	return ;
+}
+
+# Return as much of the path for the given fh as possible.  It may or
+# may not reach the root (or the mount point of the file system), but
+# right now we don't check.  Usually on busy systems the data is
+# complete enough so that most paths are complete back to the mount
+# point.
+
+sub findPath {
+	my ($fh) = @_;
+	my $isdir = 0;
+	my $cnt = 0;
+	my $MaxPathLen = 40;
+
+	if (exists $fhIsDir{$fh}) {
+		$isdir = 1;
+	}
+
+	my @path = ();
+	while ($fh && exists $fh2Name{$fh}) {
+		unshift (@path, $fh2Name{$fh});
+		if ($fh eq $fh2Parent{$fh}) {
+			unshift (@path, '(LOOP)');
+			last;
+		}
+
+		if ($cnt++ > $MaxPathLen) {
+			print STDERR "findPath: path too long (> $MaxPathLen)\n";
+			unshift (@path, '(TOO-LONG)');
+			last;
+		}
+
+		$fh = $fh2Parent{$fh};
+	}
+
+	# RFS: append the ~user (fh and !exists $fh2Name{$fh} and type is Directory)
+	if ($fh && !exists $fh2Name{$fh} && exists $fhIsDir{$fh}) {
+		if (exists $rootsName{$fh}) {
+			print "JIAWU: $rootsName{$fh}\n";
+			unshift(@path, $rootsName{$fh});
+		} else {
+			print "JIAWU: WARNING! No rootsName for this fh: $fh\n";
+			unshift(@path, $fh);
+		}
+	} else {
+		if ($fh && !exists $fh2Name{$fh} && !exists $fhIsDir{$fh}) {
+			if (exists $discardFHs{$fh}) {
+				open NOATTRDIR, ">>noattrdirdiscard";
+				print NOATTRDIR "$fh DISCARD\n";
+				close NOATTRDIR;
+			} else {
+				# RFS: if a possible fh without attr and name, then regard it as a special root ~/RFSNN0
+				unshift(@path, '"RFSNN0"');
+				$fhIsDir{$fh}=1;
+				$fh2Name{$fh} = '"RFSNN0"';
+				$rootsName{$fh} = '"RFSNN0"';
+				open NOATTRDIR, ">>noattrdir-root";
+				print NOATTRDIR "$fh RFSNN0\n";
+				close NOATTRDIR;
+			}
+		}
+	}
+
+	
+	my $str = '';
+	$cnt = 0;
+	foreach my $p ( @path ) {
+		$p =~ s/^.//;
+		$p =~ s/.$//;
+		$str .= "/$p";
+		$cnt++;
+	}
+
+	if ($isdir) {
+		$str .= '/';
+	}
+
+	if ($cnt == 0) {
+		$str = '.';
+	}
+
+	return ($str, $cnt);
+}
+
+
+$total_unknown_fh = 0;
+$total_known_fh = 0;
+
+sub printAll {
+	my ($start_time, $out) = @_;
+
+	my %allfh = ();
+	my $fh;
+	my $u = 0;
+	my $k = 0;
+
+	# RFS print more information here
+	open (OUT_RFS, ">rfsinfo") ||
+		die "Can't create $OutFileBaseName.rfs.";
+		
+	foreach $fh ( keys %fh2Attr ) {
+		$allfh{$fh} = 1; 
+	}
+	foreach $fh ( keys %fh2Name ) {
+		$allfh{$fh} = 1; 
+	}
+
+	#RFS: before printFileInfo, name those roots' name
+
+	#RFS there are three kind of fh
+	# 1. fh/name paired (fh/attr must)
+	# 2. fh/attr but no fh/name: type file (discard related operations)
+	# 3. fh/attr but no fh/name: type dir (keep as persuedo root)
+	$u = $k = 0;
+	my $sn=1;
+	foreach $fh ( keys %allfh ) {
+		if (exists $fh2Parent{$fh} ) {
+			$k++;
+		}
+		else {
+			$u++;
+			my $type = (exists $fhIsDir{$fh}) ? 'D' : 'F';
+			if ($type eq 'D') {
+				$rootsName{$fh} = sprintf("\"RFSNN%d\"", $sn++);
+				$rootsFHs{$fh} = 1;
+			}
+			else {
+				$discardFHs{$fh} = 1;
+			}
+		}
+	}
+	print OUT_RFS "#stat: fh with parent = $k, fh without parent = $u\n";
+	$u = keys %rootsFHs;
+	print OUT_RFS "#RFS: root fh list($u)\n";
+	foreach $fh (keys %rootsName) {
+		print OUT_RFS "#RFS: $rootsName{$fh} $fh\n";
+	}
+	$u = keys %discardFHs;
+	print OUT_RFS "#RFS: discard fh list($u)\n";
+	print OUT_RFS join("\n", keys %discardFHs, "");
+	
+
+	print $out "#F type state fh path pathcount attrOrig(size,mode,op,atime,mt,ct) attrLast(size,mode,op,at,mt,ct)\n";
+
+	print $out "#T starttime = $start_time\n";
+	foreach $fh ( keys %allfh ) {
+		printFileInfoOutputFile ($fh, 'A', $out);
+	}
+	
+		
+	my $numfh2Name = keys %fh2Name;
+	my $numfh2Attr = keys %fh2Attr;
+	print OUT_RFS "fh2name has $numfh2Name, fh2Attr has $numfh2Attr\n";
+	my $wantfh = "6189010057570100200000000000862077ed3800d24400006189010057570100";
+	if ($allfh{$wantfh} == 1) {
+		print OUT_RFS "JIAWU: found $wantfh\n";
+	} else {
+		print OUT_RFS "JIAWU: NOT found $wantfh\n";
+	}
+	foreach $fh ( keys %allfh ) {
+		if ( $fh eq $wantfh ) {
+			print OUT_RFS "JIAWU: found $wantfh\n";
+			printFileInfoOutputFile ($fh, 'JIAWU', *OUT_RFS);
+			last;
+		}
+	}
+	print OUT_RFS "JIAWU: after \n";
+
+	
+	$u = $k = 0;
+	foreach $fh ( keys %allfh ) {
+		if ( exists $fh2Name{$fh} ) {$k++;}
+		else {$u++;}
+	}
+	print OUT_RFS "#stat: total known fh = $total_known_fh, unknown = $total_unknown_fh\n";
+	print OUT_RFS "#stat: total fh with name = $k, without name = $u\n";
+
+	print OUT_RFS "#RFS\n";
+	close OUT_RFS;	
+
+}
+
+sub printFileInfoOutputFile {
+	my ($fh, $state, $out) = @_;
+
+	my ($p, $c) = findPath ($fh);
+	
+	if ($c == 0) {$total_unknown_fh++;}
+	else {$total_known_fh++;}
+	
+	my $type = (exists $fhIsDir{$fh}) ? 'D' : 'F';
+	my $attr = (exists $fh2Attr{$fh}) ?
+			$fh2Attr{$fh} : "-1 -1 -1 -1 -1";
+	my $attrOrig = (exists $fh2AttrOrig{$fh}) ?
+			$fh2AttrOrig{$fh} : "-1 -1 -1 -1 -1";
+
+	print $out "F $type $state $fh $p $c $attrOrig $attr\n";
+}
+
+sub printFileInfo {
+	my ($fh, $state) = @_;
+
+	my ($p, $c) = findPath ($fh);
+	
+	if ($c == 0) {$total_unknown_fh++;}
+	else {$total_known_fh++;}
+	
+	my $type = (exists $fhIsDir{$fh}) ? 'D' : 'F';
+	my $attr = (exists $fh2Attr{$fh}) ?
+			$fh2Attr{$fh} : "-1 -1 -1 -1 -1";
+	my $attrOrig = (exists $fh2AttrOrig{$fh}) ?
+			$fh2AttrOrig{$fh} : "-1 -1 -1 -1 -1";
+
+	print "F $type $state $fh $p $c $attrOrig $attr\n";
+}
+
+1;
diff --git a/TBBT/trace_init/key.pl b/TBBT/trace_init/key.pl
new file mode 100755
index 0000000..b4eacb0
--- /dev/null
+++ b/TBBT/trace_init/key.pl
@@ -0,0 +1,122 @@
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: key.pl,v 1.11 2003/07/26 20:52:04 ellard Exp $
+
+package key;
+
+sub makeKey {
+	my ($line, $proto, $op, $xid, $client, $now) = @_;
+	my ($client_id, $fh, $euid, $egid) = ('u', 'u', 'u', 'u');
+	my ($uxid) = "$client-$xid";
+
+	if ($proto eq 'R3' || $proto eq 'R2') {
+		if (exists $PendingKeyStr{$uxid}) {
+			return ($PendingKeyStr{$uxid});
+		}
+		else {
+			return 'u,u,u,u';
+		}
+	}
+
+	if ($main::UseClient) {
+		$client_id = $client;
+		$client_id =~ s/\..*//g
+	}
+	if ($main::UseFH && $op ne 'null') {
+		my $tag = ($op eq 'commit') ? 'file' : 'fh';
+
+		$fh = nfsd::nfsDumpParseLineField ($line, $tag);
+		if (! defined $fh) {
+			print STDERR "undefined fh ($line)\n";
+		}
+
+		$fh = nfsd::nfsDumpCompressFH ($main::FH_TYPE, $fh);
+
+	}
+	if ($main::UseUID && $op ne 'null') {
+		$euid = nfsd::nfsDumpParseLineField ($line, 'euid');
+	}
+	if ($main::UseGID && $op ne 'null') {
+		$egid = nfsd::nfsDumpParseLineField ($line, 'egid');
+	}
+
+	my $key = "$client_id,$fh,$euid,$egid";
+	$KeysSeen{$key} = 1;
+
+	$PendingKeyStr{$uxid} = $key;
+	$PendingKeyTime{$uxid} = $now;
+
+	return ($key);
+}
+
+sub key2str {
+	my ($key) = @_;
+
+	my ($client_id, $fh, $euid, $egid) = split (/,/, $key);
+
+	if ($client_id ne 'u') {
+
+		# just for aesthetics:
+		$client_id = sprintf ("%.8x", hex ($client_id));
+		$client_id =~ /^(..)(..)(..)(..)/;
+		$client_id = sprintf ("%d.%d.%d.%d",
+				hex ($1), hex ($2), 
+				hex ($3), hex ($4)); 
+		$client_id = sprintf ("%-15s", $client_id);
+	}
+
+	if ($euid ne 'u') {
+		$euid = hex ($euid);
+	}
+	if ($egid ne 'u') {
+		$egid = hex ($egid);
+	}
+
+	return ("$client_id $fh $euid $egid");
+}
+
+# Purge all the pending XID records dated earlier than $when (which is
+# typically at least $PRUNE_INTERVAL seconds ago).  This is important
+# because otherwise missing XID records can pile up, eating a lot of
+# memory. 
+  
+sub prunePending {
+	my ($when) = @_;
+
+	foreach my $uxid ( keys %PendingKeyTime ) {
+		if ($PendingKeyTime{$uxid} < $when) {
+			delete $PendingKeyTime{$uxid};
+			delete $PendingKeyStr{$uxid};
+		}
+	}
+
+	return ;
+}
+
+1;
diff --git a/TBBT/trace_init/latency.pl b/TBBT/trace_init/latency.pl
new file mode 100755
index 0000000..0ba1ecd
--- /dev/null
+++ b/TBBT/trace_init/latency.pl
@@ -0,0 +1,159 @@
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: latency.pl,v 1.8 2003/07/28 14:27:16 ellard Exp $
+#
+# latency.pl -
+
+package	latency;
+
+%PendingOps	= ();
+%OpCount	= ();
+%OpTime		= ();
+%KeysSeen	= ();
+
+@OpList		= ();
+
+sub init {
+	my (@oplist) = @_;
+
+	@OpList = @oplist;
+}
+
+# Bugs:  might not recognize the actual response packets.  It's an
+# approximation.
+
+sub update {
+	my ($key, $proto, $op, $xid, $client, $now) = @_;
+
+	my $uxid = "$client-$xid";
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		$PendingOps{$uxid} = $now;
+	}
+	elsif (exists $PendingOps{$uxid}) {
+		my $elapsed = $now - $PendingOps{$uxid};
+
+		$KeysSeen{$key} = 1;
+
+		$OpTime{"$key,$op"} += $elapsed;
+		$OpCount{"$key,$op"}++;
+
+		$OpTime{"$key,TOTAL"} += $elapsed;
+		$OpCount{"$key,TOTAL"}++;
+
+		$OpTime{"$key,INTERESTING"} += $elapsed;
+		$OpCount{"$key,INTERESTING"}++;
+
+		delete $PendingOps{$uxid};
+	}
+}
+
+sub resetOpCounts {
+
+	my $k;
+
+	foreach $k ( keys %OpTime ) {
+		$OpTime{$k} = 0.0;
+	}
+	foreach $k ( keys %OpCount ) {
+		$OpCount{$k} = 0;
+	}
+
+	return ;
+}
+
+sub printTitle {
+	my $str = "#L time client euid egid fh";
+
+	foreach my $op ( @OpList ) {
+		$str .= " $op-cnt $op-lat";
+	}
+	$str .= "\n";
+
+	print $str;
+} 
+
+sub printOps {
+	my ($start_time, $out) = @_;
+	my ($k, $str, $op, $nk, $latms, $cnt);
+
+	my @allkeys = sort keys %KeysSeen;
+
+	foreach $k ( @allkeys ) {
+		my $tot = "$k,TOTAL";
+
+		if ($main::OMIT_ZEROS &&
+			(! exists $OpCounts{$tot} || $OpCounts{$tot} == 0)) {
+			next;
+		}
+
+		$str = sprintf ("L %s %s", $start_time, &key::key2str ($k));
+
+		foreach $op ( @OpList ) {
+			$nk = "$k,$op";
+
+			if (exists $OpCount{$nk}) {
+				$cnt = $OpCount{"$k,$op"};
+			}
+			else {
+				$cnt = 0;
+			}
+
+			if ($cnt > 0) {
+				$latms = 1000 * $OpTime{$nk} / $cnt;
+			}
+			else {
+				$latms = -1;
+			}
+
+			$str .= sprintf (" %d %.4f", $cnt, $latms);
+		}
+
+		print $out "$str\n";
+	}
+}
+
+# Purge all the pending XID records dated earlier than $when (which is
+# typically at least $PRUNE_INTERVAL seconds ago).  This is important
+# because otherwise missing XID records can pile up, eating a lot of
+# memory. 
+  
+sub prunePending {
+	my ($when) = @_;
+
+	foreach my $uxid ( keys %PendingOps ) {
+		if ($PendingOps{$uxid} < $when) {
+			delete $PendingOps{$uxid};
+		}
+	}
+
+	return ;
+}
+
+1;
diff --git a/TBBT/trace_init/nfsdump.pl b/TBBT/trace_init/nfsdump.pl
new file mode 100755
index 0000000..69eca84
--- /dev/null
+++ b/TBBT/trace_init/nfsdump.pl
@@ -0,0 +1,338 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: nfsdump.pl,v 1.5 2003/07/26 20:52:04 ellard Exp $
+#
+# Utility for dealing with raw nfsdump records.
+
+package nfsd;
+
+# If $AllowRisky is set, then allow some optimizations that might be
+# "risky" in bizarre situations (but have never been observed to
+# actually break anything).  By default, no riskiness is permitted.
+
+$AllowRisky	= 0;
+
+# nfsDumpParseLine -- initializes the global associative array
+# %nfsd'nfsDumpLine with information about a record from nfsdump. 
+# Returns an empty list if anything goes wrong.  Otherwise, returns a
+# list of the protocol (eg R2, C2, R3, C3), the name of the operation,
+# and the xid, the client host ID, the time, and for responses, the
+# status (via nfsDumpParseLineHeader).  The reason for this particular
+# return list is that these are very frequently-accessed values, so it
+# can save time to avoid going through the associative array to access
+# them.
+#
+# All records begin with several fixed fields, and then are followed
+# by some number of name/value pairs, and finally some diagnostic
+# fields (which are mostly ignored by this routine-- the only
+# diagnostic this routine cares about is whether the packet as part of
+# a jumbo packet or not.  If so, then 'truncated' is set.)
+
+sub nfsDumpParseLine {
+	my ($line, $total) = @_;
+
+	my (@rl) = &nfsDumpParseLineHeader ($line);
+
+	if (@rl && $total) {
+		&nfsDumpParseLineBody ($line);
+	}
+
+	return @rl;
+}
+
+sub nfsDumpParseLineBody {
+	my ($line) = @_;
+	my $i;
+	my $client_id;
+	my $reseen;
+
+	undef %nfsDumpLine;
+
+	# If the line doesn't start with a digit, then it's certainly
+	# not properly formed, so bail out immediately.
+
+	if (! ($line =~ /^[0-9]/)) {
+		return undef;
+	}
+
+	my @l = split (' ', $line);
+	my $lineLen = @l;
+	if ($l[$lineLen - 1] eq 'LONGPKT') {
+		splice (@l, $lineLen - 1);
+		$nfsDumpLine{'truncated'} = 1;
+		$lineLen--;
+	}
+
+	$nfsDumpLine{'time'}	= $l[0];
+	$nfsDumpLine{'srchost'}	= $l[1];
+	$nfsDumpLine{'deshost'}	= $l[2];
+	$nfsDumpLine{'proto'}	= $l[4];
+	$nfsDumpLine{'xid'}	= $l[5];
+	$nfsDumpLine{'opcode'}	= $l[6];
+	$nfsDumpLine{'opname'}	= $l[7];
+
+	if (($l[4] eq 'R3') || ($l[4] eq 'R2')) {
+		$nfsDumpLine{'status'}	= $l[8];
+
+		$client_id = $l[2];
+		$reseen = 0;
+		for ($i = 9; $i < $lineLen - 10; $i += 2) {
+			if (defined $nfsDumpLine{$l[$i]}) {
+				$reseen = 1;
+				$nfsDumpLine{"$l[$i]-2"} = $l[$i + 1];
+			}
+			else {
+				$nfsDumpLine{$l[$i]} = $l[$i + 1];
+			}
+		}
+	}
+	else {
+		$client_id = $l[1];
+		$reseen = 0;
+		for ($i = 8; $i < $lineLen - 6; $i += 2) {
+			if (defined $nfsDumpLine{$l[$i]}) {
+				$nfsDumpLine{"$l[$i]-2"} = $l[$i + 1];
+				$reseen = 1;
+			}
+			else {
+				$nfsDumpLine{$l[$i]} = $l[$i + 1];
+			}
+		}
+	}
+}
+
+# Returns an empty list if anything goes wrong.  Otherwise, returns a
+# list of the protocol (eg R2, C2, R3, C3), the name of the operation,
+# and the xid, the client host ID, and time, and the response status. 
+# (For call messages, the status is 'na'.)
+
+sub nfsDumpParseLineHeader {
+	my ($line) = @_;
+
+	# If the line doesn't start with a digit, then it's certainly
+	# not properly formed, so bail out immediately.
+
+	if (! ($line =~ /^[0-9]/)) {
+		return ();
+	}
+	else {
+		my $client_id;
+		my $status;
+
+		my @l = split (' ', $line, 10);
+
+
+		if (($l[4] eq 'R3') || ($l[4] eq 'R2')) {
+			$client_id = $l[2];
+			$status = $l[8];
+		}
+		else {
+			$client_id = $l[1];
+			$status = 'na';
+		}
+
+		return ($l[4], $l[7], $l[5], $client_id, $l[0], $status);
+	}
+}
+
+# nfsDumpParseLineFields -- Just return a subset of the fields,
+# without parsing the entire line.
+
+sub nfsDumpParseLineFields {
+	my ($line, @fields) = @_;
+	my $i;
+
+	# If the line doesn't start with a digit, then
+	# it's certainly not properly formed, so bail out
+	# immediately.
+
+	if (! ($line =~ /^[0-9]/)) {
+		return ();
+	}
+
+	my $rest;
+	if ($AllowRisky) {
+		$rest = $line;
+	}
+	else {
+		my @foo = split (' ', $line, 9);
+		$rest = ' ' . $foo[8];
+	}
+
+	my $fl = @fields;
+	my @l = ();
+	for ($i = 0; $i < $fl; $i++) {
+		my $field = $fields[$i];
+
+		$rest =~ /\ $field\ +([^\ ]+)/;
+		$l[$i] = $1;
+	}
+
+	return (@l);
+}
+
+# nfsDumpParseLineField -- Just return ONE of the fields,
+# without parsing the entire line.
+
+sub nfsDumpParseLineField {
+	my ($line, $field) = @_;
+
+	# If the line doesn't start with a digit, then
+	# it's certainly not properly formed, so bail out
+	# immediately.
+
+	if (! ($line =~ /^[0-9]/)) {
+		return undef;
+	}
+
+	my $rest;
+	if ($AllowRisky) {
+		$rest = $line;
+	}
+	else {
+		my @foo = split (' ', $line, 9);
+		$rest = ' ' . $foo[8];
+	}
+
+	$rest =~ /\ $field\ +([^\ ]+)/;
+	return $1;
+}
+
+# Returns a new file handle that has all the "useful" information as
+# the original, but requires less storage space.  File handles
+# typically contain quite a bit of redundancy or unused bytes.
+#
+# This routine only knows about the advfs and netapp formats.  If
+# you're using anything else, just use anything else as the mode, and
+# the original file handle will be returned.
+#
+# If you extend this to handle more file handles, please send the new
+# code to me (ellard@eecs.harvard.edu) so I can add it to the
+# distribution.
+
+sub nfsDumpCompressFH {
+	my ($mode, $fh) = @_;
+
+	if ($mode eq 'advfs') {
+
+		# The fh is a long hex string:
+		# 8 chars: file system ID
+		# 8 chars: apparently unused.
+		# 8 chars: unused.
+		# 8 chars: inode
+		# 8 chars: generation
+		# rest of string: mount point (not interesting).
+		# So all we do is pluck out the fsid, inode,
+		# and generation number, and throw the rest away.
+
+		$fh =~ /^(........)(........)(........)(........)(........)/;
+
+		return ("$1-$4-$5");
+	}
+	elsif ($mode eq 'netapp') {
+
+		# Here's the netapp format (from Shane Owara):
+		#
+		# 4 bytes     mount point file inode number
+		# 4 bytes     mount point file generation number
+		# 
+		# 2 bytes     flags
+		# 1 byte      snapshot id
+		# 1 byte      unused
+		#
+		# 4 bytes     file inode number
+		# 4 bytes     file generation number
+		# 4 bytes     volume identifier
+		#
+		# 4 bytes     export point fileid
+		# 1 byte      export point snapshot id
+		# 3 bytes     export point snapshot generation number
+		#
+		# The only parts of this that are interesting are
+		# inode, generation, and volume identifier (and probably
+		# a lot of the bits of the volume identifier could be
+		# tossed, since we don't have many volumes...).
+
+		$fh =~ /^(........)(........)(........)(........)(........)(........)(........)/;
+
+		return ("$4-$5-$6-$1");
+	}
+	elsif ($mode eq 'RFSNN') {
+
+		# Here's the netapp format (from Shane Owara):
+		#
+		# 4 bytes     mount point file inode number
+		# 4 bytes     mount point file generation number
+		# 
+		# 2 bytes     flags
+		# 1 byte      snapshot id
+		# 1 byte      unused
+		#
+		# 4 bytes     file inode number
+		# 4 bytes     file generation number
+		# 4 bytes     volume identifier
+		#
+		# 4 bytes     export point fileid
+		# 1 byte      export point snapshot id
+		# 3 bytes     export point snapshot generation number
+		#
+		# The only parts of this that are interesting are
+		# inode, generation, and volume identifier (and probably
+		# a lot of the bits of the volume identifier could be
+		# tossed, since we don't have many volumes...).
+		
+		# 61890100575701002000000  0009ac710e9ea381  0d24400006189010057570100
+		# 61890100575701002000000  0009ac70ed2ea381  0d24400006189010057570100
+		# 61890100575701002000000  000479a1e008d782  0d24400006189010057570100
+		# Ningning need only 24-39 (or 12-19 bytes)
+
+		$fh =~ /^(........)(........)(........)(........)(........)(........)/;
+
+		return ("$4$5");
+	}else {
+
+		return ($fh);
+	}
+}
+
+sub testMain {
+	$lineNum = 0;
+
+	while (<STDIN>) {
+		$line = $_;
+		$lineNum++;
+
+		&nfsDumpParseLine ($line);
+	}
+}
+
+1;
+
+# end of nfsdump.pl
diff --git a/TBBT/trace_init/nfsscan.pl b/TBBT/trace_init/nfsscan.pl
new file mode 100755
index 0000000..fad5216
--- /dev/null
+++ b/TBBT/trace_init/nfsscan.pl
@@ -0,0 +1,682 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: nfsscan,v 1.18 2003/07/28 14:27:16 ellard Exp $
+
+$ProgDir = $0;
+$ProgDir =~ /(^.*)\//;
+$ProgDir = $1;
+if (!$ProgDir) {
+	$ProgDir = ".";
+}
+
+require "$ProgDir/nfsdump.pl";
+require "$ProgDir/userUtils.pl";
+require "$ProgDir/hier.pl";
+require "$ProgDir/counts.pl";
+require "$ProgDir/latency.pl";
+require "$ProgDir/key.pl";
+require "$ProgDir/common.pl";
+
+use Getopt::Std;
+
+$INTERVAL	= 5 * 60;		# in seconds (5 minutes)
+
+%KeysSeen	= ();
+
+@ADD_USERS	= ();
+@DEL_USERS	= ();
+@ADD_GROUPS	= ();
+@DEL_GROUPS	= ();
+@ADD_CLIENTS	= ();
+@DEL_CLIENTS	= ();
+
+$DO_COUNTS	= 1;
+$DO_LATENCY	= 0;
+$DO_FILES	= 0;
+$DO_PATHS	= 0;
+$DO_SQUEEZE	= 0;
+
+$FH_TYPE	= 'unknown';
+
+$END_TIME	= -1;
+$START_TIME	= -1;
+$NOW		= -1;
+$UseClient	= 0;
+$UseFH		= 0;
+$UseUID		= 0;
+$UseGID		= 0;
+$OMIT_ZEROS	= 0;
+
+$OutFileBaseName	= undef;
+
+$nextPruneTime		= -1;
+$PRUNE_INTERVAL		= 1 * 60;	# One minute.
+
+# &&&
+# Is this really the right default set of operations?
+
+$DEF_OPLIST	= 'read,write,lookup,getattr,access,create,remove';
+@OPLIST		= ('TOTAL', 'INTERESTING', 
+			split (/,/, $DEF_OPLIST));
+%OPARRAY	= ();
+
+$Usage =<< ".";
+
+Usage: $0 [options] [trace1 [trace2 ...]]
+
+If no trace files are specified, then the trace is read from stdin.
+
+Command line options:
+
+-h		Print usage message and exit.
+
+-B [CFUG]	Compute per-Client, per-File, per-User, or per-Group info.
+
+-c c1[,c2]*	Include only activity performed by the specified clients.
+
+-C c1[,c2]*	Exclude activity performed by the specified clients.
+
+-d		Compute per-directory statistics.  This implicitly
+		enables -BF so that per-file info is computed.
+
+-f		Do file info tracking.  This implicitly enables -BF so
+		that per-File info is computed.
+
+-F fhtype	Specify the file handle type used by the server.
+		(advfs or netapp)
+
+-g g1[,g2]*	Include only activity performed by the specified groups.
+
+-G g1[,g2]*	Exclude activity performed by the specified groups.
+
+-l		Record average operation latency.
+
+-o basename	Write output to files starting with the specified
+		basename.  The "Count" table goes to basename.cnt,
+		"Latency" to basename.lat, and "File" to basename.fil.
+		The default is to write all output to stdout.
+
+-O op[,op]*	Specify the list of "interesting" operations.
+		The default list is:
+
+		read,write,lookup,getattr,access,create,remove
+
+		If the first op starts with +, then the specified list
+		of ops is appended to the default list.  The special
+		pseudo-ops readM and writeM represent the number of
+		bytes read and written, expressed in MB.
+
+-t interval	Time interval for cummulative statistics (such as
+		operation count).  The default is $INTERVAL seconds. 
+		If set to 0, then the entire trace is processed.  By
+		default, time is specified in seconds, but if the last
+		character of the interval is any of s, m, h, or d,
+		then the interval is interpreted as seconds, minutes,
+		hours, or days.
+
+-u u1[,u2]*	Include only activity performed by the specified users.
+
+-U u1[,u2]*	Exclude activity performed by the specified users.
+
+-Z		Omit count and latency lines that have a zero total
+		operation count.
+.
+
+
+main ();
+
+sub main {
+
+	parseArgs ();
+
+	if ($DO_COUNTS) {
+		counts::printTitle (*OUT_COUNTS);
+	}
+
+	if ($DO_LATENCY) {
+		latency::printTitle (*OUT_LATENCY);
+	}
+
+	counts::resetOpCounts ();
+
+	my $cmdbuf = 'rm -f noattrdirdiscard noattrdir-root';
+	system($cmdbuf);
+
+	readTrace ();
+}
+
+sub parseArgs {
+
+	my $cmdline = "$0 " . join (' ', @ARGV);
+
+	my $Options = "B:dfF:g:G:hlO:o:t:u:U:SR:Z";
+	if (! getopts ($Options)) {
+		print STDERR "$0: Incorrect usage.\n";
+		print STDERR $Usage;
+	exit (1);
+	}
+	if (defined $opt_h) {
+		print $Usage;
+		exit (0);
+	}
+
+	#RFS: neednot input arguments
+	$opt_o = "test";
+	$opt_f = 1;
+	$opt_t = 0;
+	#$opt_F = 'RFSNN'; # advfs or netapp
+
+	if (defined $opt_B) {
+		$UseClient = ($opt_B =~ /C/);
+		$UseFH = ($opt_B =~ /F/);
+		$UseUID = ($opt_B =~ /U/);
+		$UseGID = ($opt_B =~ /G/);
+	}
+
+	if (defined $opt_o) {
+		$OutFileBaseName = $opt_o;
+	}
+
+	if (defined $opt_O) {
+		if ($opt_O =~ /^\+(.*)/) {
+			@OPLIST = (@OPLIST, split (/,/, $1));
+		}
+		else {
+			@OPLIST = ('TOTAL', 'INTERESTING', split (/,/, $opt_O));
+		}
+		# Error checking?
+	}
+
+	if (defined $opt_l) {
+		$DO_LATENCY = 1;
+	}
+
+	if (defined $opt_t) {
+		if ($INTERVAL =~ /([0-9]*)([smhd])/) {
+			my $n = $1;
+			my $unit = $2;
+
+			if ($unit eq 's') {
+				$INTERVAL = $opt_t;
+			}
+			elsif ($unit eq 'm') {
+				$INTERVAL = $opt_t * 60;
+			}
+			elsif ($unit eq 'h') {
+				$INTERVAL = $opt_t * 60 * 60;
+			}
+			elsif ($unit eq 'd') {
+				$INTERVAL = $opt_t * 24 * 60 * 60;
+			}
+		}
+		else {
+			$INTERVAL = $opt_t;
+		}
+	}
+
+	$DO_PATHS = (defined $opt_d);
+	$DO_FILES = (defined $opt_f);
+	$DO_SQUEEZE = (defined $opt_S);
+	$OMIT_ZEROS = (defined $opt_Z);
+
+	$TIME_ROUNDING = (defined $opt_R) ? $opt_R : 0;
+
+	if (defined $opt_F) {
+		$FH_TYPE = $opt_F;
+	}
+
+	if (defined $opt_c) {
+		@ADD_CLIENTS = split (/,/, $opt_c);
+	}
+	if (defined $opt_C) {
+		@DEL_CLIENTS = split (/,/, $opt_c);
+	}
+
+	if (defined $opt_g) {
+		@ADD_GROUPS = groups2gids (split (/,/, $opt_g));
+	}
+	if (defined $opt_G) {
+		@DEL_GROUPS = groups2gids (split (/,/, $opt_G));
+	}
+
+	if (defined $opt_u) {
+		@ADD_USERS = logins2uids (split (/,/, $opt_u));
+	}
+	if (defined $opt_U) {
+		@DEL_USERS = logins2uids (split (/,/, $opt_U));
+	}
+
+
+	# Now that we know what options the user asked for, initialize
+	# things accordingly.
+
+	if ($DO_PATHS || $DO_FILES) {
+		$UseFH = 1;
+	}
+
+	if ($DO_LATENCY) {
+		latency::init (@OPLIST);
+	}
+
+	if ($DO_COUNTS) {
+		counts::init (@OPLIST);
+	}
+
+	if (defined $OutFileBaseName) {
+		if ($DO_COUNTS) {
+			open (OUT_COUNTS, ">$OutFileBaseName.cnt") ||
+				die "Can't create $OutFileBaseName.cnt.";
+			print OUT_COUNTS "#cmdline $cmdline\n";
+		}
+		if ($DO_LATENCY) {
+			open (OUT_LATENCY, ">$OutFileBaseName.lat") ||
+				die "Can't create $OutFileBaseName.lat.";
+			print OUT_LATENCY "#cmdline $cmdline\n";
+		}
+		if ($DO_FILES) {
+			open (OUT_FILES, ">$OutFileBaseName.fil") ||
+				die "Can't create $OutFileBaseName.fil.";
+			print OUT_FILES "#cmdline $cmdline\n";
+		}
+		if ($DO_PATHS) {
+			open (OUT_PATHS, ">$OutFileBaseName.pat") ||
+				die "Can't create $OutFileBaseName.pat.";
+			print OUT_PATHS "#cmdline $cmdline\n";
+		}
+	}
+	else {
+		*OUT_COUNTS = STDOUT;
+		*OUT_LATENCY = STDOUT;
+		*OUT_FILES = STDOUT;
+		*OUT_PATHS = STDOUT;
+
+		print STDOUT "#cmdline $cmdline\n";
+	}
+
+	foreach my $op ( @OPLIST ) {
+		$OPARRAY{$op} = 1;
+	}
+
+	return ;
+}
+
+sub readTrace {
+	my (@args) = @_;
+
+	while (my $line = <>) {
+
+		$hier::rfsLineNum++;
+		if ( ($hier::rfsLineNum % 1000) eq 0) {
+			print STDERR "$hier::rfsLineNum\n";
+		}
+
+
+		if ($line =~ /SHORT\ PACKET/) {
+			next;
+		}
+
+		my ($proto, $op, $xid, $client, $now, $response) =
+				nfsd::nfsDumpParseLineHeader ($line);
+		$NOW = $now;
+
+		# NOTE:  This next bit of logic requires a little
+		# extra attention.  We want to discard lines as
+		# quickly as we can if they're not "interesting". 
+		# However, different lines are interesting in
+		# different contexts, so the order of the tests and
+		# the manner in which they are interspersed with
+		# subroutine calls to pluck info from the lines is
+		# very important.
+
+		# Check whether it is a line that we should prune and
+		# ignore, because of the filters.
+		
+		next if (($op eq 'C3' || $op eq 'C2') &&
+				! pruneCall ($line, $client));
+
+		if ($DO_PATHS || $DO_FILES) {
+			hier::processLine ($line,
+					$proto, $op, $xid, $client,
+					$now, $response, $FH_TYPE);
+		}
+
+		my $key = key::makeKey ($line, $proto, $op,
+				$xid, $client, $now,
+				$UseClient, $UseFH, $UseUID, $UseGID,
+				$FH_TYPE);
+		if (! defined $key) {
+			next ;
+		}
+		$KeysSeen{$key} = 1;
+
+		# Count everything towards the total, but only
+		# do the rest of the processing for things
+		# that are "interesting".
+
+		if ($proto eq 'C3' || $proto eq 'C2') {
+			$counts::OpCounts{"$key,TOTAL"}++;
+			$counts::KeysSeen{$key} = 1;
+
+			next if (! exists $OPARRAY{$op});
+
+			$counts::OpCounts{"$key,$op"}++;
+			$counts::OpCounts{"$key,INTERESTING"}++;
+		}
+
+		if ($op eq 'read' && exists $OPARRAY{'readM'}) {
+			doReadSize ($line, $proto, $op, $key, $client, $xid, $response, $now);
+		}
+
+		if ($op eq 'write' && exists $OPARRAY{'writeM'}) {
+			doWriteSize ($line, $proto, $op, $key, $client, $xid, $response, $now);
+		}
+
+		if ($DO_LATENCY) {
+			latency::update ($key, $proto, $op,
+					$xid, $client, $now);
+		}
+
+		if ($END_TIME < 0) {
+			$START_TIME = findStartTime ($NOW, $TIME_ROUNDING);
+			$END_TIME = $START_TIME + $INTERVAL;
+		}
+
+		# Note that this is a loop, because if the interval is
+		# short enough, or the system is very idle (or there's
+		# a filter in place that makes it look idle), entire
+		# intervals can go by without anything happening at
+		# all.  Some tools can get confused if intervals are
+		# missing from the table, so we emit them anyway.
+
+		while (($INTERVAL > 0) && ($NOW >= $END_TIME)) {
+			printAll ($START_TIME);
+
+			counts::resetOpCounts ();
+			latency::resetOpCounts ();
+
+			$START_TIME += $INTERVAL;
+			$END_TIME = $START_TIME + $INTERVAL;
+		}
+
+		if ($now > $nextPruneTime) {
+			key::prunePending ($now - $PRUNE_INTERVAL);
+			latency::prunePending ($now - $PRUNE_INTERVAL);
+
+			prunePending ($now - $PRUNE_INTERVAL);
+
+			$nextPruneTime = $now + $PRUNE_INTERVAL;
+		}
+	}
+
+	# Squeeze out the last little bit, if there's anything that we
+	# counted but did not emit.  If DO_SQUEEZE is true, then
+	# always do this.  Otherwise, only squeeze out the results of
+	# the last interval if the interval is "almost" complete (ie
+	# within 10 seconds of the end).
+
+	if (($NOW > $START_TIME) && ($DO_SQUEEZE || (($END_TIME - $NOW) < 10))) {
+		printAll ($START_TIME);
+		counts::resetOpCounts ();
+	}
+
+	print "#T endtime = $NOW\n";
+
+}
+
+sub printAll {
+	my ($start_time) = @_;
+
+	if ($DO_COUNTS) {
+		counts::printOps ($start_time, *OUT_COUNTS);
+	}
+
+	if ($DO_LATENCY) {
+		latency::printOps ($start_time, *OUT_LATENCY);
+	}
+
+	if ($DO_FILES) {
+		hier::printAll ($start_time, *OUT_FILES);
+	}
+
+	if ($DO_PATHS) {
+		printPaths ($start_time, *OUT_PATHS);
+	}
+}
+
+sub pruneCall {
+	my ($line, $client) = @_;
+
+	if (@ADD_USERS > 0 || @DEL_USERS > 0) {
+		my $c_uid = nfsd::nfsDumpParseLineField ($line, 'euid');
+		if (! defined ($c_uid)) {
+			return 0;
+		}
+		$c_uid = hex ($c_uid);
+
+		if (@ADD_USERS && !grep (/^$c_uid$/, @ADD_USERS)) {
+			return 0;
+		}
+		if (@DEL_USERS && grep (/^$c_uid$/, @DEL_USERS)) {
+			return 0;
+		}
+	}
+
+	if (@ADD_GROUPS > 0 || @DEL_GROUPS > 0) {
+		my $c_gid = nfsd::nfsDumpParseLineField ($line, 'egid');
+		if (! defined ($c_gid)) {
+			return 0;
+		}
+		$c_gid = hex ($c_gid);
+
+		if (@ADD_GROUPS && !grep (/^$c_gid$/, @ADD_GROUPS)) {
+			return 0;
+		}
+		if (@DEL_GROUPS && grep (/^$c_gid$/, @DEL_GROUPS)) {
+			return 0;
+		}
+	}
+
+	if (@ADD_CLIENTS > 0 || @DEL_CLIENTS > 0) {
+		if (@ADD_CLIENTS && !grep (/^$client$/, @ADD_CLIENTS)) {
+			return 0;
+		}
+		if (@DEL_CLIENTS && grep (/^$client$/, @DEL_CLIENTS)) {
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+%PathOpCounts	= ();
+%PathsSeen	= ();
+
+sub buildDirPath {
+	my ($fh, $key) = @_;
+	my $pfh;
+	my $cnt;
+
+	foreach my $op ( @OPLIST ) {
+		if (exists $counts::OpCounts{"$key,$op"}) {
+			$cnt = $counts::OpCounts{"$key,$op"};
+		}
+		else {
+			$cnt = 0;
+		}
+		$PathOpCounts{"$fh,$op"} = $cnt;
+
+		$PathsSeen{$fh} = 1;
+
+		$pfh = $fh;
+		my $len = 0;
+		while (defined ($pfh = $hier::fh2Parent{$pfh})) {
+
+			if ($len++ > 20) {
+				print "Really long path ($fh)\n";
+				last;
+			}
+
+			if (exists $PathOpCounts{"$pfh,$op"}) {
+				$PathOpCounts{"$pfh,$op"} += $cnt;
+			}
+			else {
+				$PathOpCounts{"$pfh,$op"} = $cnt;
+			}
+			$PathsSeen{$pfh} = 1;
+		}
+	}
+
+	return ;
+}
+
+sub printPaths {
+	my ($start_time, $out) = @_;
+
+	my $str = "#D time Dir/File dircnt path fh";
+	foreach my $op ( @OPLIST ) {
+		$str .= " $op";
+	}
+	$str .= "\n";
+
+	print $out $str;
+
+	undef %PathsSeen;
+
+	foreach my $key ( keys %KeysSeen ) {
+		my ($client_id, $fh, $euid, $egid) = split (/,/, $key);
+
+		buildDirPath ($fh, $key);
+	}
+
+	foreach my $fh ( keys %PathsSeen ) {
+		my ($path, $cnt) = hier::findPath ($fh);
+
+		if ($cnt == 0) {
+			$path = ".";
+		}
+
+		my $type = (exists $hier::fhIsDir{$fh} && $hier::fhIsDir{$fh}==2) ? 'D' : 'F';
+
+		my $str = "$cnt $type $path $fh ";
+
+		foreach my $op ( @OPLIST ) {
+			my $cnt;
+
+			if (exists $PathOpCounts{"$fh,$op"}) {
+				$cnt = $PathOpCounts{"$fh,$op"};
+			}
+			else {
+				print "Missing $fh $op\n";
+				$cnt = 0;
+			}
+
+			$str .= " $cnt";
+
+			$PathOpCounts{"$fh,$op"} = 0;	# &&& reset
+		}
+
+		print $out "D $start_time $str\n";
+	}
+}
+
+%uxid2key	= ();
+%uxid2time	= ();
+
+sub doReadSize {
+	my ($line, $proto, $op, $key, $client, $xid, $response, $time) = @_;
+
+	my $uxid = "$client-$xid";
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+		$uxid2time{$uxid} = $time;
+		$uxid2key{$uxid} = $key;
+	}
+	else {
+		if (! exists $uxid2key{$uxid}) {
+			return ;
+		}
+		if ($response ne 'OK') {
+			return ;
+		}
+
+		$key = $uxid2key{$uxid};
+		my $count = nfsd::nfsDumpParseLineField ($line, 'count');
+		$count = hex ($count);
+
+		delete $uxid2key{$uxid};
+		delete $uxid2time{$uxid};
+
+		$counts::OpCounts{"$key,readM"} += $count;
+	}
+}
+
+# Note that we always just assume that writes succeed, because on most
+# systems they virtually always do.  If you're tracing a system where
+# your users are constantly filling up the disk or exceeding their
+# quotas, then you will need to fix this.
+
+sub doWriteSize {
+	my ($line, $proto, $op, $key, $client, $xid, $response, $time) = @_;
+
+	if ($proto eq 'C3' || $proto eq 'C2') {
+
+		my $tag = ($proto eq 'C3') ? 'count' : 'tcount';
+
+		my $count = nfsd::nfsDumpParseLineField ($line, $tag);
+
+		if (! $count) {
+			printf "WEIRD count $line\n";
+		}
+
+		$count = hex ($count);
+
+		$counts::OpCounts{"$key,writeM"} += $count;
+	}
+}
+
+
+# Purge all the pending XID records dated earlier than $when (which is
+# typically at least $PRUNE_INTERVAL seconds ago).  This is important
+# because otherwise missing XID records can pile up, eating a lot of
+# memory. 
+  
+sub prunePending {
+	my ($when) = @_;
+
+	foreach my $uxid ( keys %uxid2time ) {
+		if ($uxid2time{$uxid} < $when) {
+			delete $uxid2key{$uxid};
+			delete $uxid2time{$uxid};
+		}
+	}
+
+	return ;
+}
+
diff --git a/TBBT/trace_init/nfsscan.txt b/TBBT/trace_init/nfsscan.txt
new file mode 100755
index 0000000..b004339
--- /dev/null
+++ b/TBBT/trace_init/nfsscan.txt
@@ -0,0 +1,230 @@
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# $Id: nfsscan.txt,v 1.5 2003/07/28 14:27:16 ellard Exp $
+
+NFSSCAN DOCUMENTATION
+
+This is version 0.10a of nfsscan, dated 7/25/2003.
+
+THIS IS A PRELIMINARY RELEASE OF A NEW UTILITY.  YOU SHOULD ASSUME
+THAT THE COMMANDLINE FORMATS WILL EVOLVE RAPIDLY OVER THE NEXT SEVERAL
+WEEKS.
+ 
+Please report bugs, problems or suggestions for improvements to
+ellard@eecs.harvard.edu.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+COMMANDLINE OPTIONS
+
+Usage: nfsscan [options] [trace1 [trace2 ...]]
+
+If no trace files are specified, then the trace is read from stdin.
+
+Command line options:
+
+-h		Print usage message and exit.
+
+-B [CFUG]	Compute per-Client, per-File, per-User, or per-Group info.
+
+-c c1[,c2]*	Include only activity performed by the specified clients.
+
+-C c1[,c2]*	Exclude activity performed by the specified clients.
+
+-d		Compute per-directory statistics.  This implicitly
+		enables -BF so that per-file info is computed.
+
+-f		Do file info tracking.  This implicitly enables -BF so
+		that per-File info is computed.
+
+-F fhtype	Specify the file handle type used by the server.
+		(advfs or netapp)
+
+-g g1[,g2]*	Include only activity performed by the specified groups.
+
+-G g1[,g2]*	Exclude activity performed by the specified groups.
+
+-l		Record average operation latency.
+
+-o basename	Write output to files starting with the specified
+		basename.  The "Count" table goes to basename.cnt,
+		"Latency" to basename.lat, and "File" to basename.fil.
+		The default is to write all output to stdout.
+
+-O op[,op]*	Specify the list of "interesting" operations.
+		The default list is:
+
+		read,write,lookup,getattr,access,create,remove
+
+		If the first op starts with +, then the specified list
+		of ops is appended to the default list.  The special
+		pseudo-ops readM and writeM represent the number of
+		bytes read and written, expressed in MB.
+
+-t interval	Time interval for cummulative statistics (such as
+		operation count).  The default is 300 seconds. 
+		If set to 0, then the entire trace is processed.  By
+		default, time is specified in seconds, but if the last
+		character of the interval is any of s, m, h, or d,
+		then the interval is interpreted as seconds, minutes,
+		hours, or days.
+
+-u u1[,u2]*	Include only activity performed by the specified users.
+
+-U u1[,u2]*	Exclude activity performed by the specified users.
+
+-Z		Omit count and latency lines that have a zero total
+		operation count.
+
+
+OUTPUT FORMATS
+
+Each line generated by nfsscan begins with a token that indicates the
+table to which it belongs.
+
+COUNT LINES
+
+These lines all begin with 'C' (or #C, for comments),
+and have the following format:
+
+C time client euid egid fh TOTAL INTERESTING <OPS>
+
+time - The time of the start of the measurement interval.
+
+client - The IP number of the client.  If the user has not
+	requested per-client statistics, this field is 'u'.
+
+euid - The effective uid of the caller, in decimal.  If the user has
+	not requested per-user statistics, this field is 'u'.
+
+egid - The effective gid of the caller, in decimal.  If the user has
+	not requested per-group statistics, this field is 'u'.
+
+fh - The file handle used by the operation.  If the user has not
+	requested per-file statistics, this field is 'u'.
+
+TOTAL - The total number of operations for the given client, euid,
+	egid, and fh, for all the operations in <OPS...>.  Note that
+	this is NOT the same as the total of all operations!  For
+	example, if you set <OPS> to the empty list, the TOTAL will
+	always be zero.
+
+INTERESTING - The total number of "interesting" operations.  These are
+	either the default operations (listed below) or the whatever
+	set of operations the user specifies.
+
+
+<OPS> - Following INTERESTING, the count for each "interesting"
+	operation observed during the measurement interval is printed. 
+	The list of operations can be specified or extended on the
+	commandline.  By default, the list of operations is:
+
+		read, write, lookup, getattr, access, create, remove
+
+LATENCY LINES
+
+The format for the "latency" lines is like that of the "count" lines,
+except the lines all begin with "L" (or "#L") and each count
+(including the TOTAL and INTERESTING counts) is followed the average
+latency for that operation.  If the count for a particular operation
+is 0, then the average latency is shown as -1.
+
+Note that the counts for the latency lines may be (and often are)
+different than the counts for count lines.  This is because the count
+lines show the number of calls that were observed, and the latency
+lines require observing both calls and reponses.
+
+FILE LINES
+
+These lines show information about files, rather than information
+about calls.  These lines all begin with "F" (or "#F").  The file
+information (size, mode, etc) are currently only printed for files,
+not directories.
+
+The format is:
+
+F type state fh path dirs mode size atime mtime ctime
+
+type - Either "F" for file, or "D" for directory.
+
+state - "A" if the file is still alive at the end of the
+	trace, or "D" if the file has been deleted.
+
+fh - The file handle.
+
+path - as much of the file path as can be reconstructed from the
+	observed traffic.
+
+dirs - the number of directories in the path.
+
+mode - the most recently observed permissions on the file, in hex.
+
+size - the most recently observed size of the file, in hex.
+
+atime - last access time of the file
+
+mtime - last modification time of the file
+
+ctime - last file status change time
+
+DIRECTORY LINES
+
+These lines show operation count information for files and
+directories.  These lines all begin with "D" (or "#D").  Each line
+begins with the following fields:
+
+time - The time of the start of the measurement interval.
+
+Dir/File - D for directory, F for file.
+
+dircnt - The length of the path to that directory, or zero for files.
+
+path - The path from the mount point to the directory or file.
+
+fh - The file handle of the directory or file.
+
+TOTAL - The total number of operations for the given client, euid,
+	egid, and fh, for all the operations in <OPS...>.  Note that
+	this is NOT the same as the total of all operations!  For
+	example, if you set <OPS> to the empty list, the TOTAL will
+	always be zero.
+
+Following the TOTAL, the count for each "interesting" operation
+observed during the measurement interval is printed.  The list of
+operations can be specified on the commandline.  By default, the list
+of operations is:
+
+	read, write, lookup, getattr, access, create, remove
+
+The information for files is redundant because this information is
+also reflected in the Count lines (if -BF is used), but it is
+sometimes useful to have it in the same format as the directory info.
+
+The TOTAL and op counts for directories represent the total number of
+ops for the files in that directory AND all of its subdirectories.
+
+NOTE: there are several potential problems with the directory information:
+
+	1.  It is possible (and not uncommon) for some part of a path
+		to be missing from the traces.  The path is
+		reconstructed as far back to the root as possible, but
+		this is not always successful.
+
+		If no information about the name of a file is known,
+		then it is given the name ".".
+
+	2.  If files are renamed during the trace, then the name shown
+		is the most recent name for the file.
+
+	3.  If files are removed during the trace, they are still
+		reported in the summary.
+
+		This can lead to an error:  if a directory is deleted,
+		and then another directory is created elsewhere with a
+		new name but the same inode number, this new directory
+		can "inherit" all the info about the files in the old
+		directory, including parentage.  In the worst case,
+		this can cause a loop.  The program will detect such
+		loops, and therefore not get caught forever, but it
+		doesn't do anything clever about them.
diff --git a/TBBT/trace_init/ns_loc2gmt.pl b/TBBT/trace_init/ns_loc2gmt.pl
new file mode 100755
index 0000000..815f68f
--- /dev/null
+++ b/TBBT/trace_init/ns_loc2gmt.pl
@@ -0,0 +1,108 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: ns_loc2gmt,v 1.6 2003/07/28 14:27:16 ellard Exp $
+#
+# A helper application used by ns_quickview to convert from local time
+# to GMT.  nfsdump records time as localtime, but gnuplot only know
+# how to deal with dates expressed as Greenwich Mean Time (which it
+# then displays using the local time, for some reason).
+#
+# This is a fragile tool -- it must be run in the same time zone in
+# which the data was collected via nfsdump, or else it will not do the
+# proper conversion.  Improvements welcomed!
+#
+# The 'C' (count) and 'L' (latency) records use the second column for
+# dates, expressed as seconds.microseconds in localtime.  The seconds
+# portion is the only part of the data modified by this program. 
+# Comment lines are passed through unaltered.
+#
+# There is no error checking.  Garbage in, garbage out.
+#
+# Note - we're throwing the microseconds away.
+
+
+use Getopt::Std;
+require 'timelocal.pl';
+
+$Usage =<< ".";
+
+Usage: $0 [options] [table1.ns [table2.ns ... ]]
+
+If no table files are specified, then the input is read from stdin.
+
+Command line options:
+
+-h		Print usage message and exit.
+
+-d secs		Time offset, in seconds, to subtract from each time
+		in the input tables.  Note that all times are rounded
+		down to the nearest second.
+
+IMPORTANT NOTE:  this must be run in the same time zone in which the
+data was collected via nfsdump, or else it will not do the proper
+conversion unless the -d option is used.
+
+.
+
+$Options = "d:";
+if (! getopts ($Options)) {
+	print STDERR "$0: Incorrect usage.\n";
+	print STDERR $Usage;
+	exit (1);
+}
+if (defined $opt_h) {
+	print $Usage;
+	exit (0);
+}
+
+$TimeOffset = 0;
+if (defined $opt_d) {
+	$TimeOffset = int ($opt_d);
+}
+
+while ($line = <>) {
+	if ($line =~ /^#/) {
+		print $line;
+		next;
+	}
+
+	@arr = split (' ', $line);
+
+	($secs, $usec) = split (/\./, $arr[1]);
+	$secs -= $TimeOffset;
+
+	$arr[1] = &timegm (localtime ($secs));
+
+	print join (' ', @arr);
+	print "\n";
+}
+
+exit (0);
+
diff --git a/TBBT/trace_init/ns_quickview.pl b/TBBT/trace_init/ns_quickview.pl
new file mode 100755
index 0000000..1460235
--- /dev/null
+++ b/TBBT/trace_init/ns_quickview.pl
@@ -0,0 +1,245 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: ns_quickview,v 1.9 2003/07/28 14:27:17 ellard Exp $
+
+use Getopt::Std;
+
+$ProgDir = $0;
+$ProgDir =~ /(^.*)\//;
+$ProgDir = $1;
+if (!$ProgDir) {
+	$ProgDir = ".";
+}
+
+$GNUPLOT_PATH	= "gnuplot";
+$GNUPLOT_OPTS	= "-persist";
+$LOC2GMT_PATH	= "$ProgDir/ns_loc2gmt";
+
+$OUTPUT		= "qv.ps";
+$GP_OUTPUT	= "qv.gp";
+$TERMINAL	= "postscript";
+$SIZE		= undef;
+$EXTRA_CMD	= undef;
+$TITLE_TEXT	= undef;
+$PLOT_OPTS	= '';
+@OPS		= ( 7 );
+@SCALES		= ();
+
+$Usage =<< ".";
+
+Usage: $0 [options] table1.ns [table2.ns ...]
+
+At least one table file must be specified.
+
+Command line options:
+
+-h		Print usage message and exit.
+
+-c cmd		Pass an extra command directly to gnuplot.
+
+-g		Save the gnuplot commands to $GP_OUTPUT instead
+		of executing the immediately.
+
+-k		Show the key for each line on the plot.  The default
+		is not to show the key.
+
+-l		If more than one input file is specified, superimpose
+		the plot for each so that they all appear to begin at
+		the same time as the first row in the first file.
+
+-o filename	Save the plot to the specified file.  The default
+		output file is \"$OUTPUT\".
+
+-O op1,...,opN	Plot the specified columns from the table.  The
+		default is $OPS[0], the total operation count.
+		Note that the operations must be specified by column
+		number, not by name.
+
+-t terminal	Create a plot for the given gnuplot terminal specification.
+		The default is \"$TERMINAL\".  See the gnuplot
+		documentation for more information.
+
+-T string	Use the specified string as the title for the plot.
+		The default is no title.
+
+-s sizespec	Set the output size specifier.  See the gnuplot
+		documentation for more information.
+
+-S s1,..,sN	Set the scaling factor for each file.  This is useful
+		for plotting files aggregated across different time
+		intervals on the same scale.
+
+.
+
+$Options = "c:ghklo:O:P:t:T:s:S:";
+if (! getopts ($Options)) {
+	print STDERR "$0: Incorrect usage.\n";
+	print STDERR $Usage;
+	exit (1);
+}
+if (defined $opt_h) {
+	print $Usage;
+	exit (0);
+}
+
+$EXTRA_CMD	= $opt_c	if (defined $opt_c);
+$OUTPUT		= $opt_o	if (defined $opt_o);
+$TERMINAL	= $opt_t	if (defined $opt_t);
+$SIZE		= $opt_s	if (defined $opt_s);
+$TITLE_TEXT	= $opt_T	if (defined $opt_T);
+$PLOT_OPTS	= $opt_P	if (defined $opt_P);
+@OPS	= split (/,/, $opt_O)	if (defined $opt_O);
+@SCALES	= split (/,/, $opt_S)	if (defined $opt_S);
+
+$SAVE_GNUPLOT	= defined $opt_g;
+$SHOW_KEY	= defined $opt_k;
+$LAYER		= defined $opt_l;
+
+@FILES = @ARGV;
+
+if (@FILES == 0) {
+	print STDERR "No tables to plot?\n";
+	exit (1);
+}
+
+&makePlot;
+exit (0);
+
+sub makePlot {
+	my @starts = ();
+	my @ends = ();
+
+	my $nfiles = @FILES;
+	my $nops = @OPS;
+
+	if ($SAVE_GNUPLOT) {
+		die unless open (PLOT, ">$GP_OUTPUT");
+	}
+	else {
+		die unless open (PLOT, "|$GNUPLOT_PATH $GNUPLOT_OPTS");
+	}
+
+	$preamble = `cat $ProgDir/template.gp`;
+	print PLOT $preamble;
+
+	print PLOT "set terminal $TERMINAL\n";
+	print PLOT "set output \'$OUTPUT\'\n";
+	if (defined $SIZE) {
+		print PLOT "set size $SIZE\n";
+	}
+
+	if (defined $TITLE_TEXT) {
+		print PLOT "set title \"$TITLE_TEXT\"\n";
+	}
+
+	if (defined $EXTRA_CMD) {
+		print PLOT "$EXTRA_CMD\n";
+	}
+
+	print PLOT "set key below\n";
+
+	if ($LAYER) {
+		for ($i = 0; $i < $nfiles; $i++) {
+			($starts [$i], $ends [$i]) =
+					findFileTimeSpan ($FILES [$i]);
+		}
+	}
+
+	print PLOT "plot $PLOT_OPTS \\\n";
+	for ($i = 0; $i < $nfiles; $i++) {
+		my $offset = 0;
+		my $scale = 1;
+		if (defined $SCALES[$i]) {
+			$scale = $SCALES[$i];
+		}
+
+		my $file = $FILES [$i];
+
+		if ($LAYER) {
+			$offset = $starts [$i] - $starts [0];
+		}
+
+		for ($j = 0; $j < @OPS; $j++) {
+			my $op = $OPS[$j];
+
+			print PLOT "\t\"< $LOC2GMT_PATH -d $offset $file\" \\\n";
+			print PLOT "\t\tusing 2:(\$$op*$scale) \\\n";
+			if ($SHOW_KEY) {
+				print PLOT "\t\ttitle \'$file:$op\'\\\n";
+			}
+			print PLOT "\t\twith lines lw 2";
+			if ($i != $nfiles - 1 || $j != $nops - 1) {
+				print PLOT ",\\\n";
+			}
+			else {
+				print PLOT "\n";
+			}
+		}
+	}
+	print PLOT "\n";
+	close PLOT;
+}
+
+# Find the earliest and latest times in a file created by nfsscan, and
+# return them as a list.  Returns the empty list if anything goes
+# wrong.
+
+sub findFileTimeSpan {
+	my ($fname) = @_;
+	my ($smallest, $largest) = (-1, -1);
+
+	if (! open (FF, "<$fname")) {
+		return ();
+	}
+
+	while (my $l = <FF>) {
+		if ($l =~ /^#/) {
+			next;
+		}
+
+		@a = split (' ', $l);
+
+		if ($smallest < 0 || $smallest > $a[1]) {
+			$smallest = $a[1];
+		}
+		if ($largest < 0 || $largest < $a[1]) {
+			$largest = $a[1];
+		}
+	}
+
+	close FF;
+
+	if ((! defined $smallest) || (! defined $largest)) {
+		return ();
+	}
+
+	return ($smallest, $largest);
+}
+
diff --git a/TBBT/trace_init/ns_split.pl b/TBBT/trace_init/ns_split.pl
new file mode 100755
index 0000000..b600448
--- /dev/null
+++ b/TBBT/trace_init/ns_split.pl
@@ -0,0 +1,153 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: ns_split,v 1.4 2003/07/28 14:27:17 ellard Exp $
+
+use Getopt::Std;
+
+$ProgDir = $0;
+$ProgDir =~ /(^.*)\//;
+$ProgDir = $1;
+if (!$ProgDir) {
+	$ProgDir = ".";
+}
+
+require "$ProgDir/userUtils.pl";
+
+@ADD_USERS	= ();
+@DEL_USERS	= ();
+@ADD_GROUPS	= ();
+@DEL_GROUPS	= ();
+@ADD_CLIENTS	= ();
+@DEL_CLIENTS	= ();
+
+$Usage =<< ".";
+
+Usage: $0 [options] [table1.ns [table2.ns ... ]]
+
+If no table files are specified, then the input is read from stdin.
+
+Command line options:
+
+-h		Print usage message and exit.
+
+-c c1[,c2]*	Include only activity performed by the specified clients.
+
+-C c1[,c2]*	Exclude activity performed by the specified clients.
+
+-g g1[,g2]*	Include only activity performed by the specified groups.
+
+-G g1[,g2]*	Exclude activity performed by the specified groups.
+
+-u u1[,u2]*	Include only activity performed by the specified users.
+
+-U u1[,u2]*	Exclude activity performed by the specified users.
+
+.
+
+$cmdline = "$0 " . join (' ', @ARGV);
+$Options = "c:C:g:G:u:U::";
+if (! getopts ($Options)) {
+	print STDERR "$0: Incorrect usage.\n";
+	print STDERR $Usage;
+exit (1);
+}
+if (defined $opt_h) {
+	print $Usage;
+	exit (0);
+}
+
+if (defined $opt_u) {
+	@ADD_USERS = &logins2uids ($opt_u);
+}
+if (defined $opt_U) {
+	@DEL_USERS = &logins2uids ($opt_U);
+}
+if (defined $opt_g) {
+	@ADD_GROUPS = &groups2gids ($opt_g);
+}
+if (defined $opt_G) {
+	@DEL_GROUPS = &groups2gids ($opt_G);
+}
+if (defined $opt_c) {
+	@ADD_CLIENTS = split (/,/, $opt_c);
+}
+if (defined $opt_C) {
+	@DEL_CLIENTS = split (/,/, $opt_C);
+}
+
+print "#cmdline $cmdline\n";
+
+while ($l = <>) {
+	if ($l =~ /^#/) {
+		print $l;
+		next;
+	}
+
+	my ($type, $time, $client, $fh, $euid, $egid, @vals) = split (' ', $l);
+
+	next unless ($type eq 'C');
+
+	# Something wrong with the input?
+
+	next if (@vals == 0);
+
+	if (saveRecord ($client, $fh, $euid, $egid)) {
+		print $l;
+	}
+}
+
+sub saveRecord {
+	my ($client, $fh, $euid, $egid) = @_;
+
+	if (@ADD_CLIENTS && !grep (/^$client$/, @ADD_CLIENTS)) {
+		return 0;
+	}
+	if (@DEL_CLIENTS && grep (/^$client$/, @DEL_CLIENTS)) {
+		return 0;
+	}
+
+	if (@ADD_USERS && !grep (/^$euid$/, @ADD_USERS)) {
+		return 0;
+	}
+	if (@DEL_USERS && grep (/^$euid$/, @DEL_USERS)) {
+		return 0;
+	}
+
+	if (@ADD_GROUPS && !grep (/^$egid$/, @ADD_GROUPS)) {
+		return 0;
+	}
+	if (@DEL_GROUPS && grep (/^$egid$/, @DEL_GROUPS)) {
+		return 0;
+	}
+
+	return (1);
+}
+
+exit 0;
diff --git a/TBBT/trace_init/ns_timeagg.pl b/TBBT/trace_init/ns_timeagg.pl
new file mode 100755
index 0000000..9e5e536
--- /dev/null
+++ b/TBBT/trace_init/ns_timeagg.pl
@@ -0,0 +1,218 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: ns_timeagg,v 1.7 2003/07/28 14:27:17 ellard Exp $
+
+use Getopt::Std;
+
+$ProgDir = $0;
+$ProgDir =~ /(^.*)\//;
+$ProgDir = $1;
+if (!$ProgDir) {
+	$ProgDir = ".";
+}
+
+require "$ProgDir/common.pl";
+
+$UseClient	= 0;
+$UseFH		= 0;
+$UseUID		= 0;
+$UseGID		= 0;
+$NEW_INTERVAL	= 300;
+$OMIT_ZEROS	= 0;
+
+$Usage =<< ".";
+
+Usage: $0 [options] [table1.ns [table2.ns ... ]]
+
+If no table files are specified, then the input is read from stdin.
+
+Command line options:
+
+-h		Print usage message and exit.
+
+-B flags	Choose fields to NOT aggregate.  The fields are:
+		C - client host ID
+		U - Effective user ID
+		G - Effective group ID
+		F - File handle
+
+-R secs		Round the start time to the closest multiple of
+		the given number of seconds.  This is useful for
+		dealing with small amounts of clock drift.  For example,
+		if the trace starts at 12:00:01 instead of 12:00:00,
+		it is probably convenient to pretend that it started
+		at 12:00:00.
+
+-t secs		Aggregate over the given number of seconds.   The default
+		is $NEW_INTERVAL.  If the current interval does not
+		divide the new interval, warning messages are printed
+		and the output might not be meaningful.
+
+		If secs is 0, then the total for the entire table is
+		computed.
+
+-Z		Omit count lines that have a zero total operation count.
+.
+
+$cmdline = "$0 " . join (' ', @ARGV);
+$Options = "B:hR:t:Z";
+if (! getopts ($Options)) {
+	print STDERR "$0: Incorrect usage.\n";
+	print STDERR $Usage;
+	exit (1);
+}
+if (defined $opt_h) {
+	print $Usage;
+	exit (0);
+}
+
+if (defined $opt_t) {
+	if ($opt_t <= 0) {
+		$EndTime = 0;
+	}
+	$NEW_INTERVAL	= $opt_t;
+}
+
+$TIME_ROUNDING	= defined $opt_R ? $opt_R : 0;
+
+if (defined $opt_B) {
+	$UseClient = ($opt_B =~ /C/);
+	$UseUID = ($opt_B =~ /U/);
+	$UseGID	 = ($opt_B =~ /G/);
+	$UseFH = ($opt_B =~ /F/);
+}
+
+# We need to let the measurement of time be a little bit inexact, so
+# that a small rounding error or truncation doesn't throw everything
+# off.
+
+$TimerInacc = 0.05;
+
+# Print out the commandline as a comment in the output.
+
+print "#cmdline $cmdline\n";
+
+# It would be nice to make this do the right thing with Latency lines,
+# and perhaps file op counts.
+
+while ($l = <>) {
+	if ($l =~ /^#C/) {
+		print $l;
+		next;
+	}
+
+	next if ($l =~ /^#/);
+
+	my ($type, $time, $client, $fh, $euid, $egid, @vals) = split (' ', $l);
+
+	next unless ($type eq 'C');
+
+	# Something wrong with the input?
+
+	next if (@vals == 0);
+
+	if (!defined $StartTime) {
+		$StartTime = findStartTime ($time, $TIME_ROUNDING);
+		if ($NEW_INTERVAL > 0) {
+			$EndTime = $StartTime + $NEW_INTERVAL - $TimerInacc;
+		}
+	}
+
+	if ($EndTime > 0 && $time >= $EndTime) {
+		my $diff = int ($time - $StartTime);
+		if ($diff > 0) {
+			if ($NEW_INTERVAL % $diff != 0) {
+				print STDERR "$0: time interval mismatch ";
+				print STDERR "(from $diff to $NEW_INTERVAL)\n";
+			}
+		}
+
+		dumpKeys ($StartTime);
+
+		$StartTime += $NEW_INTERVAL;
+		$EndTime = $StartTime + $NEW_INTERVAL - $TimerInacc;
+	}
+
+
+	# Aggregate across clients, files, users, and groups unless
+	# specifically asked NOT to.
+
+	$client = $UseClient ? $client : 'u';
+	$fh = $UseFH ? $fh : 'u';
+	$euid = $UseUID ? $euid : 'u';
+	$egid = $UseGID	 ? $egid : 'u';
+
+	$key = "$client,$fh,$euid,$egid";
+
+	if (exists $Totals{$key}) {
+		my (@tots) = split (' ', $Totals{$key});
+		for (my $i = 0; $i < @vals; $i++) {
+			$tots[$i] += $vals[$i];
+		}
+		$Totals{$key} = join (' ', @tots);
+	}
+	else {
+		$Totals{$key} = join (' ', @vals);
+	}
+}
+
+if ($EndTime <= 0) {
+	dumpKeys ($StartTime);
+}
+
+sub dumpKeys {
+	my ($start) = @_;
+	my ($i, $k, $ks);
+
+	foreach $k ( keys %Totals ) {
+		my (@v) = split (' ', $Totals{$k});
+
+		if ($OMIT_ZEROS && $v[0] == 0) {
+			next;
+		}
+
+		$ks = $k;
+		$ks =~ s/,/\ /g;
+
+		print "C $start $ks";
+
+		for ($i = 0; $i < @v; $i++) {
+			print " $v[$i]";
+		}
+		print "\n";
+
+		for ($i = 0; $i < @v; $i++) {
+			$v[$i] = 0;
+		}
+		$Totals{$k} = join (' ', @v);
+	}
+}
+
+exit 0;
diff --git a/TBBT/trace_init/ns_tsplit.pl b/TBBT/trace_init/ns_tsplit.pl
new file mode 100755
index 0000000..e3dd420
--- /dev/null
+++ b/TBBT/trace_init/ns_tsplit.pl
@@ -0,0 +1,219 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: ns_tsplit,v 1.4 2003/07/26 20:52:04 ellard Exp $
+
+use Getopt::Std;
+use Time::Local;
+
+$ProgDir = $0;
+$ProgDir =~ /(^.*)\//;
+$ProgDir = $1;
+if (!$ProgDir) {
+	$ProgDir = ".";
+}
+
+# Set the default start and end times.
+
+$DEF_BEGIN_TIME	= "20000101:00:00:00";
+$DEF_END_TIME	= "20360101:00:00:00";
+
+# The range includes everything from the start time up to and less
+# than the end time (so if you want one day, it is correct to go
+# midnight to midnight, instead of going until 23:59:59).
+
+$Usage =<< ".";
+
+Usage: $0 [options] rangeSpec... - [table.ns [table.ns...]]
+
+Command line options:
+
+-h		Print usage message and exit.
+
+Any number of time range specifier can be provided.  The special
+symbol "-" is used to separated the time specifiers from the input
+file names.  If input is taken from stdin, then the "-" may be
+omitted.
+
+The basic time range specification format is:  StartTime-EndTime where
+StartTime and EndTime have the form YYMMDD[:HH[:MM[:SS]]].  All
+records from the input that have a timestamp greater than or equal to
+StartTime and less than EndTime are printed to stdout.
+
+If StartTime is omitted, $DEF_BEGIN_TIME is used.
+If EndTime is omitted, $DEF_END_TIME is used.
+
+Note that omitting both the StartTime and EndTime results in a rangeSpec
+of "-", which is the special symbol that marks the end of the rangeSpecs.
+.
+
+$cmdline = "$0 " . join (' ', @ARGV);
+$Options = "h";
+if (! getopts ($Options)) {
+	print STDERR "$0: Incorrect usage.\n";
+	print STDERR $Usage;
+	exit (1);
+}
+if (defined $opt_h) {
+	print $Usage;
+	exit (0);
+}
+
+@StartTimes	= ();
+@EndTimes	= ();
+
+while ($ts = shift @ARGV) {
+	last if ($ts eq '-');
+
+	my ($ts_s, $ts_e) = split (/-/, $ts);
+	my $s;
+
+	if ($ts_s eq '') {
+		$ts_s = $DEF_START_TIME;
+	}
+	$s = &ts2secs ($ts_s);
+	if (! defined $s) {
+		print STDERR "Failed to translate ($ts_s)\n";
+		exit (1);
+	}
+	push @StartTimes, $s;
+
+	if ($ts_e eq '') {
+		$ts_e = $DEF_END_TIME;
+	}
+	$s = &ts2secs ($ts_e);
+	if (! defined $s) {
+		print STDERR "Failed to translate ($ts_e)\n";
+		exit (1);
+	}
+
+	push @EndTimes, $s;
+}
+
+print "#cmdline $cmdline\n";
+
+while ($l = <>) {
+	if ($l =~ /^#/) {
+		print $l;
+		next;
+	}
+
+	my ($type, $time, $client, $fh, $euid, $egid, @vals) = split (' ', $l);
+
+	next unless ($type eq 'C');
+
+	# Something wrong with the input?
+
+	next if (@vals == 0);
+
+	if (saveRecord ($time)) {
+		print $l;
+	}
+}
+
+exit 0;
+
+sub saveRecord {
+	my ($t) = @_;
+
+	for (my $i = 0; $i < @StartTimes ; $i++) {
+		if (($StartTimes[$i] <= $t) && ($t < $EndTimes[$i])) {
+			return (1);
+		}
+	}
+
+	return (0);
+}
+
+# This is ugly!
+#
+# The basic time specification format is:  YYMMDD[:HH[:MM[:SS]]].
+#
+# To make a time range, join two time specs with a -.
+#
+# The data spec is Y2.01K compliant...  I'm assuming that all the
+# traces processed by this tool will be gathered before 2010.  If
+# anyone is still gathering NFSv3 traces in 2010, I'm sorry.
+
+sub ts2secs {
+	my ($ts) = @_;
+	my ($hour, $min, $sec) = (0, 0, 0);
+
+	my (@d) = split (/:/, $ts);
+
+	if ($d[0] =~ /([0-9][0-9])([0-2][0-9])([0-3][0-9])/) {
+		$year = $1 + 100;
+		$mon = $2 - 1;
+		$day = $3;
+	}
+	else {
+		return undef;
+	}
+
+	if (@d > 1) {
+		if ($d[1] =~ /([0-2][0-9])/) {
+			$hour = $1;
+		}
+		else {
+			return undef;
+		}
+	}
+
+	if (@d > 2) {
+		if ($d[2] =~ /([0-5][0-9])/) {
+			$min = $1;
+		}
+		else {
+			return undef;
+		}
+	}
+
+	if (@d > 3) {
+		if ($d[3] =~ /([0-5][0-9])/) {
+			$sec = $1;
+		}
+		else {
+			return undef;
+		}
+	}
+
+	my $s = timelocal ($sec, $min, $hour, $day, $mon, $year,
+			undef, undef, undef);
+
+	my ($s2, $m2, $h2, $md2, $mon2, $y2, $isdst) = localtime ($s);
+	if (($s2 != $sec) || $min != $m2 || $hour != $h2 || $day != $md2) {
+		print "failed 1!\n";
+	}
+	if (($mon != $mon2) || $year != $y2) {
+		print "failed 2!\n";
+	}
+
+	return ($s);
+}
+
diff --git a/TBBT/trace_init/rfs.pl b/TBBT/trace_init/rfs.pl
new file mode 100755
index 0000000..c167df7
--- /dev/null
+++ b/TBBT/trace_init/rfs.pl
@@ -0,0 +1,243 @@
+#!/usr/bin/perl -w
+
+use Getopt::Std;
+$Usage =<< "EOF";
+
+Usage: $0 [options]
+
+This program runs after nfsscan.pl. It outputs the file system hierarchy (RFSFS) as well as
+the file system hierarchy map (stored in three files: fh-path-map, noattrdirdiscard, noattrdir-root).
+
+This perl program do post processing based on this file
+
+Command line options:
+
+-h	Print Usage message and exit.
+
+-S  The file in file system hierarchy are all of size 0. 
+    Without -S, the files are written to it full length.
+
+
+EOF
+
+$writebuf = "R" x 8193;
+$writeBlockSize = 8192;
+
+main ();
+
+sub rfsCreateSymlink()
+{
+        my ($path, $pathcnt, $sizeHexStr) = @_;
+        $sizeHexStr = "0x".$sizeHexStr;
+
+        my $dir = $path;
+        my $name = '';
+        my $cmdbuf;
+
+        $dir =~ /(^.*)\/(.*)/;
+        $dir = $1;
+        $name = $2;
+        if (!$dir) {$dir = ".";}
+        die "name is empty\n" if (!$name);
+        #print "path($path) dir($dir) name($name)\n";
+
+        if (! -e $dir) {
+                $cmdbuf = "mkdir -p $dir";
+                system $cmdbuf;
+                print "RFS: Warning: the directory should be created already: $path\n";
+        } else {
+                die "warning: directory name exist but not a directory: $path\n" if (!(-d $dir));
+        }
+
+        my $size = hex($sizeHexStr);
+        #print "size($sizeHexStr) lp($lp) rem($remSize)\n";
+
+        my $pathnamebuf = $sizeHexStr;
+        symlink ($pathnamebuf, $path);
+        #if (! symlink ($pathnamebuf, $path) ) {
+        #	print STDERR "JIAWU: WARNING: failed to create symlink: $path -> $pathnamebuf\n";
+        #}
+}
+
+
+sub  rfsCreateFile()
+{
+        my ($path, $pathcnt, $sizeHexStr) = @_;
+        $sizeHexStr = "0x".$sizeHexStr;
+
+        my $dir = $path;
+        my $name = '';
+        my $cmdbuf;
+
+        $dir =~ /(^.*)\/(.*)/;
+        $dir = $1;
+        $name = $2;
+        if (!$dir) {$dir = ".";}
+        die "name is empty\n" if (!$name);
+        #print "path($path) dir($dir) name($name)\n";
+
+        if (! -e $dir) {
+                $cmdbuf = "mkdir -p $dir";
+                system $cmdbuf;
+                print "RFS: Warning: the directory should be created already: $path\n";
+        } else {
+                die "warning: directory name exist but not a directory: $path\n" if (!(-d $dir));
+        }
+
+        my $size = hex($sizeHexStr);
+        my $remSize = $size % $writeBlockSize;
+        my $lp = ($size - $remSize) / $writeBlockSize;
+        #print "size($sizeHexStr) lp($lp) rem($remSize)\n";
+
+        open RFSTMPWRITE, ">$path" || die "RFS: can not open file for write";
+
+	# the eight lines below should not be commented out 
+		if (!defined $opt_S) {
+        my $i = 0;
+        for ($i = 0; $i < $lp; $i++) {
+                syswrite(RFSTMPWRITE, $writebuf, $writeBlockSize);
+        }
+        if ($remSize) {
+                syswrite(RFSTMPWRITE, $writebuf, $remSize);
+                #print "write ($remSize) byte\n";
+        }
+        close RFSTMPWRITE;
+		}
+}
+
+# Useful commands:
+# sort -n -k a,b -c -u 
+# 
+# *** WARNING *** The locale specified by the  environment  affects  sort
+#      order.  Set LC_ALL=C or LC_ALL=POSIX to get the traditional sort order that uses native
+#      byte values.
+
+sub parseArgs {
+	my $Options = "S";
+	if (! getopts($Options)) {
+		print STDERR "$0: Incorrect usage.\n";
+        print STDERR $Usage;
+		exit (1);
+	}
+}
+
+sub main {
+
+	parseArgs ();
+
+	my $cmdbuf;
+
+	# format of lines in test.fil:
+	# "F(1) $type(2) $state(3) $fh(4) $path(5) $pathcnt(6) $attrOrig(7-14) $attr()
+	# attrOrig: ($size(7) $mode(8) $op(9) $atime(10) $mtime(11) $ctime(12) $nlink(13) $ts(14))
+	# attrLast: ($size(15) $mode(16) $op(17) $atime(18) $mtime(19) $ctime(20) $nlink(21) $ts(22))
+
+	# skip comment lines
+	# if (path_count ($6) == 0 or original_op($9) == "create" or "mkdir" or "symlink") skip the file 
+
+	$cmdbuf = 'gawk \' !/^[#]/ { if ($6 != "0") print $0 }\'  test.fil > all.fil';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	# sort the test.fil according to path name
+	$cmdbuf = 'export LC_ALL=C; sort -k 5,5 all.fil > all.fil.order; echo $LC_ALL';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	# keep the interested field only
+	# 2(D/F) 4(FH) 5(path) 6(count) 15(size_last) 21(nlink_last) 14(ts_s) 22(ts_e)
+	$cmdbuf = 'gawk \' { print $14, $22, $4, $5, $15, $21}\'  all.fil.order > fh-path-map-all';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	# skip comment lines
+	# if (path_count ($6) == 0 or original_op($9) == "create" or "mkdir" or "symlink") skip the file 
+
+	$cmdbuf = 'gawk \' !/^[#]/ { if ($6 != "0" && $9 != "create" && $9 != "mkdir" && $9 != "symlink") print $0 }\'  test.fil > active.fil';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	# sort the active.fil according to path name
+	$cmdbuf = 'export LC_ALL=C; sort -k 5,5 active.fil > active.fil.order; echo $LC_ALL';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	# keep the interested field only
+	# 2(D/F) 4(FH) 5(path) 6(count) 7(size) 8(mode) 13(nlink)
+	$cmdbuf = 'gawk \' { print $2, $4, $5, $6, $7, $8 }\'  active.fil.order > active';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	$cmdbuf = 'gawk \' { print $4, $5, $7, $13}\'  active.fil.order > fh-path-map';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	# format output files
+	$cmdbuf = 'export LC_ALL=C; mv noattrdirdiscard noattrdirdiscard-tmp; sort -u -k 1,1 noattrdirdiscard-tmp > noattrdirdiscard; echo $LC_ALL; rm -f noattrdirdiscard-tmp';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	$cmdbuf = 'export LC_ALL=C; mv noattrdir-root noattrdir-root-tmp; sort -u -k 1,1 noattrdir-root-tmp > noattrdir-root; echo $LC_ALL; rm -f noattrdir-root-tmp';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	#$cmdbuf = 'mv noattrdirdiscard noattrdirdiscard-tmp; cat  noattrdirdiscard-tmp missdiscardfh >noattrdirdiscard; rm -f noattrdirdiscard-tmp missdiscardfh';
+	$cmdbuf = 'mv noattrdirdiscard noattrdirdiscard-tmp; cat  noattrdirdiscard-tmp missdiscardfh >noattrdirdiscard; rm -f noattrdirdiscard-tmp';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	$cmdbuf = "cut -d ' ' -f '1 2' fh-path-map > fh-path-map-tmp";
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	$cmdbuf = 'cat noattrdirdiscard noattrdir-root fh-path-map-tmp > fh-path-map-play; rm -rf fh-path-map-tmp';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	#exit(0);
+	
+	# so far, you got the following information
+	# in active: all files/dirs active 
+	# in noattrdir-root: a set of fhs pointing to RFSNN0
+	# in rfsinfo: a set of dir fhs refer to RFSNNxxx(>0)
+	#                a set of file fhs should be discard due to short of information
+
+	# create the active fs
+	# 1. BASEDIR/RFSNN0
+	# 2. BASEDIR/active
+	$cmdbuf = "mkdir -p RFSFS/RFSNN0";
+	system $cmdbuf;
+	open RFS_ACTIVE, "active" || die "open active failed\n";
+	while (<RFS_ACTIVE>) {
+		chop;
+		my ($type, $fh, $path, $pathcnt, $sizeHexStr, $mode) = split (' ', $_, 7);
+		if ($type==2) {
+			$cmdbuf = "mkdir -p RFSFS$path";
+			system $cmdbuf;
+		}elsif ($type==1){
+			&rfsCreateFile("RFSFS$path", $pathcnt, $sizeHexStr);
+		}elsif ($type==5){
+			#print STDERR "SYMLINK: $type fh: $fh path: $path\n";
+			&rfsCreateSymlink("RFSFS$path", $pathcnt, $sizeHexStr);
+		}else {
+			print STDERR "special file: $type fh: $fh path: $path\n";
+		}
+
+		my $line_num=0;
+		$line_num++;
+		if ( ($line_num %100)==0 ) {
+			print STDERR "$line_num\n";
+		}
+		
+	}
+
+	# create map table: key (fh), value (path/fn)
+
+	# check whether there is fh that is not mapped to any path/fn in the trace
+
+	# simulate a replay of trace
+
+	return;
+	
+}
+
+1;
diff --git a/TBBT/trace_init/rfs.pl.old b/TBBT/trace_init/rfs.pl.old
new file mode 100755
index 0000000..550f2c8
--- /dev/null
+++ b/TBBT/trace_init/rfs.pl.old
@@ -0,0 +1,138 @@
+#!/usr/bin/perl -w
+
+$Usage =<< ".";
+
+This is the rfs program
+
+After run nfsscan, you will get a file-list file in the output
+
+This perl program do post processing based on this file
+
+
+.
+
+$writebuf = "R" x 8193;
+$writeBlockSize = 8192;
+
+
+main ();
+
+sub  rfsCreateFile()
+{
+        my ($path, $pathcnt, $sizeHexStr) = @_;
+        $sizeHexStr = "0x".$sizeHexStr;
+
+        my $dir = $path;
+        my $name = '';
+        my $cmdbuf;
+
+        $dir =~ /(^.*)\/(.*)/;
+        $dir = $1;
+        $name = $2;
+        if (!$dir) {$dir = ".";}
+        die "name is empty\n" if (!$name);
+        #print "path($path) dir($dir) name($name)\n";
+
+        if (! -e $dir) {
+                $cmdbuf = "mkdir -p $dir";
+                system $cmdbuf;
+                print "RFS: Warning: the directory should be created already: $path\n";
+        } else {
+                die "warning: directory name exist but not a directory: $path\n" if (!(-d $dir));
+        }
+
+        my $size = hex($sizeHexStr);
+        my $remSize = $size % $writeBlockSize;
+        my $lp = ($size - $remSize) / $writeBlockSize;
+        #print "size($sizeHexStr) lp($lp) rem($remSize)\n";
+
+        open RFSTMPWRITE, ">$path" || die "RFS: can not open file for write";
+
+        my $i = 0;
+        for ($i = 0; $i < $lp; $i++) {
+                syswrite(RFSTMPWRITE, $writebuf, $writeBlockSize);
+        }
+        if ($remSize) {
+                syswrite(RFSTMPWRITE, $writebuf, $remSize);
+                #print "write ($remSize) byte\n";
+        }
+        close RFSTMPWRITE;
+}
+
+# Useful commands:
+# sort -n -k a,b -c -u 
+# 
+#
+
+sub main {
+
+	my $cmdbuf;
+	
+	# skip comment lines
+	# if (path_count ($6) == 0 or original_op($9) == "create" or "mkdir") skip the file 
+
+	$cmdbuf = 'gawk \' !/^[#]/ { if ($6 != "0" && $9 != "create" && $9 != "mkdir") print $0 }\'  test.fil > active.fil';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	# sort the active.fil according to path_count
+	$cmdbuf = 'sort -k 5,5 active.fil > active.fil.order';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	$cmdbuf = 'sort -n -k 6,6 active.fil > active.fil.order-pathcnt';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	# keep the interested field only
+	# 2(D/F) 4(FH) 5(path) 6(count) 7(size) 8(mode)
+	$cmdbuf = 'gawk \' { print $2, $4, $5, $6, $7, $8 }\'  active.fil.order > active';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	$cmdbuf = 'gawk \' { print $4, $5 }\'  active.fil.order > fh-path-map';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	$cmdbuf = 'gawk \' { print $2, $4, $5, $6, $7, $8 }\'  active.fil.order-pathcnt > active-pathcnt';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	$cmdbuf = 'gawk \' { print $4, $5 }\'  active.fil.order-pathcnt > fh-path-map-pathcnt';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	#exit(0);
+	
+	# so far, you got the following information
+	# in active: all files/dirs active 
+	# in noattrdir-root: a set of fhs pointing to RFSNN0
+	# in rfsinfo: a set of dir fhs refer to RFSNNxxx(>0)
+	#                a set of file fhs should be discard due to short of information
+
+	# create the active fs
+	# 1. BASEDIR/RFSNN0
+	# 2. BASEDIR/active
+	$cmdbuf = "mkdir -p RFSFS/RFSNN0";
+	system $cmdbuf;
+	open RFS_ACTIVE, "active";
+	while (<RFS_ACTIVE>) {
+		chop;
+		my ($type, $fh, $path, $pathcnt, $sizeHexStr, $mode) = split (' ', $_, 7);
+		if ($type eq "D") {
+			$cmdbuf = "mkdir -p RFSFS$path";
+			system $cmdbuf;
+		}
+		else {
+			&rfsCreateFile("RFSFS$path", $pathcnt, $sizeHexStr);
+		}
+		
+	}
+
+	# create map table: key (fh), value (path/fn)
+
+	# check whether there is fh that is not mapped to any path/fn in the trace
+
+	# simulate a replay of trace
+
+	return;
+	
+}
+
+1;
diff --git a/TBBT/trace_init/rfs.stub.pl b/TBBT/trace_init/rfs.stub.pl
new file mode 100755
index 0000000..a0de62a
--- /dev/null
+++ b/TBBT/trace_init/rfs.stub.pl
@@ -0,0 +1,213 @@
+#!/usr/bin/perl -w
+
+$Usage =<< ".";
+
+This is the rfs program
+
+After run nfsscan, you will get a file-list file in the output
+
+This perl program do post processing based on this file
+
+
+.
+
+$writebuf = "R" x 8193;
+$writeBlockSize = 8192;
+
+main ();
+
+sub rfsCreateSymlink()
+{
+        my ($path, $pathcnt, $sizeHexStr) = @_;
+        $sizeHexStr = "0x".$sizeHexStr;
+
+        my $dir = $path;
+        my $name = '';
+        my $cmdbuf;
+
+        $dir =~ /(^.*)\/(.*)/;
+        $dir = $1;
+        $name = $2;
+        if (!$dir) {$dir = ".";}
+        die "name is empty\n" if (!$name);
+        #print "path($path) dir($dir) name($name)\n";
+
+        if (! -e $dir) {
+                $cmdbuf = "mkdir -p $dir";
+                system $cmdbuf;
+                print "RFS: Warning: the directory should be created already: $path\n";
+        } else {
+                die "warning: directory name exist but not a directory: $path\n" if (!(-d $dir));
+        }
+
+        my $size = hex($sizeHexStr);
+        #print "size($sizeHexStr) lp($lp) rem($remSize)\n";
+
+        my $pathnamebuf = $sizeHexStr;
+        symlink ($pathnamebuf, $path);
+        #if (! symlink ($pathnamebuf, $path) ) {
+        #	print STDERR "JIAWU: WARNING: failed to create symlink: $path -> $pathnamebuf\n";
+        #}
+}
+
+
+sub  rfsCreateFile()
+{
+        my ($path, $pathcnt, $sizeHexStr) = @_;
+        $sizeHexStr = "0x".$sizeHexStr;
+
+        my $dir = $path;
+        my $name = '';
+        my $cmdbuf;
+
+        $dir =~ /(^.*)\/(.*)/;
+        $dir = $1;
+        $name = $2;
+        if (!$dir) {$dir = ".";}
+        die "name is empty\n" if (!$name);
+        #print "path($path) dir($dir) name($name)\n";
+
+        if (! -e $dir) {
+                $cmdbuf = "mkdir -p $dir";
+                system $cmdbuf;
+                print "RFS: Warning: the directory should be created already: $path\n";
+        } else {
+                die "warning: directory name exist but not a directory: $path\n" if (!(-d $dir));
+        }
+
+        my $size = hex($sizeHexStr);
+        my $remSize = $size % $writeBlockSize;
+        my $lp = ($size - $remSize) / $writeBlockSize;
+        #print "size($sizeHexStr) lp($lp) rem($remSize)\n";
+
+        open RFSTMPWRITE, ">$path" || die "RFS: can not open file for write";
+
+	# the eight lines below should not be commented out 
+        #my $i = 0;
+        #for ($i = 0; $i < $lp; $i++) {
+        #        syswrite(RFSTMPWRITE, $writebuf, $writeBlockSize);
+        #}
+        #if ($remSize) {
+        #        syswrite(RFSTMPWRITE, $writebuf, $remSize);
+        #        #print "write ($remSize) byte\n";
+        #}
+        close RFSTMPWRITE;
+}
+
+# Useful commands:
+# sort -n -k a,b -c -u 
+# 
+# *** WARNING *** The locale specified by the  environment  affects  sort
+#      order.  Set LC_ALL=C or LC_ALL=POSIX to get the traditional sort order that uses native
+#      byte values.
+
+sub main {
+
+	my $cmdbuf;
+
+	# format of lines in test.fil:
+	# "F(1) $type(2) $state(3) $fh(4) $path(5) $pathcnt(6) $attrOrig(7-14) $attr()
+	# attrOrig: ($size(7) $mode(8) $op(9) $atime(10) $mtime(11) $ctime(12) $nlink(13) $ts(14))
+	# attrLast: ($size(15) $mode(16) $op(17) $atime(18) $mtime(19) $ctime(20) $nlink(21) $ts(22))
+
+	# skip comment lines
+	# if (path_count ($6) == 0 or original_op($9) == "create" or "mkdir" or "symlink") skip the file 
+
+	$cmdbuf = 'gawk \' !/^[#]/ { if ($6 != "0") print $0 }\'  test.fil > all.fil';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	# sort the test.fil according to path name
+	$cmdbuf = 'export LC_ALL=C; sort -k 5,5 all.fil > all.fil.order; echo $LC_ALL';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	# keep the interested field only
+	# 2(D/F) 4(FH) 5(path) 6(count) 15(size_last) 21(nlink_last) 14(ts_s) 22(ts_e)
+	$cmdbuf = 'gawk \' { print $14, $22, $4, $5, $15, $21}\'  all.fil.order > fh-path-map-all';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	# skip comment lines
+	# if (path_count ($6) == 0 or original_op($9) == "create" or "mkdir" or "symlink") skip the file 
+
+	$cmdbuf = 'gawk \' !/^[#]/ { if ($6 != "0" && $9 != "create" && $9 != "mkdir" && $9 != "symlink") print $0 }\'  test.fil > active.fil';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	# sort the active.fil according to path name
+	$cmdbuf = 'export LC_ALL=C; sort -k 5,5 active.fil > active.fil.order; echo $LC_ALL';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	# keep the interested field only
+	# 2(D/F) 4(FH) 5(path) 6(count) 7(size) 8(mode) 13(nlink)
+	$cmdbuf = 'gawk \' { print $2, $4, $5, $6, $7, $8 }\'  active.fil.order > active';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	$cmdbuf = 'gawk \' { print $4, $5, $7, $13}\'  active.fil.order > fh-path-map';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	# format output files
+	$cmdbuf = 'export LC_ALL=C; mv noattrdirdiscard noattrdirdiscard-tmp; sort -u -k 1,1 noattrdirdiscard-tmp > noattrdirdiscard; echo $LC_ALL; rm -f noattrdirdiscard-tmp';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	$cmdbuf = 'export LC_ALL=C; mv noattrdir-root noattrdir-root-tmp; sort -u -k 1,1 noattrdir-root-tmp > noattrdir-root; echo $LC_ALL; rm -f noattrdir-root-tmp';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+
+	#$cmdbuf = 'mv noattrdirdiscard noattrdirdiscard-tmp; cat  noattrdirdiscard-tmp missdiscardfh >noattrdirdiscard; rm -f noattrdirdiscard-tmp missdiscardfh';
+	$cmdbuf = 'mv noattrdirdiscard noattrdirdiscard-tmp; cat  noattrdirdiscard-tmp missdiscardfh >noattrdirdiscard; rm -f noattrdirdiscard-tmp';
+	print "$cmdbuf\n";
+	system $cmdbuf;
+	
+	#exit(0);
+	
+	# so far, you got the following information
+	# in active: all files/dirs active 
+	# in noattrdir-root: a set of fhs pointing to RFSNN0
+	# in rfsinfo: a set of dir fhs refer to RFSNNxxx(>0)
+	#                a set of file fhs should be discard due to short of information
+
+	# create the active fs
+	# 1. BASEDIR/RFSNN0
+	# 2. BASEDIR/active
+	$cmdbuf = "mkdir -p RFSFS/RFSNN0";
+	system $cmdbuf;
+	open RFS_ACTIVE, "active" || die "open active failed\n";
+	while (<RFS_ACTIVE>) {
+		chop;
+		my ($type, $fh, $path, $pathcnt, $sizeHexStr, $mode) = split (' ', $_, 7);
+		if ($type==2) {
+			$cmdbuf = "mkdir -p RFSFS$path";
+			system $cmdbuf;
+		}elsif ($type==1){
+			&rfsCreateFile("RFSFS$path", $pathcnt, $sizeHexStr);
+		}elsif ($type==5){
+			#print STDERR "SYMLINK: $type fh: $fh path: $path\n";
+			&rfsCreateSymlink("RFSFS$path", $pathcnt, $sizeHexStr);
+		}else {
+			print STDERR "special file: $type fh: $fh path: $path\n";
+		}
+
+		my $line_num=0;
+		$line_num++;
+		if ( ($line_num %100)==0 ) {
+			print STDERR "$line_num\n";
+		}
+		
+	}
+
+	# create map table: key (fh), value (path/fn)
+
+	# check whether there is fh that is not mapped to any path/fn in the trace
+
+	# simulate a replay of trace
+
+	return;
+	
+}
+
+1;
diff --git a/TBBT/trace_init/test.cnt b/TBBT/trace_init/test.cnt
new file mode 100644
index 0000000..e78f658
--- /dev/null
+++ b/TBBT/trace_init/test.cnt
@@ -0,0 +1,2 @@
+#cmdline nfsscan.pl 
+#C time client fh euid egid TOTAL INTERESTING read write lookup getattr access create remove
diff --git a/TBBT/trace_init/test.fil b/TBBT/trace_init/test.fil
new file mode 100755
index 0000000..429a873
--- /dev/null
+++ b/TBBT/trace_init/test.fil
@@ -0,0 +1 @@
+#cmdline nfsscan.pl 
diff --git a/TBBT/trace_init/userUtils.pl b/TBBT/trace_init/userUtils.pl
new file mode 100755
index 0000000..4019d5d
--- /dev/null
+++ b/TBBT/trace_init/userUtils.pl
@@ -0,0 +1,87 @@
+#
+# Copyright (c) 2002-2003
+#      The President and Fellows of Harvard College.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: userUtils.pl,v 1.5 2003/07/26 20:52:04 ellard Exp $
+#
+# utils.pl - deal with details like turning login names into uids.
+#
+
+sub logins2uids {
+	my ($str) = @_;
+
+	my @uids = ();
+	my @logins = split (/,/, $str);
+
+	my $j = 0;
+	for (my $i = 0; $i < @logins; $i++) {
+		if ($logins[$i] =~ /^[0-9]/) {
+			$uids[$j++] = $logins[$i];
+		}
+		else {
+			my ($login, $pw, $uid, $gid) = getpwnam ($logins[$i]);
+			if (defined $uid) {
+				$uids[$j++] = $uid;
+			}
+			else {
+				# &&& Warning or error?
+				print STDERR "WARNING: Unrecognized login ($logins[$i])\n";
+				$uids[$j++] = $logins[$i];
+			}
+		}
+	}
+
+	return (@uids);
+}
+
+sub groups2gids {
+	my ($str) = @_;
+
+	my @gids = ();
+	my @groups = split (/,/, $str);
+
+	for (my $i = 0; $i < @groups; $i++) {
+		if ($groups[$i] =~ /^[0-9]/) {
+			$gids[$j++] = $groups[$i];
+		}
+		else {
+			my $gid = getgrnam ($groups[$i]);
+			if (defined $gid) {
+				$gids[$j++] = $gid;
+			}
+			else {
+				# &&& Warning or error?
+				print STDERR "WARNING: Unrecognized group ($logins[$i])\n";
+				$gids[$j++] = $groups[$i];
+			}
+		}
+	}
+
+	return (@gids);
+}
+
+1;
diff --git a/TBBT/trace_play/Makefile.org b/TBBT/trace_play/Makefile.org
new file mode 100644
index 0000000..d019a0b
--- /dev/null
+++ b/TBBT/trace_play/Makefile.org
@@ -0,0 +1,328 @@
+#
+#	@(#)Makefile	2.1	97/10/23
+#
+# Makefile to build SFS benchmark suite
+#
+#
+#    Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+#	All rights reserved.
+#		Standard Performance Evaluation Corporation (SPEC)
+#		6585 Merchant Place, Suite 100
+#		Warrenton, VA 20187
+#
+#	This tape contains benchmarks acquired from several sources who
+#	understand and agree with SPEC's goal of creating fair and objective
+#	benchmarks to measure computer performance.
+#
+#	This copyright notice is placed here only to protect SPEC in the
+#	event the source is misused in any manner that is contrary to the
+#	spirit, the goals and the intent of SPEC.
+#
+#	The source code is provided to the user or company under the license
+#	agreement for the SPEC Benchmark Suite for this tape.
+#
+#
+# *****************************************************************
+# *								  *
+# *	Copyright 1991,1992  Legato Systems, Inc.                 *
+# *	Copyright 1991,1992  Auspex Systems, Inc.                 *
+# *	Copyright 1991,1992  Data General Corporation             *
+# *	Copyright 1991,1992  Digital Equipment Corporation        *
+# *	Copyright 1991,1992  Interphase Corporation               *
+# *	Copyright 1991,1992  Sun Microsystems, Inc.               *
+# *                                                               *
+# *****************************************************************
+
+#
+# -----------------------  How to use this makefile  --------------------
+#
+# The makefile is divided into 10 sections:
+#  1) basic information
+#  2) default compiler definitions
+#  3) vendor specific definitions
+#  4) OS feature specific definitions
+#  5) final compiler definitions (includes specific vendor and feature defs)
+#  6) source file definitions
+#  7) object file definitions
+#  8) rules and targets for building sfs
+#  9) lint, install, clean, misc rules
+
+
+# ----------------------  default compiler definitions  -----------------
+#
+# For Solaris 2.X (SunOS 5.X) or later
+MACHID = solaris2
+CC=cc
+OPT = -O
+CFLAGS = -v -Xc -D__sparc -D_POSIX_SOURCE
+LDFLAGS =
+EXTRA_CFLAGS = -DPORTMAP
+EXTRA_LDFLAGS =
+EXTRA_LINTFLAGS =
+EXTRA_LIBS =
+RESVPORT_MOUNT=
+OSTYPE = -DSVR4 -DSOLARIS2
+INCDIR = -I.
+RPCLIB = rpc/librpclib.a
+LIBS = -lm -lsocket -lnsl
+
+#
+# ----------------------  OS feature specific definitions  ------------------
+#
+
+#
+# A UNIX derivative that only supports the getfsent(3) family of calls
+# should have the USEFSTAB variable set.
+# A UNIX derivative that supports the getmntent(3) family of calls
+# should have the line commented out.
+#FSTAB = -DUSEFSTAB
+
+# SFS uses the setsid(2) system call to form a new proces group
+# This prevents 'synchronization' signals from causing parent shell (sh)
+# to exit. SETPGRP_CALL allows you to specify the alternative use
+# of the setpgrp(2) and which variation you are using. 
+
+# If you are linking with BSD libraries then uncomment the next line.
+# SETPGRP_CALL = -DSETPGRP_BSD
+
+# If you are linking with SYSV type libraries then uncomment the next line.
+#SETPGRP_CALL = -DSETPGRP_SYSV
+
+# if your client is failing the mount even when run as root then you should
+# uncomment the RESVPORT_MOUNT to explicitly bind to a reserved port.
+# RESVPORT_MOUNT = -DRESVPORT
+
+#
+# ----------------------  final compiler definitions  -----------------------
+#
+
+# DEBUG = -g
+CFLAGS = 
+EXTRA_CFLAGS =
+
+LDFLAGS =  $(OSTYPE)
+
+
+#
+# ----------------------  source file definitions  ------------------
+#
+
+MAKEFILE =	Makefile
+
+DOC =		sfs.1 README sfs.1
+
+SHELLFILES =	sfs_mgr sfs_mcr sfs_rc 
+
+V2_HDR =	sfs_c_def.h sfs_c_nfs.h
+
+V3_HDR =	sfs_c_def.h sfs_c_nfs.h
+
+V2_SRC =	sfs_2_ops.c sfs_2_vld.c
+
+V3_SRC =	sfs_3_ops.c sfs_3_vld.c
+
+C_SRC =		sfs_c_clk.c sfs_c_dat.c sfs_c_dmp.c sfs_c_man.c \
+		sfs_c_pnt.c sfs_c_rnd.c sfs_c_sig.c sfs_c_bio.c \
+		sfs_2_xdr.c sfs_3_xdr.c sfs_c_mnt.c sfs_c_chd.c \
+		sfs_c_clnt.c
+
+C_COMMON_SRC =	sfs_c_sub.c
+
+M_HDR =		sfs_m_def.h
+
+M_PRIME_SRC =	sfs_m_prm.c
+
+M_SYNCD_SRC =	sfs_m_snc.c
+
+M_MSG_SRC =	sfs_m_msg.c
+
+M_COMMON_SRC =	sfs_m_xdr.c
+
+#
+# ----------------------  object file definitions  -------------------
+#
+
+V2_OBJ =	sfs_2_ops.o sfs_2_vld.o
+
+V3_OBJ =	sfs_3_ops.o sfs_3_vld.o
+
+C_OBJ =		sfs_c_clk.o sfs_c_dat.o sfs_c_dmp.o sfs_c_man.o \
+		sfs_c_pnt.o sfs_c_rnd.o sfs_c_sig.o sfs_c_bio.o \
+		sfs_2_xdr.o sfs_3_xdr.o sfs_c_mnt.o sfs_c_chd.o \
+		sfs_c_clnt.o
+
+C_COMMON_OBJ =	sfs_c_sub.o
+
+
+M_PRIME_OBJ =	sfs_m_prm.o
+
+M_SYNCD_OBJ =	sfs_m_snc.o
+
+M_MSG_OBJ =	sfs_m_msg.o
+
+M_COMMON_OBJ =	sfs_m_xdr.o
+
+#
+# ----------------------  rules and targets for building sfs  ---------
+#
+
+BENCH = /tmp/spec
+all:		fix_perm install
+
+compile:	fix_perm install
+
+fix_perm:
+		chmod 755 $(BENCH)/src
+		chmod 755 $(BENCH)/src/rpc
+		chmod 755 $(BENCH)/bin
+
+sfs:		$(V2_HDR) $(M_HDR) $(V2_OBJ) $(C_OBJ) \
+		$(C_COMMON_OBJ) $(M_COMMON_OBJ) $(M_MSG_OBJ) $(RPCLIB)
+		$(CC) -o $@ $(LDFLAGS) $(V2_OBJ) $(C_OBJ) $(C_COMMON_OBJ) \
+			$(M_COMMON_OBJ) $(M_MSG_OBJ) $(RPCLIB) $(LIBS) \
+			$(EXTRA_LIBS) 
+
+sfs3:	$(V3_HDR) $(M_HDR) $(V3_OBJ) $(C_OBJ) \
+		$(C_COMMON_OBJ) $(M_COMMON_OBJ) $(M_MSG_OBJ) $(RPCLIB)
+		$(CC) -o $@ $(LDFLAGS) $(V3_OBJ) $(C_OBJ) $(C_COMMON_OBJ) \
+			$(M_COMMON_OBJ) $(M_MSG_OBJ) $(RPCLIB) $(LIBS) \
+			$(EXTRA_LIBS) 
+
+sfs_prime:	$(V2_HDR) $(M_HDR) $(M_PRIME_OBJ) \
+		$(C_COMMON_OBJ) $(M_COMMON_OBJ) $(M_MSG_OBJ) $(RPCLIB)
+		$(CC) -o $@ $(LDFLAGS) $(M_PRIME_OBJ) $(C_COMMON_OBJ) \
+			$(M_COMMON_OBJ) $(M_MSG_OBJ) $(RPCLIB) $(LIBS) \
+			$(EXTRA_LIBS) 
+
+sfs_syncd:	$(V2_HDR) $(M_HDR) $(M_SYNCD_OBJ) \
+		$(C_COMMON_OBJ) $(M_COMMON_OBJ) $(RPCLIB)
+		$(CC) -o $@ $(LDFLAGS) $(M_SYNCD_OBJ) $(C_COMMON_OBJ) \
+			$(M_COMMON_OBJ) $(RPCLIB) $(LIBS) $(EXTRA_LIBS) 
+
+.c.o:
+		$(CC) -c $(INCDIR) $(CFLAGS) $(EXTRA_CFLAGS) $(DEBUG) \
+			$(SETPGRP_CALL) $(FSTAB) $(OSTYPE) $(OPT) \
+			$(RESVPORT_MOUNT) $*.c
+
+${RPCLIB}: FRC
+	@cd rpc; make MACHID="${MACHID}"\
+		CC="${CC}" CFLAGS="${CFLAGS}" \
+		LDFLAGS="${LDFLAGS}" EXTRA_CFLAGS="${EXTRA_CFLAGS}" \
+		EXTRA_LDFLAGS="${EXTRA_LDFLAGS}" EXTRA_LIBS="${EXTRA_LIBS}" \
+		LIBS="${LIBS}" OSTYPE="${OSTYPE}" OPT="${OPT}" \
+		EXTRA_LINTFLAGS="${EXTRA_LINTFLAGS}" \
+		RESVPORT_MOUNT="${RESVPORT_MOUNT}"\
+		librpclib.a
+
+sfs_3_ops.o:	sfs_c_nfs.h sfs_c_def.h sfs_3_ops.c
+
+sfs_3_vld.o:	sfs_c_nfs.h sfs_c_def.h sfs_3_vld.c
+
+sfs_3_xdr.o:	sfs_c_nfs.h sfs_c_def.h sfs_3_xdr.c
+
+sfs_c_bio.o:	sfs_c_nfs.h sfs_c_def.h sfs_c_bio.c
+
+sfs_c_chd.o:	sfs_c_nfs.h sfs_c_def.h sfs_m_def.h sfs_c_chd.c
+
+sfs_c_clk.o:	sfs_c_nfs.h sfs_c_def.h sfs_c_clk.c
+
+sfs_c_clnt.o:	sfs_c_nfs.h sfs_c_def.h sfs_c_clnt.c
+
+sfs_c_dat.o:	sfs_c_def.h sfs_m_def.h sfs_c_nfs.h sfs_c_dat.c
+
+sfs_c_dmp.o:	sfs_c_nfs.h sfs_c_def.h sfs_c_dmp.c
+
+sfs_c_man.o:	sfs_c_nfs.h sfs_c_def.h \
+		sfs_m_def.h sfs_c_man.c
+
+sfs_c_mnt.o:	sfs_c_nfs.h sfs_c_def.h sfs_c_mnt.c
+
+sfs_2_ops.o:	sfs_c_nfs.h sfs_c_def.h sfs_2_ops.c
+
+sfs_c_pnt.o:	sfs_c_nfs.h sfs_c_def.h \
+		sfs_m_def.h sfs_c_pnt.c
+
+sfs_c_rnd.o:	sfs_c_rnd.c
+
+sfs_c_sig.o:	sfs_c_nfs.h sfs_c_def.h sfs_c_sig.c
+
+sfs_c_sub.o:	sfs_c_nfs.h sfs_c_def.h sfs_c_sub.c
+
+sfs_2_vld.o:	sfs_c_nfs.h sfs_c_def.h sfs_2_vld.c
+
+sfs_2_xdr.o:	sfs_c_nfs.h sfs_c_def.h sfs_2_xdr.c
+
+sfs_m_msg.o:	sfs_c_nfs.h sfs_c_def.h \
+		sfs_m_def.h sfs_m_msg.c
+
+sfs_m_prm.o:	sfs_c_nfs.h sfs_c_def.h \
+		sfs_m_def.h sfs_m_prm.c
+
+sfs_m_snc.o:	sfs_c_nfs.h sfs_c_def.h \
+		sfs_m_def.h sfs_m_snc.c
+
+sfs_m_xdr.o:	sfs_m_def.h sfs_m_xdr.c
+
+#
+# ----------------------  lint, install, clean, misc rules  -----------------
+#
+
+lint:		lint_sfs lint_sfs3 lint_prime lint_syncd
+
+lint_sfs:	$(V2_HDR) $(M_HDR) $(V2_SRC) $(C_SRC) \
+		$(C_COMMON_SRC) $(M_COMMON_SRC) $(M_MSG_SRC)
+		lint -Dlint $(INCDIR) $(CFLAGS) $(EXTRA_CFLAGS) $(DEBUG) \
+			$(EXTRA_LINTFLAGS) \
+			$(SETPGRP_CALL) $(FSTAB) $(OSTYPE) \
+			$(RESVPORT_MOUNT) \
+			$(V2_SRC) $(C_SRC) $(C_COMMON_SRC) \
+			$(M_COMMON_SRC) $(M_MSG_SRC) \
+			$(LIBS) $(EXTRA_LIBS) \
+			> sfs.lint
+
+lint_prime:	$(V2_HDR) $(M_HDR) $(M_PRIME_SRC) \
+		$(C_COMMON_SRC) $(M_COMMON_SRC) $(M_MSG_SRC)
+		lint -Dlint $(INCDIR) $(CFLAGS) $(EXTRA_CFLAGS) $(DEBUG) \
+			$(EXTRA_LINTFLAGS) \
+			$(SETPGRP_CALL) $(FSTAB) $(OSTYPE) \
+			$(RESVPORT_MOUNT) \
+			$(M_PRIME_SRC) $(C_COMMON_SRC) \
+			$(M_COMMON_SRC) $(M_MSG_SRC) \
+			$(LIBS) $(EXTRA_LIBS) \
+			> sfs_prime.lint
+
+lint_syncd:	$(V2_HDR) $(M_HDR) $(M_SYNCD_SRC) \
+		$(C_COMMON_SRC) $(M_COMMON_SRC)
+		lint -Dlint $(INCDIR) $(CFLAGS) $(EXTRA_CFLAGS) $(DEBUG) \
+			$(EXTRA_LINTFLAGS) \
+			$(SETPGRP_CALL) $(FSTAB) $(OSTYPE) \
+			$(RESVPORT_MOUNT) \
+			$(M_SYNCD_SRC) $(C_COMMON_SRC) $(M_COMMON_SRC) \
+			$(LIBS) $(EXTRA_LIBS) \
+			> sfs_syncd.lint
+
+lint_sfs3:	$(V3_HDR) $(M_HDR) $(V3_SRC) $(C_SRC) \
+		$(C_COMMON_SRC) $(M_COMMON_SRC) $(M_MSG_SRC)
+		lint -Dlint $(INCDIR) $(CFLAGS) $(EXTRA_CFLAGS) $(DEBUG) \
+			$(EXTRA_LINTFLAGS) \
+			$(SETPGRP_CALL) $(FSTAB) $(OSTYPE) \
+			$(RESVPORT_MOUNT) \
+			$(V3_SRC) $(C_SRC) $(C_COMMON_SRC) \
+			$(M_COMMON_SRC) $(M_MSG_SRC) \
+			$(LIBS) $(EXTRA_LIBS) \
+			> sfs3.lint
+
+install:	sfs sfs3 sfs_syncd sfs_prime
+		chmod +x sfs_syncd sfs_prime \
+			sfs_mgr sfs_mcr sfs_ext_mon \
+			sfs_suchown sfs sfs3
+		./sfs_suchown $(RESVPORT_MOUNT) sfs sfs3
+
+clean clobber:
+		rm -f *.o sfs sfs_syncd sfs_prime \
+			sfs3 sfs_prime \
+			lint.out sfs_*.shr1 core *.lint
+		cd rpc; make clean
+		./sfs_suchown clobber
+
+FRC:
diff --git a/TBBT/trace_play/README b/TBBT/trace_play/README
new file mode 100644
index 0000000..e340761
--- /dev/null
+++ b/TBBT/trace_play/README
@@ -0,0 +1,10 @@
+
+The trace player executable is sfs3. For trace player to run, the owner of the
+executable has to be root.
+
+To make the executable:
+	make sfs3
+
+The change owner:
+	su - 
+	chown root:root sfs3
diff --git a/TBBT/trace_play/README.old b/TBBT/trace_play/README.old
new file mode 100644
index 0000000..3f31fff
--- /dev/null
+++ b/TBBT/trace_play/README.old
@@ -0,0 +1,140 @@
+A few notes about the redesign of the file selection algorithm for
+SFS 3.0, which may be incorporated into the inline comments in the
+next maintenance release.
+
+
+Q1.  How is the Poisson Distribution used in SFS?
+
+A1. The probabilities from a Poisson-derived distribution are used
+to select files from the I/O working-set in a non-uniform fashion.
+
+The load-generators are not Poisson Processes.  In particular, their
+inter-request times are not exponentially-distributed; they are programmed
+to have uniformly distributed think-times, which are only approximately
+achieved, due to limitations of the load-generating client and its
+operating system.
+
+Q2.  Why is a Poisson Distribution used in SFS, rather than, say a
+Zipf distribution?
+
+A2.  The reasoning behind the use of Poisson probabilities in SFS 2.0
+may be lost in the mists of time.  Because SFS 2.0 was withdrawn by SPEC
+before SFS 3.0 development had proceeded very far, there was considerable
+time-pressure to release SFS 3.0 quickly.  So we chose to patch the
+existing Poisson probability calculations instead of implementing a new
+distribution for file accesses.
+
+There is experimental data showing that a Zipf Distribution is a good
+model for file access probabilities.  The question of what distribution
+to use in SFS 4.0 is open, so various distributions can be considered.
+
+Q3.  Is it true that SFS 3.0 combines multiple Poisson cycles into a
+single cycle that is also a Poisson Distribution?
+
+A3.  The combination of the distributions follows the curve of a Poisson
+Distribution only if you treat each of the twelve generations of
+access-groups as a single outcome.
+
+Q4.  Why did the calculation of "Io_working_set.access_group_cnt" change 
+between SFS 2.0 and SFS 3.0?
+
+A4.  This calculation determines the number of access-groups in the I/O
+working-set.  The number of access-groups grows *roughly* in linear
+proportion to the number of files, so that no access-group contains more
+than 125 files.
+
+In SFS 2.0, 4 groups are added for every 500 files, but in SFS 3.0
+12 groups are added for every 1500 files, so the number of files per
+access-group remains roughly the same.
+
+The main effect of the change is how the number of groups is rounded.
+In SFS 2.0, the number of groups was rounded to a multiple of 4,
+with a minimum of 8 groups.  In SFS 3.0, the number of groups is
+rounded to a multiple of 12 (the value of "generations") so that the
+cycle of Poisson probabilities (for all 12 generations of access-groups)
+will be completely repeated group_cnt/12 times with no groups left over.
+
+Q5.  Why was the minimum number of access-groups changed from 8 to 12?
+Why not, say, 24?
+
+A5.  The choice was somewhat arbitrary.  Here is some of the rationale:
+
+In order to get a complete set of Poisson probabilities, there must be
+at least as many access-groups as generations.  If we had generations=24
+instead of 12, then some of the group-probabilities would be zero due to
+defect #2.  (Recall that with 24 groups in SFS 2.0, 13% were inaccessible
+due to rounding of the scaled probabilities.)  In SFS 2.0, 12 was the
+largest number of groups which did not trigger defect #2.  Of course,
+since we now know how to fix that defect, that wasn't the complete reason.
+
+Another consideration was that the number of access groups must be rounded
+to a multiple of the number of generations.  If we had used generations=24
+then the rounding would introduce a more radical change in the number
+of groups, especially for large numbers of procs.
+
+On the other hand, if we had used generations=8 instead of 12, we would
+have gotten very little variation in access probabilities, which seemed
+against the intent of the benchmark design.
+
+Q6.  Why is lambda being calculated differently in SFS 3.0?
+
+A6.  Lambda is the parameter of the Poisson Distribution which determines
+the shape of its probability density function, its mean, and other
+characteristics.
+
+SFS 2.0 set lambda to half the number of groups, which in turn was a
+function of the requested ops/sec/proc.  That was defect #4, which caused
+the shape of the access-distribution to change depending on how many
+processes a vendor chose to use -- it would get narrower as the number
+of processes was reduced.  SFS 3.0 sets lambda based on "generations",
+which is a constant.  Thus the new distribution has the same shape no
+matter how many load-generating processes are used.
+
+The key to defect #4 was that we *don't* want lambda to vary
+with the number of access-groups.  We want it to be a constant so that
+for a given size fileset the number of files that fit into cache 
+depends very little on the number of load-generation processes used.
+
+Q7.  Why was lambda set to half the number of groups in SFS 2.0
+instead of something else? 
+
+A7.  The SFS 2.0 rationale is not documented, as far as we know.  The nice
+thing about group_count/2 is that it puts the characteristic "hump" of the
+probability density function (the mode) near group_count/2, in the middle
+of the array of groups.  Probably that was the reason.
+
+In SFS 3.0, each cycle of probabilities has 12 groups, so lambda=6
+to preserve this feature of the distribution.
+
+Q8.  How is the SFS 3.0 approach differ from always using 12 access-groups
+and allowing the number of files per access-group to be more than 125?
+
+A8.  The end-result would have been roughly the same.  The reason this
+was not done was that SFS sometimes searches within an access-group, for
+instance to find the best fit for an operation.  The search is a linear
+search.  We were concerned that if the number of files in a group got
+too large, the client could get bogged down searching for the best fit.
+The search for the appropriate access-group is a binary search, which
+scales better.
+
+Q9.  Why not just limit the benchmark to 25 requested ops/second/process,
+so that the number of groups would always be 12 or less?
+ 
+A9.  Historically SPEC has given server vendors lots of leeway to
+have as few processes as they wish, modulo the Uniform Access Rule and
+the run-rule requirement for at least 8 processes per network.  In the
+interest of avoiding a long, drawn-out debate about adding a new run-rule
+to arbitrarily limit ops/process, we decided to simply fix the code so
+that it would work reasonably well for larger numbers of ops/process.
+
+Q10.  Where did the new variable "cumulative_ratio" come from?
+
+A10.  This variable is used in the loop that calculates Poisson distribution
+for I/O working-set accesses.  In 2.0, lambda^x and x! were calculated
+separately.  Both variables got very large and would overflow when 'x' got
+into the hundreds.  This was defect #3.  The Poisson distribution really
+only needs the ratio (lambda^x/x!), which is numerically more stable.
+So that is what the SFS 3.0 code calculates.
+
+Since SFS 3.0 never uses values of lambda other than 6.0, the change
+has proven to be moot.
diff --git a/TBBT/trace_play/agefs b/TBBT/trace_play/agefs
new file mode 100755
index 0000000000000000000000000000000000000000..bdebf34bc10dcc1235dc4fb5a3415a95b7d6ecbd
GIT binary patch
literal 83979
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%0DkCKlZX))p%JLRy7aofn{+!^Hg
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

literal 0
HcmV?d00001

diff --git a/TBBT/trace_play/agefs.log b/TBBT/trace_play/agefs.log
new file mode 100644
index 0000000..d3fcb00
--- /dev/null
+++ b/TBBT/trace_play/agefs.log
@@ -0,0 +1,36 @@
+
+
+agefs Wed Apr 21 18:28:42 EDT 2004
+
+
+agefs Wed Apr 21 18:31:44 EDT 2004
+Wed Apr 21 18:31:44 EDT 2004
+
+
+agefs Wed Apr 21 18:32:06 EDT 2004
+Wed Apr 21 18:32:06 EDT 2004
+
+
+agefs Wed Apr 21 18:32:58 EDT 2004
+Wed Apr 21 18:32:58 EDT 2004
+
+
+agefs Wed Apr 21 18:33:15 EDT 2004
+Wed Apr 21 18:33:15 EDT 2004
+Wed Apr 21 23:18:15 EDT 2004
+Wed Apr 21 23:18:15 EDT 2004
+Thu Apr 22 00:08:24 EDT 2004
+Thu Apr 22 00:08:24 EDT 2004
+Thu Apr 22 00:33:15 EDT 2004
+Thu Apr 22 00:33:15 EDT 2004
+Thu Apr 22 00:33:33 EDT 2004
+Thu Apr 22 00:33:33 EDT 2004
+Thu Apr 22 00:35:06 EDT 2004
+Thu Apr 22 00:35:06 EDT 2004
+Thu Apr 22 00:35:16 EDT 2004
+Thu Apr 22 00:35:16 EDT 2004
+Thu Apr 22 00:36:25 EDT 2004
+Thu Apr 22 00:38:36 EDT 2004
+Thu Apr 22 00:39:17 EDT 2004
+Thu Apr 22 00:39:19 EDT 2004
+Thu Apr 22 00:47:43 EDT 2004
diff --git a/TBBT/trace_play/frag_collect b/TBBT/trace_play/frag_collect
new file mode 100755
index 0000000..773e158
--- /dev/null
+++ b/TBBT/trace_play/frag_collect
@@ -0,0 +1,15 @@
+nfs stop
+umount $1
+mount $1
+nfs start
+cd $1
+echo "find test1 -print >$3.1"
+find test1 -print > $3.1
+echo "sed -d s/^/show_inode_info / $3.1"
+sed -e "s/^/show_inode_info /" $3.1 >$3.2
+echo "open $2" >$3.3
+cat $3.2 >> $3.3
+echo "debugfs -f $3.3"
+debugfs -f $3.3 > $3.4
+#echo "frag_count $3.4 > $3.5"
+#frag_count $3.4 > $3.5
diff --git a/TBBT/trace_play/frag_collect_cust b/TBBT/trace_play/frag_collect_cust
new file mode 100755
index 0000000..24d9c62
--- /dev/null
+++ b/TBBT/trace_play/frag_collect_cust
@@ -0,0 +1,14 @@
+#This is to collect info for something other than test1
+#test1 is hard-coded in frag_collect
+nfs stop
+umount $1
+mount $1
+nfs start
+echo "sed -d s/^/show_inode_info / $3"
+sed -e "s/^/show_inode_info /" $3 >$3.2
+echo "open $2" >$3.3
+cat $3.2 >> $3.3
+echo "debugfs -f $3.3"
+debugfs -f $3.3 > $3.4
+#echo "frag_count $3.4 > $3.5"
+#frag_count $3.4 > $3.5
diff --git a/TBBT/trace_play/frag_count b/TBBT/trace_play/frag_count
new file mode 100755
index 0000000000000000000000000000000000000000..e1cdae0c203dbc002dfef9101cd677150860f3ae
GIT binary patch
literal 26012
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

literal 0
HcmV?d00001

diff --git a/TBBT/trace_play/frag_count.c b/TBBT/trace_play/frag_count.c
new file mode 100644
index 0000000..a8d8397
--- /dev/null
+++ b/TBBT/trace_play/frag_count.c
@@ -0,0 +1,311 @@
+#include <stdio.h>
+#define RFS_ASSERT(condition)                                       \
+    if (!(condition)) {                                             \
+        fprintf(stderr, "Assertion failed: line %d, file \"%s\"\n", \
+                        __LINE__, __FILE__);                        \
+        fflush(stdout); \
+        fflush(stderr); \
+        exit(-1); \
+    }
+
+#define DISK_BLOCK_SIZE 4096
+#define SUB_DISTANCE
+int f()
+{}
+char buf[8024000];
+main(int argc, char ** argv)
+{
+	FILE * fp;
+	int ret;
+	char * p;
+	int i;
+	int frag_num, distance, tfrag_num=0;
+	int td=0, td_MB=0;
+	int max_block_num = -1;
+	int block_num = -1;
+	int last_block_num;
+	int tblock_num =0;
+	int last_block = 0;
+	int block_range_start, block_range_stop;
+	int lineno = 0;
+	int format_version = 1;
+	char * p1=NULL, *p2=NULL, *p3=NULL;
+	int size = -1;
+	int max_block = 0;
+	FILE * fpout;
+	char name[1024];
+	int file_num = 0;
+	unsigned long long distancell = 0;
+	int avg_frag_distance;
+	int avg_block_distance;
+#ifdef SUB_DISTANCE
+#define MAX_SUB_DISTANCE_NUM 50
+	int sub_distance_index;
+	int SUB_DISTANCE_NUM = 1;
+	int SUB_DISTANCE_SIZE = 1000000;
+	unsigned long long sub_distance[MAX_SUB_DISTANCE_NUM];
+	unsigned int sub_frag_num[MAX_SUB_DISTANCE_NUM], sub_block_num[MAX_SUB_DISTANCE_NUM];
+	memset (&sub_distance, 0, sizeof(sub_distance));
+	memset (&sub_frag_num, 0, sizeof(sub_frag_num));
+	memset (&sub_block_num, 0, sizeof(sub_block_num));
+
+	if (argc == 3) {
+		SUB_DISTANCE_NUM = atoi(argv[2]);
+		RFS_ASSERT ((SUB_DISTANCE_NUM >=1) && (SUB_DISTANCE_NUM <= MAX_SUB_DISTANCE_NUM));
+	}
+#endif
+
+	fp = fopen (argv[1], "r");
+    if (!fp) {
+        printf ("can not opern %s\n", argv[1]);
+        perror("open");
+        exit (0);
+    }
+
+
+	strcpy (name, argv[1]);
+	strcat (name, ".disk");
+
+	fpout = fopen(name, "w");
+	if (!fpout) {
+        printf ("can not opern %s\n", name);
+        perror("open");
+        exit (0);
+	}
+	
+	while (fgets(buf, sizeof(buf), fp)) {
+		lineno++;
+		if ((lineno%10000)==0) { // || (lineno >630000)) {
+			fprintf(stderr, "%d lines processed\n", lineno);
+		}
+		if (lineno==122165)
+			f();
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		if (buf[0]=='U') {
+			p = strstr (buf, "Size");
+			RFS_ASSERT (p);
+			if (size != -1) {
+				printf ("lineno %d size %d\n", lineno, size);
+			}
+			RFS_ASSERT (size == -1);
+			sscanf(p, "Size: %d", &size);
+			continue;
+		}
+
+
+		/* For now we ignore symbolic links */
+		if (!strncmp(buf, "Fast_link_dest", strlen("Fast_link_dest")))  {
+			f();
+			goto ENDLOOP;
+		}
+
+		if (buf[0]!='B')
+			continue;
+
+		RFS_ASSERT (!strcmp(buf, "BLOCKS:\n"));
+		fgets(buf, sizeof(buf), fp);
+		lineno++;
+		if (!(buf[strlen(buf)-1]=='\n')) {
+			printf ("line[%d] %s\n", lineno, buf);
+		};
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		if (!strcmp(buf, "\n"))
+			goto ENDLOOP;
+
+
+		RFS_ASSERT (size >= 0);
+		RFS_ASSERT (block_num == -1);
+		RFS_ASSERT (max_block_num == -1);
+		block_num = 0; /* the block number of block_range_start of current fragment */
+		last_block_num = 0; /* the block number of block_range_start of last fragment */
+		max_block_num = 0;
+		if (size >0) {
+			char line[1024];
+			int i;
+			fgets(line, sizeof(line), fp);
+			lineno++;
+			RFS_ASSERT (line[strlen(line)-1]=='\n');
+			RFS_ASSERT (strstr(line, "TOTAL: "));
+			max_block_num = atoi (line+strlen("TOTAL: "));
+			i = ((size+DISK_BLOCK_SIZE-1)/DISK_BLOCK_SIZE);
+			RFS_ASSERT ((max_block_num >= i) && ((max_block_num*9/i)<10));
+		}
+		tblock_num += max_block_num;
+
+		p = buf;
+		frag_num = 0;
+		distance = 0;
+		last_block = 0;
+		//printf ("line %d %s", lineno, buf);
+		while (p && (*p!='\n')) {
+			if (format_version == 1) {
+				p1 = strchr (p, ')');
+				if (p1) {
+					p2 = strchr (p, '-');
+					p3 = strchr (p, ':');
+					RFS_ASSERT (p3);
+					p3++;
+				} else {
+					format_version = 2;
+					p3 = p;
+				}
+			} else
+				p3 = p;
+
+#define checkit
+			/* single block range */
+			if ((p2==NULL) || p2>p1) {	
+#ifdef checkit
+				char * pt2, a;
+				pt2 = strchr(p3, ' ');
+				if (!pt2) {
+					pt2 = strchr(p3, '\n');
+					a = '\n';
+				} else
+					a = ' ';
+				RFS_ASSERT (pt2);
+				RFS_ASSERT (pt2!=p3);
+				*pt2 = 0;
+				block_range_start = atoi (p3);
+				*pt2 = a ;
+#else
+				sscanf(p3, "%d", &block_range_start);
+#endif
+				block_range_stop = block_range_start;
+			} else {
+#ifdef checkit
+				char * pt, * pt2, a;
+				pt = strchr(p3, '-');
+				RFS_ASSERT (pt);
+				*pt = 0;
+				block_range_start = atoi (p3);
+				*pt = '-';
+				pt2 = strchr(pt+1, ',');
+				if (!pt2) {
+					pt2 = strchr(pt+1, '\n');
+					a = '\n';
+				} else
+					a = ',';
+				RFS_ASSERT (pt2);
+				*pt2 = 0;
+				block_range_stop = atoi (pt+1);
+				*pt2 = a ;
+#else
+				sscanf(p3, "%d-%d", &block_range_start, &block_range_stop);
+#endif
+			}
+
+			RFS_ASSERT (block_range_start >0);
+			RFS_ASSERT (block_range_stop >= block_range_start);
+
+			block_num += (block_range_stop - block_range_start+1);
+
+			if (block_range_start != (last_block+1)) {
+				frag_num ++;
+
+#ifdef SUB_DISTANCE
+				sub_distance_index = (block_num-1) * SUB_DISTANCE_NUM/max_block_num;
+				sub_block_num[sub_distance_index] += block_num - last_block_num;
+				last_block_num = block_num;
+				//printf ("block_num %d SUB_DISTANCE_NUM %d max_block_num %d index %d\n", block_num, SUB_DISTANCE_NUM,
+//max_block_num, sub_distance_index);
+				RFS_ASSERT ((sub_distance_index>=0) && (sub_distance_index<SUB_DISTANCE_NUM));
+#endif
+				if (last_block!=0) {
+					if (block_range_start > last_block+1) {
+						distance += block_range_start - (last_block+1);
+#ifdef SUB_DISTANCE
+						sub_distance[sub_distance_index] += block_range_start - (last_block+1);
+#endif
+					} else {
+						distance += (last_block+1)-block_range_start;
+#ifdef SUB_DISTANCE
+						sub_distance[sub_distance_index] += (last_block+1)-block_range_start ;
+#endif
+					}
+
+					if (distance >= 1000000000) {
+						printf ("line[%d] %s, block_range_start %d last_block %d\n", lineno, buf, block_range_start, last_block);
+						RFS_ASSERT (0);
+					}
+					fprintf(fpout, "%d %d\n", last_block, block_range_start);
+				};
+				//printf ("range_start %d last_block %d distance %d\n", 
+						//block_range_start, last_block, distance);
+#ifdef SUB_DISTANCE
+				sub_frag_num[sub_distance_index] ++;
+#endif
+			}
+			
+			last_block = block_range_stop;
+			if (last_block > max_block)
+				max_block = last_block;
+			if (p1)
+				p = strchr (p3, '(');
+			else {
+				p = strchr (p3, ' ');
+				p++;
+			}
+		}
+		//printf ("FRAG_NUM %d DISTANCE %d\n", frag_num, distance);
+		tfrag_num += frag_num;
+		distancell += distance;
+ENDLOOP:
+		file_num ++;
+		size = -1;
+		block_num = -1;
+		max_block_num = -1;
+/*
+		td += distance;
+		if (td > 1000000) {
+			td_MB += td/1000000;
+			td = td%1000000;
+			RFS_ASSERT (td_MB < 1000000000);
+		}
+*/
+	}
+	fclose (fpout);
+	fclose (fp);
+                                                                              
+	if (tfrag_num != file_num) {
+		RFS_ASSERT ((distancell /(tfrag_num-file_num)) < 1000000000);
+		RFS_ASSERT ((distancell /(tblock_num-file_num)) < 1000000000);
+		avg_frag_distance = distancell/(tfrag_num-file_num);
+		avg_block_distance = distancell/(tblock_num-file_num);
+	} else {
+		avg_frag_distance =0;
+		avg_block_distance =0;
+	}
+	RFS_ASSERT ((distancell /1000000) < 1000000000);
+	td_MB = distancell/1000000;
+	td = distancell%1000000;
+	
+#ifdef SUB_DISTANCE
+	for (i=0; i<SUB_DISTANCE_NUM; i++) {
+		printf("sub[%d] block_num %d frag_num %d distance %d\n", i, sub_block_num[i], sub_frag_num[i], sub_distance[i]/1000000);
+	}
+#endif
+/*
+    distancell = td_MB;
+    distancell *=1000000;
+    distancell +=td;
+    distancell /= (tfrag_num-file_num);
+    if (distancell > 1000000000) {
+        printf ("error 4\n");
+        exit(-1);
+    }
+    avg_frag_distance = distancell;
+
+    distancell = td_MB;
+    distancell *=1000000;
+    distancell +=td;
+    distancell /= (tblock_num-file_num);
+    if (distancell > 1000000000) {
+        printf ("error 4\n");
+        exit(-1);
+    }
+    avg_block_distance = distancell;
+*/
+
+	printf("****total FRAG_NUM %d td_MB %d td %d tblock_num %d max_blockno %d file_num %d avg_frag_distance %d avg_block_distance %d\n", tfrag_num, td_MB, td, tblock_num, max_block, file_num, avg_frag_distance, avg_block_distance);
+}
diff --git a/TBBT/trace_play/fragment_collect b/TBBT/trace_play/fragment_collect
new file mode 100755
index 0000000..9e5b8c9
--- /dev/null
+++ b/TBBT/trace_play/fragment_collect
@@ -0,0 +1,43 @@
+# Usage: fragment_collect dev mount_dir test_path output_file
+#
+# On linux system, this script collects the fragmentation status of a 
+# particular directory. The objects under this directory SHOULD NOT be 
+# used as mount point. If they do, please umount them first, but there
+# is no danger even if you forget. The "output_file" is the one that I
+# need, please gzip it and send it back to nzhu@cs.sunysb.edu
+#
+# The program needs to be run as ROOT, but it is SAFE and KEEPS PRIVACY.
+# The pathname information on your system is completely filtered out 
+# from the final output. This program ONLY READ and DOES NOT WRITE any
+# files EXCEPT "output_file*" 
+#
+# Parameters:
+#		 dev 			:the device of the directory to be measured
+#		 mount_dir	 	:the the mount point of the device
+#		 test_path 		:the relative path of the directory under mount_dir
+#		 output_file	:where the result is stored.
+#
+# Example: fragment_collect /dev/hda7 /home ningning /tmp/home-ningning.frag
+#
+#	This gives the fragmentation information (saved in "/tmp/home-ningning.frag")
+#   of the file system objects under the directory of "/home/ningning" on the 
+#   disk partition of "/dev/hda7" mounted to "/home".
+#
+#nfs stop
+#umount $2
+#mount $2
+#nfs start
+cd $2
+echo "find $3 -print >$4.1"
+find $3 -print > $4.1
+echo "sed -d s/^/show_inode_info / $4.1"
+sed -e "s/^/show_inode_info /" $4.1 >$4.2
+echo "open $1" >$4.3
+cat $4.2 >> $4.3
+echo "debugfs -f $4.3"
+debugfs -f $4.3 > $4.4
+grep -v debugfs $4.4 > $4
+#rm $4.1
+#rm $4.2 
+#rm $4.3
+#rm $4.4
diff --git a/TBBT/trace_play/generate_xmgr b/TBBT/trace_play/generate_xmgr
new file mode 100755
index 0000000000000000000000000000000000000000..a44ed3393dc5a21d850301df1506f676c35a7b2c
GIT binary patch
literal 26083
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%0A3-<nNr
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

literal 0
HcmV?d00001

diff --git a/TBBT/trace_play/generate_xmgr.c b/TBBT/trace_play/generate_xmgr.c
new file mode 100644
index 0000000..354db18
--- /dev/null
+++ b/TBBT/trace_play/generate_xmgr.c
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include "rfs_assert.h"
+
+#define EVEN_CHUNK_SIZE_MAX 2
+#define CHUNK_NUM_MAX 17
+#define FS_SIZE_MB_MAX 81
+#define STAGE_NUM_MAX 65
+typedef	struct {
+	int flag;
+	int frag_num;
+	int avg_frag_distance;
+	int avg_block_distance;
+} result_t;
+result_t result[EVEN_CHUNK_SIZE_MAX][CHUNK_NUM_MAX][FS_SIZE_MB_MAX][STAGE_NUM_MAX];
+
+int range_check (int i, int min, int max)
+{
+	if (i<min)
+		return 0;
+	if (i>max)
+		return 0;
+	return 1;
+}
+
+int file_ratio, active_ratio, chunk_num, fs_size_MB, even_chunk_size, stage_num;
+#define SEQ_NUM 11
+int frag_num[SEQ_NUM], td_MB[SEQ_NUM], td[SEQ_NUM], tblock_num[SEQ_NUM], file_num;
+main(int argc, char ** argv)
+{
+	char line[1024];
+	FILE * fp;
+	unsigned long long distance;
+	unsigned long long tll;
+	int avg_frag_distance = 0;
+	int max_blockno=0, avg_block_distance=0;
+	char * p;
+	int sequence[SEQ_NUM]={1,2,5,10,20,30,50,100,200,250,500};
+	int i;
+	char fhmap[1024];
+	result_t * resultp= NULL;
+
+
+	memset (result, 0, sizeof(result));
+
+	fp = fopen (argv[1], "r");
+	if (!fp) {
+		perror("open");	
+		exit(-1);
+	}
+	i=-1;
+	while (fgets(line, sizeof(line), fp)) {
+		if (feof(fp))
+			break;
+		if (strstr(line, "==>")) {
+			RFS_ASSERT (resultp == NULL);
+
+			p = strrchr (line, '/');
+			if (p==NULL)
+				p=line;
+			p = strchr (p, '_');
+			if (p==NULL) {
+				printf("error 2\n");
+				exit(-1);
+			}
+			sscanf (p, "_%d_%d_%d_%d_%d_%d_%s.5 <==\n", &even_chunk_size, &file_ratio, &active_ratio, &chunk_num, &fs_size_MB, &stage_num, fhmap);
+			i = chunk_num;
+			RFS_ASSERT (range_check (even_chunk_size, 0, EVEN_CHUNK_SIZE_MAX-1));
+			RFS_ASSERT (range_check (chunk_num, 0, CHUNK_NUM_MAX-1));
+			RFS_ASSERT (range_check (fs_size_MB/100, 0, FS_SIZE_MB_MAX-1));
+			RFS_ASSERT (range_check (stage_num, 0, STAGE_NUM_MAX-1));
+			resultp = & (result[even_chunk_size][chunk_num][fs_size_MB/100][stage_num]);
+			RFS_ASSERT (resultp->flag == 0);
+		}
+		if (strstr(line, "****")) {
+
+			RFS_ASSERT (resultp);
+
+			sscanf(line, "****total FRAG_NUM %d td_MB %d td %d tblock_num %d max_blockno %d file_num %d avg_frag_distance %d avg_block_distance %d", &frag_num[0], &td_MB[0], &td[0],  &tblock_num[0], &max_blockno, &file_num, &avg_frag_distance, &avg_block_distance);
+			sscanf(line, "****total FRAG_NUM %d td_MB %d td %d tblock_num %d max_blockno %d file_num %d avg_frag_distance %d avg_block_distance %d", &(resultp->frag_num), &td_MB[0], &td[0],  &tblock_num[0], &max_blockno, &file_num, &(resultp->avg_frag_distance), &(resultp->avg_block_distance));
+			resultp ->flag = 1;
+
+			//printf("%d %d %d %d %d %d\n", chunk_num, frag_num[0], avg_frag_distance, td_MB[0], tblock_num[0], avg_block_distance);
+
+			resultp = NULL;
+		} 
+	}
+
+	print_xmgr ("avg_block_distance");
+	print_xmgr ("frag_num");
+	print_xmgr ("frag_size");
+	print_xmgr ("avg_frag_distance");
+	print_xmgr_chunk_stage ("avg_block_distance");
+}
+
+int print_y(FILE * fp, result_t * resultp, char * y_axis)
+{
+	if (!strcmp (y_axis, "avg_block_distance")) {
+		fprintf (fp, "%d ", resultp->avg_block_distance);
+	} else if (!strcmp (y_axis, "frag_num")) {
+		fprintf (fp, "%d ", resultp->frag_num);
+	} else if (!strcmp (y_axis, "frag_size")) {
+		fprintf (fp, "%f ", (float)tblock_num[0]/(float)resultp->frag_num);
+	} else if (!strcmp (y_axis, "avg_frag_distance")) {
+		fprintf (fp, "%d ", resultp->avg_frag_distance);
+	} else {
+		RFS_ASSERT (0);
+	}
+}
+	/* statistics for avg_block_distance */
+int print_xmgr (char * y_axis)
+{
+	int flag1, flag2;
+	result_t * resultp;
+	char name[1024];
+
+	FILE * fp = NULL;
+
+	for (even_chunk_size = 0; even_chunk_size < EVEN_CHUNK_SIZE_MAX; even_chunk_size ++) {
+		for (fs_size_MB = 0; fs_size_MB < FS_SIZE_MB_MAX; fs_size_MB ++) {
+
+			sprintf (name, "xmgr.%d_%d.stage.%s", even_chunk_size, fs_size_MB*100, y_axis);
+			fp = NULL;
+			flag1 = 1;
+			for (stage_num = 0; stage_num < STAGE_NUM_MAX; stage_num++) {
+				flag2 = 1;
+				for (chunk_num = 0; chunk_num < CHUNK_NUM_MAX; chunk_num++) {
+					resultp = &(result[even_chunk_size][chunk_num][fs_size_MB][stage_num]);
+					if (resultp->flag) {
+						if (flag1) {
+							printf ("*** even %d fs_size_MB %d X: stage_num Y: %s Lines: different chunk_num ***\n", even_chunk_size, fs_size_MB*100, y_axis);
+							flag1 = 0;
+							if (!fp) {
+								fp = fopen (name, "w");
+								if (!fp)
+									RFS_ASSERT (0);
+							}
+						}
+						if (flag2) {
+							//fprintf (fp, "%d ", file_num/stage_num);
+							fprintf (fp, "%f ", 1/((float)stage_num));
+							flag2 = 0;
+						}
+						print_y (fp, resultp, y_axis);
+					}
+				}
+				if (!flag2)
+					fprintf (fp, "\n");
+			}
+			if (fp)
+				fclose (fp);
+		}
+	}
+
+	for (even_chunk_size = 0; even_chunk_size < EVEN_CHUNK_SIZE_MAX; even_chunk_size ++) {
+		for (fs_size_MB = 0; fs_size_MB < FS_SIZE_MB_MAX; fs_size_MB ++) {
+			sprintf (name, "xmgr.%d_%d.chunk.%s", even_chunk_size, fs_size_MB*100, y_axis);
+			fp = NULL;
+			flag1 = 1;
+			for (chunk_num = 0; chunk_num < CHUNK_NUM_MAX; chunk_num++) {
+				flag2 = 1;
+				for (stage_num = 0; stage_num < STAGE_NUM_MAX; stage_num++) {
+					resultp = &(result[even_chunk_size][chunk_num][fs_size_MB][stage_num]);
+					if (resultp->flag) {
+						if (flag1) {
+							printf ("*** even %d fs_size_MB %d X: chunk_num Y: %s Lines: different stage_num ***\n", even_chunk_size, fs_size_MB*100, y_axis);
+							flag1 = 0;
+							if (!fp) {
+								fp = fopen (name, "w");
+								if (!fp)
+									RFS_ASSERT (0);
+							}
+						}
+						if (flag2) {
+							fprintf (fp, "%d ", chunk_num);
+							flag2 = 0;
+						}
+						print_y (fp, resultp, y_axis);
+					}
+				}
+				if (!flag2)
+					fprintf (fp, "\n");
+			}
+			if (fp)
+				fclose (fp);
+		}
+	}
+}
+int print_xmgr_chunk_stage (char * y_axis)
+{
+	int flag1, flag2;
+	result_t * resultp;
+	char name[1024];
+
+	FILE * fp = NULL;
+
+	for (even_chunk_size = 0; even_chunk_size < EVEN_CHUNK_SIZE_MAX; even_chunk_size ++) {
+		for (fs_size_MB = 0; fs_size_MB < FS_SIZE_MB_MAX; fs_size_MB ++) {
+
+			sprintf (name, "xmgr.%d_%d.stage_chunk.%s", even_chunk_size, fs_size_MB*100, y_axis);
+			fp = NULL;
+			flag1 = 1;
+			for (stage_num = STAGE_NUM_MAX-1; stage_num>=0; stage_num--) {
+				flag2 = 1;
+				for (chunk_num = 0; chunk_num < CHUNK_NUM_MAX; chunk_num++) {
+					resultp = &(result[even_chunk_size][chunk_num][fs_size_MB][stage_num]);
+					if (resultp->flag) {
+						if (flag1) {
+							printf ("*** even %d fs_size_MB %d X: stage_num Y: %s Lines: different chunk_num ***\n", even_chunk_size, fs_size_MB*100, y_axis);
+							flag1 = 0;
+							if (!fp) {
+								fp = fopen (name, "w");
+								if (!fp)
+									RFS_ASSERT (0);
+							}
+						}
+						fprintf (fp, "%f ", chunk_num/((float)stage_num));
+						print_y (fp, resultp, y_axis);
+						fprintf (fp, "\n");
+					}
+				}
+			}
+			if (fp)
+				fclose (fp);
+		}
+	}
+}
diff --git a/TBBT/trace_play/generate_xmgr.c.old b/TBBT/trace_play/generate_xmgr.c.old
new file mode 100644
index 0000000..4a12ce2
--- /dev/null
+++ b/TBBT/trace_play/generate_xmgr.c.old
@@ -0,0 +1,70 @@
+#include <stdio.h>
+main(int argc, char ** argv)
+{
+	char line[1024];
+	FILE * fp;
+	unsigned long long distance;
+	unsigned long long tll;
+	int avg_frag_distance = 0;
+#define SEQ_NUM 11
+	int frag_num[SEQ_NUM], td_MB[SEQ_NUM], td[SEQ_NUM], tblock_num[SEQ_NUM], file_num;
+	int max_blockno=0, avg_block_distance=0;
+	char * p;
+	int sequence[SEQ_NUM]={1,2,5,10,20,30,50,100,200,250,500};
+	int i;
+	int file_ratio, active_ratio, chunk_num, fs_size_MB;
+	char fhmap[1024];
+
+	fp = fopen (argv[1], "r");
+	if (!fp) {
+		perror("open");	
+		exit(-1);
+	}
+	i=-1;
+	while (fgets(line, sizeof(line), fp)) {
+		if (feof(fp))
+			break;
+		if (strstr(line, "==>")) {
+			if (i!=-1) {
+				printf("error 1\n");
+				exit(-1);
+			}
+			p = strrchr (line, '/');
+			if (p==NULL)
+				p=line;
+			p = strchr (p, '_');
+			if (p==NULL) {
+				printf("error 2\n");
+				exit(-1);
+			}
+			sscanf (p, "_%d_%d_%d_%d_%s.5 <==\n", &file_ratio, &active_ratio, &chunk_num, &fs_size_MB, fhmap);
+			i = chunk_num;
+		}
+		if (strstr(line, "****")) {
+			if (i==-1) {
+				printf("error 3\n");
+				exit(-1);
+			}
+			sscanf(line, "****total FRAG_NUM %d td_MB %d td %d tblock_num %d max_blockno %d file_num %d avg_frag_distance %d avg_block_distance %d", &frag_num[0], &td_MB[0], &td[0],  &tblock_num[0], &max_blockno, &file_num, &avg_frag_distance, &avg_block_distance);
+
+#ifdef checkit
+			distance = td_MB[0];
+			distance *=1000000;
+			distance +=td[0];
+			tll = frag_num[0];
+			distance /= frag_num[0];
+
+			if (distance > 1000000000) {
+				printf ("error 4\n");
+				exit(-1);
+			}
+			avg_frag_distance = distance;
+			printf("%d %d %d %d %d\n", chunk_num, frag_num[0], avg_frag_distance, td_MB[0], tblock_num[0]);
+#else
+			printf("%d %d %d %d %d %d\n", chunk_num, frag_num[0], avg_frag_distance, td_MB[0], tblock_num[0], avg_block_distance);
+#endif
+			i = -1;
+		} 
+	}
+}
+
diff --git a/TBBT/trace_play/generic_hash.c b/TBBT/trace_play/generic_hash.c
new file mode 100644
index 0000000..1d73a34
--- /dev/null
+++ b/TBBT/trace_play/generic_hash.c
@@ -0,0 +1,230 @@
+/* generic_hash.c: Generic hash function that hashes on a maximum of three keys
+ * $Id: generic_hash.c,v 1.5 2002/08/21 22:08:01 ningning Exp $
+ * Changes:
+ * 
+ *	$Log: generic_hash.c,v $
+ *	Revision 1.5  2002/08/21 22:08:01  ningning
+ *	*** empty log message ***
+ *	
+ */
+
+#include <stdio.h>
+#include "generic_hash.h"
+
+/* create an entry for a block */
+void generic_insert(char * key1, unsigned int key1_size, unsigned int key3, struct generic_entry **htable, int hsize)
+{
+unsigned int index;
+struct generic_entry *p,*q;
+
+unsigned int * tmp =(unsigned int *)key1;
+unsigned int i;
+index = 0;
+for (i=0; i<(key1_size/4); i++) 
+	index += *(tmp+i);
+index = index%hsize;
+{
+//printf ("generic_insert index %d key %s\n", index, key1);
+}
+p = q = htable[index];
+while (p) {
+    if ((!memcmp(p->key1, key1, key1_size))
+        && (p->key3==key3)) {
+        return;
+    }
+    q = p;
+    p = p->next;
+}
+if (!p) {
+    p = (struct generic_entry *)malloc(sizeof(struct generic_entry));
+    memcpy(p->key1, key1, key1_size);
+    p->key3 = key3;
+    p->next = NULL;
+}
+if (!q)
+    htable[index] = p;
+else
+    q->next = p;
+return;
+}
+
+void generic_delete(char * key1, unsigned int key1_size, unsigned int key3, struct generic_entry **htable, int hsize)
+{
+unsigned int index;
+int found;
+struct generic_entry *p,*q;
+
+unsigned int * tmp =(unsigned int *)key1;
+unsigned int i;
+index = 0;
+for (i=0; i<(key1_size/4); i++) 
+	index += *(tmp+i);
+index = index%hsize;
+
+p = q = htable[index];
+found = 0;
+while (p) {
+    if ((!memcmp(p->key1, key1, key1_size)) 
+	    && (p->key3==key3)) {
+		found = 1;
+		break;
+    }
+	q = p;
+    p = p->next;
+}
+RFS_ASSERT(found==1);
+if (p==htable[index])
+    htable[index] = p->next;
+else 
+    q->next = p->next;
+
+/* free hash entry */
+
+free(p);
+
+return;
+}
+
+struct generic_entry *generic_lookup(char * key1, unsigned int key1_size, unsigned int key3, struct generic_entry **htable, int hsize)
+{
+unsigned int index;
+struct generic_entry *p;
+
+unsigned int * tmp =(unsigned int *)key1;
+unsigned int i;
+index = 0;
+for (i=0; i<(key1_size/4); i++) 
+	index += *(tmp+i);
+index = index%hsize;
+{
+//printf ("generic_lookup index %d key %s\n", index, key1);
+}
+
+p = htable[index];
+while (p) {
+    if (!memcmp(p->key1, key1, key1_size)) 
+	{
+		return p;
+    }
+    p = p->next;
+}
+/*RFS_ASSERT(0);*/
+return NULL;
+}
+
+struct generic_entry *generic_lookup1(unsigned int key1, unsigned int key2, unsigned int key3, struct generic_entry **htable, int hsize)
+{
+unsigned int index;
+struct generic_entry *p;
+
+index = ((unsigned int)key1)%hsize;
+p = htable[index];
+while (p) {
+    if (p->key1==key1) 
+		return p;
+    p = p->next;
+}
+/*RFS_ASSERT(0);*/
+return NULL;
+}
+
+struct generic_entry *generic_lookup2(unsigned int key1, unsigned int key2, unsigned int key3, struct generic_entry **htable, int hsize)
+{
+unsigned int index;
+struct generic_entry *p;
+
+index = (key1 + key2)%hsize;
+p = htable[index];
+while (p) {
+    if (   (p->key1==key1) 
+	    && (p->key2==key2)
+	   )
+		return p;
+    p = p->next;
+}
+/*RFS_ASSERT(0);*/
+return NULL;
+}
+
+void generic_display(struct generic_entry **htable, int hsize, int numkeys)
+{
+int i;
+struct generic_entry *p;
+int counter = 0;
+
+for (i=0;i<hsize;i++) {
+    p = htable[i];
+	if (p) 
+		printf ("htable[%d]", i);
+    while (p) {
+		if (numkeys==1)
+			printf("%d, ", p->key1);
+		else if (numkeys==2)
+			printf("(%d,%x), ", p->key1,p->key2);
+		else 
+			printf("(%d,%d,%d), ", p->key1,p->key2,p->key3);
+	    p = p->next;
+        counter++;
+		if ((counter%4)==3) 
+		    printf("\n");
+    }
+}
+printf("\ncounter was %d\n",counter);
+}
+
+/* create an entry for a block */
+void generic_long_insert4(unsigned int key1, unsigned int key2, unsigned int key3, unsigned int key4, unsigned int key5, unsigned int key6, struct generic_long_entry **htable, int hsize)
+{
+int index;
+struct generic_long_entry *p,*q;
+
+index = (key1 + key2 + key3 + key4)%hsize;
+p = q = htable[index];
+while (p) {
+    if ((p->key1==key1) 
+	    && (p->key2==key2)
+	    && (p->key3==key3)
+	    && (p->key4==key4)
+	    && (p->key5==key5)
+	    && (p->key6==key6)) {
+		return;
+    }
+	q = p;
+    p = p->next;
+}
+if (!p) {
+	p = (struct generic_long_entry *)malloc(sizeof(struct generic_long_entry));
+	p->key1 = key1;
+	p->key2 = key2;
+	p->key3 = key3;
+	p->key4 = key4;
+	p->key5 = key5;
+	p->key6 = key6;
+    p->next = NULL;
+}
+if (!q) 
+    htable[index] = p;
+else 
+    q->next = p;
+return;
+}
+
+struct generic_entry *generic_long_lookup4(unsigned int key1, unsigned int key2, unsigned int key3, unsigned int key4, struct generic_long_entry **htable, int hsize)
+{
+int index;
+struct generic_long_entry *p;
+
+index = (key1 + key2 + key3 + key4 )%hsize;
+p = htable[index];
+while (p) {
+    if (   (p->key1==key1) 
+	    && (p->key2==key2)
+		&& (p->key3==key3)
+		&& (p->key4==key4)
+	   )
+		return p;
+    p = p->next;
+}
+/*RFS_ASSERT(0);*/
+return NULL;
+}
diff --git a/TBBT/trace_play/generic_hash.h b/TBBT/trace_play/generic_hash.h
new file mode 100644
index 0000000..cf48bd4
--- /dev/null
+++ b/TBBT/trace_play/generic_hash.h
@@ -0,0 +1,24 @@
+#include "rfs_c_def.h"
+struct generic_entry {
+	char key1[MAX_TRACE_FH_SIZE];
+    int key2;
+    int key3;
+    struct generic_entry *next;
+};
+
+struct generic_long_entry {
+    int key1;
+    int key2;
+    int key3;
+	int key4;
+	int key5;
+	int key6;
+    struct generic_long_entry *next;
+};
+
+void generic_insert(char * key1, unsigned int key2, unsigned int key3, struct generic_entry **htable, int hsize);
+void generic_delete(char * key1, unsigned int key2, unsigned int key3, struct generic_entry **htable, int hsize);
+struct generic_entry *generic_lookup(char * key1, unsigned int key2, unsigned int key3, struct generic_entry **htable, int hsize);
+
+void generic_display(struct generic_entry **htable, int hsize, int numkeys);
+
diff --git a/TBBT/trace_play/hash.h b/TBBT/trace_play/hash.h
new file mode 100644
index 0000000..808a95f
--- /dev/null
+++ b/TBBT/trace_play/hash.h
@@ -0,0 +1,87 @@
+#ifndef RFS_HASH_H
+#define RFS_HASH_H
+
+/* 
+ * hash.h: 
+ *		header file for routines to manipulate hash_tble lookup, 
+ *		insert and delete.
+ * 
+ * $Id: hash.h,v 1.1 2002/03/11 20:25:52 ningning Exp $
+ *
+ * Changes:
+ * 		$Log: hash.h,v $
+ * 		Revision 1.1  2002/03/11 20:25:52  ningning
+ * 		hash function for file handle map completely implemented.
+ * 		
+ */
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "../common/rfs_defines.h"
+#include "rfsu_defines.h"
+
+typedef struct rfsfh rfskey_t;
+
+struct hash_ent_struct {
+#ifdef HASH_DOUBLE_SAFE
+	struct timeval time;
+#endif
+	rfskey_t key;
+	int entry;
+	struct hash_ent_struct * next;
+};
+
+typedef struct hash_ent_struct hash_ent_t;
+
+typedef struct {
+	int size;
+	int used_entry;	/* number of hash table entrie which contains valid data */
+	int valid_num;	/* number of valid data including those on the chain */
+	int (*hash_func) (rfskey_t * key, int size);	
+		/*  it's not C++ class, so we have to get size from outside */
+	hash_ent_t * buf;
+} hash_tbl_t;
+ 
+inline int hash_func1 (rfskey_t * key, int size);
+inline int blk_hash_func (blkkey_t * key, int size);
+int hash_tbl_init (hash_tbl_t * hash_tbl);
+int hash_tbl_insert (hash_tbl_t * hash_tbl, rfskey_t * key, int entry, int mode);
+int hash_tbl_delete (hash_tbl_t * hash_tbl, rfskey_t * key);
+int hash_tbl_lookup (hash_tbl_t * hash_tbl, rfskey_t * key);
+
+#ifdef ULFS
+
+struct blk_hash_ent_struct {
+#ifdef HASH_DOUBLE_SAFE
+	struct timeval time;
+#endif
+	blkkey_t key;
+	int entry;
+	struct blk_hash_ent_struct * next;
+};
+
+typedef struct blk_hash_ent_struct blk_hash_ent_t;
+
+typedef struct {
+	int size;
+	int keysize;
+	int entsize;
+	int quiet_flag;
+	int used_entry;	/* number of hash table entrie which contains valid data */
+	int valid_num;	/* number of valid data including those on the chain */
+	int (*hash_func) (blkkey_t * key, int size);	
+		/*  it's not C++ class, so we have to get size from outside */
+	blk_hash_ent_t * buf;
+} blk_hash_tbl_t;
+
+int blk_hash_tbl_init (blk_hash_tbl_t * hash_tbl);
+int blk_hash_tbl_insert (blk_hash_tbl_t * hash_tbl, blkkey_t * key, int entry, int mode);
+//int blk_hash_tbl_delete (blk_hash_tbl_t * hash_tbl, blkkey_t * key);
+int blk_hash_tbl_lookup (blk_hash_tbl_t * hash_tbl, blkkey_t * key);
+
+#endif
+
+#endif
diff --git a/TBBT/trace_play/init_holder.c b/TBBT/trace_play/init_holder.c
new file mode 100644
index 0000000..f12d683
--- /dev/null
+++ b/TBBT/trace_play/init_holder.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#define FILE_NUM 25000
+#define DIR_NUM 1
+#define FILE_SIZE 40960
+
+int print_usage()
+{
+	printf("init_holder DIR_NUM HOLDER_NUM HOLDER_SIZE testdir\n");
+}
+
+main4(int argc, char ** argv)
+{
+	int i, j;
+	char name[256];
+	char cmd[1024];
+	char buf[FILE_SIZE];
+	int fd, ret;
+	char testdir[1024];
+
+	if (argc!=5) {
+		print_usage();
+		exit (-1);
+	}
+	if (DIR_NUM !=1) {
+		for (i=0; i<DIR_NUM; i++) {
+			memset (name, 0, sizeof(name));
+			sprintf(name, "%s/%d", testdir, i);
+ 			ret = mkdir (name, S_IRWXU);
+			if (ret == -1) {
+				perror(name);
+				exit(-1);
+			}
+		}
+	}
+
+	for (j=0; j<DIR_NUM; j++) {
+		for (i=0; i<FILE_NUM/DIR_NUM; i++) {
+			if (DIR_NUM == 1)  
+				sprintf(name, "%s/%d", testdir, i);
+			else
+				sprintf(name, "%s/%d/%d", testdir, j, i);
+			fd = open (name, O_CREAT|O_WRONLY);
+			if (fd == -1) {
+				perror(name);
+				exit(-1);
+			}
+			ret = write (fd, buf, FILE_SIZE );
+			close (fd);
+			if (ret!=FILE_SIZE) {
+				printf("try to write %d , get %d\n", SIZE, ret);
+				exit (-1);
+			}
+		}
+	}
+}
diff --git a/TBBT/trace_play/nfsd_nfsfh_cust.h b/TBBT/trace_play/nfsd_nfsfh_cust.h
new file mode 100644
index 0000000..942dc92
--- /dev/null
+++ b/TBBT/trace_play/nfsd_nfsfh_cust.h
@@ -0,0 +1,114 @@
+#define __u32 unsigned int
+#define u32 unsigned int
+#define __u16 unsigned short
+#define u16 unsigned short
+#define __u64 unsigned long long
+#define u64 unsigned long long
+#define __u8 unsigned char
+#define u8 unsigned char
+#define __s64 signed long long
+
+struct nfs_fhbase_old {
+	__u32		fb_dcookie;	/* dentry cookie - always 0xfeebbaca */
+	__u32		fb_ino;		/* our inode number */
+	__u32		fb_dirino;	/* dir inode number, 0 for directories */
+	__u32		fb_dev;		/* our device */
+	__u32		fb_xdev;
+	__u32		fb_xino;
+	__u32		fb_generation;
+};
+
+/*
+ * This is the new flexible, extensible style NFSv2/v3 file handle.
+ * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
+ *
+ * The file handle is seens as a list of 4byte words.
+ * The first word contains a version number (1) and four descriptor bytes
+ * that tell how the remaining 3 variable length fields should be handled.
+ * These three bytes are auth_type, fsid_type and fileid_type.
+ *
+ * All 4byte values are in host-byte-order.
+ *
+ * The auth_type field specifies how the filehandle can be authenticated
+ * This might allow a file to be confirmed to be in a writable part of a
+ * filetree without checking the path from it upto the root.
+ * Current values:
+ *     0  - No authentication.  fb_auth is 0 bytes long
+ * Possible future values:
+ *     1  - 4 bytes taken from MD5 hash of the remainer of the file handle
+ *          prefixed by a secret and with the important export flags.
+ *
+ * The fsid_type identifies how the filesystem (or export point) is
+ *    encoded.
+ *  Current values:
+ *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
+ *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
+ *              says we mustn't.  We must break it up and reassemble.
+ *  Possible future encodings:
+ *     1  - 4 byte user specified identifier
+ *
+ * The fileid_type identified how the file within the filesystem is encoded.
+ * This is (will be) passed to, and set by, the underlying filesystem if it supports
+ * filehandle operations.  The filesystem must not use the value '0' or '0xff' and may
+ * only use the values 1 and 2 as defined below:
+ *  Current values:
+ *    0   - The root, or export point, of the filesystem.  fb_fileid is 0 bytes.
+ *    1   - 32bit inode number, 32 bit generation number.
+ *    2   - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
+ *
+ */
+struct nfs_fhbase_new {
+	__u8		fb_version;	/* == 1, even => nfs_fhbase_old */
+	__u8		fb_auth_type;
+	__u8		fb_fsid_type;
+	__u8		fb_fileid_type;
+#ifndef RFS
+	__u32		fb_auth[1];
+/*	__u32		fb_fsid[0]; floating */
+/*	__u32		fb_fileid[0]; floating */
+#else
+	__u16		fb_dev_major;
+	__u16		fb_dev_minor;
+	__u32		fb_dev_ino;
+	__u32		fb_ino;
+	__u32		fb_generation;
+	__u32		fb_dirino;
+#endif
+	
+};
+
+// RFS struct knfsd_fh {			
+struct knfs_fh {												// RFS
+	unsigned int	fh_size;	/* significant for NFSv3.
+					 * Points to the current size while building
+					 * a new file handle
+					 */
+	union {
+		struct nfs_fhbase_old	fh_old;
+		__u32			fh_pad[NFS3_FHSIZE/4];
+		struct nfs_fhbase_new	fh_new;
+	} fh_base;
+};
+
+#define ofh_dcookie		fh_base.fh_old.fb_dcookie
+#define ofh_ino			fh_base.fh_old.fb_ino
+#define ofh_dirino		fh_base.fh_old.fb_dirino
+#define ofh_dev			fh_base.fh_old.fb_dev
+#define ofh_xdev		fh_base.fh_old.fb_xdev
+#define ofh_xino		fh_base.fh_old.fb_xino
+#define ofh_generation		fh_base.fh_old.fb_generation
+
+#define	fh_version		fh_base.fh_new.fb_version
+#define	fh_fsid_type		fh_base.fh_new.fb_fsid_type
+#define	fh_auth_type		fh_base.fh_new.fb_auth_type
+#define	fh_fileid_type		fh_base.fh_new.fb_fileid_type
+#define	fh_auth			fh_base.fh_new.fb_auth
+
+// RFS
+#define fh_dev_major	fh_base.fh_new.fb_dev_major
+#define fh_dev_minor	fh_base.fh_new.fb_dev_minor
+#define fh_dev_ino		fh_base.fh_new.fb_dev_ino
+#define fh_ino			fh_base.fh_new.fb_ino
+#define fh_generation	fh_base.fh_new.fb_generation
+#define fh_dirino		fh_base.fh_new.fb_dirino
+
diff --git a/TBBT/trace_play/profile.c b/TBBT/trace_play/profile.c
new file mode 100755
index 0000000..23548c1
--- /dev/null
+++ b/TBBT/trace_play/profile.c
@@ -0,0 +1,215 @@
+/*
+ * profile.c
+ *
+ * $Id: profile.c,v 1.1 2002/08/21 22:08:01 ningning Exp $
+ * Changes:
+ *	$Log: profile.c,v $
+ *	Revision 1.1  2002/08/21 22:08:01  ningning
+ *	*** empty log message ***
+ *	
+ */
+
+#include <sys/time.h>
+#include <sys/sem.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "profile.h"
+#include "rfs_assert.h"
+//#include "rfs_c_def.h"
+extern FILE * profile_fp;
+
+static struct timezone tz;
+inline void calculate_interval 
+	(struct timeval * ts, struct timeval * te, struct timeval * interval)
+{
+	if (te->tv_usec < ts->tv_usec) {
+		if (te->tv_sec <= ts->tv_sec) {
+			printf ("te->tv_sec %d ts->tv_sec %d\n", te->tv_sec, ts->tv_sec);
+			printf ("te->tv_usec %d ts->tv_usec %d\n", te->tv_usec, ts->tv_usec);
+		}
+		RFS_ASSERT (te->tv_sec > ts->tv_sec);
+		te->tv_usec += 1000000;
+		te->tv_sec -= 1;
+	}
+
+	interval->tv_sec  = te->tv_sec - ts->tv_sec;
+	interval->tv_usec = te->tv_usec - ts->tv_usec;
+	if (interval->tv_usec > 1000000) {
+		if (interval->tv_usec > 2000000) {
+			printf ("interval->tv_sec %d interval->tv_usec %d \n", interval->tv_sec, interval->tv_usec);
+			printf ("ts->tv_sec %d ts->tv_usec %d \n", ts->tv_sec, ts->tv_usec);
+			printf ("te->tv_sec %d te->tv_usec %d \n", te->tv_sec, te->tv_usec);
+		}
+		/* Sometimes it can happend that te->tv_usec > 1000000 */
+		interval->tv_sec += 1;
+		interval->tv_usec -= 1000000;
+		RFS_ASSERT (interval->tv_usec < 1000000);
+	}
+}
+
+inline void normalize_profile (int pos, struct timeval * time)
+{
+	if (!(time->tv_sec >=0 && time->tv_usec >=0 && time->tv_usec < 2000000)) {
+		printf ("pos %d tv_sec %d tv_usec %d\n", pos, time->tv_sec, time->tv_usec);
+	};
+	RFS_ASSERT (time->tv_sec >=0 && time->tv_usec >=0 && time->tv_usec < 2000000);
+	while (time->tv_usec >= 1000000) {
+		time->tv_usec -= 1000000;
+		time->tv_sec += 1;
+	}
+}
+
+inline void start_real_profile (profile_t * profile)
+{
+	start_profile(profile);
+}
+
+inline void end_real_profile (profile_t * profile)
+{
+	end_profile(profile);
+}
+
+inline void start_profile (profile_t * profile)
+{
+/*
+	if (strlen(profile->about) < 3) {
+		printf ("total_profile address: %x %x\n", &total_profile, profile);
+	}
+*/
+
+	gettimeofday(&(profile->ts), &tz);
+	normalize_profile (1, &(profile->ts));
+}
+
+inline void end_profile (profile_t * profile)
+{
+	struct timeval te, teorg;
+	struct timeval * ts; 
+	struct timeval * in;
+	struct timeval oldin;
+	
+/*
+	//printf ("end_profile %s\n", profile->about);
+
+	if (strlen(profile->about) < 3) {
+		printf ("total_profile address: %x %x\n", &total_profile, profile);
+	}
+*/
+
+	oldin = profile->in;
+	in = &(profile->in);
+	ts = &(profile->ts);
+
+	gettimeofday(&te, &tz);
+	normalize_profile (2, &te);
+	teorg = te;
+
+	RFS_ASSERT (te.tv_sec >= ts->tv_sec);
+	RFS_ASSERT (te.tv_usec >=0 && ts->tv_usec >=0);
+	while (te.tv_usec < ts->tv_usec) {
+		if (te.tv_sec <= ts->tv_sec) {
+		 	printf ("%s ts.tv_sec %d ts.tv_usec %d\n", profile->about, ts->tv_sec, ts->tv_usec);
+			printf ("teorg.tv_sec %d teorg.tv_usec %d\n", teorg.tv_sec, teorg.tv_usec);
+		}
+		RFS_ASSERT (te.tv_sec > ts->tv_sec);
+		te.tv_usec += 1000000;
+		te.tv_sec -= 1;
+	}
+
+	if (!(in->tv_sec >=0 && in->tv_usec >=0)) {
+		printf ("in->tv_sec %d, in->tv_usec %d\n", in->tv_sec, in->tv_usec);
+	};
+	RFS_ASSERT (in->tv_sec >=0 && in->tv_usec >=0);
+	in->tv_sec  += te.tv_sec - ts->tv_sec;
+	in->tv_usec += te.tv_usec - ts->tv_usec;
+	normalize_profile (3, in);
+
+	if (!(in->tv_sec >=0 && in->tv_sec <864000)) {
+		 printf (" ts.tv_sec %d ts.tv_usec %d\n", ts->tv_sec, ts->tv_usec);
+		 printf (" te.tv_sec %d te.tv_usec %d\n", te.tv_sec, te.tv_usec);
+		 printf (" in.tv_sec %d in.tv_usec %d\n", in->tv_sec, in->tv_usec);
+		 printf (" oldin.tv_sec %d oldin.tv_usec %d\n", oldin.tv_sec, oldin.tv_usec);
+	}
+
+	profile->num ++;
+	profile->ts = teorg;
+}
+
+inline void init_profile (char * string, profile_t * profile)
+{
+	RFS_ASSERT (strlen(string) < sizeof (profile->about));
+	memset (profile, 0, sizeof(profile_t));
+	strcpy (profile->about, string);
+}
+
+inline int calculate_avg_timeval (struct timeval * in, int num)
+{
+	unsigned long long i;
+	int ret;
+
+	if (in->tv_sec < 2000) {
+		return ((in->tv_sec*1000000+in->tv_usec)/num );
+	} else {
+		i = ((unsigned long long)in->tv_sec)*1000000 + in->tv_usec;
+		i/= num;
+		RFS_ASSERT (i<2000000000);
+		ret = i;
+		return ret;
+	}
+}
+
+inline void print_profile (char * string, profile_t * profile)
+{
+	struct timeval * ts = &(profile->ts);
+	struct timeval * in = &(profile->in);
+
+/*
+	if (strcmp (string, profile->about)) {
+		printf ("print_profile string %s about %s\n", string, profile->about);
+	}
+*/
+
+	//RFS_ASSERT (!strcmp (string, profile->about));
+	if (in->tv_usec<0 || in->tv_usec>1000000) {
+		printf ("%s in->tv_usec %d, in->tv_sec %d num %d\n", profile->about, in->tv_usec, in->tv_sec, profile->num);
+	}
+
+	RFS_ASSERT (in->tv_usec>=0 && in->tv_usec<1000000);
+	
+	if (!(in->tv_sec >=0 && in->tv_sec <864000)) {
+		 printf ("%s ts.tv_sec %d ts.tv_usec %d\n", profile->about, ts->tv_sec, ts->tv_usec);
+		 printf ("%s in.tv_sec %d in.tv_usec %d\n", profile->about, in->tv_sec, in->tv_usec);
+	}
+	RFS_ASSERT (in->tv_sec >=0 && in->tv_sec <864000);	/* it's about 10 days */
+
+	if (profile->num == 0) {
+		printf("... %40s %3d.%06d num %d \n", profile->about, in->tv_sec, in->tv_usec, 
+			profile->num);
+
+		if (profile_fp) {
+			fprintf(profile_fp, "... %40s %3d.%06d num %d \n", profile->about, in->tv_sec,
+				in->tv_usec, profile->num );
+			//perror("print_profile_1");
+		}
+	} else {
+
+		int avg = calculate_avg_timeval (in, profile->num);
+		printf("... %40s %3d.%06d num %d avg %d \n", profile->about, in->tv_sec, in->tv_usec, 
+			profile->num, avg);
+
+		if (profile_fp) {
+			fprintf(profile_fp, "... %40s %3d.%06d num %d avg %d \n", profile->about, in->tv_sec,
+				in->tv_usec, profile->num, avg);
+		}
+
+/*
+		printf("... %40s %3d.%06d num %d avg %d \n", string, in->tv_sec, in->tv_usec, 
+			profile->num, (in->tv_sec*1000000+in->tv_usec)/profile->num );
+
+		if (profile_fp) {
+			fprintf(profile_fp, "... %40s %3d.%06d num %d avg %d \n", string, in->tv_sec,
+				in->tv_usec, profile->num, (in->tv_sec*1000000+in->tv_usec)/profile->num );
+		}
+*/
+	}
+}
diff --git a/TBBT/trace_play/profile.h b/TBBT/trace_play/profile.h
new file mode 100755
index 0000000..606652e
--- /dev/null
+++ b/TBBT/trace_play/profile.h
@@ -0,0 +1,27 @@
+#ifndef PROFILE_H
+#define PROFILE_H
+
+/* profile.h: header file for profiling routine
+ * $Id: profile.h,v 1.2 2002/08/21 22:11:40 ningning Exp $
+ * Changes:
+ *
+ *	$Log: profile.h,v $
+ *	Revision 1.2  2002/08/21 22:11:40  ningning
+ *	*** empty log message ***
+ *	
+ */
+
+#include <sys/time.h>
+#define MAX_PROFILE_ABOUT_LEN 128
+typedef struct {
+    struct timeval ts;
+    struct timeval in;
+    int num;
+    char about[MAX_PROFILE_ABOUT_LEN];
+} profile_t;
+                                                                                                                                   
+extern inline void start_profile (profile_t * profile);
+extern inline void end_profile (profile_t * profile);
+extern inline void print_profile (char * string, profile_t * profile);
+extern inline void init_profile (char * string, profile_t * profile);
+#endif
diff --git a/TBBT/trace_play/rfs_3_ops.c b/TBBT/trace_play/rfs_3_ops.c
new file mode 100644
index 0000000..f91bf05
--- /dev/null
+++ b/TBBT/trace_play/rfs_3_ops.c
@@ -0,0 +1,827 @@
+#ifndef lint
+static char sfs_3_opsSid[] = "@(#)sfs_3_ops.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+#include "sfs_c_def.h"
+#include "rfs_c_def.h"
+
+#define TRY_SETARG_FAST
+#define TRY_SETRES_FAST
+extern fh_map_t * lookup_fh (char * trace_fh);
+extern void print_result(void);
+
+char * lookup_fhandle(char * fhandle)
+{
+	fh_map_t * fh;
+	fh = lookup_fh(fhandle);
+	RFS_ASSERT (fh);
+	return ((char *)&fh->play_fh);
+}
+
+
+#define setarg_fhandle(fhp) \
+	fh_map_t * fh; \
+	t = strstr (line, "fh");	\
+	RFS_ASSERT (t);				\
+	t += 3;						\
+	fh = lookup_fh(t);			\
+	RFS_ASSERT (fh);			\
+	(void) memmove((char *)fhp, &(fh->play_fh),			\
+					                               sizeof (nfs_fh3));	\
+	t+=TRACE_FH_SIZE+1;
+	//t = strchr (t, ' '); t++; \
+
+void setarg_getattr (int index, char * line, GETATTR3args * args)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->object, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+#else
+	setarg_fhandle(&args->object);
+#endif
+}
+
+struct ladtime * adjust_time (struct timeval tm, int * sec, int * usec)
+{
+	struct ladtime trace_pkt_time;
+	static struct ladtime trace_arg_time;
+	struct timeval curtmp;
+	struct ladtime cur;
+
+	/* not sure whether sec ==0 means anything special, do not adjust the timestamp for this */
+	if (*sec ==0) {
+		RFS_ASSERT (0);
+		RFS_ASSERT (*usec == 0);
+		trace_arg_time.sec = 0;
+		trace_arg_time.usec = 0;
+		return (&trace_arg_time);
+	}
+	trace_pkt_time.sec = tm.tv_sec;
+	trace_pkt_time.usec = tm.tv_usec;
+
+	trace_arg_time.sec = *sec;
+	trace_arg_time.usec = *usec;
+
+	gettimeofday(&curtmp, NULL);
+	cur.sec = curtmp.tv_sec;
+	cur.usec = curtmp.tv_usec;
+
+	//fprintf (stderr, "trace_pkt_time %d.%d trace_arg_time %d.%d cur %d.%d\n", trace_pkt_time.sec, trace_pkt_time.usec, trace_arg_time.sec, trace_arg_time.usec, cur.sec, cur.usec);
+
+	ADDTIME (trace_arg_time, cur);
+	//fprintf(stderr, "after add, %d.%d\n", trace_arg_time.sec, trace_arg_time.usec);
+	RFS_ASSERT (LARGERTIME (trace_arg_time, trace_pkt_time));
+	SUBTIME (trace_arg_time, trace_pkt_time);
+	return (&trace_arg_time);
+}
+
+char * parse_create_mode(char * t, createmode3 * mode)
+{
+	*mode = UNCHECKED;
+	return (t+2);
+	/* anyway, we can not get concrete result from the trace, just chose this mode */
+	RFS_ASSERT (0);
+}
+
+char * parse_sattr3(char * t, sattr3 * args, sattrguard3 * guard, int index)
+{
+	int i,j;
+	struct ladtime * tm;
+
+	/* set the default value of SETATTR3args->*/
+    args->mode.set_it = FALSE;
+    args->uid.set_it = FALSE;
+    args->gid.set_it = FALSE;
+    args->size.set_it = FALSE;
+    args->atime.set_it = FALSE;
+    args->mtime.set_it = FALSE;
+
+	//fprintf(stderr, "parse_sattr: line %s\n", t);
+	while (1) {
+		if (!strncmp (t, "mode", 4)) {
+			t+=5;
+			sscanf(t, "%x", &i); 
+			args->mode.set_it = TRUE;
+			args->mode.mode = i;		// (uint32_t) 0666;
+		} else if (!strncmp (t, "ctime", 5)) {
+			RFS_ASSERT (guard);
+			t+=6;
+			RFS_ASSERT (strncmp(t, "SERVER", 6));
+			sscanf (t, "%d.%d", &i, &j);
+			tm = adjust_time (dep_tab[index].timestamp, &i, &j);
+#ifndef IGNORE_SETATTR_CTIME
+			guard->check = TRUE;
+#endif
+			guard->obj_ctime.seconds = tm->sec;
+			guard->obj_ctime.nseconds = tm->usec*1000;
+		} else if (!strncmp (t, "atime", 5)) {
+			t+=6;
+			if (!strncmp(t, "SERVER", 6)) {
+				args->atime.set_it = SET_TO_SERVER_TIME;
+			} else {
+				args->atime.set_it = SET_TO_CLIENT_TIME;
+				sscanf (t, "%d.%d", &i, &j);
+				if (i==0) {
+					RFS_ASSERT (j==0);
+					args->atime.atime.seconds = 0;
+					args->atime.atime.nseconds = 0;
+				} else {
+					tm = adjust_time (dep_tab[index].timestamp, &i, &j);
+					args->atime.atime.seconds = tm->sec;
+					args->atime.atime.nseconds = tm->usec * 1000;
+				}
+			}
+		} else if (!strncmp (t, "mtime", 5)) {
+			t+=6;
+			if (!strncmp(t, "SERVER", 6)) {
+				args->mtime.set_it = SET_TO_SERVER_TIME;
+			} else {
+				args->mtime.set_it = SET_TO_CLIENT_TIME;
+				sscanf (t, "%d.%d", &i, &j);
+				if (i==0) {
+					RFS_ASSERT (j==0);
+					args->mtime.mtime.seconds = 0;
+					args->mtime.mtime.nseconds = 0;
+				} else {
+					tm = adjust_time (dep_tab[index].timestamp, &i, &j);
+					args->mtime.set_it = TRUE;
+					args->mtime.mtime.seconds = tm->sec;
+					args->mtime.mtime.nseconds = tm->usec * 1000;
+				}
+			}
+		} else if (!strncmp (t, "size", 4)) {
+				t+=5;
+			sscanf(t, "%x", &i); 
+			args->size.set_it = TRUE;
+			args->size.size._p._u = (uint32_t) 0;
+			args->size.size._p._l = (uint32_t) i;
+		} else if (!strncmp (t, "gid", 3)) {
+			t+=4;
+			sscanf(t, "%x", &i); 
+			args->gid.set_it = TRUE;
+#ifdef TAKE_CARE_SETATTR_GID
+			args->gid.gid = i;
+#else
+			args->gid.gid = 513;
+#endif
+		} else if ( !strncmp (t, "uid", 3)) {
+			t+=4;
+			sscanf(t, "%x", &i); 
+			args->uid.set_it = TRUE;
+#ifdef TAKE_CARE_SETATTR_UID
+			args->uid.uid = i;
+#else
+			args->uid.uid = 513;
+#endif
+		} else if (!strncmp (t, "con", 3)) {
+			break;
+		} else if (!strncmp (t, "sdata", 5)) {
+			break;
+		} else {
+			fprintf(stderr, "parse_sattr t: %s\n", t);
+			RFS_ASSERT (0);
+		}
+
+		while (*t!=' ')
+			t++;
+		t++;
+	}
+	return t;
+}
+
+char * parse_name (char * t, char * buf)
+{
+	int i;
+	if (!strncmp(t, "fn2", 3))
+		t+=4;
+	else if (!strncmp(t, "fn", 2))
+		t+=3;
+	else if (!strncmp(t, "name2", 5))
+		t+=6;
+	else if (!strncmp(t, "name", 4))
+		t+=5;
+	else if (!strncmp(t, "sdata", 5))
+		t+=6;
+	else {
+		fprintf(stderr, "%s\n", t);
+		RFS_ASSERT (0);
+	}
+
+	RFS_ASSERT (*t=='"');
+	t++;
+	i = 0;
+	while (*t!='"')
+		buf[i++] = *t++; // ??? name buffer?	
+	RFS_ASSERT ((*t)=='"');
+	buf[i] = 0;
+	return (t+2);
+}
+
+char * parse_access_mode (char * line, int * mode)
+{
+	*mode = ACCESS3_READ;	
+	return line+2;
+	/* anyway the information in the trace is not enough, so we just make up something */
+}
+
+char * parse_stable_mode (char * line, stable_how * mode)
+{
+	switch (*line) {
+	case 'U': *mode = UNSTABLE;
+			  break;
+	case 'F': *mode = FILE_SYNC;
+			  break;
+	case 'D': *mode = DATA_SYNC;
+			  break;
+	default:
+		RFS_ASSERT (0);
+	}
+	return line +2;
+}
+
+
+void setarg_setattr (int index, char * line, SETATTR3args * args)
+{
+	char * t;
+	int i, j;
+	
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->object, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->object);
+#endif
+
+	args->guard.check = FALSE;
+	t = parse_sattr3 (t, &(args->new_attributes), &(args->guard), index);
+}
+
+void setarg_lookup (int index, char * line, LOOKUP3args * args, char * Cur_filename)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->what.dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->what.dir)
+#endif
+	t = parse_name (t, Cur_filename);
+	args->what.name = Cur_filename;
+}
+
+void setarg_access (int index, char * line, ACCESS3args * args)
+{
+	char * t;
+
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->object, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->object);
+#endif
+
+	parse_access_mode (t, &args->access);	//ACCESS3_MODIFY;	// ??? the actual parameter can be different
+}
+
+void setarg_readlink (int index, char * line, READLINK3args * args)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->symlink, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle (&args->symlink);
+#endif
+}
+
+void setarg_read (int index, char * line, READ3args * args, char * buf)
+{
+	char * t;
+	int i;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->file, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle (&args->file);
+#endif
+
+	if (line[TRACE_VERSION_POS]=='3') {
+		t = strstr (t, "off");
+		RFS_ASSERT (t);
+		t+=4;
+	} else {
+		t = strstr (t, "offset");
+		RFS_ASSERT (t);
+		t+=7;
+	}
+	sscanf (t, "%x", &i);
+
+	RFS_ASSERT (i>=0 && i<0x7FFFFFFF)
+	args->offset._p._u = 0;
+	args->offset._p._l = i;
+#ifdef SEQUEN_READ
+	if (index>=memory_trace_index.head)
+		args->offset._p._l = (index-memory_trace_index.head)*4096;
+#endif
+	t = strstr (t, "count");
+	RFS_ASSERT (t);
+	t+=6;
+	sscanf (t, "%x", &i);
+
+	RFS_ASSERT (i <= 32768);
+	if (i > NFS_MAXDATA) {
+		read_data_owe += (i-NFS_MAXDATA);
+		read_data_adjust_times ++;
+		if (read_data_owe > 1073741824) {
+			read_data_owe -= 1073741824;
+			read_data_owe_GB ++;
+		}
+		
+		//printf ("adjust read count from %d to %d\n", i, NFS_MAXDATA);
+		i = NFS_MAXDATA;
+	}
+	read_data_total += i;
+	if (read_data_total > 1073741824) {
+		read_data_total -= 1073741824;
+		read_data_total_GB ++;
+	}
+
+	args->count = i;
+}
+
+void setarg_write (int index, char * line, WRITE3args * args, char * buf)
+{
+	char * t;
+	int i;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->file, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle (&args->file);
+#endif
+
+	//fprintf (stderr, "process write: %s\n", line);
+	if (line[TRACE_VERSION_POS]=='3') {
+		t = strstr (t, "off");
+		RFS_ASSERT (t);
+		t+=4;
+	} else {
+		RFS_ASSERT (line[TRACE_VERSION_POS]=='2');
+		t = strstr (t, "offset");
+		RFS_ASSERT (t);
+		t+=7;
+	}
+
+	sscanf (t, "%x", &i);
+	RFS_ASSERT (i>=0 && i<0x7FFFFFFF)
+	args->offset._p._u = 0;
+	args->offset._p._l = i;
+
+	t = strstr (t, "count");
+	RFS_ASSERT (t);
+	t+=6;
+	sscanf (t, "%x", &i);
+	RFS_ASSERT (i <= 32768);
+	if (i > NFS_MAXDATA) {
+		write_data_owe += (i-NFS_MAXDATA);
+		if (write_data_owe > 1073741824) {
+			write_data_owe -= 1073741824;
+			write_data_owe_GB ++;
+		}
+		write_data_adjust_times ++;
+		//printf ("adjust write count from %d to %d\n", i, NFS_MAXDATA);
+		i = NFS_MAXDATA;
+	}
+	write_data_total += i;
+	if (write_data_total > 1073741824) {
+		write_data_total -= 1073741824;
+		write_data_total_GB ++;
+	}
+
+	RFS_ASSERT (i < MAX_BUF1_SIZE-128);	/* 128 is some random safe number to add */
+	args->count = i;
+
+	if (line[TRACE_VERSION_POS]==3) {
+		t = strstr (t, "stable");
+		RFS_ASSERT (t);
+		t+=7;
+		parse_stable_mode(t, &args->stable);	/* *t can be F, U, etc */ 
+	} else
+		args->stable = UNSTABLE;
+	args->data.data_len = args->count;
+	args->data.data_val = buf;
+}
+
+void setarg_create (int index, char * line, CREATE3args * args, char * Cur_filename)
+{
+	char * t;
+	//fprintf(stderr, "process create %s\n", line);
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->where.dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle (&args->where.dir);
+#endif
+	t = parse_name (t, Cur_filename);
+	args->where.name = Cur_filename;
+	if (line[TRACE_VERSION_POS]=='3') {
+		RFS_ASSERT (!strncmp(t, "how", 3));
+		t+=4;
+    	t = parse_create_mode (t, &args->how.mode);
+	} else
+		args->how.mode = UNCHECKED;
+	t = parse_sattr3 (t, &(args->how.createhow3_u.obj_attributes), NULL, index);
+}
+
+void setarg_mkdir (int index, char * line, MKDIR3args * args, char * Cur_filename)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->where.dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle (&args->where.dir);
+#endif
+	t = parse_name (t, Cur_filename);
+	args->where.name = Cur_filename;
+	t = parse_sattr3 (t, &(args->attributes), NULL, index);
+}
+
+void setarg_symlink(int index, char * line, SYMLINK3args * args, char * Cur_filename, char * sym_data)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->where.dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle (&args->where.dir);
+#endif
+	t = parse_name (t, Cur_filename);
+	args->where.name = Cur_filename;
+	if (line[TRACE_VERSION_POS]=='2') {
+		t = parse_name (t, sym_data);
+		t = parse_sattr3 (t, &(args->symlink.symlink_attributes), NULL, index);
+	} else {
+		t = parse_sattr3 (t, &(args->symlink.symlink_attributes), NULL, index);
+		t = parse_name (t, sym_data);
+	}
+    args->symlink.symlink_data = sym_data;
+}
+
+void setarg_mknod(int index, char * line, MKNOD3args * args, char * Cur_filename)
+{
+	RFS_ASSERT (0);
+
+#ifdef notdef
+	/* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.what.type = NF3FIFO;
+    args.what.mknoddata3_u.pipe_attributes.mode.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mode.mode = (NFSMODE_FIFO | 0777);
+    args.what.mknoddata3_u.pipe_attributes.uid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.uid.uid = Cur_uid;
+    args.what.mknoddata3_u.pipe_attributes.gid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.gid.gid = Cur_gid;
+    args.what.mknoddata3_u.pipe_attributes.size.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._u = (uint32_t) 0;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._l =
+							(uint32_t) 512;
+    args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.seconds =
+							Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.nseconds =
+							Cur_time.usec * 1000;
+    args.what.mknoddata3_u.pipe_attributes.mtime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.seconds =
+								Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.nseconds =
+							Cur_time.usec * 1000;
+#endif
+}
+
+void setarg_remove (int index, char * line, REMOVE3args * args, char * Cur_filename)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->object.dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->object.dir)
+#endif
+	t = parse_name (t, Cur_filename);
+	args->object.name = Cur_filename;
+}
+
+void setarg_rmdir (int index, char * line, RMDIR3args * args, char * Cur_filename)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->object.dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->object.dir)
+#endif
+	t = parse_name (t, Cur_filename);
+	args->object.name = Cur_filename;
+}
+
+void setarg_rename (int index, char * line, RENAME3args * args, char * fromname, char * toname)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->from.dir, &dep_tab[index].fh_2->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh_2 + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh_2, ' '); t++; 
+#else
+	setarg_fhandle(&args->from.dir)
+#endif
+	t = parse_name (t, fromname);
+	args->from.name = fromname;
+
+	t = strstr (t, "fh2");	
+	RFS_ASSERT (t);				
+	t += 4;						
+	memmove((char *)&args->to.dir, lookup_fhandle(t), sizeof (nfs_fh3));	
+	t+=65;
+
+	t = parse_name (t, toname);
+	args->to.name = toname;
+}
+
+void setarg_link (int index, char * line, LINK3args * args, char * Cur_filename)
+{
+	char * t;
+
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->file, &dep_tab[index].fh_2->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh_2 + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh_2, ' '); t++; 
+#else
+	setarg_fhandle(&args->file)
+#endif
+
+	t = strstr (t, "fh2");	
+	RFS_ASSERT (t);				
+	t += 4;						
+	memmove((char *)&args->link.dir, lookup_fhandle(t), sizeof (nfs_fh3));	
+	t+=65;
+
+	t = parse_name (t, Cur_filename);
+	args->link.name = Cur_filename;
+}
+
+void  setarg_readdir (int index, char * line, READDIR3args * args)
+{
+	char * t;
+
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->dir);
+#endif
+	/* args->cookieverf is notset, it is not implemented in the linux-2.4.7 */
+	sscanf(t, "cookie %d count %d", &args->cookie._p._l, &args->count);
+    (void) memset((char *) args->cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+	args->cookie._p._u = (uint32_t) 0;
+}
+
+void  setarg_readdirplus (int index, char * line, READDIRPLUS3args * args)
+{
+	char * t;
+
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->dir, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->dir);
+#endif
+	/* args->cookieverf is notset, it is not implemented in the linux-2.4.7 */
+	sscanf(t, "cookie %d count %d maxcnt", &args->cookie._p._l, &args->dircount, &args->maxcount);
+    (void) memset((char *) args->cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+	args->cookie._p._u = (uint32_t) 0;
+
+#ifdef notdef
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
+    (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+	args.dircount = DEFAULT_MAX_BUFSIZE;
+	args.maxcount = DEFAULT_MAX_BUFSIZE;
+#endif
+}
+
+void setarg_fsstat (int index, char * line, FSSTAT3args * args)
+{
+	char * t;
+	setarg_fhandle(&args->fsroot);
+}
+
+void setarg_fsinfo (int index, char * line, FSINFO3args * args)
+{
+	char * t;
+	setarg_fhandle(&args->fsroot);
+}
+
+void setarg_pathconf (int index, char * line, PATHCONF3args * args)
+{
+	char * t;
+#ifdef TRY_SETARG_FAST
+	memcpy (&args->object, &dep_tab[index].fh->play_fh, sizeof(nfs_fh3));
+	//t = dep_tab[index].trace_fh + TRACE_FH_SIZE+1;
+	t = strchr(dep_tab[index].trace_fh, ' '); t++; 
+#else
+	setarg_fhandle(&args->object);
+#endif
+}
+
+void setarg_commit (int index, char * line, COMMIT3args * args)
+{
+	RFS_ASSERT (0);
+
+#ifdef notdef
+	/* set up the arguments */
+	(void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
+	           sizeof (nfs_fh3));
+	args.offset._p._u = args.offset._p._l = (uint32_t) 0;
+	args.count = Cur_file_ptr->attributes3.size._p._l;
+#endif
+}
+
+void setbuf_void (char * buf)
+{
+	return;
+}
+
+void setbuf_invalid (char * buf)
+{
+	RFS_ASSERT (0);
+}
+
+void setres_lookup (LOOKUP3res * reply)
+{
+#ifndef TRY_SETRES_FAST
+    (void) memset((char *) &(reply->resok.object), '\0', sizeof (nfs_fh3));
+#endif
+}
+
+void setres_readlink (READLINK3res * reply, char * sym_data)
+{
+    /* Have lower layers fill in the data directly. */
+    reply->resok.data = sym_data;
+}
+
+void setres_read (READ3res * reply, char * buf)
+{
+	/* Have lower layers fill in the data directly.  */
+	reply->resok.data.data_len = 0;
+	reply->resok.data.data_val = buf;
+}
+
+void setres_readdir (READDIR3res * reply, entry3 * entry_stream)
+{
+#ifndef TRY_SETRES_FAST
+    /* Have lower layers fill in the data directly.  */
+    (void) memset((char *) reply, '\0', sizeof (READDIR3res));
+    (void) memset((char *) entry_stream, '\0',
+					sizeof (entry3) * SFS_MAXDIRENTS);
+#endif
+    reply->resok.count = SFS_MAXDIRENTS;
+    reply->resok.reply.entries = entry_stream;
+}
+
+void setres_readdirplus (READDIRPLUS3res * reply, entryplus3 * entry_stream)
+{
+#ifndef TRY_SETRES_FAST
+    (void) memset((char *) reply, '\0', sizeof (READDIRPLUS3res));
+	//printf ("sizeof(entryplus3) %d SFS_MAXDIRENT %d\n", sizeof (entryplus3), SFS_MAXDIRENTS);
+    (void) memset((char *) entry_stream, '\0',
+				sizeof (entryplus3) * SFS_MAXDIRENTS);
+#endif
+    reply->resok.count = SFS_MAXDIRENTS;
+    reply->resok.reply.entries = entry_stream;
+}
+
+#define NFSPROC3_INVALID -1
+/* the array is indexed by sfs operation number */
+rfs_op_type rfs_Ops[TOTAL] = {
+{NFSPROC3_NULL,		setbuf_void, 		setbuf_void, xdr_void, xdr_void},
+{NFSPROC3_GETATTR, 	setarg_getattr, 	setbuf_void, xdr_GETATTR3args, xdr_GETATTR3res},
+{NFSPROC3_SETATTR, 	setarg_setattr, 	setbuf_void, xdr_SETATTR3args, xdr_SETATTR3res},
+{NFSPROC3_INVALID,	setbuf_invalid, 	setbuf_invalid, NULL, NULL},
+{NFSPROC3_LOOKUP, 	setarg_lookup,	 	setres_lookup, xdr_LOOKUP3args, xdr_LOOKUP3res},
+{NFSPROC3_READLINK, setarg_readlink, 	setres_readlink, xdr_READLINK3args, xdr_READLINK3res},
+{NFSPROC3_READ, 	setarg_read, 		setres_read, xdr_READ3args, xdr_READ3res},
+{NFSPROC3_INVALID, 	setbuf_invalid, 	setbuf_invalid, NULL, NULL},
+{NFSPROC3_WRITE, 	setarg_write, 		setbuf_void, xdr_WRITE3args, xdr_WRITE3res},
+{NFSPROC3_CREATE, 	setarg_create, 		setbuf_void, xdr_CREATE3args, xdr_CREATE3res},
+{NFSPROC3_REMOVE, 	setarg_remove,	 	setbuf_void, xdr_REMOVE3args, xdr_REMOVE3res},
+{NFSPROC3_RENAME, 	setarg_rename,	 	setbuf_void, xdr_RENAME3args, xdr_RENAME3res},
+{NFSPROC3_LINK, 	setarg_link,		setbuf_void, xdr_LINK3args, xdr_LINK3res},
+{NFSPROC3_SYMLINK, 	setarg_symlink, 	setbuf_void, xdr_SYMLINK3args, xdr_SYMLINK3res},
+{NFSPROC3_MKDIR, 	setarg_mkdir, 		setbuf_void, xdr_MKDIR3args, xdr_MKDIR3res},
+{NFSPROC3_RMDIR, 	setarg_rmdir,		setbuf_void, xdr_RMDIR3args, xdr_RMDIR3res},
+{NFSPROC3_READDIR, 	setarg_readdir, 	setres_readdir, xdr_READDIR3args, xdr_READDIR3res},
+{NFSPROC3_FSSTAT, 	setarg_fsstat,	 	setbuf_void, xdr_FSSTAT3args, xdr_FSSTAT3res},
+{NFSPROC3_ACCESS, 	setarg_access,	 	setbuf_void, xdr_ACCESS3args, xdr_ACCESS3res},
+{NFSPROC3_COMMIT, 	setarg_commit,	 	setbuf_void, xdr_COMMIT3args, xdr_COMMIT3res},
+{NFSPROC3_FSINFO, 	setarg_fsinfo,		setbuf_void,  xdr_FSINFO3args, xdr_FSINFO3res},
+{NFSPROC3_MKNOD, 	setarg_mknod, 		setbuf_void, xdr_MKNOD3args, xdr_MKNOD3res},
+{NFSPROC3_PATHCONF, setarg_pathconf, 	setbuf_void, xdr_PATHCONF3args, xdr_PATHCONF3res},
+{NFSPROC3_READDIRPLUS, setarg_readdirplus, setres_readdirplus, xdr_READDIRPLUS3args, xdr_READDIRPLUS3res}};
+
+/*
+ * --------------------  NFS ops vector --------------------
+ */
+/*
+ * per operation information
+ */
+sfs_op_type nfsv3_Ops[] = {
+
+/* name        mix    op    call  no  req  req  req  results */
+/*             pcnt  class  targ call pcnt cnt  targ         */
+
+ { "null",        0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "getattr",    11, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "setattr",     1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "root",        0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "lookup",     27, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readlink",    7, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "read",       18, Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "wrcache",     0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "write",       9, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "create",      1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "remove",      1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rename",      0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "link",        0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "symlink",     0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "mkdir",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rmdir",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdir",     2, Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsstat",      1, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "access",      7, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "commit",      5, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsinfo",      1, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "mknod",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "pathconf",    0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdirplus", 9, Read,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "TOTAL",     100, Lookup,  0,  0,  0.0,  0,   0,  { 0, }}
+};
+
+sfs_op_type *Ops;
+
diff --git a/TBBT/trace_play/rfs_3_ops.c.old b/TBBT/trace_play/rfs_3_ops.c.old
new file mode 100644
index 0000000..37a47be
--- /dev/null
+++ b/TBBT/trace_play/rfs_3_ops.c.old
@@ -0,0 +1,739 @@
+#ifndef lint
+static char sfs_3_opsSid[] = "@(#)sfs_3_ops.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+#include "sfs_c_def.h"
+#include "rfs_c_def.h"
+
+extern fh_map_t * lookup_fh (char * trace_fh);
+
+char * lookup_fhandle(char * fhandle)
+{
+	fh_map_t * fh;
+	fh = lookup_fh(fhandle);
+	RFS_ASSERT (fh);
+	return ((char *)&fh->play_fh);
+}
+
+
+#define setarg_fhandle(fhp) \
+	fh_map_t * fh; \
+	t = strstr (line, "fh");	\
+	RFS_ASSERT (t);				\
+	t += 3;						\
+	fh = lookup_fh(t);			\
+	RFS_ASSERT (fh);			\
+	(void) memmove((char *)fhp, &(fh->play_fh),			\
+					                               sizeof (nfs_fh3));	\
+	t+=TRACE_FH_SIZE+1;
+
+void setarg_getattr (int index, char * line, GETATTR3args * args)
+{
+	char * t;
+	setarg_fhandle(&args->object);
+}
+
+struct ladtime * adjust_time (struct timeval tm, int * sec, int * usec)
+{
+	struct ladtime trace_pkt_time;
+	static struct ladtime trace_arg_time;
+	struct timeval curtmp;
+	struct ladtime cur;
+
+	/* not sure whether sec ==0 means anything special, do not adjust the timestamp for this */
+	if (*sec ==0) {
+		RFS_ASSERT (0);
+		RFS_ASSERT (*usec == 0);
+		trace_arg_time.sec = 0;
+		trace_arg_time.usec = 0;
+		return (&trace_arg_time);
+	}
+	trace_pkt_time.sec = tm.tv_sec;
+	trace_pkt_time.usec = tm.tv_usec;
+
+	trace_arg_time.sec = *sec;
+	trace_arg_time.usec = *usec;
+
+	gettimeofday(&curtmp, NULL);
+	cur.sec = curtmp.tv_sec;
+	cur.usec = curtmp.tv_usec;
+
+	//fprintf (stderr, "trace_pkt_time %d.%d trace_arg_time %d.%d cur %d.%d\n", trace_pkt_time.sec, trace_pkt_time.usec, trace_arg_time.sec, trace_arg_time.usec, cur.sec, cur.usec);
+
+	ADDTIME (trace_arg_time, cur);
+	//fprintf(stderr, "after add, %d.%d\n", trace_arg_time.sec, trace_arg_time.usec);
+	RFS_ASSERT (LARGERTIME (trace_arg_time, trace_pkt_time));
+	SUBTIME (trace_arg_time, trace_pkt_time);
+	return (&trace_arg_time);
+}
+
+char * parse_create_mode(char * t, createmode3 * mode)
+{
+	*mode = UNCHECKED;
+	return (t+2);
+	/* anyway, we can not get concrete result from the trace, just chose this mode */
+	RFS_ASSERT (0);
+}
+
+char * parse_sattr3(char * t, sattr3 * args, sattrguard3 * guard, int index)
+{
+	int i,j;
+	struct ladtime * tm;
+
+	/* set the default value of SETATTR3args->*/
+    args->mode.set_it = FALSE;
+    args->uid.set_it = FALSE;
+    args->gid.set_it = FALSE;
+    args->size.set_it = FALSE;
+    args->atime.set_it = FALSE;
+    args->mtime.set_it = FALSE;
+
+	//fprintf(stderr, "parse_sattr: line %s\n", t);
+	while (1) {
+		if (!strncmp (t, "mode", 4)) {
+			t+=5;
+			sscanf(t, "%x", &i); 
+			args->mode.set_it = TRUE;
+			args->mode.mode = i;		// (uint32_t) 0666;
+		} else if (!strncmp (t, "ctime", 5)) {
+			RFS_ASSERT (guard);
+			t+=6;
+			RFS_ASSERT (strncmp(t, "SERVER", 6));
+			sscanf (t, "%d.%d", &i, &j);
+			tm = adjust_time (dep_tab[index].timestamp, &i, &j);
+#ifndef IGNORE_SETATTR_CTIME
+			guard->check = TRUE;
+#endif
+			guard->obj_ctime.seconds = tm->sec;
+			guard->obj_ctime.nseconds = tm->usec*1000;
+		} else if (!strncmp (t, "atime", 5)) {
+			t+=6;
+			if (!strncmp(t, "SERVER", 6)) {
+				args->atime.set_it = SET_TO_SERVER_TIME;
+			} else {
+				args->atime.set_it = SET_TO_CLIENT_TIME;
+				sscanf (t, "%d.%d", &i, &j);
+				if (i==0) {
+					RFS_ASSERT (j==0);
+					args->atime.atime.seconds = 0;
+					args->atime.atime.nseconds = 0;
+				} else {
+					tm = adjust_time (dep_tab[index].timestamp, &i, &j);
+					args->atime.atime.seconds = tm->sec;
+					args->atime.atime.nseconds = tm->usec * 1000;
+				}
+			}
+		} else if (!strncmp (t, "mtime", 5)) {
+			t+=6;
+			if (!strncmp(t, "SERVER", 6)) {
+				args->mtime.set_it = SET_TO_SERVER_TIME;
+			} else {
+				args->mtime.set_it = SET_TO_CLIENT_TIME;
+				sscanf (t, "%d.%d", &i, &j);
+				if (i==0) {
+					RFS_ASSERT (j==0);
+					args->mtime.mtime.seconds = 0;
+					args->mtime.mtime.nseconds = 0;
+				} else {
+					tm = adjust_time (dep_tab[index].timestamp, &i, &j);
+					args->mtime.set_it = TRUE;
+					args->mtime.mtime.seconds = tm->sec;
+					args->mtime.mtime.nseconds = tm->usec * 1000;
+				}
+			}
+		} else if (!strncmp (t, "size", 4)) {
+				t+=5;
+			sscanf(t, "%x", &i); 
+			args->size.set_it = TRUE;
+			args->size.size._p._u = (uint32_t) 0;
+			args->size.size._p._l = (uint32_t) i;
+		} else if (!strncmp (t, "gid", 3)) {
+			t+=4;
+			sscanf(t, "%x", &i); 
+			args->gid.set_it = TRUE;
+#ifdef TAKE_CARE_SETATTR_GID
+			args->gid.gid = i;
+#else
+			args->gid.gid = 513;
+#endif
+		} else if ( !strncmp (t, "uid", 3)) {
+			t+=4;
+			sscanf(t, "%x", &i); 
+			args->uid.set_it = TRUE;
+#ifdef TAKE_CARE_SETATTR_UID
+			args->uid.uid = i;
+#else
+			args->uid.uid = 513;
+#endif
+		} else if (!strncmp (t, "con", 3)) {
+			break;
+		} else if (!strncmp (t, "sdata", 5)) {
+			break;
+		} else {
+			fprintf(stderr, "parse_sattr t: %s\n", t);
+			RFS_ASSERT (0);
+		}
+
+		while (*t!=' ')
+			t++;
+		t++;
+	}
+	return t;
+}
+
+char * parse_name (char * t, char * buf)
+{
+	int i;
+	if (!strncmp(t, "fn2", 3))
+		t+=4;
+	else if (!strncmp(t, "fn", 2))
+		t+=3;
+	else if (!strncmp(t, "name2", 5))
+		t+=6;
+	else if (!strncmp(t, "name", 4))
+		t+=5;
+	else if (!strncmp(t, "sdata", 5))
+		t+=6;
+	else {
+		fprintf(stderr, "%s\n", t);
+		RFS_ASSERT (0);
+	}
+
+	RFS_ASSERT (*t=='"');
+	t++;
+	i = 0;
+	while (*t!='"')
+		buf[i++] = *t++; // ??? name buffer?	
+	RFS_ASSERT ((*t)=='"');
+	buf[i] = 0;
+	return (t+2);
+}
+
+char * parse_access_mode (char * line, int * mode)
+{
+	*mode = ACCESS3_READ;	
+	return line+2;
+	/* anyway the information in the trace is not enough, so we just make up something */
+}
+
+char * parse_stable_mode (char * line, stable_how * mode)
+{
+	switch (*line) {
+	case 'U': *mode = UNSTABLE;
+			  break;
+	case 'F': *mode = FILE_SYNC;
+			  break;
+	case 'D': *mode = DATA_SYNC;
+			  break;
+	default:
+		RFS_ASSERT (0);
+	}
+	return line +2;
+}
+
+
+void setarg_setattr (int index, char * line, SETATTR3args * args)
+{
+	char * t;
+	int i, j;
+	
+	setarg_fhandle(&args->object);
+	args->guard.check = FALSE;
+	t = parse_sattr3 (t, &(args->new_attributes), &(args->guard), index);
+}
+
+void setarg_lookup (int index, char * line, LOOKUP3args * args, char * Cur_filename)
+{
+	char * t;
+	setarg_fhandle(&args->what.dir)
+	t = parse_name (t, Cur_filename);
+	args->what.name = Cur_filename;
+}
+
+void setarg_access (int index, char * line, ACCESS3args * args)
+{
+	char * t;
+
+	setarg_fhandle (&args->object);
+	parse_access_mode (t, &args->access);	//ACCESS3_MODIFY;	// ??? the actual parameter can be different
+}
+
+void setarg_readlink (int index, char * line, READLINK3args * args)
+{
+	char * t;
+	setarg_fhandle (&args->symlink);
+}
+
+void setarg_read (int index, char * line, READ3args * args, char * buf)
+{
+	char * t;
+	int i;
+	setarg_fhandle (&args->file);
+
+	if (line[TRACE_VERSION_POS]=='3') {
+		t = strstr (t, "off");
+		RFS_ASSERT (t);
+		t+=4;
+	} else {
+		t = strstr (t, "offset");
+		RFS_ASSERT (t);
+		t+=7;
+	}
+	sscanf (t, "%x", &i);
+
+	RFS_ASSERT (i>=0 && i<0x7FFFFFFF)
+	args->offset._p._u = 0;
+	args->offset._p._l = i;
+	t = strstr (t, "count");
+	RFS_ASSERT (t);
+	t+=6;
+	sscanf (t, "%x", &i);
+
+	RFS_ASSERT (i <= 32768);
+	if (i > NFS_MAXDATA) {
+		read_data_owe += (i-NFS_MAXDATA);
+		read_data_adjust_times ++;
+		if (read_data_owe > 1073741824) {
+			read_data_owe -= 1073741824;
+			read_data_owe_GB ++;
+		}
+		
+		//printf ("adjust read count from %d to %d\n", i, NFS_MAXDATA);
+		i = NFS_MAXDATA;
+	}
+	read_data_total += i;
+	RFS_ASSERT (read_data_total <1073741824);
+
+	args->count = i;
+}
+
+void setarg_write (int index, char * line, WRITE3args * args, char * buf)
+{
+	char * t;
+	int i;
+	setarg_fhandle (&args->file);
+
+	//fprintf (stderr, "process write: %s\n", line);
+	if (line[TRACE_VERSION_POS]=='3') {
+		t = strstr (t, "off");
+		RFS_ASSERT (t);
+		t+=4;
+	} else {
+		RFS_ASSERT (line[TRACE_VERSION_POS]=='2');
+		t = strstr (t, "offset");
+		RFS_ASSERT (t);
+		t+=7;
+	}
+
+	sscanf (t, "%x", &i);
+	RFS_ASSERT (i>=0 && i<0x7FFFFFFF)
+	args->offset._p._u = 0;
+	args->offset._p._l = i;
+
+	t = strstr (t, "count");
+	RFS_ASSERT (t);
+	t+=6;
+	sscanf (t, "%x", &i);
+	RFS_ASSERT (i <= 32768);
+	if (i > NFS_MAXDATA) {
+		write_data_owe += (i-NFS_MAXDATA);
+		if (write_data_owe > 1073741824) {
+			write_data_owe -= 1073741824;
+			write_data_owe_GB ++;
+		}
+		write_data_adjust_times ++;
+		//printf ("adjust write count from %d to %d\n", i, NFS_MAXDATA);
+		i = NFS_MAXDATA;
+	}
+	write_data_total += i;
+	RFS_ASSERT (write_data_total <1073741824);
+
+	RFS_ASSERT (i < MAX_BUF1_SIZE-128);	/* 128 is some random safe number to add */
+	args->count = i;
+
+	if (line[TRACE_VERSION_POS]==3) {
+		t = strstr (t, "stable");
+		RFS_ASSERT (t);
+		t+=7;
+		parse_stable_mode(t, &args->stable);	/* *t can be F, U, etc */ 
+	} else
+		args->stable = UNSTABLE;
+	args->data.data_len = args->count;
+	args->data.data_val = buf;
+}
+
+void setarg_create (int index, char * line, CREATE3args * args, char * Cur_filename)
+{
+	char * t;
+	//fprintf(stderr, "process create %s\n", line);
+	setarg_fhandle (&args->where.dir);
+	t = parse_name (t, Cur_filename);
+	args->where.name = Cur_filename;
+	if (line[TRACE_VERSION_POS]=='3') {
+		RFS_ASSERT (!strncmp(t, "how", 3));
+		t+=4;
+    	t = parse_create_mode (t, &args->how.mode);
+	} else
+		args->how.mode = UNCHECKED;
+	t = parse_sattr3 (t, &(args->how.createhow3_u.obj_attributes), NULL, index);
+}
+
+void setarg_create_old (int index, char * line, CREATE3args * retargs, char * Cur_filename)
+{
+	CREATE3args args;
+
+	sprintf(Cur_filename, "%d", index);
+	if (rfs_debug)
+		printf ("create file %s\n", Cur_filename);
+
+    /* set up the arguments */
+    (void) memmove((char *)&args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename; //RFS need a buffer for the name 
+    args.how.mode = UNCHECKED;
+    args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.mode.mode = (NFSMODE_REG | 0666);
+    args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
+    args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
+    args.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.atime.atime.seconds = Cur_time.esec;
+    args.how.createhow3_u.obj_attributes.atime.atime.nseconds =
+						Cur_time.usec * 1000;
+    args.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
+						Cur_time.usec * 1000;
+    args.how.createhow3_u.obj_attributes.size.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.size.size._p._u = (uint32_t) 0;
+    args.how.createhow3_u.obj_attributes.size.size._p._l = (uint32_t) 0;
+
+	memcpy (retargs, &args, sizeof (CREATE3args));
+}
+
+void setarg_mkdir (int index, char * line, MKDIR3args * args, char * Cur_filename)
+{
+	char * t;
+	setarg_fhandle (&args->where.dir);
+	t = parse_name (t, Cur_filename);
+	args->where.name = Cur_filename;
+	t = parse_sattr3 (t, &(args->attributes), NULL, index);
+}
+
+void setarg_symlink(int index, char * line, SYMLINK3args * args, char * Cur_filename, char * sym_data)
+{
+	char * t;
+	setarg_fhandle (&args->where.dir);
+	t = parse_name (t, Cur_filename);
+	args->where.name = Cur_filename;
+	if (line[TRACE_VERSION_POS]=='2') {
+		t = parse_name (t, sym_data);
+		t = parse_sattr3 (t, &(args->symlink.symlink_attributes), NULL, index);
+	} else {
+		t = parse_sattr3 (t, &(args->symlink.symlink_attributes), NULL, index);
+		t = parse_name (t, sym_data);
+	}
+    args->symlink.symlink_data = sym_data;
+}
+
+void setarg_mknod(int index, char * line, MKNOD3args * args, char * Cur_filename)
+{
+	RFS_ASSERT (0);
+
+#ifdef notdef
+	/* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.what.type = NF3FIFO;
+    args.what.mknoddata3_u.pipe_attributes.mode.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mode.mode = (NFSMODE_FIFO | 0777);
+    args.what.mknoddata3_u.pipe_attributes.uid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.uid.uid = Cur_uid;
+    args.what.mknoddata3_u.pipe_attributes.gid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.gid.gid = Cur_gid;
+    args.what.mknoddata3_u.pipe_attributes.size.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._u = (uint32_t) 0;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._l =
+							(uint32_t) 512;
+    args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.seconds =
+							Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.nseconds =
+							Cur_time.usec * 1000;
+    args.what.mknoddata3_u.pipe_attributes.mtime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.seconds =
+								Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.nseconds =
+							Cur_time.usec * 1000;
+#endif
+}
+
+void setarg_remove (int index, char * line, REMOVE3args * args, char * Cur_filename)
+{
+	char * t;
+	setarg_fhandle(&args->object.dir)
+	t = parse_name (t, Cur_filename);
+	args->object.name = Cur_filename;
+}
+
+void setarg_rmdir (int index, char * line, RMDIR3args * args, char * Cur_filename)
+{
+	char * t;
+	setarg_fhandle(&args->object.dir)
+	t = parse_name (t, Cur_filename);
+	args->object.name = Cur_filename;
+}
+
+void setarg_rename (int index, char * line, RENAME3args * args, char * fromname, char * toname)
+{
+	char * t;
+	setarg_fhandle(&args->from.dir)
+	t = parse_name (t, fromname);
+	args->from.name = fromname;
+
+	t = strstr (t, "fh2");	
+	RFS_ASSERT (t);				
+	t += 4;						
+	memmove((char *)&args->to.dir, lookup_fhandle(t), sizeof (nfs_fh3));	
+	t+=65;
+
+	t = parse_name (t, toname);
+	args->to.name = toname;
+}
+
+void setarg_link (int index, char * line, LINK3args * args, char * Cur_filename)
+{
+	char * t;
+
+	setarg_fhandle(&args->file)
+
+	t = strstr (t, "fh2");	
+	RFS_ASSERT (t);				
+	t += 4;						
+	memmove((char *)&args->link.dir, lookup_fhandle(t), sizeof (nfs_fh3));	
+	t+=65;
+
+	t = parse_name (t, Cur_filename);
+	args->link.name = Cur_filename;
+}
+
+void  setarg_readdir (int index, char * line, READDIR3args * args)
+{
+	char * t;
+
+	setarg_fhandle(&args->dir);
+	/* args->cookieverf is notset, it is not implemented in the linux-2.4.7 */
+	sscanf(t, "cookie %d count %d", &args->cookie._p._l, &args->count);
+    (void) memset((char *) args->cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+	args->cookie._p._u = (uint32_t) 0;
+}
+
+void  setarg_readdirplus (int index, char * line, READDIRPLUS3args * args)
+{
+	char * t;
+
+	setarg_fhandle(&args->dir);
+	/* args->cookieverf is notset, it is not implemented in the linux-2.4.7 */
+	sscanf(t, "cookie %d count %d maxcnt", &args->cookie._p._l, &args->dircount, &args->maxcount);
+    (void) memset((char *) args->cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+	args->cookie._p._u = (uint32_t) 0;
+
+#ifdef notdef
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
+    (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+	args.dircount = DEFAULT_MAX_BUFSIZE;
+	args.maxcount = DEFAULT_MAX_BUFSIZE;
+#endif
+}
+
+void setarg_fsstat (int index, char * line, FSSTAT3args * args)
+{
+	char * t;
+	setarg_fhandle(&args->fsroot);
+}
+
+void setarg_fsinfo (int index, char * line, FSINFO3args * args)
+{
+	char * t;
+	setarg_fhandle(&args->fsroot);
+}
+
+void setarg_pathconf (int index, char * line, PATHCONF3args * args)
+{
+	char * t;
+	setarg_fhandle(&args->object);
+}
+
+void setarg_commit (int index, char * line, COMMIT3args * args)
+{
+	RFS_ASSERT (0);
+
+#ifdef notdef
+	/* set up the arguments */
+	(void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
+	           sizeof (nfs_fh3));
+	args.offset._p._u = args.offset._p._l = (uint32_t) 0;
+	args.count = Cur_file_ptr->attributes3.size._p._l;
+#endif
+}
+
+void setbuf_void (char * buf)
+{
+	return;
+}
+
+void setbuf_invalid (char * buf)
+{
+	RFS_ASSERT (0);
+}
+
+void setres_lookup (LOOKUP3res * reply)
+{
+    (void) memset((char *) &(reply->resok.object), '\0', sizeof (nfs_fh3));
+}
+
+void setres_readlink (READLINK3res * reply, char * sym_data)
+{
+    /* Have lower layers fill in the data directly. */
+    reply->resok.data = sym_data;
+}
+
+void setres_read (READ3res * reply, char * buf)
+{
+	/* Have lower layers fill in the data directly.  */
+	reply->resok.data.data_len = 0;
+	reply->resok.data.data_val = buf;
+}
+
+void setres_readdir (READDIR3res * reply, entry3 * entry_stream)
+{
+    /* Have lower layers fill in the data directly.  */
+    (void) memset((char *) reply, '\0', sizeof (READDIR3res));
+    (void) memset((char *) entry_stream, '\0',
+					sizeof (entry3) * SFS_MAXDIRENTS);
+    reply->resok.count = SFS_MAXDIRENTS;
+    reply->resok.reply.entries = entry_stream;
+}
+
+void setres_readdirplus (READDIRPLUS3res * reply, entryplus3 * entry_stream)
+{
+    (void) memset((char *) reply, '\0', sizeof (READDIRPLUS3res));
+	//printf ("sizeof(entryplus3) %d SFS_MAXDIRENT %d\n", sizeof (entryplus3), SFS_MAXDIRENTS);
+    (void) memset((char *) entry_stream, '\0',
+				sizeof (entryplus3) * SFS_MAXDIRENTS);
+    reply->resok.count = SFS_MAXDIRENTS;
+    reply->resok.reply.entries = entry_stream;
+}
+
+#define NFSPROC3_INVALID -1
+/* the array is indexed by sfs operation number */
+rfs_op_type rfs_Ops[TOTAL] = {
+{NFSPROC3_NULL,		setbuf_void, 		setbuf_void, xdr_void, xdr_void},
+{NFSPROC3_GETATTR, 	setarg_getattr, 	setbuf_void, xdr_GETATTR3args, xdr_GETATTR3res},
+{NFSPROC3_SETATTR, 	setarg_setattr, 	setbuf_void, xdr_SETATTR3args, xdr_SETATTR3res},
+{NFSPROC3_INVALID,	setbuf_invalid, 	setbuf_invalid, NULL, NULL},
+{NFSPROC3_LOOKUP, 	setarg_lookup,	 	setres_lookup, xdr_LOOKUP3args, xdr_LOOKUP3res},
+{NFSPROC3_READLINK, setarg_readlink, 	setres_readlink, xdr_READLINK3args, xdr_READLINK3res},
+{NFSPROC3_READ, 	setarg_read, 		setres_read, xdr_READ3args, xdr_READ3res},
+{NFSPROC3_INVALID, 	setbuf_invalid, 	setbuf_invalid, NULL, NULL},
+{NFSPROC3_WRITE, 	setarg_write, 		setbuf_void, xdr_WRITE3args, xdr_WRITE3res},
+{NFSPROC3_CREATE, 	setarg_create, 		setbuf_void, xdr_CREATE3args, xdr_CREATE3res},
+{NFSPROC3_REMOVE, 	setarg_remove,	 	setbuf_void, xdr_REMOVE3args, xdr_REMOVE3res},
+{NFSPROC3_RENAME, 	setarg_rename,	 	setbuf_void, xdr_RENAME3args, xdr_RENAME3res},
+{NFSPROC3_LINK, 	setarg_link,		setbuf_void, xdr_LINK3args, xdr_LINK3res},
+{NFSPROC3_SYMLINK, 	setarg_symlink, 	setbuf_void, xdr_SYMLINK3args, xdr_SYMLINK3res},
+{NFSPROC3_MKDIR, 	setarg_mkdir, 		setbuf_void, xdr_MKDIR3args, xdr_MKDIR3res},
+{NFSPROC3_RMDIR, 	setarg_rmdir,		setbuf_void, xdr_RMDIR3args, xdr_RMDIR3res},
+{NFSPROC3_READDIR, 	setarg_readdir, 	setres_readdir, xdr_READDIR3args, xdr_READDIR3res},
+{NFSPROC3_FSSTAT, 	setarg_fsstat,	 	setbuf_void, xdr_FSSTAT3args, xdr_FSSTAT3res},
+{NFSPROC3_ACCESS, 	setarg_access,	 	setbuf_void, xdr_ACCESS3args, xdr_ACCESS3res},
+{NFSPROC3_COMMIT, 	setarg_commit,	 	setbuf_void, xdr_COMMIT3args, xdr_COMMIT3res},
+{NFSPROC3_FSINFO, 	setarg_fsinfo,		setbuf_void,  xdr_FSINFO3args, xdr_FSINFO3res},
+{NFSPROC3_MKNOD, 	setarg_mknod, 		setbuf_void, xdr_MKNOD3args, xdr_MKNOD3res},
+{NFSPROC3_PATHCONF, setarg_pathconf, 	setbuf_void, xdr_PATHCONF3args, xdr_PATHCONF3res},
+{NFSPROC3_READDIRPLUS, setarg_readdirplus, setres_readdirplus, xdr_READDIRPLUS3args, xdr_READDIRPLUS3res}};
+
+/*
+ * --------------------  NFS ops vector --------------------
+ */
+/*
+ * per operation information
+ */
+sfs_op_type nfsv3_Ops[] = {
+
+/* name        mix    op    call  no  req  req  req  results */
+/*             pcnt  class  targ call pcnt cnt  targ         */
+
+ { "null",        0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "getattr",    11, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "setattr",     1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "root",        0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "lookup",     27, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readlink",    7, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "read",       18, Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "wrcache",     0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "write",       9, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "create",      1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "remove",      1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rename",      0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "link",        0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "symlink",     0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "mkdir",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rmdir",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdir",     2, Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsstat",      1, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "access",      7, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "commit",      5, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsinfo",      1, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "mknod",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "pathconf",    0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdirplus", 9, Read,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "TOTAL",     100, Lookup,  0,  0,  0.0,  0,   0,  { 0, }}
+};
+
+sfs_op_type *Ops;
+
diff --git a/TBBT/trace_play/rfs_assert.h b/TBBT/trace_play/rfs_assert.h
new file mode 100644
index 0000000..ec360d5
--- /dev/null
+++ b/TBBT/trace_play/rfs_assert.h
@@ -0,0 +1,13 @@
+#ifndef RFS_ASSERT_H
+#define RFS_ASSERT_H
+#define RFS_ASSERT(condition)                                       \
+    if (!(condition)) {                                             \
+        fprintf(stderr, "Assertion failed: line %d, file \"%s\"\n", \
+	                    __LINE__, __FILE__);                        \
+		fflush(stdout); \
+		fflush(stdout); \
+		fflush(stderr); \
+		fflush(stderr); \
+		exit(-1); \
+    }
+#endif
diff --git a/TBBT/trace_play/rfs_c_age.c b/TBBT/trace_play/rfs_c_age.c
new file mode 100644
index 0000000..cdf9c6c
--- /dev/null
+++ b/TBBT/trace_play/rfs_c_age.c
@@ -0,0 +1,1393 @@
+/* rfs_age_unit_base.c */
+#include <sys/vfs.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include "rfs_assert.h"
+#include "profile.h"
+#define MKDIR 1
+#define RMDIR 2
+#define CREATE 3
+#define REMOVE 4
+#define WRITE 5
+#define TRUNCATE 6
+
+#define MAX_FILES 400000
+#define MAX_DIRS  100000
+#define FILE_FH_HTABLE_SIZE MAX_FILES
+#define MAX_NAMELEN 512
+#define MAX_PLAY_PATH_SIZE 256
+//#define MAX_COMMAND_LEN (MAX_PLAY_PATH_SIZE+16)
+//#define NFS_MAXDATA 4096
+#define NFS_MAXDATA 32768
+#define TRACE_FH_SIZE 64
+
+#define FH_T_FLAG_FREE 0
+#define FH_T_FLAG_IN_USE 1
+#define IS_FILE 0
+#define IS_DIR 1
+#define EXIST 0
+#define NON_EXIST 1
+#define COMPLETE 3
+#define ACTIVE 0
+#define INACTIVE 1
+#define DONT_CARE 2
+
+int EVEN_CHUNK_SIZE = 0;
+int STAGE_NUM = 10;
+
+static char ftypename[3][32] = {"FILE", "DIR", "FTYPE_DONT_CARE"};
+static char activename[3][32] = {"ACTIVE", "INACTIVE", "ACTIVE_DONT_CARE"};
+static char existname[4][32] = {"EXIST", "NON_EXIST", "EXIST_DONT_CARE", "COMPLETE"};
+
+typedef struct {
+    char flag;
+	char ftype;
+	char exist_flag;
+	int psfh;
+	int size;
+	int cur_size;
+	int accumulated_write_size;
+    //char trace_fh [TRACE_FH_SIZE+1];
+    char path[MAX_PLAY_PATH_SIZE];
+} fh_t;
+
+typedef struct {
+	char name[32];
+	fh_t * fh;
+	//struct generic_entry * htable;
+	int fh_size;
+	int fh_max;
+	int active_fh_max;
+	//int index;
+	//int htable_size;
+} fh_info_t;
+
+fh_info_t obj_fh;
+profile_t read_line_profile, fgets_profile;
+char trace_file[MAX_NAMELEN];
+FILE * profile_fp = NULL;
+char testdir[MAX_NAMELEN];
+
+int active_obj_num = 0;
+int exist_active_obj_num = 0;
+static int active_file_num = 0, active_dir_num =0, age_file_num = 0, age_dir_num = 0;
+
+int age_create_num = 0;
+int age_mkdir_num = 0;
+int assure_create_num = 0;
+int assure_mkdir_num = 0;
+int age_write_num = 0;
+int nonage_write_num = 0;
+int overlap_write_num = 0;
+
+int fs_size_MB = 0, fs_size = 0;
+int rfs_debug = 0;
+
+
+int ACTIVE_RATIO;
+int FILE_RATIO = 50;
+int WRITE_CHUNK_NUM;
+int MAX_FS_SIZE_MB = 1000000; 
+int DISK_FRAGMENT_SIZE = 4096;
+int DISK_FRAGMENT_SIZE_MASK = 0xFFFFF000;
+
+int MIN_WRITE_SIZE;
+
+int aging_dirs ()
+{
+
+}
+
+int f()
+{};
+
+int init_profile_variables()
+{
+	init_profile ("read_line profile", &read_line_profile);
+	init_profile ("fgets profile", &fgets_profile);
+}
+
+int init_fh_info (char * name, fh_info_t * fh_infop, int fh_size, int htable_size)
+{
+	int i;
+
+	RFS_ASSERT (strlen(name) < sizeof(fh_infop->name));
+	strcpy (fh_infop->name, name);
+	fh_infop->fh_max = 0;
+	//fh_infop->index = 0;
+	fh_infop->fh_size = fh_size;
+	//fh_infop->htable_size = htable_size;
+	fh_infop->fh = (fh_t *)malloc (sizeof(fh_t)*fh_size);
+	RFS_ASSERT (fh_infop->fh);
+	//fh_infop->htable = malloc (sizeof(struct*generic_entry)*htable_size);
+	//RFS_ASSERT (fh_infop->htable);
+	printf("initialize %s size %d bytes\n", 
+		//name, sizeof(fh_t)*fh_size + sizeof(struct*generic_entry)*htable_size);
+		name, sizeof(fh_t)*fh_size);
+
+	for (i=0; i<fh_size; i++)
+		fh_infop->fh[i].flag = FH_T_FLAG_FREE;
+}
+
+int init()
+{
+//	init_fh_info ("file_fh", &file_fh, MAX_FILES, MAX_FILES);
+//	init_fh_info ("dir_fh", &dir_fh, MAX_DIRS, MAX_DIRS);
+	init_fh_info ("obj_fh", &obj_fh, MAX_FILES+MAX_DIRS, MAX_FILES+MAX_DIRS);
+}
+
+int add_fh_t (fh_info_t * fh_table, char * path, int sfh, int psfh, int size, int ftype, int exist_flag, int active_flag)
+{
+	int i;
+
+	if (size == -1) 
+		fs_size += DISK_FRAGMENT_SIZE;
+	else {
+		fs_size += ((size+DISK_FRAGMENT_SIZE-1) & DISK_FRAGMENT_SIZE_MASK);
+		if (size > (DISK_FRAGMENT_SIZE*12))	// first indirect block
+			fs_size += DISK_FRAGMENT_SIZE;
+	}
+	if (fs_size > 1000000) {
+		fs_size_MB += fs_size/1000000;
+		fs_size = fs_size % 1000000;
+	}
+
+	RFS_ASSERT (sfh >0);
+
+	if (active_flag == ACTIVE)
+		active_obj_num ++;
+	else
+		RFS_ASSERT (sfh >= fh_table->active_fh_max);
+
+	if (rfs_debug)
+		printf ("add to %s path %s sfh %d size %d %s %s %s\n", fh_table->name, path, sfh, size, 
+		ftypename[ftype], existname[exist_flag], activename[active_flag]);
+
+	RFS_ASSERT ( (sfh>=0) && (sfh<fh_table->fh_size) );
+	RFS_ASSERT (fh_table->fh[sfh].flag==FH_T_FLAG_FREE);
+	fh_table->fh[sfh].flag = FH_T_FLAG_IN_USE;
+	if (sfh >= fh_table->fh_max)
+		fh_table->fh_max = sfh+1;
+	RFS_ASSERT (strlen(path)<MAX_PLAY_PATH_SIZE);
+	strcpy (fh_table->fh[sfh].path, path);
+	fh_table->fh[sfh].psfh = psfh;
+	fh_table->fh[sfh].size = size;
+	fh_table->fh[sfh].cur_size = 0;
+	fh_table->fh[sfh].accumulated_write_size = 0;
+	fh_table->fh[sfh].ftype = ftype;
+	fh_table->fh[sfh].exist_flag = exist_flag;
+	if (active_flag == ACTIVE) {
+		if (ftype == IS_FILE)
+			active_file_num ++;
+		else {
+			RFS_ASSERT (ftype== IS_DIR);
+			active_dir_num ++;
+		}
+	} else {
+		if (ftype == IS_FILE)
+			age_file_num ++;
+		else {
+			RFS_ASSERT (ftype== IS_DIR);
+			age_dir_num ++;
+		}
+	}
+	//print_fh_map(fh_table);
+}
+
+
+int loop_write (int fd, char * buf, int buflen)
+{
+    int ret;
+    int pos = 0;
+
+    while (1) {
+        ret = write (fd, buf+pos, buflen-pos);
+
+        if (ret == -1) {
+			RFS_ASSERT (errno == ENOSPC);
+			fflush(stdout);
+            perror ("loop write");
+			check_free_blocks(0);
+			return -1;
+        }
+        if (ret == buflen-pos)
+            break;
+        pos += ret;
+    }
+    return 0;
+}
+
+int assure_exist(int sfh, char * path, int ftype_flag)
+{
+	char name[MAX_NAMELEN];
+	int ret;
+	char *p, *q;
+	int non_exist_flag = 0;
+	int count=0;
+	struct stat st;
+
+	if (rfs_debug)
+		printf("assure_exist %s\n", path);
+
+	ret = stat (path, &st);
+	if (ret == 0) {
+		if (ftype_flag == IS_DIR) {
+			RFS_ASSERT (st.st_mode & S_IFDIR);
+			RFS_ASSERT (!(st.st_mode & S_IFREG));
+		} else {
+			RFS_ASSERT (st.st_mode & S_IFREG);
+			RFS_ASSERT (!(st.st_mode & S_IFDIR));
+		}
+		return 0;
+	}
+	if (errno!=ENOENT) {
+		perror(path);
+	}
+	//RFS_ASSERT (errno == ENOENT);
+	
+	p = path;
+	q = name;
+	if (*p=='/') {
+		*q='/';
+		p++;
+		q++;
+	}
+	while (count++<100) {
+		/* copy the next component from path to name */
+		for (; *p!=0 && *p!='/'; p++, q++ ) 
+			*q = *p;
+		*q = 0;
+		ret = stat (name, &st);
+		if (ret == -1) {
+			if (errno != ENOENT)
+				perror (name);
+			RFS_ASSERT (errno == ENOENT)
+			if ((*p)==0 && (ftype_flag==IS_FILE)) {
+				ret = creat (name, S_IRWXU);
+				if (ret == -1)
+					perror (name);
+				RFS_ASSERT (ret >=0);
+				assure_create_num ++;
+				if (rfs_debug)
+					printf("sfh %d create %s\n", sfh, name);
+				close(ret);
+			} else {
+				ret = mkdir (name, S_IRWXU);
+				if (ret == -1)
+					perror (name);
+				RFS_ASSERT (ret >=0);
+				assure_mkdir_num ++;
+				if (rfs_debug) {
+					if (*p==0) 
+						printf("sfh %d mkdir %s\n", sfh, name);
+					else
+						printf("sfh %d middle mkdir %s\n", sfh, name);
+				}
+				RFS_ASSERT (ret ==0);
+			}
+		}
+		if ((*p)=='/') {
+			*q = '/';
+			p++; q++;
+		} else {
+			RFS_ASSERT ((*p)==0)
+			return 0;
+		}
+	}
+	RFS_ASSERT (0);
+}
+
+
+int print_fh_map(fh_info_t * fhp)
+{
+	int i;
+	int num = 0;
+	int active_obj_num = 0;
+
+
+	for (i=0; i<fhp->fh_max; i++) {
+		if (fhp->fh[i].flag == FH_T_FLAG_IN_USE) {
+			num ++;
+			if (i < fhp->active_fh_max)
+				active_obj_num++;
+
+			if (rfs_debug)
+				printf("%s[%d] %s %s %s\n", fhp->name, i, fhp->fh[i].path, ftypename[fhp->fh[i].ftype], existname[fhp->fh[i].exist_flag]);
+		}
+	}
+	fprintf(stderr, "fh_max %d active_fh_max %d, in_use_num %d entries active_obj_num %d \n", fhp->fh_max, fhp->active_fh_max, num, active_obj_num);
+}
+
+void read_fh_map_line_skimmer (char * buf)
+{
+	char * p;
+	char name[MAX_NAMELEN];
+	int psfh, sfh, size;
+	char filename[MAX_NAMELEN];
+
+	sfh = 0;
+	if (!strncmp(buf, "::DIR ", strlen("::DIR "))) {
+		strcpy (name, testdir);
+		if (buf[6]=='/') {
+			sscanf(buf, "::DIR %s %d\n", name+strlen(name), &sfh);
+			add_fh_t (&obj_fh, name, sfh, -1, -1, IS_DIR, NON_EXIST, ACTIVE);
+		} /* else { 
+			RFS_ASSERT (!strncmp(buf,"::DIR Fake 1\n", strlen("::DIR Fake 1\n")));
+			sfh = 1;
+			add_fh_t (&obj_fh, name, sfh, -1, -1, IS_DIR, EXIST, ACTIVE);
+			exist_active_obj_num ++;
+		} */
+	} else {
+
+		if (!strncmp(buf, "::TBDIR", strlen("::TBDIR"))) 
+			return; 
+
+		p = strstr(buf, "parent");
+		RFS_ASSERT (p);
+		sscanf(p, "parent %d\n", &psfh);
+		RFS_ASSERT (obj_fh.fh[psfh].flag == FH_T_FLAG_IN_USE);
+		p = strstr(p, "name");
+		RFS_ASSERT (p);
+		if (!strncmp(p, "name xx", strlen("name xx"))) {
+			sscanf(p, "name xx-%s sfh %d size %x", filename, &sfh, &size);
+			//printf ("name xx-%s sfh %d\n", filename, sfh);
+		} else {
+			sscanf(p, "name \"%s sfh %d size %x", filename, &sfh, &size);
+			//printf ("name %s sfh %d\n", filename, sfh);
+			filename[strlen(filename)-1]=0;
+		}
+		strcpy (name, obj_fh.fh[psfh].path);	
+		strcat (name, "/");
+		strcat (name, filename);
+		add_fh_t (&obj_fh, name, sfh, psfh, size, IS_FILE, NON_EXIST, ACTIVE);
+	}
+}
+
+void read_fh_map_line_ls (char * buf)
+{
+	static int sfh = 2;
+	int size;
+	char name[MAX_NAMELEN];
+	char * p = name;
+	
+	strcpy (name, testdir);
+	strcat (name, "/");
+	if (strchr(buf, ' ')) {
+		sscanf(buf, "%d %s\n", &size, p+strlen(name));
+		add_fh_t (&obj_fh, name, sfh, -1, size, IS_FILE, NON_EXIST, ACTIVE);
+	} else {
+		sscanf(buf, "%s\n", p+strlen(name));
+		add_fh_t (&obj_fh, name, sfh, -1, -1, IS_DIR, NON_EXIST, ACTIVE);
+	};
+	sfh ++;
+}
+
+void read_fh_map (char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	int lineno = 0;
+	int fh_map_debug =0;
+#define FH_MAP_FORMAT_SKIMMER	0
+#define FH_MAP_FORMAT_LS		1
+	int fh_map_format;
+
+	if (strstr(fh_map_file, ".ski"))
+		fh_map_format = FH_MAP_FORMAT_SKIMMER;
+	else
+		fh_map_format = FH_MAP_FORMAT_LS;
+
+	fp = fopen(fh_map_file, "r");
+	if (!fp) {
+		printf ("can not opern %s\n", fh_map_file);
+		perror("open");
+		exit (0);
+	}
+	RFS_ASSERT (fp!=NULL);
+	
+
+	memset(buf, 0, sizeof(buf));
+
+	while (fgets(buf, 1024, fp)) {
+		RFS_ASSERT (fh_map_debug==0);
+		lineno ++;
+		if (rfs_debug)
+			printf ("line %d %s", lineno, buf);
+		if (lineno % 10000==0)
+			printf("%d fh_map entry read\n", lineno);
+		if (fh_map_format == FH_MAP_FORMAT_SKIMMER)
+			read_fh_map_line_skimmer(buf);
+		else 
+			read_fh_map_line_ls (buf);
+	}
+			
+	fclose(fp);
+	obj_fh.active_fh_max  = obj_fh.fh_max;
+	if (fh_map_debug) {
+		print_fh_map (&obj_fh);
+	}
+}
+
+int print_usage()
+{
+	printf("\n\nagefs fmt4 HOLDER_NUM HOLDER_SIZE DISK_FRAGMENT_SIZE testdir\n");
+	printf("Note: fmt4 is used to initialize the holders in a logical partition before starting writing aged files in a specific pattern as by fmt3 command\n");
+
+	printf("\n\nagefs fmt3 aged_file CHUNK_SIZE CHUNK_DISTANCE CHUNK_NUM START_BNO HOLDER_SIZE HOLDER_NUM DISK_FRAGMENT_SIZE testdir\n");
+	printf("Note: one file is written as CHUNK_NUM number of continuous chunks on disk, each chunk is of CHUNK_SIZE blocks, the distance between two adjacent chunks is CHUNK_DISTANCE blocks\n");
+
+	printf("\n\nagefs fmt2 size1 .. size_n num testdir\n");
+	printf("Note: N file is writen interleavingly for _num_ times, each time _size1_ bytes is written to file1, _size2_ bytes is written to file2, _sizen_ bytes is written to filen\n");
+
+	printf("\n\nagefs EVEN_CHUNK_SIZE FILE_RATIO ACTIVE_RATIO WRITE_CHUNK_NUM MAX_FS_SIZE_MB STAGE_NUM fh_path_map testdir\n");
+	printf("Note: EVEN_CHUNK_SIZE: if 1, each file is chopped to equal size chunks, if 0, each file size is chopped randomly but with the average size to be CHUNK_SIZE");
+	printf("	  FILE_RATIO: percentage of number of inactive files over number of inactive file system objects\n");
+	printf("      ACTIVE_RATIO: percentage of number of active file system objects over all file system objects\n");
+	printf("      WRITE_CHUNK_NUM: when a file is initialized, it is written in several open-close session interleved with writes to other files. Except small files where file_size/WRITE_CHUNK_SIZE is less than DISK_FRAGMENT_SIZE, each open-close session on the average write (file_size/WRITE_CHUNK_NUM) bytes. \n");
+	printf("	  MAX_FS_SIZE_MB: another condition to stop initialization, either all active file is initialized, or max file system size is reached\n");
+	printf("	  STAGE_NUM: divide the writing of files into several stages, each stage finish initialization of some of the files. The bigger the STAGE_NUM, the less concurrency is there\n");
+}
+
+inline char * read_line (int disk_index)
+{
+	static FILE * fp=NULL;
+	static int start=0;
+	static int start_disk_index=0;
+	int i;
+	static int finish_flag = 0;
+
+#define READ_LINE_BUF_SIZE 1000
+#define READ_LINE_LENGTH 32
+
+	static char line_buf[READ_LINE_BUF_SIZE][READ_LINE_LENGTH];
+	start_profile (&read_line_profile);
+
+	if (fp==NULL) {
+		if (strcmp(trace_file, "stdin")) {
+			fp = fopen(trace_file, "r");
+			if (!fp) {
+				printf("can not open files %s\n", fp);
+				perror("open");
+			}
+		} else {
+			fp = stdin;
+		}
+		RFS_ASSERT (fp!=NULL);
+		for (i=0; i<READ_LINE_BUF_SIZE; i++) {
+			start_profile(&fgets_profile);
+			if (!fgets(line_buf[i], READ_LINE_LENGTH, fp)) {
+				RFS_ASSERT (0);
+			}
+			end_profile(&fgets_profile);
+			//printf ("read_line, line_buf[%d]:%s", i, line_buf[i]);
+		}
+	}
+	
+	RFS_ASSERT (disk_index <= start_disk_index+READ_LINE_BUF_SIZE)
+	if (disk_index==(start_disk_index+READ_LINE_BUF_SIZE)) {
+		if (finish_flag) {
+			return NULL;
+		}
+		start_profile(&fgets_profile);
+		if (!fgets(line_buf[start], READ_LINE_LENGTH, fp)) {
+			end_profile(&fgets_profile);
+			fclose(fp);
+			finish_flag = 1;
+			return NULL;
+		}
+		end_profile(&fgets_profile);
+		//printf ("read_line, line_buf[%d]:%s", start, line_buf[start]);
+		start = (start+1) % READ_LINE_BUF_SIZE;
+		start_disk_index ++;
+	}
+	RFS_ASSERT (disk_index < start_disk_index+READ_LINE_BUF_SIZE)
+	i = (start+disk_index-start_disk_index)%READ_LINE_BUF_SIZE;
+
+	end_profile (&read_line_profile);
+	return (line_buf[i]);
+}
+
+int print_result()
+{
+	struct statfs stfs;
+	int ret;
+	static struct statfs first_stfs;
+	static int first_entry = 1;
+
+	ret = statfs (testdir, &stfs);
+	RFS_ASSERT (ret == 0);
+	if (first_entry) {
+		first_entry = 0;
+		first_stfs = stfs;
+	}
+
+	fprintf(stderr, "active_file_num %d active_dir_num %d age_file_num %d age_dir_num %d\n",
+		active_file_num, active_dir_num, age_file_num, age_dir_num);
+	fprintf(stderr, "number of used file nodes %d, used (4K) blocks in fs %d (%d MB)\n", first_stfs.f_ffree-stfs.f_ffree, first_stfs.f_bfree - stfs.f_bfree, (first_stfs.f_bfree-stfs.f_bfree)/(1000000/DISK_FRAGMENT_SIZE));
+	fprintf(stderr, "assure_create_num %d assure_mkdir_num %d\n", assure_create_num, assure_mkdir_num);
+}
+
+typedef struct {
+    int     pcnt;       /* percentile */
+    int     size;       /* file size in KB */
+} sfs_io_file_size_dist;
+
+sfs_io_file_size_dist Default_file_size_dist[] = {
+    /* percentage   KB size */
+#ifdef notdef
+	{   100,    128},			
+    {    94,     64},           /*  4% */
+    {    97,    128},           /*  3% */
+#endif
+    {    33,      1},           /* 33% */
+    {    54,      2},           /* 21% */
+    {    67,      4},           /* 13% */
+    {    77,      8},           /* 10% */
+    {    85,     16},           /*  8% */
+    {    90,     32},           /*  5% */
+    {    94,     64},           /*  4% */
+    {    97,    128},           /*  3% */
+    {    99,    256},           /*  2% */
+    {   100,   1024},           /*  1% */
+    {     0,      0}
+};
+
+/*
+ * For a value between 0-99, return a size based on distribution
+ */
+static int
+get_file_size()
+{
+	static file_array_initialized = 0;
+	static int file_size_array[100];
+	int i;
+
+	i = random() % 100;
+
+    if (i < 0 || i > 99)
+    return (0);
+
+    if (file_array_initialized == 0) {
+	    int j, k;
+    	for (j = 0, k = 0; j < 100; j++) {
+        	if (j >= Default_file_size_dist[k].pcnt &&
+            	Default_file_size_dist[k + 1].size != 0)
+    	    k++;
+        	file_size_array[j] = Default_file_size_dist[k].size * 1024;
+    	}
+    	file_array_initialized++;
+    }
+    return (file_size_array[i]);
+}
+
+int range_random(int min, int max)
+{
+	int i;
+	i = (random()%(max-min)) + min;
+	return i;
+}
+
+/* answer 1 with a probability of percent/100 */
+int decide(int percent)
+{
+	int i = random()%100;
+	if (i<percent)
+		return 1;
+	else
+		return 0;
+}
+
+int select_obj (fh_info_t * fhp, int ftype, int exist_flag, int active_flag, int min, int max)
+{
+	int i;
+	int sfh, count = 0;
+
+	//printf ("select_obj %s %s %s\n", ftypename[ftype], existname[exist_flag], activename[active_flag]);
+	if (active_flag == ACTIVE) {
+		sfh = range_random (0, fhp->active_fh_max);
+		for (i=0; i<fhp->active_fh_max; i++) {
+			if ((fhp->fh[sfh].flag == FH_T_FLAG_IN_USE) &&
+				((ftype==DONT_CARE) || (ftype ==fhp->fh[sfh].ftype)) &&
+				((exist_flag==DONT_CARE) || (fhp->fh[sfh].exist_flag == exist_flag))) {
+				return sfh;
+				}
+			sfh = (sfh+1) % fhp->active_fh_max;
+		}
+	} else {
+		//min = 0;
+		//max = fhp->fh_max;
+		//printf ("select_obj min %d max %d\n", min, max);
+		RFS_ASSERT (active_flag == DONT_CARE);
+		RFS_ASSERT (exist_flag == EXIST);
+		sfh = range_random (min, max);
+		for (i=min; i<max; i++) {
+		//	printf("check %d\n", sfh);
+			RFS_ASSERT ((sfh>=min) && (sfh<max));
+			if ((fhp->fh[sfh].flag == FH_T_FLAG_IN_USE) &&
+			    ((ftype==DONT_CARE) || (fhp->fh[sfh].ftype == ftype)) &&
+				(fhp->fh[sfh].exist_flag == EXIST)) {
+				return sfh;
+			}
+			sfh++;
+			if (sfh==max)
+				sfh = min;
+		}
+	}
+/*
+	for (i=min; i<max; i++) {
+		if ((fhp->fh[i].flag == FH_T_FLAG_IN_USE) &&
+			(fhp->fh[i].ftype == IS_FILE)				) {
+			if (fhp->fh[i].exist_flag == EXIST) {
+				printf ("actually %d\n", i);
+			}
+			RFS_ASSERT (fhp->fh[i].exist_flag != EXIST);
+			RFS_ASSERT (fhp->fh[i].exist_flag == COMPLETE);
+		}
+	}
+*/
+	return -1;
+}
+
+/* append "size" to file "path" */
+int append_file (int sfh, char * path, int size)
+{
+	int fd;
+	int written_bytes = 0;
+	int ret;
+#define BUF_SIZE 32768
+	static char buf[BUF_SIZE];
+
+	if (rfs_debug)
+		printf ("sfh %d append_file %s size %d\n", sfh, path, size);
+
+	fd = open (path, O_WRONLY|O_APPEND);
+	if (fd==-1)
+		perror(path);
+	RFS_ASSERT (fd > 0);
+	
+	while (written_bytes+NFS_MAXDATA < size) {
+		ret = loop_write (fd, buf, NFS_MAXDATA);
+		RFS_ASSERT (ret!=-1);
+		written_bytes += NFS_MAXDATA;
+	}
+	ret = loop_write (fd, buf, size-written_bytes);
+	RFS_ASSERT (ret!=-1);
+	close(fd);
+}
+
+int get_write_size (int target_size, int cur_size)
+{
+	int i;
+
+	if (target_size - cur_size < MIN_WRITE_SIZE)
+		return (target_size - cur_size);
+
+	/* target_size/WRITE_CHUNK_NUM would be the average value of i */
+	if (target_size < WRITE_CHUNK_NUM) {
+		i = MIN_WRITE_SIZE;
+	} else {
+
+		if (EVEN_CHUNK_SIZE)
+			i = target_size/WRITE_CHUNK_NUM;
+		else
+			i = random() % (2*(target_size/WRITE_CHUNK_NUM));
+
+		if (i < MIN_WRITE_SIZE)
+			i = MIN_WRITE_SIZE;
+	}
+
+	if (i > (target_size - cur_size))
+		i = target_size - cur_size;
+
+	return i;
+}
+
+FILE * fplog;
+
+
+int CHUNK_SIZE;
+int CHUNK_DISTANCE;
+int CHUNK_NUM;
+int START_BNO;
+int HOLDER_NUM;
+int HOLDER_SIZE;
+int INDIRECT_FANOUT;
+char agename[1024];
+
+#define MAX_DISK_FRAGMENT_SIZE 4096
+#define MAX_HOLDER_SIZE 10
+#define HOLDER_DIR_NUM 1
+#define DUMMY_FILE_COUNT 1000
+
+main4(int argc, char ** argv)
+{
+	int i, j;
+	char name[256];
+	char cmd[1024];
+	char * buf;
+	int fd, ret;
+	char testdir[1024];
+
+	if (argc!=6) {
+		print_usage();
+		return;
+	}
+	i = 2;
+	HOLDER_NUM = atoi(argv[i++]);
+	HOLDER_SIZE = atoi(argv[i++]);
+	DISK_FRAGMENT_SIZE = atoi(argv[i++]);
+	RFS_ASSERT (DISK_FRAGMENT_SIZE <= MAX_DISK_FRAGMENT_SIZE);
+	DISK_FRAGMENT_SIZE_MASK = ~(DISK_FRAGMENT_SIZE-1);
+	RFS_ASSERT ((DISK_FRAGMENT_SIZE_MASK == 0xFFFFF000) ||
+				(DISK_FRAGMENT_SIZE_MASK == 0xFFFFFC00)		);
+	strcpy (testdir, argv[i]);
+
+	fprintf(fplog, "main4: initialize the holders HOLDER_NUM %d HOLDER_SIZE %d DISK_FRAGMENT_SIZE %d testdir %s\n",
+			HOLDER_NUM, HOLDER_SIZE, DISK_FRAGMENT_SIZE, testdir);
+	fflush(fplog);
+
+	buf = (char *)malloc (HOLDER_SIZE*DISK_FRAGMENT_SIZE);
+	RFS_ASSERT (buf);
+
+	/* create some dummy files */
+	for (i=0; i<DUMMY_FILE_COUNT; i++) {
+		memset (name, 0, sizeof(name));
+		sprintf(name, "%s/dummy%d", testdir, i);
+ 		fd = creat (name, S_IRWXU);
+		if (fd == -1) {
+			perror(name);
+			exit(-1);
+		}
+		close (fd);
+	}
+
+	/* create directories */
+	if (HOLDER_DIR_NUM !=1) {
+		for (i=0; i<HOLDER_DIR_NUM; i++) {
+			memset (name, 0, sizeof(name));
+			sprintf(name, "%s/%d", testdir, i);
+ 			ret = mkdir (name, S_IRWXU);
+			if (ret == -1) {
+				perror(name);
+				exit(-1);
+			}
+		}
+	}
+
+	/* create regular files */
+	for (j=0; j<HOLDER_DIR_NUM; j++) {
+		for (i=0; i<HOLDER_NUM/HOLDER_DIR_NUM; i++) {
+			if (HOLDER_DIR_NUM == 1)  
+				sprintf(name, "%s/%d", testdir, i);
+			else
+				sprintf(name, "%s/%d/%d", testdir, j, i);
+			fd = open (name, O_CREAT|O_WRONLY);
+			if (fd == -1) {
+				perror(name);
+				exit(-1);
+			}
+			ret = loop_write (fd, buf, HOLDER_SIZE*DISK_FRAGMENT_SIZE);
+			close (fd);
+			if (ret == -1) 
+				break;
+		}
+	}
+
+#ifdef notdef
+	/* delete the dummy files */
+	for (i=0; i<DUMMY_FILE_COUNT; i++) {
+		memset (name, 0, sizeof(name));
+		sprintf(name, "%s/dummy%d", testdir, i);
+ 		ret = unlink (name);
+		if (ret == -1) {
+			perror(name);
+			exit(-1);
+		}
+	}
+#endif
+}
+
+int append_space_occupier()
+{
+	static char name [1024];
+	static FILE * fp = NULL;
+	char buf[MAX_DISK_FRAGMENT_SIZE];
+	int ret;
+	if (fp == NULL) {
+		sprintf(name, "%s/space_ocuupier", testdir);
+		fp = fopen (name, "a+");
+		RFS_ASSERT (fp!= NULL);
+		ret = fwrite (buf, DISK_FRAGMENT_SIZE, 1, fp);
+		if (ret != 1) {
+			perror("append space occupier");
+		}
+		fclose (fp);
+		fp = NULL;
+	};
+	ret = fwrite (buf, DISK_FRAGMENT_SIZE, 1, fp);
+	if (ret != 1) {
+		perror("append space occupier");
+	}
+	RFS_ASSERT (ret == 1);
+}
+
+int create_one_dummy_file()
+{
+	int i, fd, ret;
+	static int index = 0;
+	static char name[1024];
+	struct stat st;
+
+	for (i=0; i<DUMMY_FILE_COUNT; i++) {
+		index = (index+1) % DUMMY_FILE_COUNT;
+		sprintf(name, "%s/dummy%d", testdir, i);
+		ret = stat (name, &st);
+		if (ret == -1) {
+			RFS_ASSERT (errno == ENOENT);
+			fd = open (name, O_CREAT|O_WRONLY);
+			RFS_ASSERT (fd >=0);
+			close (fd);
+			return 0;
+		};
+	}
+}
+
+int delete_one_dummy_file()
+{
+	int i,ret;
+	static int index = 0;
+	static char name[1024];
+	struct stat st;
+
+	for (i=0; i<DUMMY_FILE_COUNT; i++) {
+		index = (index+1) % DUMMY_FILE_COUNT;
+		sprintf(name, "%s/dummy%d", testdir, i);
+		ret = stat (name, &st);
+		if (ret == 0) {
+ 			ret = unlink (name);
+			RFS_ASSERT (ret == 0);
+			return;
+		} else
+		 	RFS_ASSERT (errno == ENOENT);
+	}
+	RFS_ASSERT (0);
+}
+
+int create_sub_holder_file(int holderno, int sub_holderno)
+{
+	char name[256];
+	int fd, ret;
+	static char buf[MAX_DISK_FRAGMENT_SIZE];
+
+
+	RFS_ASSERT (MAX_DISK_FRAGMENT_SIZE >= DISK_FRAGMENT_SIZE);
+
+	sprintf(name, "%d.%d", holderno, sub_holderno);
+	printf ("create/write %s\n", name);
+	fd = open (name, O_CREAT|O_WRONLY);
+	RFS_ASSERT (fd >=0);
+	loop_write (fd, buf, DISK_FRAGMENT_SIZE);
+	close(fd);
+}
+
+int get_free_blocks ()
+{
+	static struct statfs stfs;
+	int ret;
+
+	ret = statfs (testdir, &stfs);
+	RFS_ASSERT (ret == 0);
+	return (stfs.f_bfree);
+}
+
+int print_free_blocks (char *string)
+{
+	static struct statfs stfs;
+	int ret;
+
+	ret = statfs (testdir, &stfs);
+	RFS_ASSERT (ret == 0);
+	printf("%s f_bfree %d \n", string, stfs.f_bfree);
+}
+
+int check_free_blocks (int num)
+{
+	static struct statfs stfs;
+	int ret;
+
+	ret = statfs (testdir, &stfs);
+	RFS_ASSERT (ret == 0);
+	if (stfs.f_bfree!=num) {
+		printf("f_bfree %d expected %d\n", stfs.f_bfree, num);
+		RFS_ASSERT (0);
+	}
+}
+
+int progress_on_aged_file(int * num)
+{
+	char buf[MAX_DISK_FRAGMENT_SIZE*MAX_HOLDER_SIZE];
+	static need_indirect_blocks = 0;
+	static skip_for_indirect_blocks = 0;
+	static int blkno = 0;
+
+	printf ("\n");
+	print_free_blocks("progress_on_aged_file begin");
+
+	if (skip_for_indirect_blocks == need_indirect_blocks) {
+		//check_free_blocks(free_block_num);
+		//RFS_ASSERT (free_block_num >= (1+need_indirect_blocks));
+		(*num) --;
+		printf("append to aged file %d bytes\n", DISK_FRAGMENT_SIZE);
+		append_file (0, agename, DISK_FRAGMENT_SIZE);
+		//*free_block_num -= (need_indirect_blocks +1)
+		//check_free_blocks(free_block_num);
+
+		blkno ++;
+		if (((blkno - 12) % INDIRECT_FANOUT) == 0) {
+			if (((blkno - (INDIRECT_FANOUT+12)) % (INDIRECT_FANOUT*INDIRECT_FANOUT)) == 0) {
+				if (blkno == 12 + INDIRECT_FANOUT + INDIRECT_FANOUT*INDIRECT_FANOUT) {
+					printf ("need_indirect_blocks is set to 3 blkno %d\n", blkno);
+					need_indirect_blocks = 3;
+				} else {
+					printf ("need_indirect_blocks is set to 2 blkno %d\n", blkno);
+					need_indirect_blocks = 2;
+				}
+			} else {
+				printf ("need_indirect_blocks is set to 1 blkno %d\n", blkno);
+				need_indirect_blocks = 1;
+			};
+		} else {
+			need_indirect_blocks = 0;
+		}
+		skip_for_indirect_blocks = 0;  
+	} else {
+		skip_for_indirect_blocks ++;  
+	}
+
+	printf ("skip_for_indirect_blocks -- %d\n", skip_for_indirect_blocks);
+	print_free_blocks("progress_on_aged_file end");
+}
+
+int free_blocks (char * agename, int start, int num)
+{
+	int holderno;
+	char name [128];
+	int ret;
+	struct stat st;
+	int sub_holderno;
+	int i;
+
+	printf ("free_blocks start %d  num %d\n", start, num);
+
+BEGIN:
+	check_free_blocks(0);
+	if (num == 0)
+		return start;
+   	holderno = start/HOLDER_SIZE;
+	sub_holderno = start%HOLDER_SIZE;
+
+	sprintf (name, "%d", holderno);
+	
+	ret = stat (name, &st);
+	if (ret == -1) {
+		RFS_ASSERT (errno == ENOENT);
+		for (i=sub_holderno; (i<HOLDER_SIZE && num>0); i++) {
+			sprintf(name, "%d.%d", holderno, i);
+			ret = stat (name, &st);
+			if (ret == 0) {
+
+				printf ("sub_holder file %s is unlinked\n", name);
+				ret = unlink(name);
+				RFS_ASSERT (ret == 0);
+
+				create_one_dummy_file();
+
+				printf ("write to age file %d bytes\n", DISK_FRAGMENT_SIZE);
+
+				progress_on_aged_file(&num);
+
+			} else { 
+				printf ("sub_holder file %s is already used\n", name);
+				RFS_ASSERT ((ret == -1) && (errno ==ENOENT));
+			}
+			start ++;
+		}
+		goto BEGIN; 
+	}
+	
+	RFS_ASSERT (ret == 0);
+	RFS_ASSERT (st.st_size == HOLDER_SIZE * DISK_FRAGMENT_SIZE);
+	printf ("holder file %s is unlinked\n", name);
+	ret = unlink(name);
+	RFS_ASSERT (ret == 0);
+	check_free_blocks(HOLDER_SIZE);
+
+	/* create the sub holders before the first slot that we need */
+	for (i=0; i<sub_holderno; i++) {
+		delete_one_dummy_file();
+		create_sub_holder_file (holderno, i);
+	}
+
+	/*
+	i = (HOLDER_SIZE - sub_holderno) < num? (HOLDER_SIZE - sub_holderno): num;
+	sub_holderno += i;
+	start += i;
+	num -= i;
+	check_free_blocks (i);
+	ret = loop_write (agefd, buf, DISK_FRAGMENT_SIZE*i);
+	RFS_ASSERT (ret != -1);
+	*/
+	i = HOLDER_SIZE - sub_holderno;
+	check_free_blocks(i);
+
+	while ((sub_holderno < HOLDER_SIZE) && (num>0)) {
+		sub_holderno ++;
+		start ++;
+
+		progress_on_aged_file(&num);
+						
+		RFS_ASSERT (ret != -1);
+	}
+
+	/* create the sub holders after the slot that we need */
+	for (i=sub_holderno; i<HOLDER_SIZE; i++) {
+		delete_one_dummy_file();
+		create_sub_holder_file (holderno, i);
+	}
+
+	create_one_dummy_file();
+	goto BEGIN;
+}
+
+int main3(int argc, char ** argv)
+{
+
+	int block_anchor;
+	int i;
+	int agefd;
+	char * buf;
+	char cwd[1024];
+	char * ret;
+	struct stat st;
+
+	if (argc!=11) {
+		print_usage();
+		return;
+	}
+	i = 2;
+
+	CHUNK_SIZE = atoi(argv[i++]);
+	CHUNK_DISTANCE = atoi (argv[i++]);
+	CHUNK_NUM = atoi (argv[i++]);
+	START_BNO = atoi (argv[i++]);
+	HOLDER_SIZE = atoi (argv[i++]);
+	RFS_ASSERT (HOLDER_SIZE <= MAX_HOLDER_SIZE);
+	HOLDER_NUM = atoi (argv[i++]);
+	DISK_FRAGMENT_SIZE = atoi (argv[i++]);
+	RFS_ASSERT (DISK_FRAGMENT_SIZE <= MAX_DISK_FRAGMENT_SIZE);
+	INDIRECT_FANOUT = (DISK_FRAGMENT_SIZE/sizeof(int));
+	strcpy (testdir, argv[i++]);
+	strcpy (agename, testdir);
+	strcat (agename, argv[i++]);
+	ret = stat (agename, &st);
+	if (ret!=-1) {
+		printf ("%s already exists\n", agename);
+	}	
+	RFS_ASSERT (errno == ENOENT);
+
+	fprintf(fplog, "main3: to age one file %s in a customized way, CHUNK_SIZE %d CHUNK_DISTANCE %d CHUNK_NUM %d START_BNO %d HOLDER_SIZE %d HOLDER_NUM %d DISK_FRAGMENT_SIZE %d MAX_DISK_FRAGMENT_SIZE %d testdir %s\n", agename, CHUNK_SIZE, CHUNK_DISTANCE, CHUNK_NUM, START_BNO, HOLDER_SIZE, HOLDER_NUM, DISK_FRAGMENT_SIZE, MAX_DISK_FRAGMENT_SIZE, testdir);
+	fflush(fplog);
+
+	/* change working directory */
+	ret = getcwd(cwd, sizeof(cwd));
+	RFS_ASSERT (ret == cwd);
+	i = chdir (testdir);
+	RFS_ASSERT (i==0);
+
+	if (START_BNO == -1) {
+		block_anchor = random() % (HOLDER_NUM*HOLDER_SIZE);
+	} else {
+		RFS_ASSERT (START_BNO >=0);
+		block_anchor = START_BNO % (HOLDER_NUM*HOLDER_SIZE);
+	}
+	while (get_free_blocks()!=0) {
+		print_free_blocks("fill up initial file system blocks using space occupier");
+		append_file (0, "/b6/space_occupier", DISK_FRAGMENT_SIZE);
+	};
+	delete_one_dummy_file();
+	agefd = open (agename, O_CREAT|O_WRONLY);
+	RFS_ASSERT (agefd>=0);
+	close (agefd);
+
+	buf = (char *)malloc (CHUNK_SIZE*DISK_FRAGMENT_SIZE);
+	RFS_ASSERT (buf);
+
+	for (i=0; i<CHUNK_NUM; i++) {
+		block_anchor = (block_anchor + CHUNK_DISTANCE) % (HOLDER_NUM * HOLDER_SIZE);	
+		block_anchor = free_blocks (agename, block_anchor, CHUNK_SIZE);
+	}
+
+	check_free_blocks(0);
+	i = chdir (cwd);
+	RFS_ASSERT (i==0);
+}
+
+int main2(int argc, char ** argv)
+{
+	int i, j;
+	int size[3], num;
+	FILE * fp[3];
+	char name[3][128];
+	char cmd[1024];
+
+	if (argc <= 4) {
+		print_usage();
+		return;
+	}
+	num = atoi(argv[argc-2]);
+	strcpy (testdir, argv[argc-1]);
+	fprintf(fplog, "main2: generate interleaved files\n");
+    fprintf(fplog, "testdir %s number of files %d ", testdir, num);
+	for (i=0; i<argc-4; i++) {
+		size[i] = atoi(argv[i+2]);
+		fprintf(fplog, "size[%d] %d ", i, size[i]);
+
+		RFS_ASSERT (size[i] >=0 && size[i] < 1000000000);
+		strcpy (name[i], testdir);
+		sprintf (name[i], "%s/file%d", testdir, i);
+		sprintf(cmd, "touch %s", name[i]);
+		system(cmd);
+		printf ("write %s \n", name[i]);
+	};
+	fprintf(fplog, "\n");
+	fflush(fplog);
+
+	for (j=0; j<num; j++) {
+		for (i=0; i<argc-4; i++)
+			append_file (i, name[i], size[i]);
+	}
+}
+
+int main(int argc, char ** argv)
+{
+	int i;
+	char cmd[1024];
+	char AGELOG_NAME[1024]= "/home/ningning/agefs.log";
+
+	sprintf(cmd, "date >> %s", AGELOG_NAME);
+	system (cmd);
+	fplog = fopen(AGELOG_NAME, "a");
+	RFS_ASSERT (fplog);
+	for (i=0; i<argc; i++) {
+		fprintf(fplog, "%s ", argv[i]);
+	}
+	fprintf (fplog, "\n");
+
+	if (argc>1 && (!strcmp(argv[1], "fmt2"))) 
+		main2 (argc, argv);
+	else if (argc>1 && (!strcmp(argv[1], "fmt3"))) 
+		main3 (argc, argv);
+	else if (argc>1 && (!strcmp(argv[1], "fmt4"))) 
+		main4 (argc, argv);
+	else 
+		main1 (argc, argv);
+END:
+	fclose (fplog);
+	sprintf(cmd, "date >> %s", AGELOG_NAME);
+	system (cmd);
+}
+
+int main1(int argc, char ** argv)
+{
+	char * buf;
+	static int disk_index=0;
+	int nfs3proc, size, off, count;
+	char procname[16];
+	struct stat st;
+	int ret;
+	int i,j,k;
+	int ftype_flag = 0, active_flag = 0;
+	char name[MAX_PLAY_PATH_SIZE];	
+	int sfh, psfh;
+	char mapname[1024];
+
+	profile_t create_profile, write_profile;
+	if (argc!=9) {
+		print_usage();
+		return;
+	}
+
+	init();
+	EVEN_CHUNK_SIZE = atoi(argv[1]);
+	RFS_ASSERT ((EVEN_CHUNK_SIZE==0) || (EVEN_CHUNK_SIZE==1));
+	FILE_RATIO = atoi (argv[2]);
+	ACTIVE_RATIO = atoi(argv[3]);
+	WRITE_CHUNK_NUM = atoi(argv[4]);
+	MAX_FS_SIZE_MB = atoi(argv[5]);
+
+	if (WRITE_CHUNK_NUM==0)
+		MIN_WRITE_SIZE = 2000000000;
+	else {
+		//MIN_WRITE_SIZE = DISK_FRAGMENT_SIZE;
+		MIN_WRITE_SIZE = 1;
+	}
+
+	STAGE_NUM = atoi (argv[6]);
+	strcpy (mapname, argv[7]);
+	strcpy (testdir, argv[8]);
+	ret = stat (testdir, &st);
+	if ((ret == -1) && (errno==ENOENT)) {
+		ret = mkdir (testdir, S_IRWXU);
+	}
+	RFS_ASSERT (ret >= 0);
+
+	
+	/* add testdir to obj_fh */
+	add_fh_t (&obj_fh, testdir, 1, -1, -1, IS_DIR, EXIST, ACTIVE);
+	exist_active_obj_num ++;
+	if (ACTIVE_RATIO >0) 
+		read_fh_map (mapname);
+
+	print_fh_map(&obj_fh);
+	init_profile_variables();
+
+	fprintf(fplog, "main1: populate the file system with both trace files and randomly generated files\n");
+	fprintf(fplog, "EVEN_CHUNK_SIZE %d FILE_RATIO %d ACTIVE_RATIO %d WRITE_CHUNK_NUM %d MAX_FS_SIZE_MB %d STAGE_NUM %d fh_map %s testdir %s\n", EVEN_CHUNK_SIZE, FILE_RATIO, ACTIVE_RATIO, WRITE_CHUNK_NUM, MAX_FS_SIZE_MB, STAGE_NUM, mapname, testdir);
+	system("date");
+	printf("EVEN_CHUNK_SIZE %d FILE_RATIO %d ACTIVE_RATIO %d WRITE_CHUNK_NUM %d MAX_FS_SIZE_MB %d STAGE_NUM %d fh_map %s testdir %s\n", EVEN_CHUNK_SIZE, FILE_RATIO, ACTIVE_RATIO, WRITE_CHUNK_NUM, MAX_FS_SIZE_MB, STAGE_NUM, mapname, testdir);
+	fflush(fplog);
+
+	profile_fp = fplog;
+	init_profile ("create_profile", &create_profile);
+	init_profile ("write_profile", &write_profile);
+
+	start_profile (&create_profile);
+	printf ("start creat/mkdir, active_obj_num %d\n", active_obj_num);
+	for (i=0; (exist_active_obj_num <= active_obj_num) && (fs_size_MB < MAX_FS_SIZE_MB); i++) {
+
+		if ((i!=0) && ((i%10000)==0)) {
+			fprintf (stderr, "\n%d object created, exist_active_obj_num %d expected size %d MB\n", i, exist_active_obj_num, fs_size_MB);
+		}
+
+		/* decide on the exact active obj or populated obj */
+		if (decide(ACTIVE_RATIO)) {
+			sfh = select_obj (&obj_fh, DONT_CARE, NON_EXIST, ACTIVE, 0, obj_fh.fh_max);
+			if (sfh == -1)
+				break;
+
+			obj_fh.fh[sfh].exist_flag = EXIST;
+			exist_active_obj_num ++;
+			ftype_flag = obj_fh.fh[sfh].ftype;
+			size = obj_fh.fh[sfh].size;
+		} else {
+			psfh = select_obj (&obj_fh, IS_DIR, EXIST, DONT_CARE, 0, obj_fh.fh_max);
+			strcpy (name, obj_fh.fh[psfh].path);
+			sfh = obj_fh.fh_max;
+			sprintf(name+strlen(name), "/AGE%d", obj_fh.fh_max); 
+
+			/* decide next obj is file or directory */
+			if (decide(FILE_RATIO)) {
+				ftype_flag = IS_FILE;
+				size = get_file_size();
+			} else {
+				ftype_flag = IS_DIR;
+				size = -1;
+			}
+			add_fh_t (&obj_fh, name, sfh, psfh, size, ftype_flag, EXIST, INACTIVE);
+
+		}
+
+		/* make sure/create the  obj pathname on disk */
+		assure_exist (sfh, obj_fh.fh[sfh].path, ftype_flag);
+		/* write file to sizes according certain distribution 
+		if (ftype_flag == IS_FILE) 
+			append_file (obj_fh.fh[sfh].path, obj_fh.fh[sfh].size);
+		*/
+	}
+	fprintf (stderr, "\n%d object created, exist_active_obj_num %d expected size %d MB\n", i, exist_active_obj_num, fs_size_MB);
+
+	end_profile (&create_profile);
+	start_profile (&write_profile);
+	//write_file_range (0, obj_fh.fh_max);
+	for (i=1; i<=STAGE_NUM; i++) {
+		write_file_range (obj_fh.fh_max*(i-1)/STAGE_NUM, obj_fh.fh_max*i/STAGE_NUM);
+		//fprintf(stderr, "getchar\n");
+		//getchar();
+	}
+	end_profile (&write_profile);
+
+	print_profile ("create_profile", &create_profile);
+	print_profile ("write_profile", &write_profile);
+	printf ("exist_active_obj_num %d active_obj_num %d fs_size_MB %d\n",
+			exist_active_obj_num, active_obj_num, fs_size_MB);
+
+	print_fh_map(&obj_fh);
+	print_result();
+	printf ("end of file system initialization\n");
+	system("date");
+}
+
+int write_file_range (int min, int max)
+{
+	int i, j, k, sfh;
+	int write_size, disk_write_size;
+
+	i = 0, j=0, k=0;
+	printf ("start writing files min %d max %d\n", min, max);
+	while (1) {
+		sfh = select_obj (&obj_fh, IS_FILE, EXIST, DONT_CARE, min, max);
+/*
+		if (!decide(obj_fh.fh[sfh].size*100/(MIN_WRITE_SIZE*WRITE_CHUNK_NUM))) {
+			printf("skip writing small file\n");
+			continue;
+		}
+*/
+		if (sfh == -1)
+			break;
+		write_size = get_write_size (obj_fh.fh[sfh].size, obj_fh.fh[sfh].cur_size);
+		obj_fh.fh[sfh].cur_size += write_size;
+		if (obj_fh.fh[sfh].cur_size == obj_fh.fh[sfh].size) {
+			obj_fh.fh[sfh].exist_flag = COMPLETE;
+		};
+
+#define ACCUMULATE_SMALL_WRITE	
+// This option improves speed by 12 times.
+#ifdef ACCUMULATE_SMALL_WRITE
+		obj_fh.fh[sfh].accumulated_write_size += write_size;
+		if (obj_fh.fh[sfh].exist_flag == COMPLETE) {
+			disk_write_size = obj_fh.fh[sfh].accumulated_write_size;
+		} else {
+			disk_write_size = (obj_fh.fh[sfh].accumulated_write_size -
+							  (obj_fh.fh[sfh].accumulated_write_size%DISK_FRAGMENT_SIZE));
+		};
+		obj_fh.fh[sfh].accumulated_write_size -= disk_write_size;
+#else
+		disk_write_size = write_size;
+#endif
+
+		if (disk_write_size >0) {
+			append_file (sfh, obj_fh.fh[sfh].path, disk_write_size);
+			if ((i%1000)==0) {
+				printf ("%d C ", i);
+				fflush(stdout);
+				k++;
+				if ((k%10)==0)
+					printf("\n");
+			}
+			i++;
+		} else {
+			if ((j%100000)==0) {
+				printf ("%d c ", j);
+				fflush(stdout);
+				k++;
+				if ((k%10)==0)
+					printf("\n");
+			}
+			j++;
+		}
+	}
+}
+
diff --git a/TBBT/trace_play/rfs_c_age.c.trace_base b/TBBT/trace_play/rfs_c_age.c.trace_base
new file mode 100644
index 0000000..adeeca5
--- /dev/null
+++ b/TBBT/trace_play/rfs_c_age.c.trace_base
@@ -0,0 +1,551 @@
+#include <sys/vfs.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include "rfs_assert.h"
+#include "profile.h"
+#define MKDIR 1
+#define RMDIR 2
+#define CREATE 3
+#define REMOVE 4
+#define WRITE 5
+#define TRUNCATE 6
+
+#define MAX_FILES 100000
+#define MAX_DIRS  100000
+#define FILE_FH_HTABLE_SIZE MAX_FILES
+#define MAX_NAMELEN 256
+#define MAX_PLAY_PATH_SIZE 256
+#define MAX_COMMAND_LEN (MAX_PLAY_PATH_SIZE+16)
+#define NFS_MAXDATA 32768
+#define TRACE_FH_SIZE 64
+
+#define FH_T_FLAG_FREE 0
+#define FH_T_FLAG_IN_USE 1
+#define IS_FILE 0
+#define IS_DIR 1
+#define NOT_EXIST 0
+#define EXIST 1
+
+typedef struct {
+    char flag;
+    //char trace_fh [TRACE_FH_SIZE+1];
+    char path[MAX_PLAY_PATH_SIZE];
+} fh_t;
+
+typedef struct {
+	char name[32];
+	fh_t * fh;
+	//struct generic_entry * htable;
+	int fh_size;
+	int fh_max;
+	int index;
+	//int htable_size;
+} fh_info_t;
+
+fh_info_t file_fh, dir_fh;
+profile_t read_line_profile, fgets_profile;
+char trace_file[MAX_NAMELEN];
+FILE * profile_fp = NULL;
+char testdir[MAX_NAMELEN];
+
+int age_create_num = 0;
+int age_mkdir_num = 0;
+int assure_create_num = 0;
+int assure_mkdir_num = 0;
+int age_write_num = 0;
+int nonage_write_num = 0;
+int overlap_write_num = 0;
+
+int init_profile_variables()
+{
+	init_profile ("read_line profile", &read_line_profile);
+	init_profile ("fgets profile", &fgets_profile);
+}
+
+int init_fh_info (char * name, fh_info_t * fh_infop, int fh_size, int htable_size)
+{
+	RFS_ASSERT (strlen(name) < sizeof(fh_infop->name));
+	strcpy (fh_infop->name, name);
+	fh_infop->fh_max = 0;
+	fh_infop->index = 0;
+	fh_infop->fh_size = fh_size;
+	//fh_infop->htable_size = htable_size;
+	fh_infop->fh = (fh_t *)malloc (sizeof(fh_t)*fh_size);
+	RFS_ASSERT (fh_infop->fh);
+	//fh_infop->htable = malloc (sizeof(struct*generic_entry)*htable_size);
+	//RFS_ASSERT (fh_infop->htable);
+	printf("initialize %s size %d bytes\n", 
+		//name, sizeof(fh_t)*fh_size + sizeof(struct*generic_entry)*htable_size);
+		name, sizeof(fh_t)*fh_size);
+}
+
+int init()
+{
+	init_fh_info ("file_fh", &file_fh, MAX_FILES, MAX_FILES);
+	init_fh_info ("dir_fh", &dir_fh, MAX_DIRS, MAX_DIRS);
+}
+
+int add_fh_t (fh_info_t * fh_table, char * path, int exist_flag)
+{
+	int i;
+
+	for (i=0; i<fh_table->fh_size; i++,fh_table->index++) {
+		if (fh_table->index==fh_table->fh_size)
+			fh_table->index = 0;
+		if (fh_table->fh[fh_table->index].flag == FH_T_FLAG_FREE) {
+			fh_table->fh[fh_table->index].flag = FH_T_FLAG_IN_USE;
+			//RFS_ASSERT(strlen(path)<MAX_PLAY_PATH_SIZE);
+			strcpy (fh_table->fh[fh_table->index].path, path);
+			if (fh_table->index > fh_table->fh_max)
+				fh_table->fh_max = fh_table->index;
+			return 0;
+		}
+	}
+	//print_fh_map(fh_table);
+	RFS_ASSERT (0);
+}
+
+int create_mkdir_op (int flag)
+{
+	static int fhno = 0;
+	char name[MAX_NAMELEN];
+	char command[MAX_COMMAND_LEN];
+	int i;
+	int fd;
+	int count = 0;
+	fh_info_t * fh_infop;
+
+	while (count++ < 100) {
+		i = random()%dir_fh.fh_max;
+		if (dir_fh.fh[i].flag==FH_T_FLAG_IN_USE) {
+			assure_exist(dir_fh.fh[i].path);
+			strcpy (name, dir_fh.fh[i].path);
+			if (flag == IS_FILE) {
+				sprintf (name+strlen(name), "AGEfile%d", fhno++);
+				fd = creat (name, S_IRWXU);
+				age_create_num++;
+				//printf ("create fd %d\n", fd);
+				close(fd);
+				fh_infop = &file_fh;
+			} else {
+				sprintf (name+strlen(name), "AGEdir%d", fhno++);
+				fd = mkdir (name, S_IRWXU);
+				age_mkdir_num++;
+				fh_infop = &dir_fh;
+			}
+			if (fd == -1) {
+				perror("");
+				if (errno == ENOENT) {
+					dir_fh.fh[i].flag = FH_T_FLAG_FREE;
+					continue;
+				} else
+					RFS_ASSERT (0);
+			}
+			add_fh_t (fh_infop, name, EXIST);
+			RFS_ASSERT (fd >=0);
+			return 0;
+		}
+	};
+	return -1;
+}
+
+int remove_op ()
+{
+	int i;
+	int count = 0;
+	int ret;
+
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist(file_fh.fh[i].path);
+			ret = remove (file_fh.fh[i].path);
+			RFS_ASSERT (ret ==0);
+			file_fh.fh[i].flag = FH_T_FLAG_FREE;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+int rmdir_op()
+{
+	int i;
+	int count=0;
+	char command[MAX_COMMAND_LEN];
+	int ret;
+
+	while (count++<100) {
+		i = random()%dir_fh.fh_max;
+		if ( (dir_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist(file_fh.fh[i].path);
+			ret = rmdir (dir_fh.fh[i].path);
+			if (ret == 0) {
+				dir_fh.fh[i].flag = FH_T_FLAG_FREE;
+				return 0;
+			}
+			RFS_ASSERT ((ret == -1) && (errno == ENOTEMPTY));
+			//strcpy (command, "rm -r %s", dir_fh.fh[i].path);
+			//system (command);
+		}
+	}
+	return -1;
+}
+
+int loop_write (int fd, char * buf, int buflen)
+{
+    int ret;
+    int pos = 0;
+
+    while (1) {
+        ret = write (fd, buf+pos, buflen-pos);
+
+        if (ret == -1) {
+            perror ("loop write");
+            exit (-1);
+        }
+        if (ret == buflen-pos)
+            break;
+        pos += ret;
+    }
+    return 0;
+}
+
+int assure_exist(char * path)
+{
+	char name[MAX_NAMELEN];
+	int ret;
+	char *p, *q;
+	int non_exist_flag = 0;
+	int count=0;
+	struct stat st;
+
+	ret = stat (path, &st);
+	if (ret == 0)
+		return 0;
+	RFS_ASSERT (errno == ENOENT);
+	
+	RFS_ASSERT (!strstr (path, "AGE"));
+	p = path;
+	q = name;
+	while (count++<100) {
+		for (; *p!=0 && *p!='/'; p++, q++ ) 
+			*q = *p;
+		*q = 0;
+		ret = stat (name, &st);
+		if (ret == -1) {
+			RFS_ASSERT (errno == ENOENT)
+			if ((*p)==0) {
+				ret = creat (name, S_IRWXU);
+				assure_create_num ++;
+				RFS_ASSERT (ret >=0);
+				close(ret);
+			} else {
+				ret = mkdir (name, S_IRWXU);
+				assure_mkdir_num ++;
+				RFS_ASSERT (ret >=0);
+			}
+		}
+		if ((*p)=='/') {
+			*q = '/';
+			p++; q++;
+		} else {
+			RFS_ASSERT ((*p)==0)
+			return 0;
+		}
+	}
+	RFS_ASSERT (0);
+}
+
+int write_op (int off, int size)
+{
+	static char buf[NFS_MAXDATA];
+	int i;
+	int count=0;
+	int fd;
+	int ret;
+	struct stat st;
+
+	RFS_ASSERT (size <= NFS_MAXDATA);
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+			assure_exist(file_fh.fh[i].path);
+			fd = open(file_fh.fh[i].path, O_WRONLY);
+			if (fd == -1)
+				perror("");
+			//else 
+				//printf ("write fd %d\n", fd);
+			RFS_ASSERT (fd!=-1);
+			fstat (fd, &st);
+			if (st.st_size < (off+size)) {
+				int written_bytes = 0;
+				while (written_bytes+NFS_MAXDATA < off+size-st.st_size) {
+					loop_write (fd, buf, NFS_MAXDATA);
+					written_bytes += NFS_MAXDATA;
+				}
+				loop_write (fd, buf, off+size-st.st_size-written_bytes);
+				if (strstr(file_fh.fh[i].path, "AGE")) {
+					age_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
+				} else 
+					nonage_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
+			} else
+				overlap_write_num++;
+/*
+			if (strstr(file_fh.fh[i].path, "AGE")) {
+				age_write_num++;
+			} else 
+				nonage_write_num++;
+			loop_write (fd, buf, size);
+*/
+			close(fd);
+			return 0;
+		};
+	}
+	return -1;
+}
+
+int truncate_op(int size)
+{
+	int i;
+	int count=0;
+	int ret;
+
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist (file_fh.fh[i].path);
+			ret = truncate(file_fh.fh[i].path, size);
+			if (ret ==0) 
+				return 0;
+			RFS_ASSERT (errno == ENOENT);
+			file_fh.fh[i].flag = FH_T_FLAG_FREE;
+			continue;	
+		}
+	};
+	return -1;
+}
+
+int print_fh_map(fh_info_t * fhp)
+{
+	int i;
+	int num = 0;
+	for (i=0; i<fhp->fh_max; i++) {
+		if (fhp->fh[i].flag == FH_T_FLAG_IN_USE) {
+			num ++;
+			printf("%s[%d] %s\n", fhp->name, i, fhp->fh[i].path);
+		}
+	}
+	fprintf(stderr, "fh_max %d total %d entries \n", fhp->fh_max, num);
+}
+
+void read_fh_map(char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	char trace_fh[TRACE_FH_SIZE];
+	char intbuf[9];
+	char * trace_path;
+	char * p;
+	int map_flag;
+	int lineno = 0;
+	int fh_map_debug =0;
+	char name[MAX_NAMELEN];
+
+	fp = fopen(fh_map_file, "r");
+	if (!fp) {
+		printf ("can not opern %s\n", fh_map_file);
+		perror("open");
+		exit (0);
+	}
+	RFS_ASSERT (fp!=NULL);
+	
+	intbuf[8]=0;
+
+	memset(buf, 0, sizeof(buf));
+	while (fgets(buf, 1024, fp)) {
+		RFS_ASSERT (fh_map_debug==0);
+		lineno ++;
+		if (lineno % 10000==0)
+			printf("%d fh_map entry read\n", lineno);
+
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf[strlen(buf)-1]=0;
+
+		trace_path = buf + TRACE_FH_SIZE +1;
+
+		strcpy (name, testdir);
+		strcat (name, trace_path);
+		if ((*(buf+strlen(buf)-1))=='/') {
+			*(buf+strlen(buf)-1)=0;
+			add_fh_t (&dir_fh, name, NOT_EXIST);
+		} else {
+			add_fh_t (&file_fh, name, NOT_EXIST);
+		}
+	}
+			
+	fclose(fp);
+	if (fh_map_debug) {
+		print_fh_map (&file_fh);
+		print_fh_map (&dir_fh);
+	}
+}
+
+int print_usage()
+{
+	printf("age trace_file fh_path_map testdir\n");
+}
+
+inline char * read_line (int disk_index)
+{
+	static FILE * fp=NULL;
+	static int start=0;
+	static int start_disk_index=0;
+	int i;
+	static int finish_flag = 0;
+
+#define READ_LINE_BUF_SIZE 1000
+#define READ_LINE_LENGTH 32
+
+	static char line_buf[READ_LINE_BUF_SIZE][READ_LINE_LENGTH];
+	start_profile (&read_line_profile);
+
+	if (fp==NULL) {
+		if (strcmp(trace_file, "stdin")) {
+			fp = fopen(trace_file, "r");
+			if (!fp) {
+				printf("can not open files %s\n", fp);
+				perror("open");
+			}
+		} else {
+			fp = stdin;
+		}
+		RFS_ASSERT (fp!=NULL);
+		for (i=0; i<READ_LINE_BUF_SIZE; i++) {
+			start_profile(&fgets_profile);
+			if (!fgets(line_buf[i], READ_LINE_LENGTH, fp)) {
+				RFS_ASSERT (0);
+			}
+			end_profile(&fgets_profile);
+			//printf ("read_line, line_buf[%d]:%s", i, line_buf[i]);
+		}
+	}
+	
+	RFS_ASSERT (disk_index <= start_disk_index+READ_LINE_BUF_SIZE)
+	if (disk_index==(start_disk_index+READ_LINE_BUF_SIZE)) {
+		if (finish_flag) {
+			return NULL;
+		}
+		start_profile(&fgets_profile);
+		if (!fgets(line_buf[start], READ_LINE_LENGTH, fp)) {
+			end_profile(&fgets_profile);
+			fclose(fp);
+			finish_flag = 1;
+			return NULL;
+		}
+		end_profile(&fgets_profile);
+		//printf ("read_line, line_buf[%d]:%s", start, line_buf[start]);
+		start = (start+1) % READ_LINE_BUF_SIZE;
+		start_disk_index ++;
+	}
+	RFS_ASSERT (disk_index < start_disk_index+READ_LINE_BUF_SIZE)
+	i = (start+disk_index-start_disk_index)%READ_LINE_BUF_SIZE;
+
+	end_profile (&read_line_profile);
+	return (line_buf[i]);
+}
+
+int f()
+{};
+
+int print_result()
+{
+	struct statfs stfs;
+	int ret;
+	ret = statfs (testdir, &stfs);
+	RFS_ASSERT (ret == 0);
+	fprintf(stderr, "number of files %d size of file system %d\n", stfs.f_files, stfs.f_bfree);
+	fprintf(stderr, "assure_create_num %d assure_mkdir_num %d, age_create_num %d age_mkdir_num %d age_write_num %d nonage_write_num %d overlap_write_num %d\n",
+			assure_create_num, assure_mkdir_num, age_create_num, age_mkdir_num, age_write_num, nonage_write_num, overlap_write_num);
+	printf("assure_create_num %d assure_mkdir_num %d, age_create_num %d age_mkdir_num %d age_write_num %d nonage_write_num %d overlap_write_num %d\n",
+			assure_create_num, assure_mkdir_num, age_create_num, age_mkdir_num, age_write_num, nonage_write_num, overlap_write_num);
+}
+
+int main(int argc, char ** argv)
+{
+	char * buf;
+	static int disk_index=0;
+	int j, nfs3proc, size, off, count;
+	char procname[16];
+	struct stat st;
+	int ret;
+
+	if (argc!=4) {
+		print_usage();
+		exit(0);
+	}
+
+	init();
+	strcpy (trace_file, argv[1]);
+	strcpy (testdir, argv[3]);
+	ret = stat (testdir, &st);
+	RFS_ASSERT (ret == 0);
+	read_fh_map(argv[2]);
+	init_profile_variables();
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+
+		memset (procname, 0, sizeof(procname));
+		//printf ("line[%d] %s", disk_index, buf);
+		sscanf (&buf[0], "%s", procname);
+		j = 0;
+  		while ((*(buf+j)!=' ') && (*(buf+j)!='\n'))
+			j++;
+		j++;
+		if (!strcmp(procname, "write"))
+			sscanf (&buf[j], "off %x count %x", &off, &count);
+
+		if (!strcmp(procname, "setattr")) 
+			sscanf (&buf[j], "size %x", &size);
+
+		if (!strcmp(procname, "write"))
+			ret = write_op(off, count);
+		else if (!strcmp(procname, "create")) 
+			ret = create_mkdir_op(IS_FILE); 
+		else if (!strcmp(procname, "mkdir")) 
+			ret = create_mkdir_op(IS_DIR);
+		else if (!strcmp(procname, "remove")) 
+			ret = remove_op(); 
+		else if (!strcmp(procname, "rmdir")) 
+			ret = rmdir_op();
+		else if (!strcmp(procname, "setattr")) 
+			ret = truncate_op(size);
+		else {
+			printf("disk_index %d procname %s\n", disk_index, procname);
+			RFS_ASSERT (0);
+		}
+		if (ret!=0) {
+			printf("execute disk_line[%d] %s error\n", disk_index, buf);
+		}
+		if ((disk_index%100)==0) {
+			fprintf (stderr, "%d disk trace parsed \n", disk_index);
+			print_result();
+		}
+	}
+	print_result();
+}
diff --git a/TBBT/trace_play/rfs_c_age.c.unit_base b/TBBT/trace_play/rfs_c_age.c.unit_base
new file mode 100644
index 0000000..176ad54
--- /dev/null
+++ b/TBBT/trace_play/rfs_c_age.c.unit_base
@@ -0,0 +1,915 @@
+/* rfs_age_unit_base.c */
+#include <sys/vfs.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include "rfs_assert.h"
+#include "profile.h"
+#define MKDIR 1
+#define RMDIR 2
+#define CREATE 3
+#define REMOVE 4
+#define WRITE 5
+#define TRUNCATE 6
+
+#define MAX_FILES 100000
+#define MAX_DIRS  100000
+#define FILE_FH_HTABLE_SIZE MAX_FILES
+#define MAX_NAMELEN 512
+#define MAX_PLAY_PATH_SIZE 1024
+#define MAX_COMMAND_LEN (MAX_PLAY_PATH_SIZE+16)
+#define NFS_MAXDATA 4096
+//#define NFS_MAXDATA 32768
+#define TRACE_FH_SIZE 64
+
+#define FH_T_FLAG_FREE 0
+#define FH_T_FLAG_IN_USE 1
+#define IS_FILE 0
+#define IS_DIR 1
+#define EXIST 0
+#define NON_EXIST 1
+#define COMPLETE 3
+#define ACTIVE 0
+#define INACTIVE 1
+#define DONT_CARE 2
+#define FILE_RATIO 50
+#define DISK_FRAGMENT_SIZE 4096
+//#define FRAGMENT_NUM 5
+//#define MIN_WRITE_SIZE 512
+//#define MIN_WRITE_SIZE 2000000000
+
+static char ftypename[3][32] = {"FILE", "DIR", "FTYPE_DONT_CARE"};
+static char activename[3][32] = {"ACTIVE", "INACTIVE", "ACTIVE_DONT_CARE"};
+static char existname[4][32] = {"EXIST", "NON_EXIST", "EXIST_DONT_CARE", "COMPLETE"};
+
+typedef struct {
+    char flag;
+	char ftype;
+	char exist_flag;
+	int psfh;
+	int size;
+	int cur_size;
+    //char trace_fh [TRACE_FH_SIZE+1];
+    char path[MAX_PLAY_PATH_SIZE];
+} fh_t;
+
+typedef struct {
+	char name[32];
+	fh_t * fh;
+	//struct generic_entry * htable;
+	int fh_size;
+	int fh_max;
+	int active_fh_max;
+	//int index;
+	//int htable_size;
+} fh_info_t;
+
+fh_info_t obj_fh;
+profile_t read_line_profile, fgets_profile;
+char trace_file[MAX_NAMELEN];
+FILE * profile_fp = NULL;
+char testdir[MAX_NAMELEN];
+
+int active_obj_num = 0;
+int exist_active_obj_num = 0;
+static int active_file_num = 0, active_dir_num =0, age_file_num = 0, age_dir_num = 0;
+
+int age_create_num = 0;
+int age_mkdir_num = 0;
+int assure_create_num = 0;
+int assure_mkdir_num = 0;
+int age_write_num = 0;
+int nonage_write_num = 0;
+int overlap_write_num = 0;
+
+int rfs_debug = 0;
+
+
+int ACTIVE_RATIO;
+int FRAGMENT_NUM;
+int MIN_WRITE_SIZE = 512;
+
+int aging_dirs ()
+{
+
+}
+
+
+int init_profile_variables()
+{
+	init_profile ("read_line profile", &read_line_profile);
+	init_profile ("fgets profile", &fgets_profile);
+}
+
+int init_fh_info (char * name, fh_info_t * fh_infop, int fh_size, int htable_size)
+{
+	int i;
+
+	RFS_ASSERT (strlen(name) < sizeof(fh_infop->name));
+	strcpy (fh_infop->name, name);
+	fh_infop->fh_max = 0;
+	//fh_infop->index = 0;
+	fh_infop->fh_size = fh_size;
+	//fh_infop->htable_size = htable_size;
+	fh_infop->fh = (fh_t *)malloc (sizeof(fh_t)*fh_size);
+	RFS_ASSERT (fh_infop->fh);
+	//fh_infop->htable = malloc (sizeof(struct*generic_entry)*htable_size);
+	//RFS_ASSERT (fh_infop->htable);
+	printf("initialize %s size %d bytes\n", 
+		//name, sizeof(fh_t)*fh_size + sizeof(struct*generic_entry)*htable_size);
+		name, sizeof(fh_t)*fh_size);
+
+	for (i=0; i<fh_size; i++)
+		fh_infop->fh[i].flag = FH_T_FLAG_FREE;
+}
+
+int init()
+{
+//	init_fh_info ("file_fh", &file_fh, MAX_FILES, MAX_FILES);
+//	init_fh_info ("dir_fh", &dir_fh, MAX_DIRS, MAX_DIRS);
+	init_fh_info ("obj_fh", &obj_fh, MAX_FILES+MAX_DIRS, MAX_FILES+MAX_DIRS);
+}
+
+int add_fh_t (fh_info_t * fh_table, char * path, int sfh, int psfh, int size, int ftype, int exist_flag, int active_flag)
+{
+	int i;
+
+	RFS_ASSERT (sfh >0);
+
+	if (active_flag == ACTIVE)
+		active_obj_num ++;
+	else
+		RFS_ASSERT (sfh >= fh_table->active_fh_max);
+
+	if (rfs_debug)
+		printf ("add to %s path %s sfh %d size %d %s %s %s\n", fh_table->name, path, sfh, size, 
+		ftypename[ftype], existname[exist_flag], activename[active_flag]);
+
+	RFS_ASSERT ( (sfh>=0) && (sfh<fh_table->fh_size) );
+	RFS_ASSERT (fh_table->fh[sfh].flag==FH_T_FLAG_FREE);
+	fh_table->fh[sfh].flag = FH_T_FLAG_IN_USE;
+	if (sfh >= fh_table->fh_max)
+		fh_table->fh_max = sfh+1;
+	strcpy (fh_table->fh[sfh].path, path);
+	fh_table->fh[sfh].psfh = psfh;
+	fh_table->fh[sfh].size = size;
+	fh_table->fh[sfh].cur_size = 0;
+	fh_table->fh[sfh].ftype = ftype;
+	fh_table->fh[sfh].exist_flag = exist_flag;
+	if (active_flag == ACTIVE) {
+		if (ftype == IS_FILE)
+			active_file_num ++;
+		else {
+			RFS_ASSERT (ftype== IS_DIR);
+			active_dir_num ++;
+		}
+	} else {
+		if (ftype == IS_FILE)
+			age_file_num ++;
+		else {
+			RFS_ASSERT (ftype== IS_DIR);
+			age_dir_num ++;
+		}
+	}
+	//print_fh_map(fh_table);
+}
+
+
+int loop_write (int fd, char * buf, int buflen)
+{
+    int ret;
+    int pos = 0;
+
+    while (1) {
+        ret = write (fd, buf+pos, buflen-pos);
+
+        if (ret == -1) {
+			printf ("fd %d\n", fd);
+            perror ("loop write");
+            exit (-1);
+        }
+        if (ret == buflen-pos)
+            break;
+        pos += ret;
+    }
+    return 0;
+}
+
+int assure_exist(int sfh, char * path, int ftype_flag)
+{
+	char name[MAX_NAMELEN];
+	int ret;
+	char *p, *q;
+	int non_exist_flag = 0;
+	int count=0;
+	struct stat st;
+
+	if (rfs_debug)
+		printf("assure_exist %s\n", path);
+
+	ret = stat (path, &st);
+	if (ret == 0)
+		return 0;
+	RFS_ASSERT (errno == ENOENT);
+	
+	p = path;
+	q = name;
+	if (*p=='/') {
+		*q='/';
+		p++;
+		q++;
+	}
+	while (count++<100) {
+		/* copy the next component from path to name */
+		for (; *p!=0 && *p!='/'; p++, q++ ) 
+			*q = *p;
+		*q = 0;
+		ret = stat (name, &st);
+		if (ret == -1) {
+			RFS_ASSERT (errno == ENOENT)
+			if ((*p)==0 && (ftype_flag==IS_FILE)) {
+				ret = creat (name, S_IRWXU);
+				if (ret == -1)
+					perror (name);
+				RFS_ASSERT (ret >=0);
+				assure_create_num ++;
+				if (rfs_debug)
+					printf("sfh %d create %s\n", sfh, name);
+				close(ret);
+			} else {
+				ret = mkdir (name, S_IRWXU);
+				assure_mkdir_num ++;
+				if (rfs_debug) {
+					if (*p==0) 
+						printf("sfh %d mkdir %s\n", sfh, name);
+					else
+						printf("sfh %d middle mkdir %s\n", sfh, name);
+				}
+				RFS_ASSERT (ret >=0);
+			}
+		}
+		if ((*p)=='/') {
+			*q = '/';
+			p++; q++;
+		} else {
+			RFS_ASSERT ((*p)==0)
+			return 0;
+		}
+	}
+	RFS_ASSERT (0);
+}
+
+
+int print_fh_map(fh_info_t * fhp)
+{
+	int i;
+	int num = 0;
+	int active_obj_num = 0;
+
+
+	for (i=0; i<fhp->fh_max; i++) {
+		if (fhp->fh[i].flag == FH_T_FLAG_IN_USE) {
+			num ++;
+			if (i < fhp->active_fh_max)
+				active_obj_num++;
+
+			if (rfs_debug)
+				printf("%s[%d] %s %s %s\n", fhp->name, i, fhp->fh[i].path, ftypename[fhp->fh[i].ftype], existname[fhp->fh[i].exist_flag]);
+		}
+	}
+	fprintf(stderr, "fh_max %d active_fh_max %d, in_use_num %d entries active_obj_num %d \n", fhp->fh_max, fhp->active_fh_max, num, active_obj_num);
+}
+
+void read_fh_map(char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	char trace_fh[TRACE_FH_SIZE];
+	char intbuf[9];
+	char * trace_path;
+	char * p;
+	int map_flag;
+	int lineno = 0;
+	int fh_map_debug =0;
+	char name[MAX_NAMELEN];
+	int sfh;
+
+	fp = fopen(fh_map_file, "r");
+	if (!fp) {
+		printf ("can not opern %s\n", fh_map_file);
+		perror("open");
+		exit (0);
+	}
+	RFS_ASSERT (fp!=NULL);
+	
+	intbuf[8]=0;
+
+	memset(buf, 0, sizeof(buf));
+	while (fgets(buf, 1024, fp)) {
+		RFS_ASSERT (fh_map_debug==0);
+		lineno ++;
+		if (rfs_debug)
+			printf ("line %d %s", lineno, buf);
+		if (lineno % 10000==0)
+			printf("%d fh_map entry read\n", lineno);
+
+		sfh = 0;
+		if (!strncmp(buf, "::DIR ", strlen("::DIR "))) {
+			strcpy (name, testdir);
+			if (buf[6]=='/') {
+				sscanf(buf, "::DIR %s %d\n", name+strlen(name), &sfh);
+				add_fh_t (&obj_fh, name, sfh, -1, -1, IS_DIR, NON_EXIST, ACTIVE);
+			} else { 
+				RFS_ASSERT (!strncmp(buf,"::DIR Fake 1\n", strlen("::DIR Fake 1\n")));
+				sfh = 1;
+				add_fh_t (&obj_fh, name, sfh, -1, -1, IS_DIR, EXIST, ACTIVE);
+				exist_active_obj_num ++;
+			}
+		} else {
+			char * p;
+			int psfh, sfh, size;
+			char filename[MAX_NAMELEN];
+
+			if (!strncmp(buf, "::TBDIR", strlen("::TBDIR"))) 
+				continue; 
+
+			p = strstr(buf, "parent");
+			RFS_ASSERT (p);
+			sscanf(p, "parent %d\n", &psfh);
+			RFS_ASSERT (obj_fh.fh[psfh].flag == FH_T_FLAG_IN_USE);
+			p = strstr(p, "name");
+			RFS_ASSERT (p);
+			if (!strncmp(p, "name xx", strlen("name xx"))) {
+				sscanf(p, "name xx-%s sfh %d size %x", filename, &sfh, &size);
+				//printf ("name xx-%s sfh %d\n", filename, sfh);
+			} else {
+				sscanf(p, "name \"%s sfh %d size %x", filename, &sfh, &size);
+				//printf ("name %s sfh %d\n", filename, sfh);
+				filename[strlen(filename)-1]=0;
+			}
+			strcpy (name, obj_fh.fh[psfh].path);	
+			strcat (name, "/");
+			strcat (name, filename);
+			add_fh_t (&obj_fh, name, sfh, psfh, size, IS_FILE, NON_EXIST, ACTIVE);
+		}
+	}
+			
+	fclose(fp);
+	obj_fh.active_fh_max  = obj_fh.fh_max;
+	if (fh_map_debug) {
+		print_fh_map (&obj_fh);
+	}
+}
+
+int print_usage()
+{
+	printf("agefs ACTIVE_RATIO FRAGMENT_NUM fh_path_map testdir\n");
+	printf("Note: if populate_scale is 4, the total active file size is 1GB\n");
+	printf("      then the total initial file system size is about 4GB\n");
+}
+
+inline char * read_line (int disk_index)
+{
+	static FILE * fp=NULL;
+	static int start=0;
+	static int start_disk_index=0;
+	int i;
+	static int finish_flag = 0;
+
+#define READ_LINE_BUF_SIZE 1000
+#define READ_LINE_LENGTH 32
+
+	static char line_buf[READ_LINE_BUF_SIZE][READ_LINE_LENGTH];
+	start_profile (&read_line_profile);
+
+	if (fp==NULL) {
+		if (strcmp(trace_file, "stdin")) {
+			fp = fopen(trace_file, "r");
+			if (!fp) {
+				printf("can not open files %s\n", fp);
+				perror("open");
+			}
+		} else {
+			fp = stdin;
+		}
+		RFS_ASSERT (fp!=NULL);
+		for (i=0; i<READ_LINE_BUF_SIZE; i++) {
+			start_profile(&fgets_profile);
+			if (!fgets(line_buf[i], READ_LINE_LENGTH, fp)) {
+				RFS_ASSERT (0);
+			}
+			end_profile(&fgets_profile);
+			//printf ("read_line, line_buf[%d]:%s", i, line_buf[i]);
+		}
+	}
+	
+	RFS_ASSERT (disk_index <= start_disk_index+READ_LINE_BUF_SIZE)
+	if (disk_index==(start_disk_index+READ_LINE_BUF_SIZE)) {
+		if (finish_flag) {
+			return NULL;
+		}
+		start_profile(&fgets_profile);
+		if (!fgets(line_buf[start], READ_LINE_LENGTH, fp)) {
+			end_profile(&fgets_profile);
+			fclose(fp);
+			finish_flag = 1;
+			return NULL;
+		}
+		end_profile(&fgets_profile);
+		//printf ("read_line, line_buf[%d]:%s", start, line_buf[start]);
+		start = (start+1) % READ_LINE_BUF_SIZE;
+		start_disk_index ++;
+	}
+	RFS_ASSERT (disk_index < start_disk_index+READ_LINE_BUF_SIZE)
+	i = (start+disk_index-start_disk_index)%READ_LINE_BUF_SIZE;
+
+	end_profile (&read_line_profile);
+	return (line_buf[i]);
+}
+
+int f()
+{};
+
+int print_result()
+{
+	struct statfs stfs;
+	int ret;
+	static struct statfs first_stfs;
+	static int first_entry = 1;
+
+	ret = statfs (testdir, &stfs);
+	RFS_ASSERT (ret == 0);
+	if (first_entry) {
+		first_entry = 0;
+		first_stfs = stfs;
+	}
+
+	fprintf(stderr, "active_file_num %d active_dir_num %d age_file_num %d age_dir_num %d\n",
+		active_file_num, active_dir_num, age_file_num, age_dir_num);
+	fprintf(stderr, "number of used file nodes %d, used (4K) blocks in fs %d (%d MB)\n", first_stfs.f_ffree-stfs.f_ffree, first_stfs.f_bfree - stfs.f_bfree, (first_stfs.f_bfree-stfs.f_bfree)/(1000000/4096));
+	fprintf(stderr, "assure_create_num %d assure_mkdir_num %d\n", assure_create_num, assure_mkdir_num);
+}
+
+typedef struct {
+    int     pcnt;       /* percentile */
+    int     size;       /* file size in KB */
+} sfs_io_file_size_dist;
+
+sfs_io_file_size_dist Default_file_size_dist[] = {
+    /* percentage   KB size */
+    {    94,     64},           /*  4% */
+    {    97,    128},           /*  3% */
+#ifdef notdef
+    {    33,      1},           /* 33% */
+    {    54,      2},           /* 21% */
+    {    67,      4},           /* 13% */
+    {    77,      8},           /* 10% */
+    {    85,     16},           /*  8% */
+    {    90,     32},           /*  5% */
+    {    94,     64},           /*  4% */
+    {    97,    128},           /*  3% */
+#endif
+    {    99,    256},           /*  2% */
+    {   100,   1024},           /*  1% */
+    {     0,      0}
+};
+
+/*
+ * For a value between 0-99, return a size based on distribution
+ */
+static int
+get_file_size()
+{
+	static file_array_initialized = 0;
+	static int file_size_array[100];
+	int i;
+
+	i = random() % 100;
+
+    if (i < 0 || i > 99)
+    return (0);
+
+    if (file_array_initialized == 0) {
+	    int j, k;
+    	for (j = 0, k = 0; j < 100; j++) {
+        	if (j >= Default_file_size_dist[k].pcnt &&
+            	Default_file_size_dist[k + 1].size != 0)
+    	    k++;
+        	file_size_array[j] = Default_file_size_dist[k].size * 1024;
+    	}
+    	file_array_initialized++;
+    }
+    return (file_size_array[i]);
+}
+
+int range_random(int min, int max)
+{
+	int i;
+	i = random()%(max-min) + min;
+	return i;
+}
+
+/* answer 1 with a probability of percent/100 */
+int decide(int percent)
+{
+	int i = random()%100;
+	if (i<percent)
+		return 1;
+	else
+		return 0;
+}
+
+int select_obj (fh_info_t * fhp, int ftype, int exist_flag, int active_flag)
+{
+	int i;
+	int min, max;
+	int sfh, count = 0;
+
+	//printf ("select_obj %s %s %s\n", ftypename[ftype], existname[exist_flag], activename[active_flag]);
+	if (active_flag == ACTIVE) {
+		sfh = range_random (0, fhp->active_fh_max);
+		for (i=0; i<fhp->active_fh_max; i++) {
+			if ((fhp->fh[sfh].flag == FH_T_FLAG_IN_USE) &&
+				((ftype==DONT_CARE) || (ftype ==fhp->fh[sfh].ftype)) &&
+				((exist_flag==DONT_CARE) || (fhp->fh[sfh].exist_flag == exist_flag))) 
+				return sfh;
+			sfh = (sfh+1) % fhp->active_fh_max;
+		}
+	} else {
+		RFS_ASSERT (active_flag == DONT_CARE);
+		RFS_ASSERT (exist_flag == EXIST);
+		sfh = range_random (0, fhp->fh_max);
+		for (i=0; i<fhp->fh_max; i++) {
+			if ((fhp->fh[sfh].flag == FH_T_FLAG_IN_USE) &&
+			    ((ftype==DONT_CARE) || (fhp->fh[sfh].ftype == ftype)) &&
+				(fhp->fh[sfh].exist_flag == EXIST)) {
+				return sfh;
+			}
+			sfh = (sfh+1) % fhp->fh_max;
+		}
+	}
+	return -1;
+
+	print_fh_map(&obj_fh);
+	printf ("active_obj_num %d exist_active_obj_num %d \n", active_obj_num, exist_active_obj_num);
+	printf ("failed select_obj %s %s\n", ftypename[ftype], activename[active_flag]);
+	RFS_ASSERT (0);
+}
+
+/* append "size" to file "path" */
+int append_file (int sfh, char * path, int size)
+{
+	int fd;
+	int written_bytes = 0;
+	static char buf[NFS_MAXDATA];
+
+	if (rfs_debug)
+		printf ("sfh %d append_file %s size %d\n", sfh, path, size);
+
+	fd = open (path, O_WRONLY|O_APPEND);
+	if (fd==-1)
+		perror(path);
+	RFS_ASSERT (fd > 0);
+	
+	while (written_bytes+NFS_MAXDATA < size) {
+		loop_write (fd, buf, NFS_MAXDATA);
+		written_bytes += NFS_MAXDATA;
+	}
+	loop_write (fd, buf, size-written_bytes);
+	close(fd);
+}
+
+int get_write_size (int target_size, int cur_size)
+{
+	int i;
+	if (target_size - cur_size < MIN_WRITE_SIZE)
+		return (target_size - cur_size);
+
+	/* target_size/FRAGMENT_NUM would be the average value of i */
+	if (target_size < FRAGMENT_NUM) {
+		i = MIN_WRITE_SIZE;
+	} else {
+		i = random() % (2*(target_size/FRAGMENT_NUM));
+		if (i < MIN_WRITE_SIZE)
+			i = MIN_WRITE_SIZE;
+	}
+	if (i > (target_size - cur_size))
+		i = target_size - cur_size;
+
+	return i;
+}
+
+int main(int argc, char ** argv)
+{
+	char * buf;
+	static int disk_index=0;
+	int j, nfs3proc, size, off, count;
+	char procname[16];
+	struct stat st;
+	int ret;
+	int i;
+	int ftype_flag = 0, active_flag = 0;
+	char name[MAX_PLAY_PATH_SIZE];	
+	int sfh, psfh;
+
+	if (argc!=5) {
+		print_usage();
+		exit(0);
+	}
+
+	init();
+	ACTIVE_RATIO = atoi(argv[1]);
+	FRAGMENT_NUM = atoi(argv[2]);
+	if (FRAGMENT_NUM==0)
+		MIN_WRITE_SIZE = 2000000000;
+	else
+		MIN_WRITE_SIZE = DISK_FRAGMENT_SIZE;
+
+	strcpy (testdir, argv[4]);
+	ret = stat (testdir, &st);
+	if ((ret == -1) && (errno==ENOENT)) {
+		ret = mkdir (testdir, S_IRWXU);
+	}
+	RFS_ASSERT (ret >= 0);
+	read_fh_map(argv[3]);
+	print_fh_map(&obj_fh);
+	init_profile_variables();
+
+/* NOTE: should have put file and directories in one table */
+
+	for (i=0; exist_active_obj_num < active_obj_num; i++) {
+
+		if ((i!=0) && ((i%1000)==0)) {
+			fprintf (stderr, "\n%d object created \n", i);
+			print_result();
+		}
+
+		/* decide on the exact active obj or populated obj */
+		if (decide(ACTIVE_RATIO)) {
+			sfh = select_obj (&obj_fh, DONT_CARE, NON_EXIST, ACTIVE);
+			if (sfh == -1)
+				break;
+
+			obj_fh.fh[sfh].exist_flag = EXIST;
+			exist_active_obj_num ++;
+			ftype_flag = obj_fh.fh[sfh].ftype;
+			size = obj_fh.fh[sfh].size;
+
+/*
+			{
+				int tmpfh = sfh;
+			  	while (obj_fh.fh[--tmpfh].exist_flag == NON_EXIST) {
+					if (strstr(obj_fh.fh[sfh].path, obj_fh.fh[tmpfh].path)) {
+						obj_fh.fh[tmpfh].exist_flag = EXIST;
+						//printf ("set %s to exist due to %s\n", obj_fh.fh[tmpfh].path, obj_fh.fh[sfh].path);
+						exist_active_obj_num ++;
+					}
+				}	
+			}
+*/
+		} else {
+			psfh = select_obj (&obj_fh, IS_DIR, EXIST, DONT_CARE);
+			strcpy (name, obj_fh.fh[psfh].path);
+			sfh = obj_fh.fh_max;
+			sprintf(name+strlen(name), "/AGE%d", obj_fh.fh_max); 
+
+			/* decide next obj is file or directory */
+			if (decide(FILE_RATIO)) {
+				ftype_flag = IS_FILE;
+				size = get_file_size();
+			} else {
+				ftype_flag = IS_DIR;
+				size = -1;
+			}
+			add_fh_t (&obj_fh, name, sfh, psfh, size, ftype_flag, EXIST, INACTIVE);
+
+		}
+
+		/* make sure/create the  obj pathname on disk */
+		assure_exist (sfh, obj_fh.fh[sfh].path, ftype_flag);
+		/* write file to sizes according certain distribution 
+		if (ftype_flag == IS_FILE) 
+			append_file (obj_fh.fh[sfh].path, obj_fh.fh[sfh].size);
+		*/
+
+	}
+
+	i = 0;
+	printf ("start writing files\n");
+	while (1) {
+		int write_size;
+		sfh = select_obj (&obj_fh, IS_FILE, EXIST, DONT_CARE);
+		if (sfh == -1)
+			break;
+		write_size = get_write_size (obj_fh.fh[sfh].size, obj_fh.fh[sfh].cur_size);
+		append_file (sfh, obj_fh.fh[sfh].path, write_size);
+		obj_fh.fh[sfh].cur_size += write_size;
+		if (obj_fh.fh[sfh].cur_size == obj_fh.fh[sfh].size) {
+			obj_fh.fh[sfh].exist_flag = COMPLETE;
+		}
+		if ((i%100)==0)
+			printf ("%d append_file operation performed\n", i);
+		i++;
+	}
+
+	printf ("end of file system object creation\n");
+	print_fh_map(&obj_fh);
+	print_result();
+}
+
+#ifdef notdef
+int create_mkdir_op (int flag)
+{
+	static int fhno = 0;
+	char name[MAX_NAMELEN];
+	char command[MAX_COMMAND_LEN];
+	int i;
+	int fd;
+	int count = 0;
+	fh_info_t * fh_infop;
+
+	while (count++ < 100) {
+		i = random()%dir_fh.fh_max;
+		if (dir_fh.fh[i].flag==FH_T_FLAG_IN_USE) {
+			assure_exist(dir_fh.fh[i].path);
+			strcpy (name, dir_fh.fh[i].path);
+			if (flag == IS_FILE) {
+				sprintf (name+strlen(name), "AGEfile%d", fhno++);
+				fd = creat (name, S_IRWXU);
+				age_create_num++;
+				//printf ("create fd %d\n", fd);
+				close(fd);
+				fh_infop = &file_fh;
+			} else {
+				sprintf (name+strlen(name), "AGEdir%d", fhno++);
+				fd = mkdir (name, S_IRWXU);
+				age_mkdir_num++;
+				fh_infop = &dir_fh;
+			}
+			if (fd == -1) {
+				perror("");
+				if (errno == ENOENT) {
+					dir_fh.fh[i].flag = FH_T_FLAG_FREE;
+					continue;
+				} else
+					RFS_ASSERT (0);
+			}
+			add_fh_t (fh_infop, name, EXIST);
+			RFS_ASSERT (fd >=0);
+			return 0;
+		}
+	};
+	return -1;
+}
+
+int remove_op ()
+{
+	int i;
+	int count = 0;
+	int ret;
+
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist(file_fh.fh[i].path);
+			ret = remove (file_fh.fh[i].path);
+			RFS_ASSERT (ret ==0);
+			file_fh.fh[i].flag = FH_T_FLAG_FREE;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+int rmdir_op()
+{
+	int i;
+	int count=0;
+	char command[MAX_COMMAND_LEN];
+	int ret;
+
+	while (count++<100) {
+		i = random()%dir_fh.fh_max;
+		if ( (dir_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist(file_fh.fh[i].path);
+			ret = rmdir (dir_fh.fh[i].path);
+			if (ret == 0) {
+				dir_fh.fh[i].flag = FH_T_FLAG_FREE;
+				return 0;
+			}
+			RFS_ASSERT ((ret == -1) && (errno == ENOTEMPTY));
+			//strcpy (command, "rm -r %s", dir_fh.fh[i].path);
+			//system (command);
+		}
+	}
+	return -1;
+}
+
+int write_op (int off, int size)
+{
+	static char buf[NFS_MAXDATA];
+	int i;
+	int count=0;
+	int fd;
+	int ret;
+	struct stat st;
+
+	RFS_ASSERT (size <= NFS_MAXDATA);
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+			assure_exist(file_fh.fh[i].path);
+			fd = open(file_fh.fh[i].path, O_WRONLY);
+			if (fd == -1)
+				perror("");
+			//else 
+				//printf ("write fd %d\n", fd);
+			RFS_ASSERT (fd!=-1);
+			fstat (fd, &st);
+			if (st.st_size < (off+size)) {
+				int written_bytes = 0;
+				while (written_bytes+NFS_MAXDATA < off+size-st.st_size) {
+					loop_write (fd, buf, NFS_MAXDATA);
+					written_bytes += NFS_MAXDATA;
+				}
+				loop_write (fd, buf, off+size-st.st_size-written_bytes);
+				if (strstr(file_fh.fh[i].path, "AGE")) {
+					age_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
+				} else 
+					nonage_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
+			} else
+				overlap_write_num++;
+/*
+			if (strstr(file_fh.fh[i].path, "AGE")) {
+				age_write_num++;
+			} else 
+				nonage_write_num++;
+			loop_write (fd, buf, size);
+*/
+			close(fd);
+			return 0;
+		};
+	}
+	return -1;
+}
+
+int truncate_op(int size)
+{
+	int i;
+	int count=0;
+	int ret;
+
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist (file_fh.fh[i].path);
+			ret = truncate(file_fh.fh[i].path, size);
+			if (ret ==0) 
+				return 0;
+			RFS_ASSERT (errno == ENOENT);
+			file_fh.fh[i].flag = FH_T_FLAG_FREE;
+			continue;	
+		}
+	};
+	return -1;
+}
+
+int aging_files ()
+{
+	char name[MAX_NAMELEN];
+	int sfh;	/* file to be aged */
+	int psfh;
+	int ret;
+	struct stat st;
+	int agefd;
+
+	/* get the sfh and size of the selected file to be aged */
+	sfh = select_obj (&obj_fh, IS_FILE, EXIST, ACTIVE);
+	ret = stat (obj_fh.fh[sfh].path, &st);
+	RFS_ASSERT (ret == 0);
+	ret = truncate(obj_fh.fh[i].path, st.st_size/2);
+	RFS_ASSERT (ret==0);
+
+	psfh = obj_fh.fh[sfh].psfh;
+	strcpy (name, obj_fh.fh[psfh].path);
+	sprintf(name+strlen(name), "/AGE%d", obj_fh.fh_max); 
+	agefd = creat (name, S_IRWXU);
+	//write (agefs, buf, 0);
+
+	add_fh_t (&obj_fh, name, sfh, psfh, size, ftype_flag, EXIST, INACTIVE);
+}
+#endif
diff --git a/TBBT/trace_play/rfs_c_age.obsolete.c b/TBBT/trace_play/rfs_c_age.obsolete.c
new file mode 100644
index 0000000..aab4644
--- /dev/null
+++ b/TBBT/trace_play/rfs_c_age.obsolete.c
@@ -0,0 +1,194 @@
+#ifdef notdef
+int create_mkdir_op (int flag)
+{
+	static int fhno = 0;
+	char name[MAX_NAMELEN];
+	char command[MAX_COMMAND_LEN];
+	int i;
+	int fd;
+	int count = 0;
+	fh_info_t * fh_infop;
+
+	while (count++ < 100) {
+		i = random()%dir_fh.fh_max;
+		if (dir_fh.fh[i].flag==FH_T_FLAG_IN_USE) {
+			assure_exist(dir_fh.fh[i].path);
+			strcpy (name, dir_fh.fh[i].path);
+			if (flag == IS_FILE) {
+				sprintf (name+strlen(name), "AGEfile%d", fhno++);
+				fd = creat (name, S_IRWXU);
+				age_create_num++;
+				//printf ("create fd %d\n", fd);
+				close(fd);
+				fh_infop = &file_fh;
+			} else {
+				sprintf (name+strlen(name), "AGEdir%d", fhno++);
+				fd = mkdir (name, S_IRWXU);
+				age_mkdir_num++;
+				fh_infop = &dir_fh;
+			}
+			if (fd == -1) {
+				perror("");
+				if (errno == ENOENT) {
+					dir_fh.fh[i].flag = FH_T_FLAG_FREE;
+					continue;
+				} else
+					RFS_ASSERT (0);
+			}
+			add_fh_t (fh_infop, name, EXIST);
+			RFS_ASSERT (fd >=0);
+			return 0;
+		}
+	};
+	return -1;
+}
+
+int remove_op ()
+{
+	int i;
+	int count = 0;
+	int ret;
+
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist(file_fh.fh[i].path);
+			ret = remove (file_fh.fh[i].path);
+			RFS_ASSERT (ret ==0);
+			file_fh.fh[i].flag = FH_T_FLAG_FREE;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+int rmdir_op()
+{
+	int i;
+	int count=0;
+	char command[MAX_COMMAND_LEN];
+	int ret;
+
+	while (count++<100) {
+		i = random()%dir_fh.fh_max;
+		if ( (dir_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist(file_fh.fh[i].path);
+			ret = rmdir (dir_fh.fh[i].path);
+			if (ret == 0) {
+				dir_fh.fh[i].flag = FH_T_FLAG_FREE;
+				return 0;
+			}
+			RFS_ASSERT ((ret == -1) && (errno == ENOTEMPTY));
+			//strcpy (command, "rm -r %s", dir_fh.fh[i].path);
+			//system (command);
+		}
+	}
+	return -1;
+}
+
+int write_op (int off, int size)
+{
+	static char buf[NFS_MAXDATA];
+	int i;
+	int count=0;
+	int fd;
+	int ret;
+	struct stat st;
+
+	RFS_ASSERT (size <= NFS_MAXDATA);
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+			assure_exist(file_fh.fh[i].path);
+			fd = open(file_fh.fh[i].path, O_WRONLY);
+			if (fd == -1)
+				perror("");
+			//else 
+				//printf ("write fd %d\n", fd);
+			RFS_ASSERT (fd!=-1);
+			fstat (fd, &st);
+			if (st.st_size < (off+size)) {
+				int written_bytes = 0;
+				while (written_bytes+NFS_MAXDATA < off+size-st.st_size) {
+					loop_write (fd, buf, NFS_MAXDATA);
+					written_bytes += NFS_MAXDATA;
+				}
+				loop_write (fd, buf, off+size-st.st_size-written_bytes);
+				if (strstr(file_fh.fh[i].path, "AGE")) {
+					age_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
+				} else 
+					nonage_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
+			} else
+				overlap_write_num++;
+/*
+			if (strstr(file_fh.fh[i].path, "AGE")) {
+				age_write_num++;
+			} else 
+				nonage_write_num++;
+			loop_write (fd, buf, size);
+*/
+			close(fd);
+			return 0;
+		};
+	}
+	return -1;
+}
+
+int truncate_op(int size)
+{
+	int i;
+	int count=0;
+	int ret;
+
+	while (count++<100) {
+		i = random()%file_fh.fh_max;
+		if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
+/*
+			if (!strstr(file_fh.fh[i].path, "AGE"))
+				continue;
+*/
+			assure_exist (file_fh.fh[i].path);
+			ret = truncate(file_fh.fh[i].path, size);
+			if (ret ==0) 
+				return 0;
+			RFS_ASSERT (errno == ENOENT);
+			file_fh.fh[i].flag = FH_T_FLAG_FREE;
+			continue;	
+		}
+	};
+	return -1;
+}
+
+int aging_files ()
+{
+	char name[MAX_NAMELEN];
+	int sfh;	/* file to be aged */
+	int psfh;
+	int ret;
+	struct stat st;
+	int agefd;
+
+	/* get the sfh and size of the selected file to be aged */
+	sfh = select_obj (&obj_fh, IS_FILE, EXIST, ACTIVE);
+	ret = stat (obj_fh.fh[sfh].path, &st);
+	RFS_ASSERT (ret == 0);
+	ret = truncate(obj_fh.fh[i].path, st.st_size/2);
+	RFS_ASSERT (ret==0);
+
+	psfh = obj_fh.fh[sfh].psfh;
+	strcpy (name, obj_fh.fh[psfh].path);
+	sprintf(name+strlen(name), "/AGE%d", obj_fh.fh_max); 
+	agefd = creat (name, S_IRWXU);
+	//write (agefs, buf, 0);
+
+	add_fh_t (&obj_fh, name, sfh, psfh, size, ftype_flag, EXIST, INACTIVE);
+}
+#endif
diff --git a/TBBT/trace_play/rfs_c_dat.c b/TBBT/trace_play/rfs_c_dat.c
new file mode 100644
index 0000000..bcd3525
--- /dev/null
+++ b/TBBT/trace_play/rfs_c_dat.c
@@ -0,0 +1,188 @@
+#include "rfs_c_def.h"
+#include "generic_hash.h"
+dep_tab_t dep_tab[DEP_TAB_SIZE];
+int req_num_with_new_fh = 0;
+int	req_num_with_discard_fh = 0;
+int req_num_with_init_fh =0;
+
+int event_order [EVENT_ORDER_SIZE];
+int event_order_index = 0;
+
+memory_trace_ent_t memory_trace[MAX_MEMORY_TRACE_LINES];
+	
+/* the offset between the replay time and timestamp in the log */
+struct ladtime current;
+#if	0
+//struct ladtime trace_starttime = {1003636801, 39949, 0};
+struct ladtime trace_starttime = {1003723201, 313373, 0};
+#else
+/* timestamp extracted from the used trace. G. Jason Peng */
+//struct ladtime trace_starttime = {1005620400, 499221, 0};
+/* timestamp extracted nfsdump.gzip.pair Ningning for osdi measurement */
+struct ladtime trace_starttime = {1085067131, 107476, 0};
+#endif
+struct ladtime time_offset;
+
+fh_map_t fh_map [FH_MAP_SIZE];
+struct generic_entry * fh_htable[FH_HTABLE_SIZE];
+int fh_i=0;
+int fh_map_debug = 0;
+struct generic_entry * fh_htable [FH_HTABLE_SIZE];
+
+#ifdef notdef
+/* the array is indexed by sfs operation number */
+rfs_op_type rfs_Ops[TOTAL] = {
+{NFSPROC3_NULL,		setbuf_void, 		setbuf_void, xdr_void, xdr_void},
+{NFSPROC3_GETATTR, 	setarg_GETATTR3, 	setbuf_void, xdr_GETATTR3args, xdr_GETATTR3res},
+{NFSPROC3_SETATTR, 	setarg_SETATTR3, 	setbuf_void, xdr_SETATTR3args, xdr_SETATTR3res},
+{NFSPROC3_INVALID,	setbuf_invalid, 	setbuf_invalid, xdr_invalid, xdr_invalid},
+{NFSPROC3_LOOKUP, 	setarg_LOOKUP3, 	setres_lookup, xdr_LOOKUP3args, xdr_LOOKUP3res},
+{NFSPROC3_READLINK, setarg_READLINK3, 	setres_readlink, xdr_READLINK3args, xdr_READLINK3res},
+{NFSPROC3_READ, 	setarg_READ3, 		setres_read, xdr_READ3args, xdr_READ3res},
+{NFSPROC3_INVALID, 	setarg_invalid, 	setbuf_invalid, xdr_invalid, xdr_invalid},
+{NFSPROC3_WRITE, 	setarg_WRITE3, 		setbuf_void, xdr_WRITE3args, xdr_WRITE3res},
+{NFSPROC3_CREATE, 	setarg_CREATE3, 	setbuf_void, xdr_CREATE3args, xdr_CREATE3res},
+{NFSPROC3_REMOVE, 	setarg_REMOVE3, 	setbuf_void, xdr_REMOVE3args, xdr_REMOVE3res},
+{NFSPROC3_RENAME, 	setarg_RENAME3, 	setbuf_void, xdr_RENAME3args, xdr_RENAME3res},
+{NFSPROC3_LINK, 	setarg_LINK3, 		setbuf_void, xdr_LINK3args, xdr_LINK3res},
+{NFSPROC3_SYMLINK, 	setarg_SYMLINK3, 	setbuf_void, xdr_SYMLINK3args, xdr_SYMLINK3res},
+{NFSPROC3_MKDIR, 	setarg_MKDIR3, 		setbuf_void, xdr_MKDIR3args, xdr_MKDIR3res},
+{NFSPROC3_RMDIR, 	setarg_RMDIR3,		setbuf_void, xdr_RMDIR3args, xdr_RMDIR3res},
+{NFSPROC3_READDIR, 	setarg_READDIR3, 	setres_readdir, xdr_READDIR3args, xdr_READDIR3res},
+{NFSPROC3_FSSTAT, 	setarg_FSSTAT3, 	setbuf_void, xdr_FSSTAT3args, xdr_FSSTAT3res},
+{NFSPROC3_ACCESS, 	setarg_ACCESS3, 	setbuf_void, xdr_ACCESS3args, xdr_ACCESS3res},
+{NFSPROC3_COMMIT, 	setarg_COMMIT3, 	setbuf_void, xdr_COMMIT3args, xdr_COMMIT3res},
+{NFSPROC3_FSINFO, 	setarg_FSINFO3,		setbuf_void,  xdr_FSINFO3args, xdr_FSINFO3res},
+{NFSPROC3_MKNOD, 	setarg_MKNOD3, 		setbuf_void, xdr_MKNOD3args, xdr_MKNOD3res},
+{NFSPROC3_PATHCONF, setarg_PATHCONF3, 	setbuf_void, xdr_PATHCONF3args, xdr_PATHCONF3res}
+{NFSPROC3_READDIRPLUS, setarg_READDIRPLUS3, setres_readdirplus, xdr_READDIRPLUS3args, xdr_READDIRPLUS3res}};
+
+/*
+ * --------------------  NFS ops vector --------------------
+ */
+/*
+ * per operation information
+ */
+sfs_op_type nfsv3_Ops[] = {
+
+/* name        mix    op    call  no  req  req  req  results */
+/*             pcnt  class  targ call pcnt cnt  targ         */
+
+ { "null",        0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "getattr",    11, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "setattr",     1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "root",        0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "lookup",     27, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readlink",    7, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "read",       18, Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "wrcache",     0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "write",       9, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "create",      1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "remove",      1, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rename",      0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "link",        0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "symlink",     0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "mkdir",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rmdir",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdir",     2, Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsstat",      1, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "access",      7, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "commit",      5, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsinfo",      1, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "mknod",       0, Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "pathconf",    0, Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdirplus", 9, Read,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "TOTAL",     100, Lookup,  0,  0,  0.0,  0,   0,  { 0, }}
+};
+#endif
+
+sfs_op_type *Ops;
+
+int num_out_reqs = 0;
+
+cyclic_index_t dep_tab_index;
+cyclic_index_t dep_window_index;
+cyclic_index_t memory_trace_index;
+int dep_window_max = 0;
+
+/* note that for each dep_tab entry, there is a memory trace line, but
+ * not vise vesa because some memory trace line may not have corresponding
+ * dep_tab entry. According entry TIMESTAMP value, the order is
+ *
+ * memory_trace_tail line < dep_tab_tail entry < dep_window_max entry <
+ * dep_tab_head entry < memory_trace_head entry */
+
+int rfs_debug = 0;
+int per_packet_debug = 0;
+int adjust_play_window_debug = 0;
+int dependency_debug = 0;
+int profile_debug = 0;
+int quiet_flag = 0;
+int stage = FIRST_STAGE;
+int read_data_owe = 0;
+int read_data_total = 0;
+int write_data_owe = 0;
+int write_data_total = 0;
+int read_data_adjust_times = 0;
+int write_data_adjust_times = 0;
+int read_data_owe_GB = 0;
+int write_data_owe_GB = 0;
+int read_data_total_GB = 0;
+int write_data_total_GB = 0;
+
+int failed_create_command_num = 0;
+int failed_other_command_num = 0;
+int skipped_readlink_command_num = 0;
+int skipped_custom_command_num = 0;
+int fh_path_map_err_num = 0;
+int skipped_fsstat_command_num = 0;
+int missing_reply_num = 0;
+int rename_rmdir_noent_reply_num = 0;
+int rmdir_not_empty_reply_num = 0;
+int loose_access_control_reply_num = 0;
+int lookup_err_due_to_rename_num = 0;
+int lookup_err_due_to_parallel_remove_num = 0;
+int lookup_eaccess_enoent_mismatch_num = 0;
+int read_io_err_num = 0;
+int stale_fhandle_err_num = 0;
+int proper_reply_num = 0;
+int run_stage_proper_reply_num = 0;
+int lookup_retry_num = 0;
+int can_not_catch_speed_num = 0;
+int can_not_catch_speed_num_total = 0;
+int poll_timeout_0_num = 0;
+int poll_timeout_pos_num = 0;
+int abnormal_EEXIST_num = 0;
+int abnormal_ENOENT_num = 0;
+
+FILE * profile_fp = 0;
+profile_t total_profile;
+profile_t valid_get_nextop_profile;
+profile_t invalid_get_nextop_profile;
+profile_t valid_poll_and_get_reply_profile;
+profile_t invalid_poll_and_get_reply_profile;
+profile_t execute_next_request_profile;
+profile_t receive_next_reply_profile;
+profile_t decode_reply_profile;
+profile_t check_reply_profile;
+profile_t add_create_object_profile;
+profile_t prepare_argument_profile;
+profile_t biod_clnt_call_profile;
+profile_t check_timeout_profile;
+profile_t adjust_play_window_profile;
+profile_t fgets_profile;
+profile_t read_line_profile;
+profile_t read_trace_profile;
+
+int PLAY_SCALE = 1;
+int skip_sec = 0;
+int trace_timestamp1=0, trace_timestamp2=0;
+
+int disk_io_status = TRACE_BUF_FULL;
+int WARMUP_TIME = 0;	/* other values that has been used: 100 */
+int disk_index = -1;
+
+int TRACE_COMMAND_REPLY_FLAG_POS=36;
+int TRACE_VERSION_POS=37;
+int TRACE_MSGID_POS=39;
+int TRACE_FH_SIZE=64;
diff --git a/TBBT/trace_play/rfs_c_def.h b/TBBT/trace_play/rfs_c_def.h
new file mode 100644
index 0000000..daeea6c
--- /dev/null
+++ b/TBBT/trace_play/rfs_c_def.h
@@ -0,0 +1,357 @@
+#ifndef RFS_H
+#define RFS_H
+#include "sfs_c_def.h"
+#include "profile.h"
+#include "rfs_assert.h"
+
+/* the maximum number of operations depended by one operation */
+/* the dependency include read/write, write/write, all operations with a
+ * one file handle/delete or rename's target if exists, the dependency
+ * does not include the create/all operations with relevant file handle
+ * This dependency is maintained by a flag in file handle mapping table
+ */
+#define MAX_DEP_OPS 10 
+//#define DEP_TAB_SIZE	200000 /* the dependency table size */
+/* Right now we don't wrap around with dep_tab, for each request, there
+ * is one entry in dependency table and one entry in lines buffer.
+ */
+#define REDUCE_MEMORY_TRACE_SIZE
+
+#define EVENT_ORDER_SIZE 1000000
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+//#define DEP_TAB_SIZE	 1100000 /* the dependency table size */
+#define DEP_TAB_SIZE	 100000 /* the dependency table size */
+//#define DEP_TAB_SIZE	 10000 /* the dependency table size */
+#define MAX_MEMORY_TRACE_LINES	DEP_TAB_SIZE 
+//#define MAX_TRACE_LINE_LENGTH 768
+#define MAX_TRACE_LINE_LENGTH 300
+#else
+#define MAX_TRACE_LINE_LENGTH 768
+#define DEP_TAB_SIZE	500000 /* the dependency table size */
+#define MAX_MEMORY_TRACE_LINES	DEP_TAB_SIZE*2 
+#endif
+
+#define FH_MAP_SIZE 400000
+//#define FH_MAP_SIZE 40000
+#define FH_HTABLE_SIZE FH_MAP_SIZE								 
+
+/* trace play policy related defines */
+#define SPEED_UP		// only one of SPEED_UP and	SLOW_DOWN is defined
+//#define SLOW_DOWN
+extern int PLAY_SCALE;
+//#define TIME_PLAY /* play according original timestamp or scaled timestamp together with dependency */
+#define NO_DEPENDENCY_TABLE
+//#define MAX_COMMAND_REPLY_DISTANCE 1000
+#define MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR 1000
+#define MAX_COMMAND_REPLY_DISTANCE 2
+
+#define WORKLOAD_PLAY /* play according dependency and as fast as it can, ignore timestamp */
+
+#ifdef TIME_PLAY
+#define MAX_PLAY_WINDOW 8
+#define MAX_OUTSTANDING_REQ 4	/* too big outstanding window reduces throughput */
+#else
+#define MAX_PLAY_WINDOW 1000
+//#define MAX_PLAY_WINDOW 8
+#define MAX_OUTSTANDING_REQ 8
+//#define MAX_OUTSTANDING_REQ 16
+#endif
+#define UDP	/* currently we only support using UDP, support for TCP will be added later */
+
+/* the flag to indicate the current status of a trace request */
+#define DEP_FLAG_FREE 0			/* free entry */
+#define DEP_FLAG_INIT 1			/* initialized */
+#define DEP_FLAG_CANDIDATE 2
+#define DEP_FLAG_WAIT_FHANDLE 3	/* waiting for leading fhandle */
+#define DEP_FLAG_FHANDLE_READY 4
+#define DEP_FLAG_WAIT_DIRECTORY 5
+#define DEP_FLAG_DIRECTORY_READY 6
+#define DEP_FLAG_WAIT_DELETE 7	/* waiting for deleting the object */
+#define DEP_FLAG_SENT 8			/* Request has been sent out, waiting for replies */
+#define DEP_FLAG_DONE 9			/* Reply has been received and processed */
+#define BUSY	1
+#define IDLE	0
+
+#define MAX_ARG_RES_SIZE 512
+#define MAX_BUF1_SIZE 65536 	/* for readdirplus, 208 each entry, max 128 entries */
+#define MAX_BUF2_SIZE NFS_MAXPATHLEN
+
+extern int TRACE_COMMAND_REPLY_FLAG_POS;
+extern int TRACE_VERSION_POS;
+extern int TRACE_MSGID_POS;
+extern int TRACE_FH_SIZE;
+
+/* Two setbuf_t procedure exists for each NFS operation, one for setting up NFS 
+ * operation argument buffer, another for setting up NFS operation result receiving buffer.
+ *
+ * When setting up argument, the function takes two argument, the first 
+ * argument is index to dep_tab, the second argument is the buffer pointer to 
+ * be setup. Sometimes, there is no extra argument other than index, for example: read
+ * Sometimes, there is one extra argument, e.g the buffer for lookup name.
+ * Sometimes, there are two extra arguments, e..g rename, symlink.
+ *
+ * void (*setbuf_t)(int index, char * arg, char * arg);
+ *
+ * When setting up receiving result buffer, the function takes one arguement,
+ * the buffer pointer.
+ * void (*setbuf_t)(char * res, char * arg);
+ */
+typedef void (*setbuf_t)();
+
+typedef struct {
+	int nfsv3_proc;
+	setbuf_t setarg;
+	setbuf_t setres;
+	xdrproc_t xdr_arg;
+	xdrproc_t xdr_res;
+} rfs_op_type;
+
+#define MAX_TRACE_FH_SIZE 64
+#define TRACE_FH_FILE_SIZE 48
+#define TRACE_FH_DIR_SIZE 40
+#define MAX_PLAY_PATH_SIZE 256
+
+/* flags in fh_map_t */
+#define FH_MAP_FLAG_FREE 0
+#define FH_MAP_FLAG_DISCARD 1
+#define FH_MAP_FLAG_PARTIAL 2
+#define FH_MAP_FLAG_COMPLETE 3
+typedef struct {
+	int flag;
+	int lock;
+	char trace_fh [MAX_TRACE_FH_SIZE+1];
+	char path[MAX_PLAY_PATH_SIZE];
+	nfs_fh3 play_fh;
+} fh_map_t;
+
+typedef struct {
+	int disk_index;
+	int trace_status;
+	char reply_trace_fh[MAX_TRACE_FH_SIZE+1];
+	char line[MAX_TRACE_LINE_LENGTH];
+} memory_trace_ent_t;
+	
+
+typedef struct {
+	int flag;	
+	int disk_index;
+	int memory_index;
+	char * line;
+	char * reply_line;
+	fh_map_t * fh;
+	fh_map_t * fh_2;
+	char * trace_fh;
+	char * trace_fh_2;
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+	char * reply_trace_fh;
+#endif
+	int proc;	/* the prototype independent NFS operation number defined in sfs_c_def.h
+				 * e.g. NULLCALL NFS3PROC_READ etc */
+	struct timeval timestamp;	/* The timestamp of a request in the trace */
+#ifdef NO_DEPENDENCY_TABLE
+	int dep_ops[MAX_DEP_OPS]; /* Other requests need to be processed prior this request */
+								 /* dep_tab[i] == -1 means the dependency has been resolved */
+	int init_dep_num;			/* The number of request being depended initially */
+	int cur_dep_num;			/* The number of remaining ones which have not been finished */ 
+								/* at initialization time, init_dep_num == cur_dep_num */
+#endif
+	int biod_req_index;	/* Index in to the biod_req array which contains all outstanding requests */
+	struct ladtime start;
+	struct ladtime stop;
+	struct ladtime interval;
+	int skip_sec;
+	int status;
+	int trace_status;
+} dep_tab_t;
+
+typedef struct {
+	char name[32];
+	int head;
+	int tail;
+	int size;
+} cyclic_index_t;
+
+#define CYCLIC_INIT(str,index,SIZE) \
+	{index.head=0; index.tail=0; index.size=SIZE; \
+	 RFS_ASSERT(strlen(str)<sizeof(index.name)); \
+	 strcpy(index.name, str); }
+
+#define CYCLIC_PRINT(index) \
+	{printf("%s head %d tail %d, size %d\n", index.name, index.head, index.tail, index.size);}
+
+#define CYCLIC_FULL(index) \
+	(((index.head+1)%index.size)==index.tail)
+
+#define CYCLIC_EMPTY(index)	\
+	(index.tail==index.head)
+
+#define CYCLIC_NUM(index) \
+	((index.head + index.size - index.tail) % index.size)
+
+#define CYCLIC_MOVE_HEAD(index) \
+	{ \
+		if (CYCLIC_FULL(index)) { \
+			CYCLIC_PRINT(index) \
+		} \
+		RFS_ASSERT (!CYCLIC_FULL(index)); \
+		index.head=(index.head+1)%(index.size); \
+	}
+
+#define CYCLIC_MOVE_TAIL(index) \
+	{ \
+		RFS_ASSERT (!CYCLIC_EMPTY(index)) \
+		index.tail=(index.tail+1)%(index.size); \
+	}
+
+/*
+#define CYCLIC_MOVE_TAIL_TO(index,dest) \
+	{ \
+		int oldnum = CYCLIC_NUM(index); \
+		if (! ((dest>=0) && (dest<index.size) && (dest!=index.head))) { \
+			CYCLIC_PRINT(index); \
+			printf("dest %d\n", dest); \
+		} \
+		RFS_ASSERT ((dest>=0) && (dest<index.size) && (dest!=index.head)) \
+		index.tail = dest; \
+		if (CYCLIC_NUM(index) > oldnum) { \
+			CYCLIC_PRINT(index); \
+			printf("dest %d old_num %d \n", dest, oldnum); \
+		} \
+		RFS_ASSERT (CYCLIC_NUM(index) <= oldnum); \
+	}
+*/
+
+#define CYCLIC_MINUS(A,B,size) ((A+size-B)%size)
+#define CYCLIC_ADD(A,B,size) ((A+B)%size)
+#define CYCLIC_LESS(index,A,B) \
+(CYCLIC_MINUS(A,index.tail,index.size)<CYCLIC_MINUS(B,index.tail,index.size))
+
+extern struct ladtime current;
+extern struct ladtime trace_starttime;
+extern struct ladtime time_offset;
+
+extern rfs_op_type rfs_Ops[];
+extern sfs_op_type nfsv3_Ops[];
+extern sfs_op_type * Ops;
+extern int num_out_reqs;
+
+extern cyclic_index_t dep_tab_index;
+extern cyclic_index_t dep_window_index;
+extern cyclic_index_t memory_trace_index;
+int dep_window_max; /* the first entry outside of the dependency window */
+/* If ordered by TIMESTAMP,
+ * memory_trace_index.tail <= dep_tab_index.tail < dep_window_max <=
+ * dep_tab_index.head <= memory_trace_index.head
+ */
+
+extern fh_map_t fh_map [FH_MAP_SIZE];
+extern int fh_i;
+extern int fh_map_debug ;
+extern struct generic_entry * fh_htable [FH_HTABLE_SIZE];
+
+extern dep_tab_t dep_tab[DEP_TAB_SIZE];
+extern int req_num_with_new_fh;
+extern int req_num_with_discard_fh;
+extern int req_num_with_init_fh;
+extern memory_trace_ent_t memory_trace[MAX_MEMORY_TRACE_LINES];
+extern int event_order[];
+extern int event_order_index;
+extern struct biod_req * biod_reqp;
+extern int max_biod_reqs;
+extern int rfs_debug;
+extern int per_packet_debug;
+extern int profile_debug;
+extern int adjust_play_window_debug;
+extern int dependency_debug;
+extern int quiet_flag;
+extern int read_data_owe;
+extern int write_data_owe;
+extern int read_data_total;
+extern int write_data_total;
+extern int read_data_adjust_times;
+extern int write_data_adjust_times;
+extern int read_data_owe_GB;
+extern int write_data_owe_GB;
+extern int read_data_total_GB;
+extern int write_data_total_GB;
+
+extern int failed_create_command_num;
+extern int failed_other_command_num;
+extern int skipped_readlink_command_num;
+extern int skipped_custom_command_num;
+extern int fh_path_map_err_num;
+extern int skipped_fsstat_command_num;
+extern int missing_reply_num;
+extern int lookup_noent_reply_num;
+extern int rename_rmdir_noent_reply_num;
+extern int rmdir_not_empty_reply_num;
+extern int loose_access_control_reply_num;
+extern int lookup_err_due_to_rename_num;
+extern int lookup_err_due_to_parallel_remove_num;
+extern int lookup_eaccess_enoent_mismatch_num;
+extern int read_io_err_num;
+extern int stale_fhandle_err_num;
+extern int proper_reply_num;
+extern int run_stage_proper_reply_num;
+extern int lookup_retry_num;
+extern int can_not_catch_speed_num_total;
+extern int can_not_catch_speed_num;
+extern int poll_timeout_0_num;
+extern int poll_timeout_pos_num;
+extern int abnormal_EEXIST_num;
+extern int abnormal_ENOENT_num;
+
+#define FIRST_STAGE 0
+#define READ_DEP_TAB_STAGE 1
+#define TRACE_PLAY_STAGE 2
+extern int stage;
+
+#define IGNORE_SETATTR_CTIME
+//#define TAKE_CARE_SETATTR_GID
+//#define TAKE_CARE_SETATTR_UID
+//#define TAKE_CARE_CREATE_MODE_BY_DAN
+//#define TAKE_CARE_OTHER_FAILED_COMMAND
+//#define TAKE_CARE_CUSTOM_COMMAND
+//#define TAKE_CARE_FSSTAT_COMMAND
+//#define TAKE_CARE_UNLOOKED_UP_NON_NEW_FILES
+//#define TAKE_CARE_NOEMPTY_RMDIR
+//#define TAKE_CARE_LOOKUP_EACCESS_ENOENT_MISMATCH
+//#define TAKE_CARE_ACCESS_ERROR
+//#define TAKE_CARE_SYMBOLIC_LINK
+#define TOLERANT_READ_IO_ERR
+#define TOLERANT_STALE_FHANDLE_ERR
+#define IO_THREAD
+//#define RECV_THREAD	can not tune up the version with receive thread quickly
+
+extern FILE * profile_fp;
+extern profile_t total_profile;
+extern profile_t valid_get_nextop_profile;
+extern profile_t invalid_get_nextop_profile;
+extern profile_t valid_poll_and_get_reply_profile;
+extern profile_t invalid_poll_and_get_reply_profile;
+extern profile_t execute_next_request_profile;
+extern profile_t receive_next_reply_profile;
+extern profile_t decode_reply_profile;
+extern profile_t check_reply_profile;
+extern profile_t add_create_object_profile;
+extern profile_t prepare_argument_profile;
+extern profile_t biod_clnt_call_profile;
+extern profile_t check_timeout_profile;
+extern profile_t adjust_play_window_profile;
+extern profile_t fgets_profile;
+extern profile_t read_line_profile;
+extern profile_t read_trace_profile;
+
+extern int skip_sec;
+extern int trace_timestamp1, trace_timestamp2;
+//#define SEQUEN_READ
+//#define SEQUEN_READ_NUM 1000
+
+#define TRACE_BUF_FULL 0
+#define TRACE_FILE_END 1
+#define ASYNC_RPC_SEM_KEY 60000
+extern int disk_io_status;
+extern int WARMUP_TIME;
+extern int disk_index; 
+//#define NO_SEM
+#endif
diff --git a/TBBT/trace_play/rpc/auth.h b/TBBT/trace_play/rpc/auth.h
new file mode 100755
index 0000000..b184cf5
--- /dev/null
+++ b/TBBT/trace_play/rpc/auth.h
@@ -0,0 +1,185 @@
+/*
+ * @(#)auth.h     2.1     97/10/23
+ */
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/* @(#)auth.h	2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The data structures are completely opaque to the client.  The client
+ * is required to pass a AUTH * to routines that create rpc
+ * "sessions".
+ */
+
+
+#define MAX_AUTH_BYTES	400
+#define MAXNETNAMELEN	255	/* maximum length of network user's name */
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+	AUTH_OK=0,
+	/*
+	 * failed at remote end
+	 */
+	AUTH_BADCRED=1,			/* bogus credentials (seal broken) */
+	AUTH_REJECTEDCRED=2,		/* client should begin new session */
+	AUTH_BADVERF=3,			/* bogus verifier (seal broken) */
+	AUTH_REJECTEDVERF=4,		/* verifier expired or was replayed */
+	AUTH_TOOWEAK=5,			/* rejected due to security reasons */
+	/*
+	 * failed locally
+	*/
+	AUTH_INVALIDRESP=6,		/* bogus response verifier */
+	AUTH_FAILED=7			/* some unknown reason */
+};
+
+union des_block {
+	struct {
+		uint_t high;
+		uint_t low;
+	} key;
+	char c[8];
+};
+typedef union des_block des_block;
+extern bool_t xdr_des_block();
+
+/*
+ * Authentication info.  Opaque to client.
+ */
+struct opaque_auth {
+	enum_t	oa_flavor;		/* flavor of auth */
+	void 	*oa_base;		/* address of more auth stuff */
+	uint_t	oa_length;		/* not to exceed MAX_AUTH_BYTES */
+};
+
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+typedef struct {
+	struct	opaque_auth	ah_cred;
+	struct	opaque_auth	ah_verf;
+	union	des_block	ah_key;
+	struct auth_ops {
+		void	(*ah_nextverf)();
+		int	(*ah_marshal)();	/* nextverf & serialize */
+		int	(*ah_validate)();	/* validate varifier */
+		int	(*ah_refresh)();	/* refresh credentials */
+		void	(*ah_destroy)();	/* destroy this structure */
+	} *ah_ops;
+	void * ah_private;
+} AUTH;
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH	*auth;
+ * XDR	*xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth)		\
+		((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth)		\
+		((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs)	\
+		((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs)	\
+		((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp)	\
+		((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp)	\
+		((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth)		\
+		((*((auth)->ah_ops->ah_refresh))(auth))
+#define auth_refresh(auth)		\
+		((*((auth)->ah_ops->ah_refresh))(auth))
+
+#define AUTH_DESTROY(auth)		\
+		((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth)		\
+		((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+extern struct opaque_auth _null_auth;
+
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ *	char *machname;
+ *	int uid;
+ *	int gid;
+ *	int len;
+ *	int *aup_gids;
+ */
+extern AUTH *authunix_create(char *, uid_t, gid_t, int, gid_t *);
+extern AUTH *authunix_create_default(void);
+extern AUTH *authnone_create();		/* takes no parameters */
+extern AUTH *authdes_create();
+
+#define AUTH_NONE	0		/* no authentication */
+#define	AUTH_NULL	0		/* backward compatibility */
+#define	AUTH_UNIX	1		/* unix style (uid, gids) */
+#define	AUTH_SHORT	2		/* short hand unix style */
+#define AUTH_DES	3		/* des style (encrypted timestamps) */
diff --git a/TBBT/trace_play/rpc/auth_none.c b/TBBT/trace_play/rpc/auth_none.c
new file mode 100755
index 0000000..4644ac4
--- /dev/null
+++ b/TBBT/trace_play/rpc/auth_none.c
@@ -0,0 +1,154 @@
+#ifndef lint
+static char sfs_auth_none_c_id[] = "@(#)auth_none.c     2.1     97/10/23";
+#endif
+/* @(#)auth_none.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null" 
+ * credentials and verifiers to remote systems. 
+ * 
+ * Copyright (C) 1984, Sun Microsystems, Inc. 
+ */
+
+#include <stdlib.h>
+#include "rpc/rpc.h"
+#define MAX_MARSHEL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+static void	authnone_verf(void);
+static void	authnone_destroy(void);
+static bool_t	authnone_marshal(AUTH *, XDR *);
+static bool_t	authnone_validate(void);
+static bool_t	authnone_refresh(void);
+
+static struct auth_ops ops = {
+	authnone_verf,
+	authnone_marshal,
+	authnone_validate,
+	authnone_refresh,
+	authnone_destroy
+};
+
+static struct authnone_private {
+	AUTH	no_client;
+	char	marshalled_client[MAX_MARSHEL_SIZE];
+	uint_t	mcnt;
+} *authnone_private;
+
+AUTH *
+authnone_create(void)
+{
+	register struct authnone_private *ap = authnone_private;
+	XDR xdr_stream;
+	register XDR *xdrs;
+
+	if (ap == 0) {
+		ap = (struct authnone_private *)calloc(1,
+					sizeof (struct authnone_private));
+		if (ap == 0)
+			return (0);
+		authnone_private = ap;
+	}
+	if (!ap->mcnt) {
+		ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
+		ap->no_client.ah_ops = &ops;
+		xdrs = &xdr_stream;
+		xdrmem_create(xdrs, ap->marshalled_client, (uint_t)MAX_MARSHEL_SIZE,
+		    XDR_ENCODE);
+		(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
+		(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
+		ap->mcnt = XDR_GETPOS(xdrs);
+		XDR_DESTROY(xdrs);
+	}
+	return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_marshal(
+	AUTH *client,
+	XDR *xdrs)
+{
+	register struct authnone_private *ap = authnone_private;
+
+	if (ap == 0)
+		return (0);
+	return ((*xdrs->x_ops->x_putbytes)(xdrs,
+	    ap->marshalled_client, ap->mcnt));
+}
+
+static void 
+authnone_verf(void)
+{
+}
+
+static bool_t
+authnone_validate(void)
+{
+
+	return (TRUE);
+}
+
+static bool_t
+authnone_refresh(void)
+{
+
+	return (FALSE);
+}
+
+static void
+authnone_destroy(void)
+{
+}
diff --git a/TBBT/trace_play/rpc/auth_unix.c b/TBBT/trace_play/rpc/auth_unix.c
new file mode 100755
index 0000000..06f7033
--- /dev/null
+++ b/TBBT/trace_play/rpc/auth_unix.c
@@ -0,0 +1,345 @@
+#ifndef lint
+static char sfs_auth_unix_c_id[] = "@(#)auth_unix.c     2.1     97/10/23";
+#endif
+/* @(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * auth_unix.c, Implements UNIX style authentication parameters. 
+ *  
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The system is very weak.  The client uses no encryption for it's
+ * credentials and only sends null verifiers.  The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+
+#include "rpc/rpc.h"
+
+extern getmyhostname(char *, int);
+
+/*
+ * Unix authenticator operations vector
+ */
+static void	authunix_nextverf(AUTH *);
+static bool_t	authunix_marshal(AUTH *, XDR *);
+static bool_t	authunix_validate(AUTH *, struct opaque_auth);
+static bool_t	authunix_refresh(AUTH *);
+static void	authunix_destroy(AUTH *);
+
+static struct auth_ops auth_unix_ops = {
+	authunix_nextverf,
+	authunix_marshal,
+	authunix_validate,
+	authunix_refresh,
+	authunix_destroy
+};
+
+/*
+ * This struct is pointed to by the ah_private field of an auth_handle.
+ */
+struct audata {
+	struct opaque_auth	au_origcred;	/* original credentials */
+	struct opaque_auth	au_shcred;	/* short hand cred */
+	uint32_t		au_shfaults;	/* short hand cache faults */
+	char			au_marshed[MAX_AUTH_BYTES];
+	uint_t			au_mpos;	/* xdr pos at end of marshed */
+};
+#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
+
+static bool_t marshal_new_auth(AUTH *);
+
+
+/*
+ * Create a unix style authenticator.
+ * Returns an auth handle with the given stuff in it.
+ */
+AUTH *
+authunix_create(
+	char *machname,
+	uid_t uid,
+	gid_t gid,
+	int len,
+	gid_t *aup_gids)
+{
+	struct authunix_parms aup;
+	char mymem[MAX_AUTH_BYTES];
+	struct timeval now;
+	XDR xdrs;
+	register AUTH *auth;
+	register struct audata *au;
+
+	/*
+	 * Allocate and set up auth handle
+	 */
+	auth = (AUTH *)mem_alloc(sizeof(AUTH));
+#ifndef KERNEL
+	if (auth == NULL) {
+		(void)fprintf(stderr, "authunix_create: out of memory\n");
+		return (NULL);
+	}
+#endif
+	au = (struct audata *)mem_alloc(sizeof(struct audata));
+#ifndef KERNEL
+	if (au == NULL) {
+		(void)fprintf(stderr, "authunix_create: out of memory\n");
+		return (NULL);
+	}
+#endif
+	auth->ah_ops = &auth_unix_ops;
+	auth->ah_private = (void *)au;
+	auth->ah_verf = au->au_shcred = _null_auth;
+	au->au_shfaults = 0;
+
+	/*
+	 * fill in param struct from the given params
+	 */
+	(void)gettimeofday(&now,  (struct timezone *)0);
+	aup.aup_time = now.tv_sec;
+	aup.aup_machname = machname;
+	aup.aup_uid = uid;
+	aup.aup_gid = gid;
+	aup.aup_len = (uint_t)len;
+	aup.aup_gids = (int *)aup_gids;
+
+	/*
+	 * Serialize the parameters into origcred
+	 */
+	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
+	if (! xdr_authunix_parms(&xdrs, &aup)) 
+		abort();
+	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
+	au->au_origcred.oa_flavor = AUTH_UNIX;
+#ifdef KERNEL
+	au->au_origcred.oa_base = mem_alloc((uint_t) len);
+#else
+	if ((au->au_origcred.oa_base = mem_alloc((uint_t) len)) == NULL) {
+		(void)fprintf(stderr, "authunix_create: out of memory\n");
+		return (NULL);
+	}
+#endif
+	memmove(au->au_origcred.oa_base, mymem, (uint_t)len);
+
+	/*
+	 * set auth handle to reflect new cred.
+	 */
+	auth->ah_cred = au->au_origcred;
+	marshal_new_auth(auth);
+	return (auth);
+}
+
+/*
+ * Returns an auth handle with parameters determined by doing lots of
+ * syscalls.
+ */
+AUTH *
+authunix_create_default(void)
+{
+	register int len;
+	char machname[MAX_MACHINE_NAME + 1];
+	uid_t uid;
+	gid_t gid;
+	gid_t gids[NGRPS];
+
+	if (getmyhostname(machname, MAX_MACHINE_NAME) == -1)
+		abort();
+	machname[MAX_MACHINE_NAME] = 0;
+	uid = geteuid();
+	gid = getegid();
+	if ((len = getgroups(NGRPS, gids)) < 0)
+		abort();
+	return (authunix_create(machname, uid, gid, len, gids));
+}
+
+/*
+ * authunix operations
+ */
+
+/* ARGSUSED */
+static void
+authunix_nextverf(
+	AUTH *auth)
+{
+	/* no action necessary */
+}
+
+static bool_t
+authunix_marshal(
+	AUTH *auth,
+	XDR *xdrs)
+{
+	register struct audata *au = AUTH_PRIVATE(auth);
+
+	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+}
+
+static bool_t
+authunix_validate(
+	AUTH *auth,
+	struct opaque_auth verf)
+{
+	register struct audata *au;
+	XDR xdrs;
+
+	if (verf.oa_flavor == AUTH_SHORT) {
+		au = AUTH_PRIVATE(auth);
+		xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
+
+		if (au->au_shcred.oa_base != NULL) {
+			mem_free(au->au_shcred.oa_base,
+			    au->au_shcred.oa_length);
+			au->au_shcred.oa_base = NULL;
+		}
+		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
+			auth->ah_cred = au->au_shcred;
+		} else {
+			xdrs.x_op = XDR_FREE;
+			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
+			au->au_shcred.oa_base = NULL;
+			auth->ah_cred = au->au_origcred;
+		}
+		marshal_new_auth(auth);
+	}
+	return (TRUE);
+}
+
+static bool_t
+authunix_refresh(
+	AUTH *auth)
+{
+	register struct audata *au = AUTH_PRIVATE(auth);
+	struct authunix_parms aup;
+	struct timeval now;
+	XDR xdrs;
+	register int stat;
+
+	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
+		/* there is no hope.  Punt */
+		return (FALSE);
+	}
+	au->au_shfaults ++;
+
+	/* first deserialize the creds back into a struct authunix_parms */
+	aup.aup_machname = NULL;
+	aup.aup_gids = (int *)NULL;
+	xdrmem_create(&xdrs, au->au_origcred.oa_base,
+	    au->au_origcred.oa_length, XDR_DECODE);
+	stat = xdr_authunix_parms(&xdrs, &aup);
+	if (! stat) 
+		goto done;
+
+	/* update the time and serialize in place */
+	(void)gettimeofday(&now, (struct timezone *)0);
+	aup.aup_time = now.tv_sec;
+	xdrs.x_op = XDR_ENCODE;
+	XDR_SETPOS(&xdrs, 0);
+	stat = xdr_authunix_parms(&xdrs, &aup);
+	if (! stat)
+		goto done;
+	auth->ah_cred = au->au_origcred;
+	marshal_new_auth(auth);
+done:
+	/* free the struct authunix_parms created by deserializing */
+	xdrs.x_op = XDR_FREE;
+	(void)xdr_authunix_parms(&xdrs, &aup);
+	XDR_DESTROY(&xdrs);
+	return (stat);
+}
+
+static void
+authunix_destroy(
+	AUTH *auth)
+{
+	register struct audata *au = AUTH_PRIVATE(auth);
+
+	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
+
+	if (au->au_shcred.oa_base != NULL)
+		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
+
+	mem_free(auth->ah_private, sizeof(struct audata));
+
+	if (auth->ah_verf.oa_base != NULL)
+		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
+
+	mem_free((void *)auth, sizeof(AUTH));
+}
+
+/*
+ * Marshals (pre-serializes) an auth struct.
+ * sets private data, au_marshed and au_mpos
+ */
+static bool_t
+marshal_new_auth(
+	AUTH *auth)
+{
+	XDR		xdr_stream;
+	register XDR	*xdrs = &xdr_stream;
+	register struct audata *au = AUTH_PRIVATE(auth);
+
+	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
+	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
+	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
+		perror("auth_none.c - Fatal marshalling problem");
+	} else {
+		au->au_mpos = XDR_GETPOS(xdrs);
+	}
+	XDR_DESTROY(xdrs);
+	return (TRUE);
+}
diff --git a/TBBT/trace_play/rpc/auth_unix.h b/TBBT/trace_play/rpc/auth_unix.h
new file mode 100755
index 0000000..24147e0
--- /dev/null
+++ b/TBBT/trace_play/rpc/auth_unix.h
@@ -0,0 +1,95 @@
+/*
+ * @(#)auth_unix.h     2.1     97/10/23
+ */
+
+/* @(#)auth_unix.h	2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)auth_unix.h 1.5 86/07/16 SMI      */
+
+/*
+ * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+
+/*
+ * The system is very weak.  The client uses no encryption for  it
+ * credentials and only sends null verifiers.  The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ */
+
+/* The machine name is part of a credential; it may not exceed 255 bytes */
+#define MAX_MACHINE_NAME 255
+
+/* gids compose part of a credential; there may not be more than 16 of them */
+#define NGRPS 16
+
+/*
+ * Unix style credentials.
+ */
+struct authunix_parms {
+	uint32_t aup_time;
+	char	*aup_machname;
+	int	 aup_uid;
+	int	 aup_gid;
+	uint_t	 aup_len;
+	int	*aup_gids;
+};
+
+extern bool_t xdr_authunix_parms();
+
+/* 
+ * If a response verifier has flavor AUTH_SHORT, 
+ * then the body of the response verifier encapsulates the following structure;
+ * again it is serialized in the obvious fashion.
+ */
+struct short_hand_verf {
+	struct opaque_auth new_cred;
+};
diff --git a/TBBT/trace_play/rpc/authunix_prot.c b/TBBT/trace_play/rpc/authunix_prot.c
new file mode 100755
index 0000000..bc18e7b
--- /dev/null
+++ b/TBBT/trace_play/rpc/authunix_prot.c
@@ -0,0 +1,86 @@
+#ifndef lint
+static char sfs_authunix_prot_c_id[] = "@(#)authunix_prot.c     2.1     97/10/23";
+#endif
+/* @(#)authunix_prot.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * authunix_prot.c
+ * XDR for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+#include "rpc/auth.h"
+#include "rpc/auth_unix.h"
+
+/*
+ * XDR for unix authentication parameters.
+ */
+bool_t
+xdr_authunix_parms(
+	XDR *xdrs,
+	struct authunix_parms *p)
+{
+
+	if (xdr_uint32_t(xdrs, &(p->aup_time))
+	    && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
+	    && xdr_int(xdrs, &(p->aup_uid))
+	    && xdr_int(xdrs, &(p->aup_gid))
+	    && xdr_array(xdrs, (void **)&(p->aup_gids),
+		    &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
diff --git a/TBBT/trace_play/rpc/bindresvport.c b/TBBT/trace_play/rpc/bindresvport.c
new file mode 100755
index 0000000..32927fe
--- /dev/null
+++ b/TBBT/trace_play/rpc/bindresvport.c
@@ -0,0 +1,103 @@
+#ifndef lint
+static char sfs_bindresvport_id[] = "@(#)bindresvport.c     2.1     97/10/23";
+#endif
+/* 2.2 88/07/29 4.0 RPCSRC 1.8 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "rpc/rpc.h"
+#include <sys/types.h>
+#include "rpc/osdep.h"
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport(
+	int sd,
+	struct sockaddr_in *sin)
+{
+	int res;
+	static int16_t port;
+	struct sockaddr_in myaddr;
+	int i;
+
+#define STARTPORT 600
+#define ENDPORT (IPPORT_RESERVED - 1)
+#define NPORTS	(ENDPORT - STARTPORT + 1)
+
+	if (sin == (struct sockaddr_in *)0) {
+		sin = &myaddr;
+		memset(sin, '\0', sizeof (struct sockaddr_in));
+		sin->sin_family = AF_INET;
+	} else if (sin->sin_family != AF_INET) {
+		errno = EPFNOSUPPORT;
+		return (-1);
+	}
+	if (port == 0) {
+		port = (getpid() % NPORTS) + STARTPORT;
+	}
+	res = -1;
+	errno = EADDRINUSE;
+	for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) {
+		sin->sin_port = htons(port++);
+		if (port > ENDPORT) {
+			port = STARTPORT;
+		}
+		res = bind(sd, (struct sockaddr *)sin, sizeof(struct sockaddr_in));
+	}
+	return (res);
+}
diff --git a/TBBT/trace_play/rpc/clnt.h b/TBBT/trace_play/rpc/clnt.h
new file mode 100755
index 0000000..3288d5b
--- /dev/null
+++ b/TBBT/trace_play/rpc/clnt.h
@@ -0,0 +1,384 @@
+/*
+ * @(#)clnt.h     2.1     97/10/23
+ */
+
+/* @(#)clnt.h	2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+
+#ifndef _CLNT_
+#define _CLNT_
+
+/*
+ * Rpc calls return an enum clnt_stat.  This should be looked at more,
+ * since each implementation is required to live with this (implementation
+ * independent) list of errors.
+ */
+enum clnt_stat {
+	RPC_SUCCESS=0,			/* call succeeded */
+	/*
+	 * local errors
+	 */
+	RPC_CANTENCODEARGS=1,		/* can't encode arguments */
+	RPC_CANTDECODERES=2,		/* can't decode results */
+	RPC_CANTSEND=3,			/* failure in sending call */
+	RPC_CANTRECV=4,			/* failure in receiving result */
+	RPC_TIMEDOUT=5,			/* call timed out */
+	/*
+	 * remote errors
+	 */
+	RPC_VERSMISMATCH=6,		/* rpc versions not compatible */
+	RPC_AUTHERROR=7,		/* authentication error */
+	RPC_PROGUNAVAIL=8,		/* program not available */
+	RPC_PROGVERSMISMATCH=9,		/* program version mismatched */
+	RPC_PROCUNAVAIL=10,		/* procedure unavailable */
+	RPC_CANTDECODEARGS=11,		/* decode arguments error */
+	RPC_SYSTEMERROR=12,		/* generic "other problem" */
+
+	/*
+	 * callrpc & clnt_create errors
+	 */
+	RPC_UNKNOWNHOST=13,		/* unknown host name */
+	RPC_UNKNOWNPROTO=17,		/* unkown protocol */
+
+	/*
+	 * _ create errors
+	 */
+	RPC_PMAPFAILURE=14,		/* the pmapper failed in its call */
+	RPC_PROGNOTREGISTERED=15,	/* remote program is not registered */
+	/*
+	 * unspecified error
+	 */
+	RPC_FAILED=16
+};
+
+
+/*
+ * Error info.
+ */
+struct rpc_err {
+	enum clnt_stat re_status;
+	union {
+		int RE_errno;		/* realated system error */
+		enum auth_stat RE_why;	/* why the auth error occurred */
+		struct {
+			uint32_t low;	/* lowest verion supported */
+			uint32_t high;	/* highest verion supported */
+		} RE_vers;
+		struct {		/* maybe meaningful if RPC_FAILED */
+			int32_t s1;
+			int32_t s2;
+		} RE_lb;		/* life boot & debugging only */
+	} ru;
+#define	re_errno	ru.RE_errno
+#define	re_why		ru.RE_why
+#define	re_vers		ru.RE_vers
+#define	re_lb		ru.RE_lb
+};
+
+
+/*
+ * Client rpc handle.
+ * Created by individual implementations, see e.g. rpc_udp.c.
+ * Client is responsible for initializing auth, see e.g. auth_none.c.
+ */
+typedef struct {
+	AUTH	*cl_auth;			/* authenticator */
+	struct clnt_ops	*cl_ops;
+	void	*cl_private;			/* private stuff */
+} CLIENT;
+
+struct clnt_ops {
+	enum clnt_stat	(*cl_call)(CLIENT *, uint32_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval);
+	void		(*cl_abort)(CLIENT *);
+	void		(*cl_geterr)(CLIENT *, struct rpc_err *);
+	bool_t		(*cl_freeres)(CLIENT *, xdrproc_t, void *);
+	void		(*cl_destroy)(CLIENT *);
+	bool_t          (*cl_control)(CLIENT *, uint_t, void *);
+	bool_t		(*cl_getreply)(CLIENT *, xdrproc_t, void *, int,
+				uint32_t *, uint32_t *, struct timeval *);
+	int		(*cl_poll)(CLIENT *, uint32_t);
+};
+
+/*
+ * client side rpc interface ops
+ *
+ * Parameter types are:
+ *
+ */
+
+/*
+ * enum clnt_stat
+ * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
+ * 	CLIENT *rh;
+ *	uint32_t proc;
+ *	xdrproc_t xargs;
+ *	void * argsp;
+ *	xdrproc_t xres;
+ *	void * resp;
+ *	struct timeval timeout;
+ */
+#define	CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs)	\
+	((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+#define	clnt_call(rh, proc, xargs, argsp, xres, resp, secs)	\
+	((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+
+/*
+ * void
+ * CLNT_ABORT(rh);
+ * 	CLIENT *rh;
+ */
+#define	CLNT_ABORT(rh)	((*(rh)->cl_ops->cl_abort)(rh))
+#define	clnt_abort(rh)	((*(rh)->cl_ops->cl_abort)(rh))
+
+/*
+ * struct rpc_err
+ * CLNT_GETERR(rh);
+ * 	CLIENT *rh;
+ */
+#define	CLNT_GETERR(rh,errp)	((*(rh)->cl_ops->cl_geterr)(rh, errp))
+#define	clnt_geterr(rh,errp)	((*(rh)->cl_ops->cl_geterr)(rh, errp))
+
+
+/*
+ * bool_t
+ * CLNT_FREERES(rh, xres, resp);
+ * 	CLIENT *rh;
+ *	xdrproc_t xres;
+ *	void * resp;
+ */
+#define	CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+#define	clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+
+/*
+ * bool_t
+ * CLNT_CONTROL(cl, request, info)
+ *      CLIENT *cl;
+ *      uint_t request;
+ *      void *info;
+ */
+#define	CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+#define	clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+
+/*
+ * control operations that apply to both udp and tcp transports
+ */
+#define CLSET_TIMEOUT       1   /* set timeout (timeval) */
+#define CLGET_TIMEOUT       2   /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR   3   /* get server's address (sockaddr) */
+/*
+ * udp only control operations
+ */
+#define CLSET_RETRY_TIMEOUT 4   /* set retry timeout (timeval) */
+#define CLGET_RETRY_TIMEOUT 5   /* get retry timeout (timeval) */
+
+/*
+ * void
+ * CLNT_DESTROY(rh);
+ * 	CLIENT *rh;
+ */
+#define	CLNT_DESTROY(rh)	((*(rh)->cl_ops->cl_destroy)(rh))
+#define	clnt_destroy(rh)	((*(rh)->cl_ops->cl_destroy)(rh))
+
+/*
+ * bool_t
+ * CLNT_GETREPLY(rh,xres,xresp,xid,tv)
+ *	CLIENT *rh;
+ *	xdrproc_t xres;
+ *	void * resp;
+ *	int cnt;
+ *	uint32_t *xids;
+ *	uint32_t *xid;
+ *	struct timeval *tv;
+ */
+#define	CLNT_GETREPLY(rh,xres,xresp,cnt,xids,xid,tv) ((*(rh)->cl_ops->cl_getreply)(rh,xres,xresp,cnt,xids,xid,tv))
+#define	clnt_getreply(rh,xres,xresp,cnt,xids,xid,tv) ((*(rh)->cl_ops->cl_getreply)(rh,xres,xresp,cnt,xids,xid,tv))
+
+/*
+ * bool_t
+ * CLNT_POLL(rh,xusec)
+ *	CLIENT *rh;
+ *	uint32_t xusec;
+ */
+#define	CLNT_POLL(rh,xid) ((*(rh)->cl_ops->cl_poll)(rh,xid))
+#define	clnt_poll(rh,xid) ((*(rh)->cl_ops->cl_poll)(rh,xid))
+
+/*
+ * RPCTEST is a test program which is accessable on every rpc
+ * transport/port.  It is used for testing, performance evaluation,
+ * and network administration.
+ */
+
+#define RPCTEST_PROGRAM		((uint32_t)1)
+#define RPCTEST_VERSION		((uint32_t)1)
+#define RPCTEST_NULL_PROC	((uint32_t)2)
+#define RPCTEST_NULL_BATCH_PROC	((uint32_t)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((uint32_t)0)
+
+/*
+ * Below are the client handle creation routines for the various
+ * implementations of client side rpc.  They can return NULL if a 
+ * creation failure occurs.
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ * CLIENT *
+ * clntraw_create(prog, vers)
+ *	uint32_t prog;
+ *	uint32_t vers;
+ */
+extern CLIENT *clntraw_create(uint32_t, uint32_t);
+
+/*
+ * Generic client creation routine. Supported protocols are "udp" and "tcp"
+ */
+extern CLIENT *clnt_create(char *, uint32_t, uint32_t, char *);
+
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * sfs_ctcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ *	struct sockaddr_in *raddr;
+ *	uint32_t prog;
+ *	uint32_t version;
+ *	register int *sockp;
+ *	uint_t sendsz;
+ *	uint_t recvsz;
+ */
+extern CLIENT *sfs_ctcp_create(struct sockaddr_in *, uint32_t, uint32_t,
+					int *, uint_t, uint_t);
+extern CLIENT *clnttcp_create(struct sockaddr_in *, uint32_t, uint32_t,
+					int *, uint_t, uint_t);
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * sfs_cudp_create(raddr, program, version, wait, sockp)
+ *	struct sockaddr_in *raddr;
+ *	uint32_t program;
+ *	uint32_t version;
+ *	struct timeval wait;
+ *	int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * sfs_cudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ *	struct sockaddr_in *raddr;
+ *	uint32_t program;
+ *	uint32_t version;
+ *	struct timeval wait;
+ *	int *sockp;
+ *	uint_t sendsz;
+ *	uint_t recvsz;
+ */
+extern CLIENT *clntudp_create(struct sockaddr_in *, uint32_t, uint32_t,
+					struct timeval, int *);
+extern CLIENT *clntudp_bufcreate(struct sockaddr_in *, uint32_t, uint32_t,
+					struct timeval, int *, uint_t, uint_t);
+extern CLIENT *sfs_cudp_create(struct sockaddr_in *, uint32_t, uint32_t,
+					struct timeval, int *);
+extern CLIENT *sfs_cudp_bufcreate(struct sockaddr_in *, uint32_t, uint32_t,
+					struct timeval, int *, uint_t, uint_t);
+
+/*
+ * Print why creation failed
+ */
+extern void clnt_pcreateerror(char *);
+extern char *clnt_spcreateerror(char *);
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */ 
+extern void clnt_perrno(enum clnt_stat);
+
+/*
+ * Print an English error message, given the client error code
+ */
+extern void clnt_perror(CLIENT *, char *);
+extern char *clnt_sperror(CLIENT *, char *);
+
+/* 
+ * If a creation fails, the following allows the user to figure out why.
+ */
+struct rpc_createerr {
+	enum clnt_stat cf_stat;
+	struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
+};
+
+extern struct rpc_createerr rpc_createerr;
+
+/*
+ * Copy error message to buffer.
+ */
+extern char *clnt_sperrno(enum clnt_stat);
+
+extern int callrpc(char *, int, int, int, xdrproc_t, char *, xdrproc_t, char *);
+
+extern int bindresvport(int sd, struct sockaddr_in *sin);
+
+#define UDPMSGSIZE	(63 * 1024) /* rpc imposed limit on udp msg size */
+#define RPCSMALLMSGSIZE	400	    /* a more reasonable packet size */
+
+#if !defined(RPC_ANYSOCK)
+#define RPC_ANYSOCK     -1
+#endif
+
+#endif /*!_CLNT_*/
diff --git a/TBBT/trace_play/rpc/clnt_generic.c b/TBBT/trace_play/rpc/clnt_generic.c
new file mode 100755
index 0000000..16538ef
--- /dev/null
+++ b/TBBT/trace_play/rpc/clnt_generic.c
@@ -0,0 +1,133 @@
+#ifndef lint
+static char sfs_clnt_generic_id[] = "@(#)clnt_generic.c     2.1     97/10/23";
+#endif
+
+/* @(#)clnt_generic.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";
+#endif
+/*
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <errno.h>
+#include <netdb.h>
+
+/*
+ * Generic client creation: takes (hostname, program-number, protocol) and
+ * returns client handle. Default options are set, which the user can 
+ * change using the rpc equivalent of ioctl()'s.
+ */
+CLIENT *
+clnt_create(char *hostname,
+	uint32_t prog,
+	uint32_t vers,
+	char *proto)
+{
+	struct hostent *h;
+	struct protoent *p;
+	struct sockaddr_in sin;
+	int sock;
+	struct timeval tv;
+	CLIENT *client;
+
+	h = gethostbyname(hostname);
+	if (h == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+		return (NULL);
+	}
+	if (h->h_addrtype != AF_INET) {
+		/*
+		 * Only support INET for now
+		 */
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = EAFNOSUPPORT; 
+		return (NULL);
+	}
+	sin.sin_family = h->h_addrtype;
+	sin.sin_port = 0;
+	memset(sin.sin_zero, '\0', sizeof(sin.sin_zero));
+	memmove((char*)&sin.sin_addr, h->h_addr, h->h_length);
+	p = getprotobyname(proto);
+	if (p == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; 
+		return (NULL);
+	}
+	sock = RPC_ANYSOCK;
+	switch (p->p_proto) {
+	case IPPROTO_UDP:
+		tv.tv_sec = 5;
+		tv.tv_usec = 0;
+		client = sfs_cudp_create(&sin, prog, vers, tv, &sock);
+		if (client == NULL) {
+			return (NULL);
+		}
+		tv.tv_sec = 25;
+		clnt_control(client, CLSET_TIMEOUT, &tv);
+		break;
+	case IPPROTO_TCP:
+		client = sfs_ctcp_create(&sin, prog, vers, &sock, 0, 0);
+		if (client == NULL) {
+			return (NULL);
+		}
+		tv.tv_sec = 25;
+		tv.tv_usec = 0;
+		clnt_control(client, CLSET_TIMEOUT, &tv);
+		break;
+	default:
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; 
+		return (NULL);
+	}
+	return (client);
+}
diff --git a/TBBT/trace_play/rpc/clnt_perror.c b/TBBT/trace_play/rpc/clnt_perror.c
new file mode 100755
index 0000000..71d1502
--- /dev/null
+++ b/TBBT/trace_play/rpc/clnt_perror.c
@@ -0,0 +1,316 @@
+#ifndef lint
+static char sfs_clnt_perror_c_id[] = "@(#)clnt_perror.c     2.1     97/10/23";
+#endif
+/* @(#)clnt_perror.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rpc/rpc.h"
+
+static char *auth_errmsg(enum auth_stat);
+
+static char *
+_buf()
+{
+	static char *buf = NULL;
+	if (buf == NULL)
+		buf = (char *)malloc(256);
+	return (buf);
+}
+
+/*
+ * Print reply error info
+ */
+char *
+clnt_sperror(
+	CLIENT *rpch,
+	char *s)
+{
+	struct rpc_err e;
+	char *err;
+	char *str = _buf();
+	char *strstart = str;
+
+	if (str == 0)
+		return (0);
+	CLNT_GETERR(rpch, &e);
+
+	(void) sprintf(str, "%s: ", s);  
+	str += strlen(str);
+
+	(void) strcpy(str, clnt_sperrno(e.re_status));  
+	str += strlen(str);
+
+	switch (e.re_status) {
+	case RPC_SUCCESS:
+	case RPC_CANTENCODEARGS:
+	case RPC_CANTDECODERES:
+	case RPC_TIMEDOUT:     
+	case RPC_PROGUNAVAIL:
+	case RPC_PROCUNAVAIL:
+	case RPC_CANTDECODEARGS:
+	case RPC_SYSTEMERROR:
+	case RPC_UNKNOWNHOST:
+	case RPC_UNKNOWNPROTO:
+	case RPC_PMAPFAILURE:
+	case RPC_PROGNOTREGISTERED:
+	case RPC_FAILED:
+		break;
+
+	case RPC_CANTSEND:
+	case RPC_CANTRECV:
+		(void) sprintf(str, "; errno = %s",
+		    strerror(e.re_errno)); 
+		str += strlen(str);
+		break;
+
+	case RPC_VERSMISMATCH:
+		(void) sprintf(str,
+			"; low version = %lu, high version = %lu", 
+			e.re_vers.low, e.re_vers.high);
+		str += strlen(str);
+		break;
+
+	case RPC_AUTHERROR:
+		err = auth_errmsg(e.re_why);
+		(void) sprintf(str,"; why = ");
+		str += strlen(str);
+		if (err != NULL) {
+			(void) sprintf(str, "%s",err);
+		} else {
+			(void) sprintf(str,
+				"(unknown authentication error - %d)",
+				(int) e.re_why);
+		}
+		str += strlen(str);
+		break;
+
+	case RPC_PROGVERSMISMATCH:
+		(void) sprintf(str, 
+			"; low version = %lu, high version = %lu", 
+			e.re_vers.low, e.re_vers.high);
+		str += strlen(str);
+		break;
+
+	default:	/* unknown */
+		(void) sprintf(str, 
+			"; s1 = %lu, s2 = %lu", 
+			e.re_lb.s1, e.re_lb.s2);
+		str += strlen(str);
+		break;
+	}
+	(void) sprintf(str, "\n");
+	return(strstart) ;
+}
+
+void
+clnt_perror(
+	CLIENT *rpch,
+	char *s)
+{
+	(void) fprintf(stderr,"%s",clnt_sperror(rpch,s));
+}
+
+
+struct rpc_errtab {
+	enum clnt_stat status;
+	char *message;
+};
+
+static struct rpc_errtab  rpc_errlist[] = {
+	{ RPC_SUCCESS, 
+		"RPC: Success" }, 
+	{ RPC_CANTENCODEARGS, 
+		"RPC: Can't encode arguments" },
+	{ RPC_CANTDECODERES, 
+		"RPC: Can't decode result" },
+	{ RPC_CANTSEND, 
+		"RPC: Unable to send" },
+	{ RPC_CANTRECV, 
+		"RPC: Unable to receive" },
+	{ RPC_TIMEDOUT, 
+		"RPC: Timed out" },
+	{ RPC_VERSMISMATCH, 
+		"RPC: Incompatible versions of RPC" },
+	{ RPC_AUTHERROR, 
+		"RPC: Authentication error" },
+	{ RPC_PROGUNAVAIL, 
+		"RPC: Program unavailable" },
+	{ RPC_PROGVERSMISMATCH, 
+		"RPC: Program/version mismatch" },
+	{ RPC_PROCUNAVAIL, 
+		"RPC: Procedure unavailable" },
+	{ RPC_CANTDECODEARGS, 
+		"RPC: Server can't decode arguments" },
+	{ RPC_SYSTEMERROR, 
+		"RPC: Remote system error" },
+	{ RPC_UNKNOWNHOST, 
+		"RPC: Unknown host" },
+	{ RPC_UNKNOWNPROTO,
+		"RPC: Unknown protocol" },
+	{ RPC_PMAPFAILURE, 
+		"RPC: Port mapper failure" },
+	{ RPC_PROGNOTREGISTERED, 
+		"RPC: Program not registered"},
+	{ RPC_FAILED, 
+		"RPC: Failed (unspecified error)"}
+};
+
+
+/*
+ * This interface for use by clntrpc
+ */
+char *
+clnt_sperrno(
+	enum clnt_stat stat)
+{
+	int i;
+
+	for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) {
+		if (rpc_errlist[i].status == stat) {
+			return (rpc_errlist[i].message);
+		}
+	}
+	return ("RPC: (unknown error code)");
+}
+
+void
+clnt_perrno(
+	enum clnt_stat num)
+{
+	(void) fprintf(stderr,"%s",clnt_sperrno(num));
+}
+
+
+char *
+clnt_spcreateerror(char *s)
+{
+	char *sp;
+	char *str = _buf();
+
+	if (str == 0)
+		return(0);
+	(void) sprintf(str, "%s: ", s);
+	(void) strcat(str, clnt_sperrno(rpc_createerr.cf_stat));
+	switch (rpc_createerr.cf_stat) {
+	case RPC_PMAPFAILURE:
+		(void) strcat(str, " - ");
+		(void) strcat(str,
+		    clnt_sperrno(rpc_createerr.cf_error.re_status));
+		break;
+
+	case RPC_SYSTEMERROR:
+		sp = strerror(rpc_createerr.cf_error.re_errno);
+		(void) strcat(str, " - ");
+		if (rpc_createerr.cf_error.re_errno > 0
+		    && sp != NULL)
+			(void) strcat(str, sp);
+		else
+			(void) sprintf(&str[strlen(str)], "Error %d",
+			    rpc_createerr.cf_error.re_errno);
+		break;
+	}
+	(void) strcat(str, "\n");
+	return (str);
+}
+
+void
+clnt_pcreateerror(char *s)
+{
+	(void) fprintf(stderr, "%s", clnt_spcreateerror(s));
+}
+
+struct auth_errtab {
+	enum auth_stat status;	
+	char *message;
+};
+
+static struct auth_errtab auth_errlist[] = {
+	{ AUTH_OK,
+		"Authentication OK" },
+	{ AUTH_BADCRED,
+		"Invalid client credential" },
+	{ AUTH_REJECTEDCRED,
+		"Server rejected credential" },
+	{ AUTH_BADVERF,
+		"Invalid client verifier" },
+	{ AUTH_REJECTEDVERF,
+		"Server rejected verifier" },
+	{ AUTH_TOOWEAK,
+		"Client credential too weak" },
+	{ AUTH_INVALIDRESP,
+		"Invalid server verifier" },
+	{ AUTH_FAILED,
+		"Failed (unspecified error)" },
+};
+
+static char *
+auth_errmsg(
+	enum auth_stat stat)
+{
+	int i;
+
+	for (i = 0; i < sizeof(auth_errlist)/sizeof(struct auth_errtab); i++) {
+		if (auth_errlist[i].status == stat) {
+			return(auth_errlist[i].message);
+		}
+	}
+	return(NULL);
+}
diff --git a/TBBT/trace_play/rpc/clnt_simple.c b/TBBT/trace_play/rpc/clnt_simple.c
new file mode 100755
index 0000000..ab5ae9a
--- /dev/null
+++ b/TBBT/trace_play/rpc/clnt_simple.c
@@ -0,0 +1,141 @@
+#ifndef lint
+static char sfs_clnt_simple_id[] = "@(#)clnt_simple.c     2.1     97/10/23";
+#endif
+/* @(#)clnt_simple.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/* 
+ * clnt_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <netdb.h>
+#include <string.h>
+
+static struct callrpc_private {
+	CLIENT	*client;
+	int	socket;
+	int	oldprognum, oldversnum, valid;
+	char	*oldhost;
+} *callrpc_private;
+
+callrpc(
+	char *host,
+	int prognum,
+	int versnum,
+	int procnum,
+	xdrproc_t inproc,
+	char *in,
+	xdrproc_t outproc,
+	char *out)
+{
+	register struct callrpc_private *crp = callrpc_private;
+	struct sockaddr_in server_addr;
+	enum clnt_stat clnt_stat;
+	struct hostent *hp;
+	struct timeval timeout, tottimeout;
+
+	if (crp == 0) {
+		crp = (struct callrpc_private *)calloc(1,
+					sizeof (struct callrpc_private));
+		if (crp == 0)
+			return (0);
+		callrpc_private = crp;
+	}
+	if (crp->oldhost == NULL) {
+		crp->oldhost = malloc(256);
+		crp->oldhost[0] = 0;
+		crp->socket = RPC_ANYSOCK;
+	}
+	if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
+		&& strcmp(crp->oldhost, host) == 0) {
+		/* reuse old client */		
+	} else {
+		crp->valid = 0;
+		(void)close(crp->socket);
+		crp->socket = RPC_ANYSOCK;
+		if (crp->client) {
+			clnt_destroy(crp->client);
+			crp->client = NULL;
+		}
+		if ((hp = gethostbyname(host)) == NULL)
+			return ((int) RPC_UNKNOWNHOST);
+		timeout.tv_usec = 0;
+		timeout.tv_sec = 5;
+		memmove((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length);
+		server_addr.sin_family = AF_INET;
+		server_addr.sin_port =  0;
+		if ((crp->client = clntudp_create(&server_addr, (uint32_t)prognum,
+		    (uint32_t)versnum, timeout, &crp->socket)) == NULL)
+			return ((int) rpc_createerr.cf_stat);
+		crp->valid = 1;
+		crp->oldprognum = prognum;
+		crp->oldversnum = versnum;
+		(void) strcpy(crp->oldhost, host);
+	}
+	tottimeout.tv_sec = 25;
+	tottimeout.tv_usec = 0;
+	clnt_stat = clnt_call(crp->client, procnum, inproc, in,
+	    outproc, out, tottimeout);
+	/* 
+	 * if call failed, empty cache
+	 */
+	if (clnt_stat != RPC_SUCCESS)
+		crp->valid = 0;
+	return ((int) clnt_stat);
+}
diff --git a/TBBT/trace_play/rpc/clnt_tcp.c b/TBBT/trace_play/rpc/clnt_tcp.c
new file mode 100755
index 0000000..4054f01
--- /dev/null
+++ b/TBBT/trace_play/rpc/clnt_tcp.c
@@ -0,0 +1,522 @@
+#ifndef lint
+static char sfs_clnt_tcp_c_id[] = "@(#)clnt_tcp.c     2.1     97/10/23";
+#endif
+/* @(#)clnt_tcp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+#endif
+ 
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer.  The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message.  Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <netdb.h>
+#include <errno.h>
+#include "rpc/pmap_clnt.h"
+
+#define MCALL_MSG_SIZE 24
+
+struct ct_data {
+	int		ct_sock;
+	bool_t		ct_closeit;
+	struct timeval	ct_wait;
+	bool_t          ct_waitset;       /* wait set by clnt_control? */
+	struct sockaddr_in ct_addr; 
+	struct rpc_err	ct_error;
+	char		ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */
+	uint_t		ct_mpos;			/* pos after marshal */
+	XDR		ct_xdrs;
+};
+
+static int	readtcp(struct ct_data *, char *, int);
+static int	writetcp(struct ct_data *, char *, int);
+
+static enum clnt_stat	clnttcp_call(CLIENT *, uint32_t, xdrproc_t, void *,
+					xdrproc_t, void *, struct timeval);
+static void		clnttcp_abort(CLIENT *);
+static void		clnttcp_geterr(CLIENT *, struct rpc_err *);
+static bool_t		clnttcp_freeres(CLIENT *, xdrproc_t, void *);
+static bool_t		clnttcp_control(CLIENT *, uint_t, void *);
+static void		clnttcp_destroy(CLIENT *h);
+static bool_t		clnttcp_getreply(CLIENT *, xdrproc_t, void *,
+				int, uint32_t *, uint32_t *, struct timeval *);
+static int		clnttcp_poll(CLIENT *, uint32_t);
+
+
+static struct clnt_ops tcp_ops = {
+	clnttcp_call,
+	clnttcp_abort,
+	clnttcp_geterr,
+	clnttcp_freeres,
+	clnttcp_destroy,
+	clnttcp_control,
+	clnttcp_getreply,
+	clnttcp_poll
+};
+
+/*
+ * Create a client handle for a tcp/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr.  If *sockp non-negative then
+ * raddr is ignored.  The rpc/tcp package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clnttcp_create(
+	struct sockaddr_in *raddr,
+	uint32_t prog,
+	uint32_t vers,
+	int *sockp,
+	uint_t sendsz,
+	uint_t recvsz)
+{
+	CLIENT *h;
+	struct ct_data *ct;
+	struct timeval now;
+	struct rpc_msg call_msg;
+
+	h  = (CLIENT *)mem_alloc(sizeof(CLIENT));
+	if (h == NULL) {
+		(void)fprintf(stderr, "clnttcp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	ct = (struct ct_data *)mem_alloc(sizeof(struct ct_data));
+	if (ct == NULL) {
+		(void)fprintf(stderr, "clnttcp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+
+	/*
+	 * If no port number given ask the pmap for one
+	 */
+	if (raddr->sin_port == 0) {
+		uint16_t port;
+		if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
+			mem_free((void *)ct, sizeof(struct ct_data));
+			mem_free((void *)h, sizeof(CLIENT));
+			return ((CLIENT *)NULL);
+		}
+		raddr->sin_port = htons(port);
+	}
+
+	/*
+	 * If no socket given, open one
+	 */
+	if (*sockp < 0) {
+		*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		(void)bindresvport(*sockp, (struct sockaddr_in *)0);
+		if ((*sockp < 0)
+		    || (connect(*sockp, (struct sockaddr *)raddr,
+		    sizeof(struct sockaddr_in)) < 0)) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			(void)close(*sockp);
+			goto fooy;
+		}
+		ct->ct_closeit = TRUE;
+	} else {
+		ct->ct_closeit = FALSE;
+	}
+
+	/*
+	 * Set up private data struct
+	 */
+	ct->ct_sock = *sockp;
+	ct->ct_wait.tv_usec = 0;
+	ct->ct_waitset = FALSE;
+	ct->ct_addr = *raddr;
+
+	/*
+	 * Initialize call message
+	 */
+	(void)gettimeofday(&now, (struct timezone *)0);
+	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = prog;
+	call_msg.rm_call.cb_vers = vers;
+
+	/*
+	 * pre-serialize the staic part of the call msg and stash it away
+	 */
+	xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
+	    XDR_ENCODE);
+	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+		if (ct->ct_closeit) {
+			(void)close(*sockp);
+		}
+		goto fooy;
+	}
+	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+	XDR_DESTROY(&(ct->ct_xdrs));
+
+	/*
+	 * Create a client handle which uses xdrrec for serialization
+	 * and authnone for authentication.
+	 */
+	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+	    (void *)ct, readtcp, writetcp);
+	h->cl_ops = &tcp_ops;
+	h->cl_private = (char *) ct;
+	h->cl_auth = authnone_create();
+	return (h);
+
+fooy:
+	/*
+	 * Something goofed, free stuff and barf
+	 */
+	mem_free((void *)ct, sizeof(struct ct_data));
+	mem_free((void *)h, sizeof(CLIENT));
+	return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnttcp_call(
+	CLIENT *h,
+	uint32_t proc,
+	xdrproc_t xdr_args,
+	void * args_ptr,
+	xdrproc_t xdr_results,
+	void * results_ptr,
+	struct timeval timeout)
+{
+	struct ct_data *ct = (struct ct_data *) h->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+	struct rpc_msg reply_msg;
+	uint32_t x_id;
+	uint32_t *msg_x_id = (uint32_t *)(ct->ct_mcall);	/* yuk */
+	bool_t shipnow;
+	int refreshes = 2;
+
+	if (!ct->ct_waitset) {
+		ct->ct_wait = timeout;
+	}
+
+	shipnow =
+	    (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
+	    && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+	xdrs->x_op = XDR_ENCODE;
+	ct->ct_error.re_status = RPC_SUCCESS;
+	x_id = ntohl(--(*msg_x_id));
+	if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+	    (! XDR_PUTLONG(xdrs, (int32_t *)&proc)) ||
+	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+	    (! (*xdr_args)(xdrs, args_ptr))) {
+		if (ct->ct_error.re_status == RPC_SUCCESS)
+			ct->ct_error.re_status = RPC_CANTENCODEARGS;
+		(void)xdrrec_endofrecord(xdrs, TRUE);
+		return (ct->ct_error.re_status);
+	}
+	if (! xdrrec_endofrecord(xdrs, shipnow))
+		return (ct->ct_error.re_status = RPC_CANTSEND);
+	if (! shipnow)
+		return (RPC_SUCCESS);
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+		return(ct->ct_error.re_status = RPC_TIMEDOUT);
+	}
+
+
+	/*
+	 * Keep receiving until we get a valid transaction id
+	 */
+	xdrs->x_op = XDR_DECODE;
+	/* CONSTCOND */
+	while (TRUE) {
+		reply_msg.acpted_rply.ar_verf = _null_auth;
+		reply_msg.acpted_rply.ar_results.where = NULL;
+		reply_msg.acpted_rply.ar_results.proc = xdr_void;
+		if (! xdrrec_skiprecord(xdrs))
+			return (ct->ct_error.re_status);
+		/* now decode and validate the response header */
+		if (! xdr_replymsg(xdrs, &reply_msg)) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				continue;
+			return (ct->ct_error.re_status);
+		}
+		if (reply_msg.rm_xid == x_id)
+			break;
+	}
+
+	/*
+	 * process header
+	 */
+	_seterr_reply(&reply_msg, &(ct->ct_error));
+	if (ct->ct_error.re_status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
+			ct->ct_error.re_status = RPC_AUTHERROR;
+			ct->ct_error.re_why = AUTH_INVALIDRESP;
+		} else if (! (*xdr_results)(xdrs, results_ptr)) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				ct->ct_error.re_status = RPC_CANTDECODERES;
+		}
+		/* free verifier ... */
+		if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+			xdrs->x_op = XDR_FREE;
+			(void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
+		}
+	}  /* end successful completion */
+	else {
+		/* maybe our credentials need to be refreshed ... */
+		if (refreshes-- && AUTH_REFRESH(h->cl_auth))
+			goto call_again;
+	}  /* end of unsuccessful completion */
+	return (ct->ct_error.re_status);
+}
+
+static void
+clnttcp_geterr(
+	CLIENT *h,
+	struct rpc_err *errp)
+{
+	struct ct_data *ct =
+	    (struct ct_data *) h->cl_private;
+
+	*errp = ct->ct_error;
+}
+
+static bool_t
+clnttcp_freeres(
+	CLIENT *cl,
+	xdrproc_t xdr_res,
+	void * res_ptr)
+{
+	struct ct_data *ct = (struct ct_data *)cl->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/* ARGSUSED */
+static void
+clnttcp_abort(CLIENT *c)
+{
+}
+
+static bool_t
+clnttcp_control(
+	CLIENT *cl,
+	uint_t request,
+	void *info)
+{
+	struct ct_data *ct = (struct ct_data *)cl->cl_private;
+
+	switch (request) {
+	case CLSET_TIMEOUT:
+		ct->ct_wait = *(struct timeval *)info;
+		ct->ct_waitset = TRUE;
+		break;
+	case CLGET_TIMEOUT:
+		*(struct timeval *)info = ct->ct_wait;
+		break;
+	case CLGET_SERVER_ADDR:
+		*(struct sockaddr_in *)info = ct->ct_addr;
+		break;
+	default:
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+
+static void
+clnttcp_destroy(
+	CLIENT *h)
+{
+	struct ct_data *ct =
+	    (struct ct_data *) h->cl_private;
+
+	if (ct->ct_closeit) {
+		(void)close(ct->ct_sock);
+	}
+	XDR_DESTROY(&(ct->ct_xdrs));
+	mem_free((void *)ct, sizeof(struct ct_data));
+	mem_free((void *)h, sizeof(CLIENT));
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readtcp(
+	struct ct_data *ct,
+	char *buf,
+	int len)
+{
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+
+	if (len == 0)
+		return (0);
+	FD_ZERO(&mask);
+	FD_SET(ct->ct_sock, &mask);
+#else
+	int mask = 1 << (ct->ct_sock);
+	int readfds;
+
+	if (len == 0)
+		return (0);
+
+#endif /* def FD_SETSIZE */
+	/* CONSTCOND */
+	while (TRUE) {
+		readfds = mask;
+		switch (select(_rpc_dtablesize(), &readfds, NULL, NULL,
+			       &(ct->ct_wait))) {
+		case 0:
+			ct->ct_error.re_status = RPC_TIMEDOUT;
+			return (-1);
+
+		case -1:
+			if (errno == EINTR)
+				continue;
+			ct->ct_error.re_status = RPC_CANTRECV;
+			ct->ct_error.re_errno = errno;
+			return (-1);
+		}
+		break;
+	}
+	switch (len = read(ct->ct_sock, buf, len)) {
+
+	case 0:
+		/* premature eof */
+		ct->ct_error.re_errno = ECONNRESET;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		len = -1;  /* it's really an error */
+		break;
+
+	case -1:
+		ct->ct_error.re_errno = errno;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		break;
+	}
+	return (len);
+}
+
+static int
+writetcp(
+	struct ct_data *ct,
+	char *buf,
+	int len)
+{
+	int i, cnt;
+
+	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+		if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
+			ct->ct_error.re_errno = errno;
+			ct->ct_error.re_status = RPC_CANTSEND;
+			return (-1);
+		}
+	}
+	return (len);
+}
+ 
+/* ARGSUSED */
+static bool_t
+clnttcp_getreply(
+        CLIENT *cl,
+        xdrproc_t xproc,
+        void *xres,
+	int cnt,
+	uint32_t *xids,
+        uint32_t *xid,
+	struct timeval *tv)
+{
+        return (FALSE);
+}
+ 
+/* ARGSUSED */
+static int
+clnttcp_poll(
+        CLIENT *cl,
+        uint32_t usec)
+{
+        return (-1);
+}
+
diff --git a/TBBT/trace_play/rpc/clnt_udp.c b/TBBT/trace_play/rpc/clnt_udp.c
new file mode 100755
index 0000000..d362f10
--- /dev/null
+++ b/TBBT/trace_play/rpc/clnt_udp.c
@@ -0,0 +1,510 @@
+#ifndef lint
+static char sfs_clnt_id[] = "@(#)clnt_udp.c     2.1     97/10/23";
+#endif
+/* @(#)clnt_udp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_udp.c, Implements a UDP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifndef FreeBSD
+#include <stropts.h>
+#endif /* ndef Free BSD */
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <netdb.h>
+#include <errno.h>
+#include "rpc/pmap_clnt.h"
+
+/* 
+ * Private data kept per client handle
+ */
+struct cu_data {
+	int		   cu_sock;
+	bool_t		   cu_closeit;
+	struct sockaddr_in cu_raddr;
+	int		   cu_rlen;
+	struct timeval	   cu_wait;
+	struct timeval     cu_total;
+	struct rpc_err	   cu_error;
+	XDR		   cu_outxdrs;
+	uint_t		   cu_xdrpos;
+	uint_t		   cu_sendsz;
+	char		   *cu_outbuf;
+	uint_t		   cu_recvsz;
+	char		   cu_inbuf[1];
+};
+
+/*
+ * UDP bases client side rpc operations
+ */
+static enum clnt_stat	clntudp_call(CLIENT *, uint32_t, xdrproc_t, void *,
+					xdrproc_t, void *, struct timeval);
+static void		clntudp_abort(CLIENT *);
+static void		clntudp_geterr(CLIENT *, struct rpc_err *);
+static bool_t		clntudp_freeres(CLIENT *, xdrproc_t, void *);
+static bool_t		clntudp_control(CLIENT *, uint_t, void *);
+static void		clntudp_destroy(CLIENT *);
+static bool_t		clntudp_getreply(CLIENT *, xdrproc_t, void *,
+				int, uint32_t *, uint32_t *, struct timeval *);
+static int		clntudp_poll(CLIENT *, uint32_t);
+
+static struct clnt_ops udp_ops = {
+	clntudp_call,
+	clntudp_abort,
+	clntudp_geterr,
+	clntudp_freeres,
+	clntudp_destroy,
+	clntudp_control,
+	clntudp_getreply,
+	clntudp_poll
+};
+
+/*
+ * Create a UDP based client handle.
+ * If *sockp<0, *sockp is set to a newly created UPD socket.
+ * If raddr->sin_port is 0 a binder on the remote machine
+ * is consulted for the correct port number.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ *     Caller may wish to set this something more useful.
+ *
+ * wait is the amount of time used between retransmitting a call if
+ * no response has been heard;  retransmition occurs until the actual
+ * rpc call times out.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received.
+ */
+CLIENT *
+clntudp_bufcreate(
+	struct sockaddr_in *raddr,
+	uint32_t program,
+	uint32_t version,
+	struct timeval wait,
+	int *sockp,
+	uint_t sendsz,
+	uint_t recvsz)
+{
+	CLIENT *cl;
+	struct cu_data *cu;
+	struct timeval now;
+	struct rpc_msg call_msg;
+
+	cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
+	if (cl == NULL) {
+		(void) fprintf(stderr, "clntudp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	sendsz = ((sendsz + 3) / 4) * 4;
+	recvsz = ((recvsz + 3) / 4) * 4;
+	cu = (struct cu_data *)mem_alloc(sizeof(struct cu_data) +
+						sendsz + recvsz);
+	if (cu == NULL) {
+		(void) fprintf(stderr, "clntudp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+
+	(void)gettimeofday(&now, (struct timezone *)0);
+	if (raddr->sin_port == 0) {
+		uint16_t port;
+		if ((port =
+		    pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
+			goto fooy;
+		}
+		raddr->sin_port = htons(port);
+	}
+	cl->cl_ops = &udp_ops;
+	cl->cl_private = (char *)cu;
+	cu->cu_raddr = *raddr;
+	cu->cu_rlen = sizeof (cu->cu_raddr);
+	cu->cu_wait = wait;
+	cu->cu_total.tv_sec = -1;
+	cu->cu_total.tv_usec = -1;
+	cu->cu_sendsz = sendsz;
+	cu->cu_recvsz = recvsz;
+	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = program;
+	call_msg.rm_call.cb_vers = version;
+	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
+	    sendsz, XDR_ENCODE);
+	if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
+		goto fooy;
+	}
+	cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+	if (*sockp < 0) {
+#if defined(O_NONBLOCK)
+		int flags;
+#elif defined(FIONBIO)
+		int dontblock = 1;
+#endif
+
+		*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+		if (*sockp < 0) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			goto fooy;
+		}
+		/* attempt to bind to prov port */
+		(void)bindresvport(*sockp, (struct sockaddr_in *)0);
+		/* the sockets rpc controls are non-blocking */
+#if defined(O_NONBLOCK)
+                flags = fcntl(*sockp, F_GETFL, 0) | O_NONBLOCK;
+                (void)fcntl(*sockp, F_SETFL, flags);
+#elif defined(FIONBIO)
+                (void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
+#endif
+		cu->cu_closeit = TRUE;
+	} else {
+		cu->cu_closeit = FALSE;
+	}
+	cu->cu_sock = *sockp;
+	cl->cl_auth = authnone_create();
+	return (cl);
+fooy:
+	if (cu)
+		mem_free((void *)cu, sizeof(struct cu_data) + sendsz + recvsz);
+	if (cl)
+		mem_free((void *)cl, sizeof(CLIENT));
+	return ((CLIENT *)NULL);
+}
+
+CLIENT *
+clntudp_create(
+	struct sockaddr_in *raddr,
+	uint32_t program,
+	uint32_t version,
+	struct timeval wait,
+	int *sockp)
+{
+
+	return(clntudp_bufcreate(raddr, program, version, wait, sockp,
+	    UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum clnt_stat 
+clntudp_call(
+	CLIENT	*cl,
+	uint32_t	proc,
+	xdrproc_t	xargs,
+	void *		argsp,
+	xdrproc_t	xresults,
+	void *		resultsp,
+	struct timeval	utimeout)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	XDR *xdrs;
+	int outlen;
+	int inlen;
+#if defined(AIX)
+	size_t fromlen;
+#else
+	int fromlen;
+#endif
+#ifdef FD_SETSIZE
+	fd_set readfds;
+	fd_set mask;
+#else
+	int readfds;
+	int mask;
+#endif /* def FD_SETSIZE */
+	struct sockaddr_in from;
+	struct rpc_msg reply_msg;
+	XDR reply_xdrs;
+	struct timeval time_waited;
+	bool_t ok;
+	int nrefreshes = 2;	/* number of times to refresh cred */
+	struct timeval timeout;
+
+	if (cu->cu_total.tv_usec == -1) {
+		timeout = utimeout;     /* use supplied timeout */
+	} else {
+		timeout = cu->cu_total; /* use default timeout */
+	}
+
+	time_waited.tv_sec = 0;
+	time_waited.tv_usec = 0;
+call_again:
+	xdrs = &(cu->cu_outxdrs);
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, cu->cu_xdrpos);
+	/*
+	 * the transaction is the first thing in the out buffer
+	 */
+	(*(uint32_t *)(cu->cu_outbuf))++;
+	if ((! XDR_PUTLONG(xdrs, (int32_t *)&proc)) ||
+	    (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+	    (! (*xargs)(xdrs, argsp)))
+		return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+	outlen = (int)XDR_GETPOS(xdrs);
+
+send_again:
+	if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
+	    (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
+	    != outlen) {
+		cu->cu_error.re_errno = errno;
+		return (cu->cu_error.re_status = RPC_CANTSEND);
+	}
+
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+		return (cu->cu_error.re_status = RPC_TIMEDOUT);
+	}
+	/*
+	 * sub-optimal code appears here because we have
+	 * some clock time to spare while the packets are in flight.
+	 * (We assume that this is actually only executed once.)
+	 */
+	reply_msg.acpted_rply.ar_verf = _null_auth;
+	reply_msg.acpted_rply.ar_results.where = resultsp;
+	reply_msg.acpted_rply.ar_results.proc = xresults;
+#ifdef FD_SETSIZE
+	FD_ZERO(&mask);
+	FD_SET(cu->cu_sock, &mask);
+#else
+	mask = 1 << cu->cu_sock;
+#endif /* def FD_SETSIZE */
+	for (;;) {
+		readfds = mask;
+		switch (select(_rpc_dtablesize(), &readfds, NULL, 
+			       NULL, &(cu->cu_wait))) {
+
+		case 0:
+			time_waited.tv_sec += cu->cu_wait.tv_sec;
+			time_waited.tv_usec += cu->cu_wait.tv_usec;
+			while (time_waited.tv_usec >= 1000000) {
+				time_waited.tv_sec++;
+				time_waited.tv_usec -= 1000000;
+			}
+			if ((time_waited.tv_sec < timeout.tv_sec) ||
+				((time_waited.tv_sec == timeout.tv_sec) &&
+				(time_waited.tv_usec < timeout.tv_usec)))
+				goto send_again;	
+			return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+		/*
+		 * buggy in other cases because time_waited is not being
+		 * updated.
+		 */
+		case -1:
+			if (errno == EINTR)
+				continue;	
+			cu->cu_error.re_errno = errno;
+			return (cu->cu_error.re_status = RPC_CANTRECV);
+		}
+		do {
+			fromlen = sizeof(struct sockaddr);
+			inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, 
+				(int) cu->cu_recvsz, 0,
+				(struct sockaddr *)&from, &fromlen);
+		} while (inlen < 0 && errno == EINTR);
+		if (inlen < 0) {
+			if (errno == EWOULDBLOCK)
+				continue;	
+			cu->cu_error.re_errno = errno;
+			return (cu->cu_error.re_status = RPC_CANTRECV);
+		}
+		if (inlen < sizeof(uint32_t))
+			continue;	
+		/* see if reply transaction id matches sent id */
+		if (*((uint32_t *)(cu->cu_inbuf)) != *((uint32_t *)(cu->cu_outbuf)))
+			continue;	
+		/* we now assume we have the proper reply */
+		break;
+	}
+
+	/*
+	 * now decode and validate the response
+	 */
+	xdrmem_create(&reply_xdrs, cu->cu_inbuf, (uint_t)inlen, XDR_DECODE);
+	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+	/* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
+	if (ok) {
+		_seterr_reply(&reply_msg, &(cu->cu_error));
+		if (cu->cu_error.re_status == RPC_SUCCESS) {
+			if (! AUTH_VALIDATE(cl->cl_auth,
+				&reply_msg.acpted_rply.ar_verf)) {
+				cu->cu_error.re_status = RPC_AUTHERROR;
+				cu->cu_error.re_why = AUTH_INVALIDRESP;
+			}
+			if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+				xdrs->x_op = XDR_FREE;
+				(void)xdr_opaque_auth(xdrs,
+				    &(reply_msg.acpted_rply.ar_verf));
+			} 
+		}  /* end successful completion */
+		else {
+			/* maybe our credentials need to be refreshed ... */
+			if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
+				nrefreshes--;
+				goto call_again;
+			}
+		}  /* end of unsuccessful completion */
+	}  /* end of valid reply message */
+	else {
+		cu->cu_error.re_status = RPC_CANTDECODERES;
+	}
+	return (cu->cu_error.re_status);
+}
+
+static void
+clntudp_geterr(
+	CLIENT *cl,
+	struct rpc_err *errp)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	*errp = cu->cu_error;
+}
+
+
+static bool_t
+clntudp_freeres(
+	CLIENT *cl,
+	xdrproc_t xdr_res,
+	void * res_ptr)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	XDR *xdrs = &(cu->cu_outxdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/* ARGSUSED */
+static void 
+clntudp_abort(
+	CLIENT *h)
+{
+}
+
+static bool_t
+clntudp_control(
+	CLIENT *cl,
+	uint_t request,
+	void *info)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	switch (request) {
+	case CLSET_TIMEOUT:
+		cu->cu_total = *(struct timeval *)info;
+		break;
+	case CLGET_TIMEOUT:
+		*(struct timeval *)info = cu->cu_total;
+		break;
+	case CLSET_RETRY_TIMEOUT:
+		cu->cu_wait = *(struct timeval *)info;
+		break;
+	case CLGET_RETRY_TIMEOUT:
+		*(struct timeval *)info = cu->cu_wait;
+		break;
+	case CLGET_SERVER_ADDR:
+		*(struct sockaddr_in *)info = cu->cu_raddr;
+		break;
+	default:
+		return (FALSE);
+	}
+	return (TRUE);
+}
+	
+static void
+clntudp_destroy(
+	CLIENT *cl)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	if (cu->cu_closeit) {
+		(void)close(cu->cu_sock);
+	}
+	XDR_DESTROY(&(cu->cu_outxdrs));
+	mem_free((void *)cu, (sizeof(struct cu_data) + cu->cu_sendsz + cu->cu_recvsz));
+	mem_free((void *)cl, sizeof(CLIENT));
+}
+
+/* ARGSUSED */
+static bool_t
+clntudp_getreply(
+	CLIENT *cl,
+	xdrproc_t xproc,
+	void *xres,
+	int cnt,
+	uint32_t *xids,
+	uint32_t *xid,
+	struct timeval *tv)
+{
+	return (FALSE);
+}
+
+/* ARGSUSED */
+static int
+clntudp_poll(
+	CLIENT *cl,
+	uint32_t usec)
+{
+	return (-1);
+}
diff --git a/TBBT/trace_play/rpc/get_myaddress.c b/TBBT/trace_play/rpc/get_myaddress.c
new file mode 100755
index 0000000..37bb930
--- /dev/null
+++ b/TBBT/trace_play/rpc/get_myaddress.c
@@ -0,0 +1,169 @@
+#ifndef lint
+static char sfs_get_myaddress_id[] = "@(#)get_myaddress.c     2.1     97/10/23";
+#endif
+/* @(#)get_myaddress.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * get_myaddress.c
+ *
+ * Get client's IP address via ioctl.  This avoids using the yellowpages.
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> 
+#ifndef FreeBSD
+#include <stropts.h>	
+#endif /* ndef FreeBSD */
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/pmap_prot.h"
+#include "rpc/osdep.h"
+#include <sys/utsname.h>
+
+#ifdef FreeBSD
+#include <netdb.h>	
+#define MY_NAMELEN 256
+static char myhostname[MY_NAMELEN];
+#endif /* def FreeBSD */
+
+void
+get_myaddress(
+	struct sockaddr_in *addr)
+{
+	int s;
+	char buf[BUFSIZ];
+	struct ifconf ifc;
+	struct ifreq ifreq, *ifr;
+	int len; 	
+	struct sockaddr_in tmp_addr;
+#ifdef _AIX
+	char	*cp, *cplim;
+#endif
+
+#ifdef FreeBSD
+        static struct in_addr *my_addr;
+        struct hostent *ent;     
+
+	/* In FreeBSD, SIOCGIFCONF provides AF_LINK information, not AF_INET. */
+        gethostname(myhostname, MY_NAMELEN);
+        ent = gethostbyname(myhostname);
+        if (ent == NULL) {
+            fprintf(stderr, "lookup on server's name failed\n");
+            exit(1);
+        }
+        bzero(addr, sizeof(struct sockaddr_in));
+        my_addr = (struct in_addr *)(*(ent->h_addr_list));
+        bcopy(my_addr, &(addr->sin_addr.s_addr), sizeof(struct in_addr));
+        addr->sin_family = AF_INET;
+        addr->sin_port = htons(PMAPPORT);
+        return;                
+#endif /* def FreeBSD */
+
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	    perror("get_myaddress: socket");
+	    exit(1);
+	}
+	ifc.ifc_len = sizeof (buf);
+	ifc.ifc_buf = buf;
+	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+		perror("get_myaddress: ioctl (get interface configuration)");
+		exit(1);
+	}
+	ifr = ifc.ifc_req;
+#ifdef _AIX
+	cplim = buf + ifc.ifc_len;
+	for (cp = buf; cp < cplim;
+	     cp += MAX(sizeof(struct ifreq),
+		       (sizeof (ifr->ifr_name) +
+			MAX((ifr->ifr_addr).sa_len, sizeof(ifr->ifr_addr))))) {
+  		ifr = (struct ifreq *)cp;
+#else
+	for (len = ifc.ifc_len; len; len -= sizeof(ifreq), ifr++) {
+#endif
+		ifreq = *ifr;
+                /* Save address, since SIOCGIFFLAGS may scribble over *ifr. */
+                tmp_addr = *((struct sockaddr_in *)&ifr->ifr_addr);
+		if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+			perror("get_myaddress: ioctl");
+			exit(1);
+		}
+		if ((ifreq.ifr_flags & IFF_UP) &&
+		    ifr->ifr_addr.sa_family == AF_INET) {
+			*addr = tmp_addr;
+			addr->sin_port = htons(PMAPPORT);
+			break;
+		}
+	}
+	(void) close(s);
+}
+
+/*
+ * A generic gethostname
+ */
+int
+getmyhostname(char *name, int namelen)
+{
+#if !defined(HAS_GETHOSTNAME)
+        struct utsname utsname;
+	int ret;
+
+        ret = uname(&utsname);
+	if (ret == -1)
+		return (-1);
+        (void) strncpy(name, utsname.nodename, namelen);
+	return (0);
+#else
+	return(gethostname(name, namelen));
+#endif
+}
diff --git a/TBBT/trace_play/rpc/getrpcent.c b/TBBT/trace_play/rpc/getrpcent.c
new file mode 100755
index 0000000..2649af6
--- /dev/null
+++ b/TBBT/trace_play/rpc/getrpcent.c
@@ -0,0 +1,250 @@
+#ifndef lint
+static char sfs_getrpcent_id[] = "@(#)getrpcent.c     2.1     97/10/23";
+#endif
+/* @(#)getrpcent.c	2.2 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static  char sccsid[] = "@(#)getrpcent.c 1.9 87/08/11  Copyr 1984 Sun Micro";
+#endif
+/*
+ *  Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "rpc/rpc.h"
+#include "rpc/netdb.h"
+#include "rpc/osdep.h"
+
+/*
+ * Internet version.
+ */
+struct rpcdata {
+	FILE	*rpcf;
+	char	*current;
+	int	currentlen;
+	int	stayopen;
+#define	MAXALIASES	35
+	char	*rpc_aliases[MAXALIASES];
+	struct	rpcent rpc;
+	char	line[BUFSIZ+1];
+	char	*domain;
+} *rpcdata;
+
+extern void setrpcent(int);
+extern void endrpcent(void);
+static struct rpcent *interpret(char *, int);
+
+static char RPCDB[] = "/etc/rpc";
+
+static struct rpcdata *
+_rpcdata(void)
+{
+	register struct rpcdata *d = rpcdata;
+
+	if (d == 0) {
+		d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
+		rpcdata = d;
+	}
+	return (d);
+}
+
+struct rpcent *
+getrpcbynumber(
+	int number)
+{
+	register struct rpcdata *d = _rpcdata();
+	register struct rpcent *p;
+
+	if (d == 0)
+		return (0);
+	setrpcent(0);
+	while ((p = getrpcent()) != NULL) {
+		if (p->r_number == number)
+			break;
+	}
+	endrpcent();
+	return (p);
+}
+
+struct rpcent *
+getrpcbyname(
+	char *name)
+{
+	struct rpcent *rpc;
+	char **rp;
+
+	setrpcent(0);
+	while((rpc = getrpcent()) != NULL) {
+		if (strcmp(rpc->r_name, name) == 0)
+			return (rpc);
+		for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+			if (strcmp(*rp, name) == 0)
+				return (rpc);
+		}
+	}
+	endrpcent();
+	return (NULL);
+}
+
+void
+setrpcent(
+	int f)
+{
+	register struct rpcdata *d = _rpcdata();
+
+	if (d == 0)
+		return;
+	if (d->rpcf == NULL)
+		d->rpcf = fopen(RPCDB, "r");
+	else
+		rewind(d->rpcf);
+	if (d->current)
+		free(d->current);
+	d->current = NULL;
+	d->stayopen |= f;
+}
+
+void
+endrpcent(void)
+{
+	register struct rpcdata *d = _rpcdata();
+
+	if (d == 0)
+		return;
+	if (d->current && !d->stayopen) {
+		free(d->current);
+		d->current = NULL;
+	}
+	if (d->rpcf && !d->stayopen) {
+		fclose(d->rpcf);
+		d->rpcf = NULL;
+	}
+}
+
+struct rpcent *
+getrpcent(void)
+{
+	register struct rpcdata *d = _rpcdata();
+
+	if (d == 0)
+		return(NULL);
+	if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
+		return (NULL);
+	if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
+		return (NULL);
+	return (interpret(d->line, strlen(d->line)));
+}
+
+static struct rpcent *
+interpret(
+	char *val,
+	int len)
+{
+	register struct rpcdata *d = _rpcdata();
+	char *p;
+	register char *cp, **q;
+
+	if (d == 0)
+		return (NULL);
+	strncpy(d->line, val, len);
+	p = d->line;
+	d->line[len] = '\n';
+	if (*p == '#')
+		return (getrpcent());
+	cp = strchr(p, '#');
+	if (cp == NULL) {
+		cp = strchr(p, '\n');
+		if (cp == NULL)
+			return (getrpcent());
+	}
+	*cp = '\0';
+	cp = strchr(p, ' ');
+	if (cp == NULL) {
+		cp = strchr(p, '\t');
+		if (cp == NULL)
+			return (getrpcent());
+	}
+	*cp++ = '\0';
+	/* THIS STUFF IS INTERNET SPECIFIC */
+	d->rpc.r_name = d->line;
+	while (*cp == ' ' || *cp == '\t')
+		cp++;
+	d->rpc.r_number = atoi(cp);
+	q = d->rpc.r_aliases = d->rpc_aliases;
+	cp = strchr(p, ' ');
+	if (cp != NULL)
+		*cp++ = '\0';
+	else {
+		cp = strchr(p, '\t');
+		if (cp != NULL)
+			*cp++ = '\0';
+	}
+	while (cp && *cp) {
+		if (*cp == ' ' || *cp == '\t') {
+			cp++;
+			continue;
+		}
+		if (q < &(d->rpc_aliases[MAXALIASES - 1]))
+			*q++ = cp;
+		cp = strchr(p, ' ');
+		if (cp != NULL)
+			*cp++ = '\0';
+		else {
+			cp = strchr(p, '\t');
+			if (cp != NULL)
+				*cp++ = '\0';
+		}
+	}
+	*q = NULL;
+	return (&d->rpc);
+}
diff --git a/TBBT/trace_play/rpc/getrpcport.c b/TBBT/trace_play/rpc/getrpcport.c
new file mode 100755
index 0000000..6434082
--- /dev/null
+++ b/TBBT/trace_play/rpc/getrpcport.c
@@ -0,0 +1,77 @@
+#ifndef lint
+static char sfs_getrpcport_id[] = "@(#)getrpcport.c     2.1     97/10/23";
+#endif
+/* @(#)getrpcport.c	2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static  char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+#endif
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "rpc/rpc.h"
+#include <netdb.h>
+#include "rpc/osdep.h"
+
+getrpcport(host, prognum, versnum, proto)
+	char *host;
+{
+	struct sockaddr_in addr;
+	struct hostent *hp;
+
+	if ((hp = gethostbyname(host)) == NULL)
+		return (0);
+	memmove((char *) &addr.sin_addr, hp->h_addr, hp->h_length);
+	addr.sin_family = AF_INET;
+	addr.sin_port =  0;
+	return (pmap_getport(&addr, prognum, versnum, proto));
+}
diff --git a/TBBT/trace_play/rpc/netdb.h b/TBBT/trace_play/rpc/netdb.h
new file mode 100755
index 0000000..a3a96fc
--- /dev/null
+++ b/TBBT/trace_play/rpc/netdb.h
@@ -0,0 +1,63 @@
+/*
+ * @(#)netdb.h     2.1     97/10/23
+ */
+/* @(#)netdb.h	2.1 88/07/29 3.9 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*	@(#)rpc.h 1.8 87/07/24 SMI	*/
+
+/* Really belongs in <netdb.h> */
+
+struct rpcent {
+      char    *r_name;        /* name of server for this rpc program */
+      char    **r_aliases;    /* alias list */
+      int     r_number;       /* rpc program number */
+};
+
+extern struct rpcent *getrpcbynumber(int);
+extern struct rpcent *getrpcbyname(char *);
+extern struct rpcent *getrpcent(void);
diff --git a/TBBT/trace_play/rpc/osdep.h b/TBBT/trace_play/rpc/osdep.h
new file mode 100755
index 0000000..67598d0
--- /dev/null
+++ b/TBBT/trace_play/rpc/osdep.h
@@ -0,0 +1,218 @@
+/*
+ * @(#)osdep.h     2.1     97/10/23
+ */
+/*      @(#)types.h 1.18 87/07/24 SMI      */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+#ifndef __RPC_OSDEP_H__
+#define __RPC_OSDEP_H__
+
+/*
+ * OS dependancies
+ *
+ * These are non-XPG4.2 standard include files, if not compiling in a
+ * strict environment simply #include them, otherwise we must define
+ * our own missing pieces.  The definitions below are specific to
+ * Solaris 2.X and may be different on other systems.
+ */
+
+#if !defined(_XOPEN_SOURCE) || defined (OSF1) || defined(AIX)
+#if defined(SVR4)
+#define BSD_COMP
+#endif
+#if defined(AIX)
+#include <sys/param.h>
+#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#else
+#if defined(_BIG_ENDIAN) && !defined(ntohl) && !defined(lint)
+/* big-endian */
+#define ntohl(x)        (x)
+#define ntohs(x)        (x)
+#define htonl(x)        (x)
+#define htons(x)        (x)
+ 
+#elif !defined(ntohl) /* little-endian */
+ 
+extern unsigned short ntohs(unsigned short ns);
+extern unsigned short htons(unsigned short hs);
+extern unsigned long  ntohl(unsigned long nl);
+extern unsigned long  htonl(unsigned long hl);
+ 
+#endif
+/*
+ * Internet address
+ *	This definition contains obsolete fields for compatibility
+ *	with SunOS 3.x and 4.2bsd.  The presence of subnets renders
+ *	divisions into fixed fields misleading at best.  New code
+ *	should use only the s_addr field.
+ */
+struct in_addr {
+	union {
+		struct { unsigned char s_b1, s_b2, s_b3, s_b4; } S_un_b;
+		struct { unsigned short s_w1, s_w2; } S_un_w;
+		unsigned long S_addr;
+	} S_un;
+#define s_addr  S_un.S_addr             /* should be used for all code */
+#define s_host  S_un.S_un_b.s_b2        /* OBSOLETE: host on imp */
+#define s_net   S_un.S_un_b.s_b1        /* OBSOLETE: network */
+#define s_imp   S_un.S_un_w.s_w2        /* OBSOLETE: imp */
+#define s_impno S_un.S_un_b.s_b4        /* OBSOLETE: imp # */
+#define s_lh    S_un.S_un_b.s_b3        /* OBSOLETE: logical host */
+};
+
+struct sockaddr_in {
+        short   sin_family;
+        unsigned short sin_port;
+        struct  in_addr sin_addr;
+        char    sin_zero[8];
+};
+
+/*
+ * Structure used by kernel to store most
+ * addresses.
+ */
+struct sockaddr {
+	uint16_t sa_family;		/* address family */
+	char	sa_data[14];		/* up to 14 bytes of direct address */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's.  All interface ioctl's must have parameter
+ * definitions which begin with ifr_name.  The
+ * remainder may be interface specific.
+ */
+struct	ifreq {
+#define	IFNAMSIZ	16
+	char	ifr_name[IFNAMSIZ];             /* if name, e.g. "en0" */
+	union {
+		struct	sockaddr ifru_addr;
+		struct	sockaddr ifru_dstaddr;
+		char	ifru_oname[IFNAMSIZ];	/* other if name */
+		struct	sockaddr ifru_broadaddr;
+		short	ifru_flags;
+		int	ifru_metric;
+		char	ifru_data[1];		/* interface dependent data */
+		char	ifru_enaddr[6];
+		int	if_muxid[2];		/* mux id's for arp and ip */
+
+		/* Struct for FDDI ioctl's */
+		struct ifr_dnld_reqs {
+			void	*v_addr;
+			void	*m_addr;
+			void	*ex_addr;
+			uint_t	size;
+		} ifru_dnld_req;
+
+		/* Struct for FDDI stats */
+		struct ifr_fddi_stats {
+			uint_t	stat_size;
+			void	*fddi_stats;
+		} ifru_fddi_stat;
+
+		struct ifr_netmapents {
+			uint_t	map_ent_size,	/* size of netmap structure */
+				entry_number;	/* index into netmap list */
+			void	*fddi_map_ent;	/* pointer to user structure */
+		} ifru_netmapent;
+
+		/* Field for generic ioctl for fddi */
+
+		struct ifr_fddi_gen_struct {
+			int	ifru_fddi_gioctl; /* field for gen ioctl */
+			void	*ifru_fddi_gaddr; /* Generic ptr to a field */
+		} ifru_fddi_gstruct;
+
+	} ifr_ifru;
+
+#define	ifr_addr	ifr_ifru.ifru_addr	/* address */
+#define	ifr_dstaddr	ifr_ifru.ifru_dstaddr	/* other end of p-to-p link */
+#define	ifr_oname	ifr_ifru.ifru_oname	/* other if name */
+#define	ifr_broadaddr	ifr_ifru.ifru_broadaddr /* broadcast address */
+#define	ifr_flags	ifr_ifru.ifru_flags	/* flags */
+#define	ifr_metric	ifr_ifru.ifru_metric	/* metric */
+#define	ifr_data	ifr_ifru.ifru_data	/* for use by interface */
+#define	ifr_enaddr	ifr_ifru.ifru_enaddr	/* ethernet address */
+
+/* FDDI specific */
+#define	ifr_dnld_req	ifr_ifru.ifru_dnld_req
+#define	ifr_fddi_stat	ifr_ifru.ifru_fddi_stat
+#define	ifr_fddi_netmap	ifr_ifru.ifru_netmapent /* FDDI network map entries */
+#define	ifr_fddi_gstruct ifr_ifru.ifru_fddi_gstruct
+
+#define	ifr_ip_muxid	ifr_ifru.if_muxid[0]
+#define	ifr_arp_muxid	ifr_ifru.if_muxid[1]
+};
+
+struct	ifconf {
+	int	ifc_len;		/* size of associated buffer */
+	union {
+		void	*ifcu_buf;
+		struct	ifreq *ifcu_req;
+	} ifc_ifcu;
+#define	ifc_buf ifc_ifcu.ifcu_buf	/* buffer address */
+#define	ifc_req ifc_ifcu.ifcu_req	/* array of structures returned */
+};
+
+#define	AF_INET			2
+#define	IPPROTO_TCP		6
+#define	IPPROTO_UDP		17
+#define	IPPORT_RESERVED		1024
+#define	SOCK_DGRAM		1
+#define	SOCK_STREAM		2
+#define	SO_SNDBUF		0x1001
+#define	SO_RCVBUF		0x1002
+#define	SOL_SOCKET		0xffff
+#define	INADDR_ANY		(uint32_t)0x00000000
+#define	IFF_BROADCAST		0x2
+#define	IFF_UP			0x1
+
+#define	IOCPARM_MASK	0xff
+#define	IOC_OUT		0x40000000
+#define	IOC_IN		0x80000000
+#define	IOC_INOUT	(IOC_IN|IOC_OUT)
+#define	_IOWR(x, y, t) \
+	(IOC_INOUT|((((int)sizeof (t))&IOCPARM_MASK)<<16)|(x<<8)|y)
+#define	SIOCGIFCONF		_IOWR('i', 20, struct ifconf)
+#define	SIOCGIFFLAGS	_IOWR('i', 17, struct ifreq)
+#define	SIOCGIFBRDADDR	_IOWR('i', 23, struct ifreq)
+
+extern int accept(int, struct sockaddr *, int *);
+extern int bind(int, struct sockaddr *, int);
+extern int connect(int, struct sockaddr *, int);
+extern int getsockname(int, struct sockaddr *, int *);
+extern int getsockopt(int, int, int, char *, int *);
+extern int listen(int, int);
+extern int recvfrom(int, char *, int, int, struct sockaddr *, int *);
+extern int sendto(int, const char *, int, int, const struct sockaddr *, int);
+extern int setsockopt(int, int, int, const char *, int);
+extern int socket(int, int, int);
+extern unsigned long inet_netof(struct in_addr);
+extern struct in_addr inet_makeaddr(int, int);
+
+#endif /* _XOPEN_SOURCE */
+
+#endif /* __RPC_OSDEP_H__ */
diff --git a/TBBT/trace_play/rpc/pmap_clnt.c b/TBBT/trace_play/rpc/pmap_clnt.c
new file mode 100755
index 0000000..b2de53f
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_clnt.c
@@ -0,0 +1,138 @@
+#ifndef lint
+static char sfs_pmap_clnt_id[] = "@(#)pmap_clnt.c     2.1     97/10/23";
+#endif
+/* @(#)pmap_clnt.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_clnt.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "rpc/rpc.h"
+#include "rpc/pmap_prot.h"
+#include "rpc/pmap_clnt.h"
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+extern void get_myaddress(struct sockaddr_in *addr);
+
+/*
+ * Set a mapping between program,version and port.
+ * Calls the pmap service remotely to do the mapping.
+ */
+bool_t
+pmap_set(
+	uint32_t program,
+	uint32_t version,
+	int protocol,
+	uint16_t port)
+{
+	struct sockaddr_in myaddress;
+	int socket = -1;
+	register CLIENT *client;
+	struct pmap parms;
+	bool_t rslt;
+
+	get_myaddress(&myaddress);
+	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (client == (CLIENT *)NULL)
+		return (FALSE);
+	parms.pm_prog = program;
+	parms.pm_vers = version;
+	parms.pm_prot = protocol;
+	parms.pm_port = port;
+	if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
+	    tottimeout) != RPC_SUCCESS) {
+		clnt_perror(client, "Cannot register service");
+		return (FALSE);
+	}
+	CLNT_DESTROY(client);
+	(void)close(socket);
+	return (rslt);
+}
+
+/*
+ * Remove the mapping between program,version and port.
+ * Calls the pmap service remotely to do the un-mapping.
+ */
+bool_t
+pmap_unset(
+	uint32_t program,
+	uint32_t version)
+{
+	struct sockaddr_in myaddress;
+	int socket = -1;
+	register CLIENT *client;
+	struct pmap parms;
+	bool_t rslt;
+
+	get_myaddress(&myaddress);
+	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (client == (CLIENT *)NULL)
+		return (FALSE);
+	parms.pm_prog = program;
+	parms.pm_vers = version;
+	parms.pm_port = parms.pm_prot = 0;
+	CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
+	    tottimeout);
+	CLNT_DESTROY(client);
+	(void)close(socket);
+	return (rslt);
+}
diff --git a/TBBT/trace_play/rpc/pmap_clnt.h b/TBBT/trace_play/rpc/pmap_clnt.h
new file mode 100755
index 0000000..9d7b74e
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_clnt.h
@@ -0,0 +1,97 @@
+/*
+ * @(#)pmap_clnt.h     2.1     97/10/23
+ */
+/* @(#)pmap_clnt.h	2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * pmap_clnt.h
+ * Supplies C routines to get to portmap services.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+#ifndef _SRPC_PMAP_CLNT_H
+#define _SRPC_PMAP_CLNT_H
+
+
+/*
+ * Usage:
+ *	success = pmap_set(program, version, protocol, port);
+ *	success = pmap_unset(program, version);
+ *	port = pmap_getport(address, program, version, protocol);
+ *	head = pmap_getmaps(address);
+ *	clnt_stat = pmap_rmtcall(address, program, version, procedure,
+ *		xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ *		(works for udp only.) 
+ * 	clnt_stat = clnt_broadcast(program, version, procedure,
+ *		xdrargs, argsp,	xdrres, resp, eachresult)
+ *		(like pmap_rmtcall, except the call is broadcasted to all
+ *		locally connected nets.  For each valid response received,
+ *		the procedure eachresult is called.  Its form is:
+ *	done = eachresult(resp, raddr)
+ *		bool_t done;
+ *		void * resp;
+ *		struct sockaddr_in raddr;
+ *		where resp points to the results of the call and raddr is the
+ *		address if the responder to the broadcast.
+ */
+
+typedef bool_t (*resultproc_t)();
+extern bool_t		pmap_set(uint32_t, uint32_t, int, uint16_t);
+extern bool_t		pmap_unset(uint32_t, uint32_t);
+extern struct pmaplist	*pmap_getmaps(struct sockaddr_in *);
+extern enum clnt_stat	pmap_rmtcall(struct sockaddr_in *, uint32_t, uint32_t,
+					uint32_t, xdrproc_t, void *,
+					xdrproc_t, void *,
+					struct timeval, uint32_t *);
+extern enum clnt_stat	clnt_broadcast(uint32_t, uint32_t, uint32_t, xdrproc_t,
+				        void *, xdrproc_t,
+					void *, resultproc_t);
+extern uint16_t		pmap_getport(struct sockaddr_in *, uint32_t, uint32_t,
+								uint_t);
+#endif /* _SRPC_PMAP_CLNT_H */
diff --git a/TBBT/trace_play/rpc/pmap_getmaps.c b/TBBT/trace_play/rpc/pmap_getmaps.c
new file mode 100755
index 0000000..ab1ce75
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_getmaps.c
@@ -0,0 +1,105 @@
+#ifndef lint
+static char sfs_pmap_getmaps_id[] = "@(#)pmap_getmaps.c     2.1     97/10/23";
+#endif
+/* @(#)pmap_getmaps.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_getmap.c
+ * Client interface to pmap rpc service.
+ * contains pmap_getmaps, which is only tcp service involved
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include "rpc/rpc.h"
+#include "rpc/pmap_prot.h"
+#include "rpc/pmap_clnt.h"
+#include "rpc/osdep.h"
+#include <netdb.h>
+
+#define NAMELEN 255
+#define MAX_BROADCAST_SIZE 1400
+
+
+/*
+ * Get a copy of the current port maps.
+ * Calls the pmap service remotely to do get the maps.
+ */
+struct pmaplist *
+pmap_getmaps(
+	 struct sockaddr_in *address)
+{
+	struct pmaplist *head = (struct pmaplist *)NULL;
+	int socket = -1;
+	struct timeval minutetimeout;
+	register CLIENT *client;
+
+	minutetimeout.tv_sec = 60;
+	minutetimeout.tv_usec = 0;
+	address->sin_port = htons(PMAPPORT);
+	client = clnttcp_create(address, PMAPPROG,
+	    PMAPVERS, &socket, 50, 500);
+	if (client != (CLIENT *)NULL) {
+		if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
+		    &head, minutetimeout) != RPC_SUCCESS) {
+			clnt_perror(client, "pmap_getmaps rpc problem");
+		}
+		CLNT_DESTROY(client);
+	}
+	(void)close(socket);
+	address->sin_port = 0;
+	return (head);
+}
diff --git a/TBBT/trace_play/rpc/pmap_getport.c b/TBBT/trace_play/rpc/pmap_getport.c
new file mode 100755
index 0000000..2457475
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_getport.c
@@ -0,0 +1,110 @@
+#ifndef lint
+static char sfs_clnt_id[] = "@(#)pmap_getport.c     2.1     97/10/23";
+#endif
+/* @(#)pmap_getport.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "rpc/rpc.h"
+#include "rpc/pmap_prot.h"
+#include "rpc/pmap_clnt.h"
+#include "rpc/osdep.h"
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+uint16_t
+pmap_getport(
+	struct sockaddr_in *address,
+	uint32_t program,
+	uint32_t version,
+	uint_t protocol)
+{
+	uint16_t port = 0;
+	int socket = -1;
+	register CLIENT *client;
+	struct pmap parms;
+
+	address->sin_port = htons(PMAPPORT);
+	client = clntudp_bufcreate(address, PMAPPROG,
+	    PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (client != (CLIENT *)NULL) {
+		parms.pm_prog = program;
+		parms.pm_vers = version;
+		parms.pm_prot = protocol;
+		parms.pm_port = 0;  /* not needed or used */
+		if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms,
+		    xdr_uint16_t, &port, tottimeout) != RPC_SUCCESS){
+			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+		} else if (port == 0) {
+			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+		}
+		CLNT_DESTROY(client);
+	}
+	(void)close(socket);
+	address->sin_port = 0;
+	return (port);
+}
diff --git a/TBBT/trace_play/rpc/pmap_prot.c b/TBBT/trace_play/rpc/pmap_prot.c
new file mode 100755
index 0000000..242e846
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_prot.c
@@ -0,0 +1,78 @@
+#ifndef lint
+static char sfs_clnt_id[] = "@(#)pmap_prot.c     2.1     97/10/23";
+#endif
+/* @(#)pmap_prot.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_prot.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+#include "rpc/pmap_prot.h"
+
+
+bool_t
+xdr_pmap(
+	XDR *xdrs,
+	struct pmap *regs)
+{
+
+	if (xdr_uint32_t(xdrs, &regs->pm_prog) && 
+		xdr_uint32_t(xdrs, &regs->pm_vers) && 
+		xdr_uint32_t(xdrs, &regs->pm_prot))
+		return (xdr_uint32_t(xdrs, &regs->pm_port));
+	return (FALSE);
+}
diff --git a/TBBT/trace_play/rpc/pmap_prot.h b/TBBT/trace_play/rpc/pmap_prot.h
new file mode 100755
index 0000000..adbd407
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_prot.h
@@ -0,0 +1,114 @@
+/*
+ * @(#)pmap_prot.h     2.1     97/10/23
+ */
+/* @(#)pmap_prot.h	2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*
+ * pmap_prot.h
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The following procedures are supported by the protocol:
+ *
+ * PMAPPROC_NULL() returns ()
+ * 	takes nothing, returns nothing
+ *
+ * PMAPPROC_SET(struct pmap) returns (bool_t)
+ * 	TRUE is success, FALSE is failure.  Registers the tuple
+ *	[prog, vers, prot, port].
+ *
+ * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+ *	TRUE is success, FALSE is failure.  Un-registers pair
+ *	[prog, vers].  prot and port are ignored.
+ *
+ * PMAPPROC_GETPORT(struct pmap) returns (int32_t unsigned).
+ *	0 is failure.  Otherwise returns the port number where the pair
+ *	[prog, vers] is registered.  It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
+ * 	RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * 	Calls the procedure on the local machine.  If it is not registered,
+ *	this procedure is quite; ie it does not return error information!!!
+ *	This procedure only is supported on rpc/udp and calls via
+ *	rpc/udp.  This routine only passes null authentication parameters.
+ *	This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#define PMAPPORT		((uint16_t)111)
+#define PMAPPROG		((uint32_t)100000)
+#define PMAPVERS		((uint32_t)2)
+#define PMAPVERS_PROTO		((uint32_t)2)
+#define PMAPVERS_ORIG		((uint32_t)1)
+#define PMAPPROC_NULL		((uint32_t)0)
+#define PMAPPROC_SET		((uint32_t)1)
+#define PMAPPROC_UNSET		((uint32_t)2)
+#define PMAPPROC_GETPORT	((uint32_t)3)
+#define PMAPPROC_DUMP		((uint32_t)4)
+#define PMAPPROC_CALLIT		((uint32_t)5)
+
+struct pmap {
+	uint32_t pm_prog;
+	uint32_t pm_vers;
+	uint32_t pm_prot;
+	uint32_t pm_port;
+};
+
+extern bool_t xdr_pmap();
+
+struct pmaplist {
+	struct pmap	pml_map;
+	struct pmaplist *pml_next;
+};
+
+extern bool_t xdr_pmaplist();
diff --git a/TBBT/trace_play/rpc/pmap_prot2.c b/TBBT/trace_play/rpc/pmap_prot2.c
new file mode 100755
index 0000000..9cb238a
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_prot2.c
@@ -0,0 +1,138 @@
+#ifndef lint
+static char sfs_clnt_id[] = "@(#)pmap_prot2.c     2.1     97/10/23";
+#endif
+/* @(#)pmap_prot2.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+#include "rpc/pmap_prot.h"
+
+
+/* 
+ * What is going on with linked lists? (!)
+ * First recall the link list declaration from pmap_prot.h:
+ *
+ * struct pmaplist {
+ *	struct pmap pml_map;
+ *	struct pmaplist *pml_map;
+ * };
+ *
+ * Compare that declaration with a corresponding xdr declaration that 
+ * is (a) pointer-less, and (b) recursive:
+ *
+ * typedef union switch (bool_t) {
+ * 
+ *	case TRUE: struct {
+ *		struct pmap;
+ * 		pmaplist_t foo;
+ *	};
+ *
+ *	case FALSE: struct {};
+ * } pmaplist_t;
+ *
+ * Notice that the xdr declaration has no nxt pointer while
+ * the C declaration has no bool_t variable.  The bool_t can be
+ * interpreted as ``more data follows me''; if FALSE then nothing
+ * follows this bool_t; if TRUE then the bool_t is followed by
+ * an actual struct pmap, and then (recursively) by the 
+ * xdr union, pamplist_t.  
+ *
+ * This could be implemented via the xdr_union primitive, though this
+ * would cause a one recursive call per element in the list.  Rather than do
+ * that we can ``unwind'' the recursion
+ * into a while loop and do the union arms in-place.
+ *
+ * The head of the list is what the C programmer wishes to past around
+ * the net, yet is the data that the pointer points to which is interesting;
+ * this sounds like a job for xdr_reference!
+ */
+bool_t
+xdr_pmaplist(
+	XDR *xdrs,
+	struct pmaplist **rp)
+{
+	/*
+	 * more_elements is pre-computed in case the direction is
+	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
+	 * xdr_bool when the direction is XDR_DECODE.
+	 */
+	bool_t more_elements;
+	register int freeing = (xdrs->x_op == XDR_FREE);
+	register struct pmaplist **next;
+
+	/* CONSTCOND */
+	while (TRUE) {
+		more_elements = (bool_t)(*rp != NULL);
+		if (! xdr_bool(xdrs, &more_elements))
+			return (FALSE);
+		if (! more_elements)
+			return (TRUE);  /* we are done */
+		/*
+		 * the unfortunate side effect of non-recursion is that in
+		 * the case of freeing we must remember the next object
+		 * before we free the current object ...
+		 */
+		if (freeing)
+			next = &((*rp)->pml_next); 
+		if (! xdr_reference(xdrs, (void **)rp,
+		    (uint_t)sizeof(struct pmaplist), xdr_pmap))
+			return (FALSE);
+		rp = (freeing) ? next : &((*rp)->pml_next);
+	}
+}
diff --git a/TBBT/trace_play/rpc/pmap_rmt.c b/TBBT/trace_play/rpc/pmap_rmt.c
new file mode 100755
index 0000000..a834cfd
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_rmt.c
@@ -0,0 +1,419 @@
+#ifndef lint
+static char sfs_pmap_rmt_id[] = "@(#)pmap_rmt.c     2.1     97/10/23";
+#endif
+/* @(#)pmap_rmt.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifndef FreeBSD
+#include <stropts.h>
+#endif /* ndef FreeBSD */
+#include <string.h>
+#include <errno.h>
+#include "rpc/rpc.h"
+#include "rpc/pmap_prot.h"
+#include "rpc/pmap_clnt.h"
+#include "rpc/pmap_rmt.h"
+#include "rpc/osdep.h"
+
+#define MAX_BROADCAST_SIZE 1400
+
+static struct timeval timeout = { 3, 0 };
+
+
+/*
+ * pmapper remote-call-service interface.
+ * This routine is used to call the pmapper remote call service
+ * which will look up a service program in the port maps, and then
+ * remotely call that routine with the given parameters.  This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+pmap_rmtcall(
+	struct sockaddr_in *addr,
+	uint32_t prog,
+	uint32_t vers,
+	uint32_t proc,
+	xdrproc_t xdrargs,
+	void *argsp,
+	xdrproc_t xdrres,
+	void *resp,
+	struct timeval tout,
+	uint32_t *port_ptr)
+{
+	int socket = -1;
+	register CLIENT *client;
+	struct rmtcallargs a;
+	struct rmtcallres r;
+	enum clnt_stat stat;
+
+	addr->sin_port = htons(PMAPPORT);
+	client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
+	if (client != (CLIENT *)NULL) {
+		a.prog = prog;
+		a.vers = vers;
+		a.proc = proc;
+		a.args_ptr = argsp;
+		a.xdr_args = xdrargs;
+		r.port_ptr = port_ptr;
+		r.results_ptr = resp;
+		r.xdr_results = xdrres;
+		stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
+		    xdr_rmtcallres, &r, tout);
+		CLNT_DESTROY(client);
+	} else {
+		stat = RPC_FAILED;
+	}
+	(void)close(socket);
+	addr->sin_port = 0;
+	return (stat);
+}
+
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rmtcall_args(
+	XDR *xdrs,
+	struct rmtcallargs *cap)
+{
+	uint_t lenposition, argposition, position;
+
+	if (xdr_uint32_t(xdrs, &(cap->prog)) &&
+	    xdr_uint32_t(xdrs, &(cap->vers)) &&
+	    xdr_uint32_t(xdrs, &(cap->proc))) {
+		lenposition = XDR_GETPOS(xdrs);
+		if (! xdr_uint32_t(xdrs, &(cap->arglen)))
+		    return (FALSE);
+		argposition = XDR_GETPOS(xdrs);
+		if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
+		    return (FALSE);
+		position = XDR_GETPOS(xdrs);
+		cap->arglen = (uint32_t)position - (uint32_t)argposition;
+		XDR_SETPOS(xdrs, lenposition);
+		if (! xdr_uint32_t(xdrs, &(cap->arglen)))
+		    return (FALSE);
+		XDR_SETPOS(xdrs, position);
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rmtcallres(
+	XDR *xdrs,
+	struct rmtcallres *crp)
+{
+	void *port_ptr;
+
+	port_ptr = (void *)crp->port_ptr;
+	if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
+	    xdr_uint32_t) && xdr_uint32_t(xdrs, &crp->resultslen)) {
+		crp->port_ptr = (uint32_t *)port_ptr;
+		return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+	}
+	return (FALSE);
+}
+
+
+/*
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these trivial 
+ * routines which only support udp/ip .
+ */
+
+static int
+getbroadcastnets(
+	struct in_addr *addrs,
+	int sock,
+	char *buf)
+{
+	struct ifconf ifc;
+        struct ifreq ifreq, *ifr;
+	struct sockaddr_in *sin;
+        int n, i;
+
+        ifc.ifc_len = UDPMSGSIZE;
+        ifc.ifc_buf = buf;
+        if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+                perror("broadcast: ioctl (get interface configuration)");
+                return (0);
+        }
+        ifr = ifc.ifc_req;
+        for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
+                ifreq = *ifr;
+                if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+                        perror("broadcast: ioctl (get interface flags)");
+                        continue;
+                }
+                if ((ifreq.ifr_flags & IFF_BROADCAST) &&
+		    (ifreq.ifr_flags & IFF_UP) &&
+		    ifr->ifr_addr.sa_family == AF_INET) {
+			sin = (struct sockaddr_in *)&ifr->ifr_addr;
+#ifdef SIOCGIFBRDADDR   /* 4.3BSD */
+			if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+				addrs[i++] = inet_makeaddr((int)inet_netof
+			    (sin->sin_addr), INADDR_ANY);
+			} else {
+				addrs[i++] = ((struct sockaddr_in*)
+				  &ifreq.ifr_addr)->sin_addr;
+			}
+#else /* 4.2 BSD */
+			addrs[i++] = inet_makeaddr(inet_netof
+			  (sin->sin_addr.s_addr), INADDR_ANY);
+#endif
+		}
+	}
+	return (i);
+}
+
+enum clnt_stat 
+clnt_broadcast(
+	uint32_t	prog,		/* program number */
+	uint32_t	vers,		/* version number */
+	uint32_t	proc,		/* procedure number */
+	xdrproc_t	xargs,		/* xdr routine for args */
+	void *		argsp,		/* pointer to args */
+	xdrproc_t	xresults,	/* xdr routine for results */
+	void *		resultsp,	/* pointer to results */
+	resultproc_t	eachresult)	/* call with each result obtained */
+{
+	enum clnt_stat stat;
+	AUTH *unix_auth = authunix_create_default();
+	XDR xdr_stream;
+	register XDR *xdrs = &xdr_stream;
+	int outlen, inlen, nets;
+#if defined(AIX)
+	size_t fromlen;
+#else
+	int fromlen;
+#endif /* AIX */
+	register int sock;
+	int on = 1;
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+#else
+	int readfds;
+	register int mask;
+#endif /* def FD_SETSIZE */
+	register int i;
+	bool_t done = FALSE;
+	register uint32_t xid;
+	uint32_t port;
+	struct in_addr addrs[20];
+	struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
+	struct rmtcallargs a;
+	struct rmtcallres r;
+	struct rpc_msg msg;
+	struct timeval t; 
+	char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
+
+	/*
+	 * initialization: create a socket, a broadcast address, and
+	 * preserialize the arguments into a send buffer.
+	 */
+	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+		perror("Cannot create socket for broadcast rpc");
+		stat = RPC_CANTSEND;
+		goto done_broad;
+	}
+#ifdef SO_BROADCAST
+	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof (on)) < 0) {
+		perror("Cannot set socket option SO_BROADCAST");
+		stat = RPC_CANTSEND;
+		goto done_broad;
+	}
+#endif /* def SO_BROADCAST */
+#ifdef FD_SETSIZE
+	FD_ZERO(&mask);
+	FD_SET(sock, &mask);
+#else
+	mask = (1 << sock);
+#endif /* def FD_SETSIZE */
+	nets = getbroadcastnets(addrs, sock, inbuf);
+	memset((char *)&baddr, '\0', sizeof (baddr));
+	baddr.sin_family = AF_INET;
+	baddr.sin_port = htons(PMAPPORT);
+	baddr.sin_addr.s_addr = htonl(INADDR_ANY);
+/*	baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
+	(void)gettimeofday(&t, (struct timezone *)0);
+	msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
+	t.tv_usec = 0;
+	msg.rm_direction = CALL;
+	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	msg.rm_call.cb_prog = PMAPPROG;
+	msg.rm_call.cb_vers = PMAPVERS;
+	msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+	msg.rm_call.cb_cred = unix_auth->ah_cred;
+	msg.rm_call.cb_verf = unix_auth->ah_verf;
+	a.prog = prog;
+	a.vers = vers;
+	a.proc = proc;
+	a.xdr_args = xargs;
+	a.args_ptr = argsp;
+	r.port_ptr = &port;
+	r.xdr_results = xresults;
+	r.results_ptr = resultsp;
+	xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
+	if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
+		stat = RPC_CANTENCODEARGS;
+		goto done_broad;
+	}
+	outlen = (int)xdr_getpos(xdrs);
+	xdr_destroy(xdrs);
+	/*
+	 * Basic loop: broadcast a packet and wait a while for response(s).
+	 * The response timeout grows larger per iteration.
+	 */
+	for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
+		for (i = 0; i < nets; i++) {
+			baddr.sin_addr = addrs[i];
+			if (sendto(sock, outbuf, outlen, 0,
+				(struct sockaddr *)&baddr,
+				sizeof (struct sockaddr)) != outlen) {
+				perror("Cannot send broadcast packet");
+				stat = RPC_CANTSEND;
+				goto done_broad;
+			}
+		}
+		if (eachresult == NULL) {
+			stat = RPC_SUCCESS;
+			goto done_broad;
+		}
+	recv_again:
+		msg.acpted_rply.ar_verf = _null_auth;
+		msg.acpted_rply.ar_results.where = (void *)&r;
+                msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
+		readfds = mask;
+		switch (select(_rpc_dtablesize(), &readfds, NULL, 
+			       NULL, &t)) {
+
+		case 0:  /* timed out */
+			stat = RPC_TIMEDOUT;
+			continue;
+
+		case -1:  /* some kind of error */
+			if (errno == EINTR)
+				goto recv_again;
+			perror("Broadcast select problem");
+			stat = RPC_CANTRECV;
+			goto done_broad;
+
+		}  /* end of select results switch */
+	try_again:
+		fromlen = sizeof(struct sockaddr);
+		inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
+			(struct sockaddr *)&raddr, &fromlen);
+		if (inlen < 0) {
+			if (errno == EINTR)
+				goto try_again;
+			perror("Cannot receive reply to broadcast");
+			stat = RPC_CANTRECV;
+			goto done_broad;
+		}
+		if (inlen < sizeof(uint32_t))
+			goto recv_again;
+		/*
+		 * see if reply transaction id matches sent id.
+		 * If so, decode the results.
+		 */
+		xdrmem_create(xdrs, inbuf, (uint_t)inlen, XDR_DECODE);
+		if (xdr_replymsg(xdrs, &msg)) {
+			if ((msg.rm_xid == xid) &&
+				(msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+				(msg.acpted_rply.ar_stat == SUCCESS)) {
+				raddr.sin_port = htons((uint16_t)port);
+				done = (*eachresult)(resultsp, &raddr);
+			}
+			/* otherwise, we just ignore the errors ... */
+		} else {
+#ifdef notdef
+			/* some kind of deserialization problem ... */
+			if (msg.rm_xid == xid)
+				fprintf(stderr, "Broadcast deserialization problem");
+			/* otherwise, just random garbage */
+#endif
+		}
+		xdrs->x_op = XDR_FREE;
+		msg.acpted_rply.ar_results.proc = xdr_void;
+		(void)xdr_replymsg(xdrs, &msg);
+		(void)(*xresults)(xdrs, resultsp);
+		xdr_destroy(xdrs);
+		if (done) {
+			stat = RPC_SUCCESS;
+			goto done_broad;
+		} else {
+			goto recv_again;
+		}
+	}
+done_broad:
+	(void)close(sock);
+	AUTH_DESTROY(unix_auth);
+	return (stat);
+}
+
diff --git a/TBBT/trace_play/rpc/pmap_rmt.h b/TBBT/trace_play/rpc/pmap_rmt.h
new file mode 100755
index 0000000..40a770a
--- /dev/null
+++ b/TBBT/trace_play/rpc/pmap_rmt.h
@@ -0,0 +1,74 @@
+/*
+ * @(#)pmap_rmt.h     2.1     97/10/23
+ */
+/* @(#)pmap_rmt.h	2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Structures and XDR routines for parameters to and replies from
+ * the portmapper remote-call-service.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+struct rmtcallargs {
+	uint32_t prog, vers, proc, arglen;
+	void *args_ptr;
+	xdrproc_t xdr_args;
+};
+
+bool_t xdr_rmtcall_args();
+
+struct rmtcallres {
+	uint32_t *port_ptr;
+	uint32_t resultslen;
+	caddr_t results_ptr;
+	xdrproc_t xdr_results;
+};
+
+bool_t xdr_rmtcallres();
diff --git a/TBBT/trace_play/rpc/rpc.h b/TBBT/trace_play/rpc/rpc.h
new file mode 100755
index 0000000..43935d6
--- /dev/null
+++ b/TBBT/trace_play/rpc/rpc.h
@@ -0,0 +1,93 @@
+/*
+ * @(#)rpc.h     2.1     97/10/23
+ */
+
+/* @(#)rpc.h	2.4 89/07/11 4.0 RPCSRC; from 1.9 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __RPC_HEADER__
+#define __RPC_HEADER__
+
+#include "rpc/types.h"		/* some typedefs */
+
+#include "rpc/osdep.h"
+
+/* external data representation interfaces */
+#include "rpc/xdr.h"		/* generic (de)serializer */
+
+/* Client side only authentication */
+#include "rpc/auth.h"		/* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include "rpc/clnt.h"		/* generic rpc stuff */
+
+#include "rpc/pmap_clnt.h"
+
+/* semi-private protocol headers */
+#include "rpc/rpc_msg.h"	/* protocol for rpc messages */
+#include "rpc/auth_unix.h"	/* protocol for unix style cred */
+/*
+ *  Uncomment-out the next line if you are building the rpc library with    
+ *  DES Authentication (see the README file in the secure_rpc/ directory).
+ */
+#ifdef notdef
+#include "rpc/auth_des.h"	/* protocol for des style cred */
+#endif
+
+/* Server side only remote procedure callee */
+#include "rpc/svc.h"		/* service manager and multiplexer */
+#include "rpc/svc_auth.h"	/* service side authenticator */
+
+#endif /* ndef __RPC_HEADER__ */
diff --git a/TBBT/trace_play/rpc/rpc_callmsg.c b/TBBT/trace_play/rpc/rpc_callmsg.c
new file mode 100755
index 0000000..e7bfdc8
--- /dev/null
+++ b/TBBT/trace_play/rpc/rpc_callmsg.c
@@ -0,0 +1,214 @@
+#ifndef lint
+static char sfs_rpc_callmsg_c_id[] = "@(#)rpc_callmsg.c     2.1     97/10/23";
+#endif
+/* @(#)rpc_callmsg.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "rpc/rpc.h"
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(
+	XDR *xdrs,
+	struct rpc_msg *cmsg)
+{
+	int32_t *buf;
+	struct opaque_auth *oa;
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
+			return (FALSE);
+		}
+		if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
+			return (FALSE);
+		}
+		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
+			+ RNDUP(cmsg->rm_call.cb_cred.oa_length)
+			+ 2 * BYTES_PER_XDR_UNIT
+			+ RNDUP(cmsg->rm_call.cb_verf.oa_length));
+		if (buf != NULL) {
+			IXDR_PUT_LONG(buf, cmsg->rm_xid);
+			IXDR_PUT_ENUM(buf, cmsg->rm_direction);
+			if (cmsg->rm_direction != CALL) {
+				return (FALSE);
+			}
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
+			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+				return (FALSE);
+			}
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
+			oa = &cmsg->rm_call.cb_cred;
+			IXDR_PUT_ENUM(buf, oa->oa_flavor);
+			IXDR_PUT_LONG(buf, oa->oa_length);
+			if (oa->oa_length) {
+				memmove((caddr_t)buf, oa->oa_base, oa->oa_length);
+				buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+			}
+			oa = &cmsg->rm_call.cb_verf;
+			IXDR_PUT_ENUM(buf, oa->oa_flavor);
+			IXDR_PUT_LONG(buf, oa->oa_length);
+			if (oa->oa_length) {
+				memmove((caddr_t)buf, oa->oa_base, oa->oa_length);
+				/* no real need....
+				buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+				*/
+			}
+			return (TRUE);
+		}
+	}
+	if (xdrs->x_op == XDR_DECODE) {
+		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
+		if (buf != NULL) {
+			cmsg->rm_xid = IXDR_GET_LONG(buf);
+			cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
+			if (cmsg->rm_direction != CALL) {
+				return (FALSE);
+			}
+			cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf);
+			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+				return (FALSE);
+			}
+			cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf);
+			cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
+			cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
+			oa = &cmsg->rm_call.cb_cred;
+			oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+			oa->oa_length = IXDR_GET_LONG(buf);
+			if (oa->oa_length) {
+				if (oa->oa_length > MAX_AUTH_BYTES) {
+					return (FALSE);
+				}
+				if (oa->oa_base == NULL) {
+					oa->oa_base = (caddr_t)
+						mem_alloc(oa->oa_length);
+				}
+				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+				if (buf == NULL) {
+					if (xdr_opaque(xdrs, oa->oa_base,
+					    oa->oa_length) == FALSE) {
+						return (FALSE);
+					}
+				} else {
+					memmove(oa->oa_base, (caddr_t)buf,
+					    oa->oa_length);
+					/* no real need....
+					buf += RNDUP(oa->oa_length) /
+						sizeof (int32_t);
+					*/
+				}
+			}
+			oa = &cmsg->rm_call.cb_verf;
+			buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+			if (buf == NULL) {
+				if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
+				    xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
+					return (FALSE);
+				}
+			} else {
+				oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+				oa->oa_length = IXDR_GET_LONG(buf);
+			}
+			if (oa->oa_length) {
+				if (oa->oa_length > MAX_AUTH_BYTES) {
+					return (FALSE);
+				}
+				if (oa->oa_base == NULL) {
+					oa->oa_base = (caddr_t)
+						mem_alloc(oa->oa_length);
+				}
+				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+				if (buf == NULL) {
+					if (xdr_opaque(xdrs, oa->oa_base,
+					    oa->oa_length) == FALSE) {
+						return (FALSE);
+					}
+				} else {
+					memmove(oa->oa_base, (caddr_t)buf,
+					    oa->oa_length);
+					/* no real need...
+					buf += RNDUP(oa->oa_length) /
+						sizeof (int32_t);
+					*/
+				}
+			}
+			return (TRUE);
+		}
+	}
+	if (
+	    xdr_uint32_t(xdrs, &(cmsg->rm_xid)) &&
+	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+	    (cmsg->rm_direction == CALL) &&
+	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+	    (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_prog)) &&
+	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_vers)) &&
+	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_proc)) &&
+	    xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
+	    return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
+	return (FALSE);
+}
+
diff --git a/TBBT/trace_play/rpc/rpc_commondata.c b/TBBT/trace_play/rpc/rpc_commondata.c
new file mode 100755
index 0000000..c2df017
--- /dev/null
+++ b/TBBT/trace_play/rpc/rpc_commondata.c
@@ -0,0 +1,62 @@
+#ifndef lint
+static char sfs_rpc_commondata_id[] = "@(#)rpc_commondata.c     2.1     97/10/23";
+#endif
+/* @(#)rpc_commondata.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#include "rpc/rpc.h"
+/*
+ * This file should only contain common data (global data) that is exported
+ * by public interfaces 
+ */
+struct opaque_auth _null_auth;
+#ifdef FD_SETSIZE
+fd_set svc_fdset;
+#else
+int svc_fds;
+#endif /* def FD_SETSIZE */
+struct rpc_createerr rpc_createerr;
diff --git a/TBBT/trace_play/rpc/rpc_dtablesize.c b/TBBT/trace_play/rpc/rpc_dtablesize.c
new file mode 100755
index 0000000..8c1d9f9
--- /dev/null
+++ b/TBBT/trace_play/rpc/rpc_dtablesize.c
@@ -0,0 +1,114 @@
+#ifndef lint
+static char sfs_clnt_id[] = "@(#)rpc_dtablesize.c     2.1     97/10/23";
+#endif
+/* @(#)rpc_dtablesize.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
+#endif
+
+
+/*
+ * Cache the result of getdtablesize(), so we don't have to do an
+ * expensive system call every time.
+ */
+
+#if !(defined(USE_GETDTABLESIZE) || defined(USE_GETRLIMIT) || defined(USE_NOFILE))
+#define USE_GETDTABLESIZE
+#endif
+
+#ifdef USE_GETDTABLESIZE
+#include <unistd.h>
+
+int
+_rpc_dtablesize(void)
+{
+	static int size = 0;
+	
+	if (size == 0) {
+		size = getdtablesize();
+#ifdef FD_SETSIZE
+		/*
+		 * FreeBSD select() produces a segmentation violation if
+		 * the argument is larger than FD_SETSIZE.
+		 */
+		if (size > FD_SETSIZE) {
+		        size = FD_SETSIZE;
+		}
+#endif /* def FD_SETSIZE */
+	}
+	return (size);
+}
+#endif
+
+#ifdef USE_GETRLIMIT
+#include <sys/resource.h>
+
+int
+_rpc_dtablesize(void)
+{
+	static int size = 0;
+	struct rlimit rlimit;
+
+	if (size == 0) {
+		(void)getrlimit(RLIMIT_NOFILE, &rlimit);
+		size = (int) rlimit.rlim_cur;
+	}
+	return (size);
+}
+#endif
+
+#ifdef USE_NOFILE
+#include <sys/param.h>
+
+int
+_rpc_dtablesize(void)
+{
+	return (NOFILE);
+}
+#endif
diff --git a/TBBT/trace_play/rpc/rpc_msg.h b/TBBT/trace_play/rpc/rpc_msg.h
new file mode 100755
index 0000000..fde7b93
--- /dev/null
+++ b/TBBT/trace_play/rpc/rpc_msg.h
@@ -0,0 +1,215 @@
+/*
+ * @(#)rpc_msg.h     2.1     97/10/23
+ */
+/* @(#)rpc_msg.h	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)rpc_msg.h 1.7 86/07/16 SMI      */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __RPC_MSG_H
+#define __RPC_MSG_H
+
+#define RPC_MSG_VERSION		((uint32_t) 2)
+#define RPC_SERVICE_PORT	((uint16_t) 2048)
+
+/*
+ * Bottom up definition of an rpc message.
+ * NOTE: call and reply use the same overall stuct but
+ * different parts of unions within it.
+ */
+
+enum msg_type {
+	CALL=0,
+	REPLY=1
+};
+
+enum reply_stat {
+	MSG_ACCEPTED=0,
+	MSG_DENIED=1
+};
+
+enum accept_stat {
+	SUCCESS=0,
+	PROG_UNAVAIL=1,
+	PROG_MISMATCH=2,
+	PROC_UNAVAIL=3,
+	GARBAGE_ARGS=4,
+	SYSTEM_ERR=5
+};
+
+enum reject_stat {
+	RPC_MISMATCH=0,
+	AUTH_ERROR=1
+};
+
+/*
+ * Reply part of an rpc exchange
+ */
+
+/*
+ * Reply to an rpc request that was accepted by the server.
+ * Note: there could be an error even though the request was
+ * accepted.
+ */
+struct accepted_reply {
+	struct opaque_auth	ar_verf;
+	enum accept_stat	ar_stat;
+	union {
+		struct {
+			uint32_t	low;
+			uint32_t	high;
+		} AR_versions;
+		struct {
+			void *	where;
+			xdrproc_t proc;
+		} AR_results;
+		/* and many other null cases */
+	} ru;
+#define	ar_results	ru.AR_results
+#define	ar_vers		ru.AR_versions
+};
+
+/*
+ * Reply to an rpc request that was rejected by the server.
+ */
+struct rejected_reply {
+	enum reject_stat rj_stat;
+	union {
+		struct {
+			uint32_t low;
+			uint32_t high;
+		} RJ_versions;
+		enum auth_stat RJ_why;  /* why authentication did not work */
+	} ru;
+#define	rj_vers	ru.RJ_versions
+#define	rj_why	ru.RJ_why
+};
+
+/*
+ * Body of a reply to an rpc request.
+ */
+struct reply_body {
+	enum reply_stat rp_stat;
+	union {
+		struct accepted_reply RP_ar;
+		struct rejected_reply RP_dr;
+	} ru;
+#define	rp_acpt	ru.RP_ar
+#define	rp_rjct	ru.RP_dr
+};
+
+/*
+ * Body of an rpc request call.
+ */
+struct call_body {
+	uint32_t cb_rpcvers;	/* must be equal to two */
+	uint32_t cb_prog;
+	uint32_t cb_vers;
+	uint32_t cb_proc;
+	struct opaque_auth cb_cred;
+	struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+	uint32_t		rm_xid;
+	enum msg_type		rm_direction;
+	union {
+		struct call_body RM_cmb;
+		struct reply_body RM_rmb;
+	} ru;
+#define	rm_call		ru.RM_cmb
+#define	rm_reply	ru.RM_rmb
+};
+#define	acpted_rply	ru.RM_rmb.ru.RP_ar
+#define	rjcted_rply	ru.RM_rmb.ru.RP_dr
+
+
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * 	XDR *xdrs;
+ * 	struct rpc_msg *cmsg;
+ */
+extern bool_t	xdr_callmsg(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * 	XDR *xdrs;
+ * 	struct rpc_msg *cmsg;
+ */
+extern bool_t	xdr_callhdr(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * 	XDR *xdrs;
+ * 	struct rpc_msg *rmsg;
+ */
+extern bool_t	xdr_replymsg(XDR *, struct rpc_msg *);
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * 	struct rpc_msg *msg;
+ * 	struct rpc_err *error;
+ */
+extern void	_seterr_reply(struct rpc_msg *, struct rpc_err *);
+
+extern int	_rpc_dtablesize(void);
+extern bool_t	xdr_opaque_auth(XDR *, struct opaque_auth *);
+#endif /* __RPC_MSG_H */
diff --git a/TBBT/trace_play/rpc/rpc_prot.c b/TBBT/trace_play/rpc/rpc_prot.c
new file mode 100755
index 0000000..623ee7a
--- /dev/null
+++ b/TBBT/trace_play/rpc/rpc_prot.c
@@ -0,0 +1,307 @@
+#ifndef lint
+static char sfs_rpc_prot_id[] = "@(#)rpc_prot.c     2.1     97/10/23";
+#endif
+/* @(#)rpc_prot.c	2.3 88/08/07 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_prot.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements the rpc message definition,
+ * its serializer and some common rpc utility routines.
+ * The routines are meant for various implementations of rpc -
+ * they are NOT for the rpc client or rpc service implementations!
+ * Because authentication stuff is easy and is part of rpc, the opaque
+ * routines are also in this program.
+ */
+
+#include "rpc/rpc.h"
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+struct opaque_auth _null_auth;
+
+/*
+ * XDR an opaque authentication struct
+ * (see auth.h)
+ */
+bool_t
+xdr_opaque_auth(
+	XDR *xdrs,
+	struct opaque_auth *ap)
+{
+
+	if (xdr_enum(xdrs, &(ap->oa_flavor)))
+		return (xdr_bytes(xdrs, (void *)&ap->oa_base,
+			&ap->oa_length, MAX_AUTH_BYTES));
+	return (FALSE);
+}
+
+/*
+ * XDR a DES block
+ */
+bool_t
+xdr_des_block(
+	XDR *xdrs,
+	des_block *blkp)
+{
+	return (xdr_opaque(xdrs, (void *)blkp, sizeof(des_block)));
+}
+
+/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
+
+/*
+ * XDR the MSG_ACCEPTED part of a reply message union
+ */
+bool_t 
+xdr_accepted_reply(
+	XDR *xdrs,   
+	struct accepted_reply *ar)
+{
+
+	/* personalized union, rather than calling xdr_union */
+	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
+		return (FALSE);
+	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
+		return (FALSE);
+	switch (ar->ar_stat) {
+
+	case SUCCESS:
+		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
+
+	case PROG_MISMATCH:
+		if (! xdr_uint32_t(xdrs, &(ar->ar_vers.low)))
+			return (FALSE);
+		return (xdr_uint32_t(xdrs, &(ar->ar_vers.high)));
+	}
+	return (TRUE);  /* TRUE => open ended set of problems */
+}
+
+/*
+ * XDR the MSG_DENIED part of a reply message union
+ */
+bool_t 
+xdr_rejected_reply(
+	XDR *xdrs,
+	struct rejected_reply *rr)
+{
+
+	/* personalized union, rather than calling xdr_union */
+	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
+		return (FALSE);
+	switch (rr->rj_stat) {
+
+	case RPC_MISMATCH:
+		if (! xdr_uint32_t(xdrs, &(rr->rj_vers.low)))
+			return (FALSE);
+		return (xdr_uint32_t(xdrs, &(rr->rj_vers.high)));
+
+	case AUTH_ERROR:
+		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
+	}
+	return (FALSE);
+}
+
+static struct xdr_discrim reply_dscrm[3] = {
+	{ (int)MSG_ACCEPTED, xdr_accepted_reply },
+	{ (int)MSG_DENIED, xdr_rejected_reply },
+	{ __dontcare__, NULL_xdrproc_t } };
+
+/*
+ * XDR a reply message
+ */
+bool_t
+xdr_replymsg(
+	XDR *xdrs,
+	struct rpc_msg *rmsg)
+{
+	if (
+	    xdr_uint32_t(xdrs, &(rmsg->rm_xid)) && 
+	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
+	    (rmsg->rm_direction == REPLY) )
+		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
+		   (void *)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
+	return (FALSE);
+}
+
+
+/*
+ * Serializes the "static part" of a call message header.
+ * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
+ * The rm_xid is not really static, but the user can easily munge on the fly.
+ */
+bool_t
+xdr_callhdr(
+	XDR *xdrs,
+	struct rpc_msg *cmsg)
+{
+
+	cmsg->rm_direction = CALL;
+	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	if (
+	    (xdrs->x_op == XDR_ENCODE) &&
+	    xdr_uint32_t(xdrs, &(cmsg->rm_xid)) &&
+	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
+	    return (xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_vers)));
+	return (FALSE);
+}
+
+/* ************************** Client utility routine ************* */
+
+static void
+accepted(
+	enum accept_stat acpt_stat,
+	struct rpc_err *error)
+{
+
+	switch (acpt_stat) {
+
+	case PROG_UNAVAIL:
+		error->re_status = RPC_PROGUNAVAIL;
+		return;
+
+	case PROG_MISMATCH:
+		error->re_status = RPC_PROGVERSMISMATCH;
+		return;
+
+	case PROC_UNAVAIL:
+		error->re_status = RPC_PROCUNAVAIL;
+		return;
+
+	case GARBAGE_ARGS:
+		error->re_status = RPC_CANTDECODEARGS;
+		return;
+
+	case SYSTEM_ERR:
+		error->re_status = RPC_SYSTEMERROR;
+		return;
+
+	case SUCCESS:
+		error->re_status = RPC_SUCCESS;
+		return;
+	}
+	/* something's wrong, but we don't know what ... */
+	error->re_status = RPC_FAILED;
+	error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
+	error->re_lb.s2 = (int32_t)acpt_stat;
+}
+
+static void 
+rejected(
+	enum reject_stat rjct_stat,
+	struct rpc_err *error)
+{
+
+	if ((int)rjct_stat == (int)RPC_VERSMISMATCH) {
+		error->re_status = RPC_VERSMISMATCH;
+		return;
+	}
+	if (rjct_stat == AUTH_ERROR) {
+		error->re_status = RPC_AUTHERROR;
+		return;
+	}
+
+	/* something's wrong, but we don't know what ... */
+	error->re_status = RPC_FAILED;
+	error->re_lb.s1 = (int32_t)MSG_DENIED;
+	error->re_lb.s2 = (int32_t)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+_seterr_reply(
+	struct rpc_msg *msg,
+	struct rpc_err *error)
+{
+
+	/* optimized for normal, SUCCESSful case */
+	switch (msg->rm_reply.rp_stat) {
+
+	case MSG_ACCEPTED:
+		if (msg->acpted_rply.ar_stat == SUCCESS) {
+			error->re_status = RPC_SUCCESS;
+			return;
+		};
+		accepted(msg->acpted_rply.ar_stat, error);
+		break;
+
+	case MSG_DENIED:
+		rejected(msg->rjcted_rply.rj_stat, error);
+		break;
+
+	default:
+		error->re_status = RPC_FAILED;
+		error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
+		break;
+	}
+	switch (error->re_status) {
+
+	case RPC_VERSMISMATCH:
+		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
+		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
+		break;
+
+	case RPC_AUTHERROR:
+		error->re_why = msg->rjcted_rply.rj_why;
+		break;
+
+	case RPC_PROGVERSMISMATCH:
+		error->re_vers.low = msg->acpted_rply.ar_vers.low;
+		error->re_vers.high = msg->acpted_rply.ar_vers.high;
+		break;
+	}
+}
diff --git a/TBBT/trace_play/rpc/sfs_ctcp.c b/TBBT/trace_play/rpc/sfs_ctcp.c
new file mode 100755
index 0000000..d6a19f0
--- /dev/null
+++ b/TBBT/trace_play/rpc/sfs_ctcp.c
@@ -0,0 +1,727 @@
+#ifndef lint
+static char sfs_ctcp_id[] = "@(#)sfs_ctcp.c     2.1     97/10/23";
+#endif
+/* @(#)clnt_tcp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+#endif
+ 
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer.  The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message.  Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <netdb.h>
+#include <errno.h>
+#include "rpc/pmap_clnt.h"
+
+#define MCALL_MSG_SIZE 24
+
+struct ct_data {
+	int		ct_sock;
+	bool_t		ct_closeit;
+	struct timeval	ct_wait;
+	struct sockaddr_in ct_addr; 
+	struct sockaddr_in ct_oaddr; 
+	struct rpc_err	ct_error;
+	char		ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */
+	uint_t		ct_mpos;			/* pos after marshal */
+	XDR		ct_xdrs;
+	int		ct_first;
+	uint32_t	ct_prog;
+	uint32_t	ct_vers;
+	uint_t		ct_sendsz;
+	uint_t		ct_recvsz;
+};
+
+static int	readtcp(struct ct_data *, char *, int);
+static int	writetcp(struct ct_data *ct, char * buf, int len);
+
+static enum clnt_stat	sfs_ctcp_call(CLIENT *, uint32_t, xdrproc_t, void *,
+					xdrproc_t, void *, struct timeval);
+static void		sfs_ctcp_abort(CLIENT *);
+static void		sfs_ctcp_geterr(CLIENT *, struct rpc_err *);
+static bool_t		sfs_ctcp_freeres(CLIENT *, xdrproc_t, void *);
+static bool_t		sfs_ctcp_control(CLIENT *, uint_t, void *);
+static void		sfs_ctcp_destroy(CLIENT *);
+static bool_t		sfs_ctcp_getreply(CLIENT *, xdrproc_t, void *,
+				int, uint32_t *, uint32_t *, struct timeval *);
+static int		sfs_ctcp_poll(CLIENT *, uint32_t);
+
+static struct clnt_ops tcp_ops = {
+	sfs_ctcp_call,
+	sfs_ctcp_abort,
+	sfs_ctcp_geterr,
+	sfs_ctcp_freeres,
+	sfs_ctcp_destroy,
+	sfs_ctcp_control,
+	sfs_ctcp_getreply,
+	sfs_ctcp_poll
+};
+
+static int
+sfs_ctcp_make_conn(
+	struct ct_data *ct,
+	struct sockaddr_in *raddr,
+	int *sockp)
+{
+	int i;
+        int min_buf_sz;
+        int new_buf_sz;
+        int type;
+        int error;
+	int setopt = 1;
+#if defined(UNIXWARE) || defined(AIX)
+        size_t optlen;
+#else
+        int optlen;
+#endif
+
+	if (ct->ct_first == 0)
+		ct->ct_first++;
+
+#ifdef DEBUG
+	if (ct->ct_first)
+		(void) fprintf(stderr, "Re-establishing connection.\n");
+#endif
+
+	/*
+	 * If no port number given ask the pmap for one
+	 */
+	if (raddr->sin_port == 0) {
+		uint16_t port;
+		if ((port = pmap_getport(raddr, ct->ct_prog, ct->ct_vers,
+							IPPROTO_TCP)) == 0) {
+			return (-1);
+		}
+		raddr->sin_port = htons(port);
+	}
+
+	/*
+	 * If no socket given, open one
+	 */
+	if (*sockp >= 0) {
+		ct->ct_closeit = FALSE;
+		return (*sockp);
+	}
+
+	ct->ct_closeit = TRUE;
+
+	*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	(void)bindresvport(*sockp, (struct sockaddr_in *)0);
+	if ((*sockp < 0)
+	    || (connect(*sockp, (struct sockaddr *)raddr,
+	    sizeof(struct sockaddr_in)) < 0)) {
+		return (-1);
+	}
+
+        /*
+         * Need to try to size the socket buffers based on the number of
+         * outstanding requests desired.  NFS reads and writes can do as
+         * much as 8K per request which can quickly run us out of space
+         * on the socket buffer queue.  Use the maximum number of bio style
+         * requests * NFS_MAXDATA plus a pad as a starting point for desired
+         * socket buffer size and then back off by NFS_MAXDATA until the buffer
+         * sizes are successfully set.  Note, the algorithm never sets the
+         * buffer size to less than the OS default.
+         */
+        type = SO_SNDBUF;
+        for (i = 0; i < 2; i++) {
+                optlen = sizeof(min_buf_sz);
+#ifdef UNIXWARE
+                if (getsockopt(*sockp, SOL_SOCKET, type,
+                                (void *)&min_buf_sz, &optlen) < 0) {
+                        /* guess the default */
+                        min_buf_sz = 18 * 1024;
+                }
+#else
+                if (getsockopt(*sockp, SOL_SOCKET, type,
+                                (char *)&min_buf_sz, &optlen) < 0) {
+                        /* guess the default */
+                        min_buf_sz = 18 * 1024;
+                }
+#endif
+
+                new_buf_sz = 512 * 1024;
+                if (new_buf_sz > min_buf_sz) {
+                        do {
+                                error = setsockopt(*sockp, SOL_SOCKET,
+                                                type, (char *)&new_buf_sz,
+                                                sizeof(int));
+                                new_buf_sz -= (8 * 1024);
+                        } while (error != 0 && new_buf_sz > min_buf_sz);
+                }
+
+                type = SO_RCVBUF;
+        }
+
+#ifdef TCP_NODELAY
+	setsockopt(*sockp, IPPROTO_TCP, TCP_NODELAY, (char *) &setopt,
+		sizeof(setopt));
+#endif /* TCP_NODELAY */
+
+	return (*sockp);
+}
+
+/*
+ * Create a client handle for a tcp/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr.  If *sockp non-negative then
+ * raddr is ignored.  The rpc/tcp package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+sfs_ctcp_create(
+	struct sockaddr_in *raddr,
+	uint32_t prog,
+	uint32_t vers,
+	int *sockp,
+	uint_t sendsz,
+	uint_t recvsz)
+{
+	CLIENT *h;
+	struct ct_data *ct;
+	struct timeval now;
+	struct rpc_msg call_msg;
+
+	h  = (CLIENT *)mem_alloc(sizeof(CLIENT));
+	if (h == NULL) {
+		(void)fprintf(stderr, "clnttcp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	ct = (struct ct_data *)mem_alloc(sizeof(struct ct_data));
+	if (ct == NULL) {
+		(void)fprintf(stderr, "clnttcp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	(void) memset(ct, '\0', sizeof (struct ct_data));
+
+	ct->ct_oaddr = *raddr;
+	ct->ct_prog = prog;
+	ct->ct_vers = vers;
+
+	if (sfs_ctcp_make_conn(ct, raddr, sockp) < 0) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		(void)close(*sockp);
+		goto fooy;
+	}
+
+	/*
+	 * Set up private data struct
+	 */
+	ct->ct_sock = *sockp;
+	ct->ct_wait.tv_sec = 0;
+	ct->ct_wait.tv_usec = 0;
+	ct->ct_addr = *raddr;
+
+	/*
+	 * Initialize call message
+	 */
+	(void)gettimeofday(&now, (struct timezone *)0);
+	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = prog;
+	call_msg.rm_call.cb_vers = vers;
+
+	/*
+	 * pre-serialize the static part of the call msg and stash it away
+	 */
+	xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
+	    XDR_ENCODE);
+	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+		if (ct->ct_closeit) {
+			(void)close(*sockp);
+		}
+		goto fooy;
+	}
+	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+	XDR_DESTROY(&(ct->ct_xdrs));
+
+	/*
+	 * Create a client handle which uses xdrrec for serialization
+	 * and authnone for authentication.
+	 */
+	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+	    (void *)ct, readtcp, writetcp);
+	ct->ct_sendsz = sendsz;
+	ct->ct_recvsz = recvsz;
+	h->cl_ops = &tcp_ops;
+	h->cl_private = (void *) ct;
+	h->cl_auth = authnone_create();
+	return (h);
+
+fooy:
+	/*
+	 * Something goofed, free stuff and barf
+	 */
+	mem_free((void *)ct, sizeof(struct ct_data));
+	mem_free((void *)h, sizeof(CLIENT));
+	return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+get_areply(
+	CLIENT *h,
+	struct rpc_msg *reply_msg)
+{
+	struct ct_data *ct = (struct ct_data *) h->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+
+	/* CONSTCOND */
+	while (TRUE) {
+		reply_msg->acpted_rply.ar_verf = _null_auth;
+		reply_msg->acpted_rply.ar_results.where = NULL;
+		reply_msg->acpted_rply.ar_results.proc = xdr_void;
+		if (! xdrrec_skiprecord(xdrs)) {
+			return (ct->ct_error.re_status);
+		}
+		/* now decode and validate the response header */
+		if (! xdr_replymsg(xdrs, reply_msg)) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				continue;
+                }
+		return (ct->ct_error.re_status);
+	}
+}
+
+static enum clnt_stat
+proc_header(
+	CLIENT *h,
+	struct rpc_msg *reply_msg,
+	xdrproc_t xdr_results,
+	void * results_ptr)
+{
+	struct ct_data *ct = (struct ct_data *) h->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+
+	/*
+	 * process header
+	 */
+	_seterr_reply(reply_msg, &(ct->ct_error));
+	if (ct->ct_error.re_status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(h->cl_auth,
+					&reply_msg->acpted_rply.ar_verf)) {
+			ct->ct_error.re_status = RPC_AUTHERROR;
+			ct->ct_error.re_why = AUTH_INVALIDRESP;
+		} else if (! (*xdr_results)(xdrs, results_ptr)) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				ct->ct_error.re_status = RPC_CANTDECODERES;
+		}
+		/* free verifier ... */
+		if (reply_msg->acpted_rply.ar_verf.oa_base != NULL) {
+			xdrs->x_op = XDR_FREE;
+			(void)xdr_opaque_auth(xdrs,
+					&(reply_msg->acpted_rply.ar_verf));
+		}
+	}  /* end successful completion */
+	return (ct->ct_error.re_status);
+}
+
+static enum clnt_stat
+sfs_ctcp_call(
+	CLIENT *h,
+	uint32_t proc,
+	xdrproc_t xdr_args,
+	void * args_ptr,
+	xdrproc_t xdr_results,
+	void * results_ptr,
+	struct timeval timeout)
+{
+	struct ct_data *ct = (struct ct_data *) h->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+	struct rpc_msg reply_msg;
+	uint32_t x_id;
+	uint32_t *msg_x_id = (uint32_t *)(ct->ct_mcall);	/* yuk */
+	bool_t shipnow;
+
+	ct->ct_wait = timeout;
+
+	shipnow =
+	    (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
+	    && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+	xdrs->x_op = XDR_ENCODE;
+	ct->ct_error.re_status = RPC_SUCCESS;
+	x_id = ntohl(--(*msg_x_id));
+	if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+	    (! XDR_PUTLONG(xdrs, (int32_t *)&proc)) ||
+	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+	    (! (*xdr_args)(xdrs, args_ptr))) {
+		if (ct->ct_error.re_status == RPC_SUCCESS)
+			ct->ct_error.re_status = RPC_CANTENCODEARGS;
+		(void)xdrrec_endofrecord(xdrs, TRUE);
+		return (ct->ct_error.re_status);
+	}
+	if (! xdrrec_endofrecord(xdrs, TRUE))
+		return (ct->ct_error.re_status = RPC_CANTSEND);
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+		if (! shipnow && results_ptr == NULL)
+			return (RPC_SUCCESS);
+
+		/*
+		 * Double hack, send back xid in results_prt if non-NULL
+		 */
+		*(uint32_t *)results_ptr = x_id;
+		return(ct->ct_error.re_status = RPC_TIMEDOUT);
+	}
+
+
+	/*
+	 * Keep receiving until we get a valid transaction id
+	 */
+	xdrs->x_op = XDR_DECODE;
+	/* CONSTCOND */
+	while (TRUE) {
+		enum clnt_stat res;
+
+		if ((res = get_areply(h, &reply_msg)) != RPC_SUCCESS)
+			return (res);
+
+		if (reply_msg.rm_xid == x_id)
+			break;
+	}
+
+	/*
+	 * process header
+	 */
+	return (proc_header(h, &reply_msg, xdr_results, results_ptr));
+}
+
+static void
+sfs_ctcp_geterr(
+	CLIENT *h,
+	struct rpc_err *errp)
+{
+	struct ct_data *ct =
+	    (struct ct_data *) h->cl_private;
+
+	*errp = ct->ct_error;
+}
+
+static bool_t
+sfs_ctcp_freeres(
+	CLIENT *cl,
+	xdrproc_t xdr_res,
+	void * res_ptr)
+{
+	struct ct_data *ct = (struct ct_data *)cl->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/* ARGSUSED */
+static void
+sfs_ctcp_abort(CLIENT *h)
+{
+}
+
+static bool_t
+sfs_ctcp_control(
+	CLIENT *cl,
+	uint_t request,
+	void *info)
+{
+	struct ct_data *ct = (struct ct_data *)cl->cl_private;
+
+	switch (request) {
+	case CLGET_SERVER_ADDR:
+		*(struct sockaddr_in *)info = ct->ct_addr;
+		break;
+	default:
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+
+static void
+sfs_ctcp_destroy(
+	CLIENT *h)
+{
+	struct ct_data *ct =
+	    (struct ct_data *) h->cl_private;
+
+	if (ct->ct_closeit) {
+		(void)close(ct->ct_sock);
+	}
+	XDR_DESTROY(&(ct->ct_xdrs));
+	mem_free((void *)ct, sizeof(struct ct_data));
+	mem_free((void *)h, sizeof(CLIENT));
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readtcp(struct ct_data *ct,
+	char * buf,
+	int len)
+{
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+
+	FD_ZERO(&mask);
+	FD_SET(ct->ct_sock, &mask);
+#else
+	int mask = 1 << (ct->ct_sock);
+	int readfds;
+#endif /* def FD_SETSIZE */
+
+	if (len == 0)
+		return (0);
+
+	/* CONSTCOND */
+	while (TRUE) {
+		readfds = mask;
+		switch (select(_rpc_dtablesize(), &readfds, NULL, NULL,
+			       &(ct->ct_wait))) {
+		case 0:
+			ct->ct_error.re_status = RPC_TIMEDOUT;
+			return (-1);
+
+		case -1:
+			if (errno == EINTR)
+				continue;
+			ct->ct_error.re_status = RPC_CANTRECV;
+			ct->ct_error.re_errno = errno;
+			goto lost;
+		}
+		break;
+	}
+	switch (len = read(ct->ct_sock, buf, len)) {
+
+	case 0:
+		/* premature eof */
+		ct->ct_error.re_errno = ECONNRESET;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		len = -1;  /* it's really an error */
+		goto lost;
+
+	case -1:
+		ct->ct_error.re_errno = errno;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		goto lost;
+	}
+	return (len);
+lost:
+	/*
+	 * We have lost our connection to the server.  Try and
+	 * reestablish it.
+	 */
+	(void) close(ct->ct_sock);
+	ct->ct_addr = ct->ct_oaddr;
+	ct->ct_sock = -1;
+	XDR_DESTROY(&(ct->ct_xdrs));
+
+	(void) sfs_ctcp_make_conn(ct, &ct->ct_addr, &ct->ct_sock);
+	/*
+	 * Create a client handle which uses xdrrec for
+	 * serialization and authnone for authentication.
+	 */
+	xdrrec_create(&(ct->ct_xdrs), ct->ct_sendsz, ct->ct_recvsz,
+						(void *)ct, readtcp, writetcp);
+	return (-1);
+}
+
+static int
+writetcp(
+	struct ct_data *ct,
+	char * buf,
+	int len)
+{
+	int i, cnt;
+
+	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+		if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
+			/*
+			 * We have lost our connection to the server.  Try and
+			 * reestablish it.
+			 */
+			(void) close(ct->ct_sock);
+			ct->ct_addr = ct->ct_oaddr;
+			ct->ct_sock = -1;
+			XDR_DESTROY(&(ct->ct_xdrs));
+
+			(void) sfs_ctcp_make_conn(ct, &ct->ct_addr,
+								&ct->ct_sock);
+			/*
+			 * Create a client handle which uses xdrrec for
+			 * serialization and authnone for authentication.
+			 */
+			xdrrec_create(&(ct->ct_xdrs), ct->ct_sendsz,
+						ct->ct_recvsz,
+						(void *)ct, readtcp, writetcp);
+			ct->ct_error.re_errno = errno;
+			ct->ct_error.re_status = RPC_CANTSEND;
+			return (-1);
+		}
+	}
+	return (len);
+}
+
+/* ARGSUSED */
+static bool_t
+sfs_ctcp_getreply(
+        CLIENT *cl,
+        xdrproc_t xdr_results,
+        void *results_ptr,
+	int cnt,
+	uint32_t *xids,
+        uint32_t *xid,
+	struct timeval *tv)
+{
+	struct ct_data *ct = (struct ct_data *) cl->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+	struct rpc_msg reply_msg;
+	enum clnt_stat res;
+	int i;
+
+	/*
+	 * Receive just one returning transaction id
+	 */
+	xdrs->x_op = XDR_DECODE;
+	ct->ct_error.re_status = RPC_SUCCESS;
+	ct->ct_wait.tv_sec = tv->tv_sec;
+	ct->ct_wait.tv_usec = tv->tv_usec;
+
+	if ((res = get_areply(cl, &reply_msg)) != RPC_SUCCESS)
+		return (res);
+
+	*xid = reply_msg.rm_xid;
+
+	/*
+	 * Check to make sure xid matchs one that we are interested in
+	 */
+	for (i = 0; i < cnt; i++) {
+		if (xids[i] == *xid)
+			break;
+	}
+
+	if (i == cnt)
+		return (RPC_CANTDECODERES);
+
+	/*
+	 * process header
+	 */
+	return (proc_header(cl, &reply_msg, xdr_results, results_ptr));
+}
+ 
+/* ARGSUSED */
+static int
+sfs_ctcp_poll(
+        CLIENT *cl,
+        uint32_t usecs)
+{
+	struct ct_data *ct = (struct ct_data *)cl->cl_private;
+	XDR *xdrs = &(ct->ct_xdrs);
+	struct timeval tv;
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+
+	FD_ZERO(&mask);
+	FD_SET(ct->ct_sock, &mask);
+#else
+	int mask = 1 << (ct->ct_sock);
+	int readfds;
+#endif /* def FD_SETSIZE */
+
+	if (xdrrec_eof(xdrs) == FALSE)
+		return (1);
+
+	tv.tv_sec = 0;
+	if (usecs > 1000000)
+		tv.tv_sec = usecs / 1000000;
+	tv.tv_usec = usecs % 1000000;
+
+	readfds = mask;
+	return (select(_rpc_dtablesize(), &readfds, NULL, NULL, &tv));
+}
diff --git a/TBBT/trace_play/rpc/sfs_cudp.c b/TBBT/trace_play/rpc/sfs_cudp.c
new file mode 100755
index 0000000..1dee989
--- /dev/null
+++ b/TBBT/trace_play/rpc/sfs_cudp.c
@@ -0,0 +1,604 @@
+#ifndef lint
+static char sfs_cudp_id[] = "@(#)sfs_cudp.c	2.1	97/10/23";
+#endif
+
+/* @(#)clnt_udp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * clnt_udp.c, Implements a UDP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifndef FreeBSD
+#include <stropts.h>
+#endif  /* ndef FreeBSD */
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <netdb.h>
+#include "rpc/pmap_clnt.h"
+#include <errno.h>
+#include "rfs_c_def.h"	/* Just for the define of RFS */
+/*
+ * UDP bases client side rpc operations
+ */
+static enum clnt_stat sfs_cudp_call(CLIENT *, uint32_t, xdrproc_t,
+					void *, xdrproc_t, void *,
+					struct timeval);
+static void		sfs_cudp_abort(CLIENT *h);
+static void		sfs_cudp_geterr(CLIENT *, struct rpc_err *);
+static bool_t		sfs_cudp_freeres(CLIENT *, xdrproc_t, void *);
+static bool_t		sfs_cudp_control(CLIENT *, uint_t, void *);
+static void		sfs_cudp_destroy(CLIENT *);
+static bool_t           sfs_cudp_getreply(CLIENT *, xdrproc_t, void *,
+				int, uint32_t *, uint32_t *, struct timeval *);
+static int              sfs_cudp_poll(CLIENT *, uint32_t);
+
+static struct clnt_ops sfs_cudp_ops = {
+	sfs_cudp_call,
+	sfs_cudp_abort,
+	sfs_cudp_geterr,
+	sfs_cudp_freeres,
+	sfs_cudp_destroy,
+	sfs_cudp_control,
+	sfs_cudp_getreply,
+	sfs_cudp_poll
+};
+
+/* 
+ * Private data kept per client handle
+ */
+struct cu_data {
+	int		   cu_sock;
+	bool_t		   cu_closeit;
+	struct sockaddr_in cu_raddr;
+	int		   cu_rlen;
+	struct rpc_err cu_error;
+	XDR		   cu_outxdrs;
+	uint_t		   cu_xdrpos;
+	uint_t		   cu_sendsz;
+	char		   *cu_outbuf;
+	uint_t		   cu_recvsz;
+	char		   cu_inbuf[1];
+};
+
+/*
+ * Create a UDP based client handle.
+ * If *sockp<0, *sockp is set to a newly created UPD socket.
+ * If raddr->sin_port is 0 a binder on the remote machine
+ * is consulted for the correct port number.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ *     Caller may wish to set this something more useful.
+ *
+ * wait is the amount of time used between retransmitting a call if
+ * no response has been heard;  retransmition occurs until the actual
+ * rpc call times out.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received.
+ */
+/* ARGSUSED */
+CLIENT *
+sfs_cudp_bufcreate(
+	struct sockaddr_in *raddr,
+	uint32_t program,
+	uint32_t version,
+	struct timeval wait,
+	int *sockp,
+	uint_t sendsz,
+	uint_t recvsz)
+{
+	CLIENT *cl;
+	struct cu_data *cu;
+	struct timeval now;
+	struct rpc_msg call_msg;
+	int min_buf_sz;
+	int new_buf_sz;
+	int type;
+	int i;
+	int error;
+#if defined(UNIXWARE) || defined(AIX)
+	size_t optlen;
+#else
+	int optlen;
+#endif
+
+	cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
+	if (cl == NULL) {
+		(void) fprintf(stderr, "sfs_cudp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	sendsz = ((sendsz + 3) / 4) * 4;
+	recvsz = ((recvsz + 3) / 4) * 4;
+	cu = (struct cu_data *)mem_alloc(sizeof(struct cu_data) +
+							sendsz + recvsz);
+	if (cu == NULL) {
+		(void) fprintf(stderr, "sfs_cudp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+
+	(void)gettimeofday(&now, (struct timezone *)0);
+	if (raddr->sin_port == 0) {
+		uint16_t port;
+		if ((port =
+		    pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
+			goto fooy;
+		}
+		raddr->sin_port = htons(port);
+	}
+	cl->cl_ops = &sfs_cudp_ops;
+	cl->cl_private = (void *)cu;
+	cu->cu_raddr = *raddr;
+	cu->cu_rlen = sizeof (cu->cu_raddr);
+	cu->cu_sendsz = sendsz;
+	cu->cu_recvsz = recvsz;
+	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = program;
+	call_msg.rm_call.cb_vers = version;
+	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
+	    sendsz, XDR_ENCODE);
+	if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
+		goto fooy;
+	}
+	cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+	if (*sockp < 0) {
+#if defined(O_NONBLOCK)
+		int flags;
+#elif defined(FIONBIO)
+		int dontblock = 1;
+#endif
+
+		*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+		if (*sockp < 0) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			goto fooy;
+		}
+		/* attempt to bind to prov port */
+		(void)bindresvport(*sockp, (struct sockaddr_in *)0);
+		/* the sockets rpc controls are non-blocking */
+#if defined(O_NONBLOCK)
+		flags = fcntl(*sockp, F_GETFL, 0) | O_NONBLOCK;
+		(void)fcntl(*sockp, F_SETFL, flags);
+#elif defined(FIONBIO)
+		(void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
+#endif
+		cu->cu_closeit = TRUE;
+	} else {
+		cu->cu_closeit = FALSE;
+	}
+	cu->cu_sock = *sockp;
+	/*
+	 * Need to try to size the socket buffers based on the number of
+	 * outstanding requests desired.  NFS reads and writes can do as
+	 * much as 8K per request which can quickly run us out of space
+	 * on the socket buffer queue.  Use the maximum number of bio style
+	 * requests * NFS_MAXDATA plus a pad as a starting point for desired
+	 * socket buffer size and then back off by NFS_MAXDATA until the buffer
+	 * sizes are successfully set.  Note, the algorithm never sets the
+	 * buffer size to less than the OS default.
+	 */  
+	type = SO_SNDBUF;
+	for (i = 0; i < 2; i++) {
+		optlen = sizeof(min_buf_sz);
+#if defined(UNIXWARE)
+		if (getsockopt(cu->cu_sock, SOL_SOCKET, type,
+				(void *)&min_buf_sz, &optlen) < 0) {
+			/* guess the default */
+			min_buf_sz = 18 * 1024;
+		}
+#else
+		if (getsockopt(cu->cu_sock, SOL_SOCKET, type,
+				(char *)&min_buf_sz, &optlen) < 0) {
+			/* guess the default */
+			min_buf_sz = 18 * 1024;
+		}
+#endif
+
+		new_buf_sz = 512 * 1024;
+		if (new_buf_sz > min_buf_sz) {
+			do {
+				error = setsockopt(cu->cu_sock, SOL_SOCKET,
+						type, (char *)&new_buf_sz,
+						sizeof(int));
+				new_buf_sz -= (8 * 1024);
+			} while (error != 0 && new_buf_sz > min_buf_sz);
+		}
+
+		type = SO_RCVBUF;
+	}
+
+	cl->cl_auth = authnone_create();
+	return (cl);
+fooy:
+	if (cu)
+		mem_free((void *)cu, sizeof(struct cu_data) + sendsz + recvsz);
+	if (cl)
+		mem_free((void *)cl, sizeof(CLIENT));
+	return ((CLIENT *)NULL);
+}
+
+CLIENT *
+sfs_cudp_create(
+	struct sockaddr_in *raddr,
+	uint32_t program,
+	uint32_t version,
+	struct timeval wait,
+	int *sockp)
+{
+
+	return(sfs_cudp_bufcreate(raddr, program, version, wait, sockp,
+	    UDPMSGSIZE, UDPMSGSIZE));
+}
+
+#ifdef RFS
+enum clnt_stat get_areply_udp (
+		CLIENT * cl,
+		uint32_t *xid,
+		struct timeval *timeout) 
+{
+	return get_areply (cl, xid, timeout);
+}
+#endif
+
+static enum clnt_stat
+get_areply(
+        CLIENT *cl,
+        uint32_t *xid,
+	struct timeval *timeout)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	int inlen;
+#if defined(AIX)
+	size_t fromlen;
+#else
+	int fromlen;
+#endif
+	struct sockaddr_in from;
+#ifdef FD_SETSIZE
+	fd_set readfds;
+	fd_set mask;
+#else
+	int readfds;
+	int mask;
+#endif /* def FD_SETSIZE */
+
+#ifdef FD_SETSIZE
+	FD_ZERO(&mask);
+	FD_SET(cu->cu_sock, &mask);
+#else
+	mask = 1 << cu->cu_sock;
+#endif /* def FD_SETSIZE */
+
+	for (;;) {
+		readfds = mask;
+		switch (select(_rpc_dtablesize(), &readfds, NULL, 
+			       NULL, timeout)) {
+
+		case 0:
+			return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+		case -1:
+			if (errno == EINTR)
+				continue;	
+			cu->cu_error.re_errno = errno;
+			return (cu->cu_error.re_status = RPC_CANTRECV);
+		}
+		do {
+			fromlen = sizeof(struct sockaddr);
+			inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, 
+				(int) cu->cu_recvsz, 0,
+				(struct sockaddr *)&from, &fromlen);
+		} while (inlen < 0 && errno == EINTR);
+		if (inlen < 0) {
+			if (errno == EWOULDBLOCK)
+				continue;	
+			cu->cu_error.re_errno = errno;
+			return (cu->cu_error.re_status = RPC_CANTRECV);
+		}
+
+		if (inlen < sizeof(uint32_t))
+			continue;	
+
+		*xid = ntohl(*((uint32_t *)(cu->cu_inbuf)));
+		return (RPC_SUCCESS);
+	}
+}
+
+enum clnt_stat
+proc_header(
+	CLIENT *cl,
+	xdrproc_t xdr_results,
+	void *results_ptr)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	XDR *xdrs = &(cu->cu_outxdrs);
+	struct rpc_msg reply_msg;
+	XDR reply_xdrs;
+	bool_t ok;
+
+	/*
+	 * now decode and validate the response
+	 */
+	xdrmem_create(&reply_xdrs, cu->cu_inbuf, cu->cu_recvsz, XDR_DECODE);
+
+	reply_msg.acpted_rply.ar_verf = _null_auth;
+	reply_msg.acpted_rply.ar_results.where = results_ptr;
+	reply_msg.acpted_rply.ar_results.proc = xdr_results;
+
+	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+	/* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
+	if (!ok) {
+		return (cu->cu_error.re_status = RPC_CANTDECODERES);
+	}
+
+	_seterr_reply(&reply_msg, &(cu->cu_error));
+
+	if (cu->cu_error.re_status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(cl->cl_auth,
+				&reply_msg.acpted_rply.ar_verf)) {
+			cu->cu_error.re_status = RPC_AUTHERROR;
+			cu->cu_error.re_why = AUTH_INVALIDRESP;
+		}
+		if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+			xdrs->x_op = XDR_FREE;
+			(void)xdr_opaque_auth(xdrs,
+				&(reply_msg.acpted_rply.ar_verf));
+		}
+	}
+
+	return (cu->cu_error.re_status);
+}
+
+/*
+ * Non-standard changes.  Make a call an at-most-once with a per call
+ * timer.  Ignore the timeout set at creation. Never retransmit.
+ */
+static enum clnt_stat 
+sfs_cudp_call(
+	CLIENT		*cl,		/* client handle */
+	uint32_t	proc,		/* procedure number */
+	xdrproc_t	xargs,		/* xdr routine for args */
+	void *		argsp,		/* pointer to args */
+	xdrproc_t	xresults,	/* xdr routine for results */
+	void *		resultsp,	/* pointer to results */
+	struct timeval	timeout)	/* seconds to wait before giving up */
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	XDR *xdrs = &(cu->cu_outxdrs);
+	int outlen;
+	uint32_t x_id, r_xid;
+
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, cu->cu_xdrpos);
+
+	/*
+	 * the transaction is the first thing in the out buffer
+	 */
+	(*(uint32_t *)(cu->cu_outbuf))++;
+	x_id = ntohl(*(uint32_t *)(cu->cu_outbuf));
+
+	if ((! XDR_PUTLONG(xdrs, (int32_t *)&proc)) ||
+	    (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+	    (! (*xargs)(xdrs, argsp)))
+		return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+
+	outlen = (int)XDR_GETPOS(xdrs);
+
+	if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
+	    (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) {
+		cu->cu_error.re_errno = errno;
+		return (cu->cu_error.re_status = RPC_CANTSEND);
+	}
+
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+                /* 
+                 * Double hack, send back xid in results_prt if non-NULL
+                 */ 
+                if (resultsp != NULL) 
+                        *(uint32_t *)resultsp = x_id; 
+
+		return (cu->cu_error.re_status = RPC_TIMEDOUT);
+	}
+
+	/* CONSTCOND */
+	while (TRUE) {
+		enum clnt_stat res;
+
+		if ((res = get_areply(cl, &r_xid, &timeout)) != RPC_SUCCESS)
+			return (res);
+
+		if (r_xid == x_id)
+			break;
+	}
+
+	/*
+	 * process header
+	 */
+	return (proc_header(cl, xresults, resultsp));
+}
+
+static void
+sfs_cudp_geterr(CLIENT *cl, struct rpc_err *errp)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	*errp = cu->cu_error;
+}
+
+
+static bool_t
+sfs_cudp_freeres(
+	CLIENT *cl,
+	xdrproc_t xdr_res,
+	void * res_ptr)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	XDR *xdrs = &(cu->cu_outxdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/* ARGSUSED */
+static void 
+sfs_cudp_abort(CLIENT *h)
+{
+}
+
+static bool_t
+sfs_cudp_control(
+	CLIENT *cl,
+	uint_t request,
+	void *info)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	switch (request) {
+	case CLGET_SERVER_ADDR:
+		*(struct sockaddr_in *)info = cu->cu_raddr;
+		break;
+	default:
+		return (FALSE);
+	}
+	return (TRUE);
+}
+	
+static void
+sfs_cudp_destroy(CLIENT *cl)
+{
+	struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	if (cu->cu_closeit) {
+		(void)close(cu->cu_sock);
+	}
+	XDR_DESTROY(&(cu->cu_outxdrs));
+	mem_free((void *)cu, (sizeof(struct cu_data) + cu->cu_sendsz + cu->cu_recvsz));
+	mem_free((void *)cl, sizeof(CLIENT));
+}
+
+/* ARGSUSED */
+static bool_t
+sfs_cudp_getreply(
+        CLIENT *cl,
+        xdrproc_t xproc,
+        void *xres,
+	int cnt,
+	uint32_t *xids,
+        uint32_t *xid,
+	struct timeval *tv)
+{
+        struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	bool_t res;
+	int i;
+
+	cu->cu_error.re_status = RPC_SUCCESS;
+
+	if ((res = get_areply(cl, xid, tv)) != RPC_SUCCESS)
+		return (res);
+
+	/*
+	 * Check to make sure xid matchs one that we are interested in
+	 */
+	for (i = 0; i < cnt; i++) {
+		if (xids[i] == *xid)
+			break;
+	}
+
+	if (i == cnt)
+		return (RPC_CANTDECODERES);
+
+	/*
+	 * process header
+	 */
+	return (proc_header(cl, xproc, xres));
+}
+ 
+static int
+sfs_cudp_poll(
+        CLIENT *cl,
+        uint32_t usecs)
+{
+        struct cu_data *cu = (struct cu_data *)cl->cl_private;
+        struct timeval tv;
+#ifdef FD_SETSIZE
+        fd_set mask;
+        fd_set readfds;
+ 
+        FD_ZERO(&mask);
+        FD_SET(cu->cu_sock, &mask);
+#else
+        int mask = 1 << (cu->cu_sock);
+        int readfds;
+#endif /* def FD_SETSIZE */
+ 
+        tv.tv_sec = 0; 
+        if (usecs > 1000000) 
+                tv.tv_sec = usecs / 1000000; 
+        tv.tv_usec = usecs % 1000000; 
+ 
+        readfds = mask;
+        return (select(_rpc_dtablesize(), &readfds, NULL, NULL, &tv));
+}
diff --git a/TBBT/trace_play/rpc/svc.c b/TBBT/trace_play/rpc/svc.c
new file mode 100755
index 0000000..9a8d905
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc.c
@@ -0,0 +1,479 @@
+#ifndef lint
+static char sfs_svc_c_id[] = "@(#)svc.c     2.1     97/10/23";
+#endif
+/* @(#)svc.c	2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc.c, Server-side remote procedure call interface.
+ *
+ * There are two sets of procedures here.  The xprt routines are
+ * for handling transport handles.  The svc routines handle the
+ * list of service routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "rpc/rpc.h"
+#include "rpc/pmap_clnt.h"
+
+#ifdef FD_SETSIZE
+static SVCXPRT **xports;
+#else
+#define NOFILE 32
+
+static SVCXPRT *xports[NOFILE];
+#endif /* def FD_SETSIZE */
+
+#define NULL_SVC ((struct svc_callout *)0)
+#define	RQCRED_SIZE	400		/* this size is excessive */
+
+/*
+ * The services list
+ * Each entry represents a set of procedures (an rpc program).
+ * The dispatch routine takes request structs and runs the
+ * apropriate procedure.
+ */
+static struct svc_callout {
+	struct svc_callout *sc_next;
+	uint32_t	    sc_prog;
+	uint32_t	    sc_vers;
+	void		    (*sc_dispatch)();
+} *svc_head;
+
+static struct svc_callout *svc_find();
+
+/* ***************  SVCXPRT related stuff **************** */
+
+/*
+ * Activate a transport handle.
+ */
+void
+xprt_register(
+	SVCXPRT *xprt)
+{
+	int sock = xprt->xp_sock;
+
+#ifdef FD_SETSIZE
+	if (xports == NULL) {
+		xports = (SVCXPRT **)
+			mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
+	}
+	if (sock < _rpc_dtablesize()) {
+		xports[sock] = xprt;
+		FD_SET(sock, &svc_fdset);
+	}
+#else
+	if (sock < NOFILE) {
+		xports[sock] = xprt;
+		svc_fds |= (1 << sock);
+	}
+#endif /* def FD_SETSIZE */
+
+}
+
+/*
+ * De-activate a transport handle. 
+ */
+void
+xprt_unregister(
+	SVCXPRT *xprt)
+{ 
+	int sock = xprt->xp_sock;
+
+#ifdef FD_SETSIZE
+	if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) {
+		xports[sock] = (SVCXPRT *)0;
+		FD_CLR(sock, &svc_fdset);
+	}
+#else
+	if ((sock < NOFILE) && (xports[sock] == xprt)) {
+		xports[sock] = (SVCXPRT *)0;
+		svc_fds &= ~(1 << sock);
+	}
+#endif /* def FD_SETSIZE */
+}
+
+
+/* ********************** CALLOUT list related stuff ************* */
+
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_register(
+	SVCXPRT *xprt,
+	uint32_t prog,
+	uint32_t vers,
+	void (*dispatch)(),
+	int protocol)
+{
+	struct svc_callout *prev;
+	struct svc_callout *s;
+
+	if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
+		if (s->sc_dispatch == dispatch)
+			goto pmap_it;  /* he is registering another xptr */
+		return (FALSE);
+	}
+	s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
+	if (s == (struct svc_callout *)0) {
+		return (FALSE);
+	}
+	s->sc_prog = prog;
+	s->sc_vers = vers;
+	s->sc_dispatch = dispatch;
+	s->sc_next = svc_head;
+	svc_head = s;
+pmap_it:
+	/* now register the information with the local binder service */
+	if (protocol) {
+		return (pmap_set(prog, vers, protocol, xprt->xp_port));
+	}
+	return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unregister(
+	uint32_t prog,
+	uint32_t vers)
+{
+	struct svc_callout *prev;
+	struct svc_callout *s;
+
+	if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
+		return;
+	if (prev == NULL_SVC) {
+		svc_head = s->sc_next;
+	} else {
+		prev->sc_next = s->sc_next;
+	}
+	s->sc_next = NULL_SVC;
+	mem_free((char *) s, (uint_t) sizeof(struct svc_callout));
+	/* now unregister the information with the local binder service */
+	(void)pmap_unset(prog, vers);
+}
+
+/*
+ * Search the callout list for a program number, return the callout
+ * struct.
+ */
+static struct svc_callout *
+svc_find(
+	uint32_t prog,
+	uint32_t vers,
+	struct svc_callout **prev)
+{
+	struct svc_callout *s, *p;
+
+	p = NULL_SVC;
+	for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+		if ((s->sc_prog == prog) && (s->sc_vers == vers))
+			goto done;
+		p = s;
+	}
+done:
+	*prev = p;
+	return (s);
+}
+
+/* ******************* REPLY GENERATION ROUTINES  ************ */
+
+/*
+ * Send a reply to an rpc request
+ */
+bool_t
+svc_sendreply(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_results,
+	void *xdr_location)
+{
+	struct rpc_msg rply; 
+
+	rply.rm_direction = REPLY;  
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf; 
+	rply.acpted_rply.ar_stat = SUCCESS;
+	rply.acpted_rply.ar_results.where = xdr_location;
+	rply.acpted_rply.ar_results.proc = xdr_results;
+	return (SVC_REPLY(xprt, &rply)); 
+}
+
+/*
+ * No procedure error reply
+ */
+void
+svcerr_noproc(
+	SVCXPRT *xprt)
+{
+	struct rpc_msg rply;
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = PROC_UNAVAIL;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Can't decode args error reply
+ */
+void
+svcerr_decode(
+	SVCXPRT *xprt)
+{
+	struct rpc_msg rply; 
+
+	rply.rm_direction = REPLY; 
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = GARBAGE_ARGS;
+	SVC_REPLY(xprt, &rply); 
+}
+
+/*
+ * Some system error
+ */
+void
+svcerr_systemerr(
+	SVCXPRT *xprt)
+{
+	struct rpc_msg rply; 
+
+	rply.rm_direction = REPLY; 
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = SYSTEM_ERR;
+	SVC_REPLY(xprt, &rply); 
+}
+
+/*
+ * Authentication error reply
+ */
+void
+svcerr_auth(
+	SVCXPRT *xprt,
+	enum auth_stat why)
+{
+	struct rpc_msg rply;
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_DENIED;
+	rply.rjcted_rply.rj_stat = AUTH_ERROR;
+	rply.rjcted_rply.rj_why = why;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Auth too weak error reply
+ */
+void
+svcerr_weakauth(
+	SVCXPRT *xprt)
+{
+
+	svcerr_auth(xprt, AUTH_TOOWEAK);
+}
+
+/*
+ * Program unavailable error reply
+ */
+void 
+svcerr_noprog(
+	SVCXPRT *xprt)
+{
+	struct rpc_msg rply;  
+
+	rply.rm_direction = REPLY;   
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;  
+	rply.acpted_rply.ar_verf = xprt->xp_verf;  
+	rply.acpted_rply.ar_stat = PROG_UNAVAIL;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Program version mismatch error reply
+ */
+void  
+svcerr_progvers(
+	SVCXPRT *xprt,
+	uint32_t low_vers,
+	uint32_t high_vers)
+{
+	struct rpc_msg rply;
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = PROG_MISMATCH;
+	rply.acpted_rply.ar_vers.low = low_vers;
+	rply.acpted_rply.ar_vers.high = high_vers;
+	SVC_REPLY(xprt, &rply);
+}
+
+/* ******************* SERVER INPUT STUFF ******************* */
+
+/*
+ * Get server side input from some transport.
+ *
+ * Statement of authentication parameters management:
+ * This function owns and manages all authentication parameters, specifically
+ * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
+ * the "cooked" credentials (rqst->rq_clntcred).
+ * However, this function does not know the structure of the cooked
+ * credentials, so it make the following assumptions: 
+ *   a) the structure is contiguous (no pointers), and
+ *   b) the cred structure size does not exceed RQCRED_SIZE bytes. 
+ * In all events, all three parameters are freed upon exit from this routine.
+ * The storage is trivially management on the call stack in user land, but
+ * is mallocated in kernel land.
+ */
+
+void
+svc_getreqset(
+#ifdef FD_SETSIZE
+	fd_set *readfds)
+{
+#else
+	int *readfds)
+{
+    int readfds_local = *readfds;
+#endif /* def FD_SETSIZE */
+	enum xprt_stat stat;
+	struct rpc_msg msg;
+	int prog_found;
+	uint32_t low_vers;
+	uint32_t high_vers;
+	struct svc_req r;
+	SVCXPRT *xprt;
+	int setsize;
+	int sock;
+	char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
+	msg.rm_call.cb_cred.oa_base = cred_area;
+	msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
+	r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
+
+
+#ifdef FD_SETSIZE
+	setsize = _rpc_dtablesize();	
+	for (sock = 0; sock < setsize; sock++) {
+	    if (FD_ISSET(sock, readfds)) {
+#else
+	for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
+	    if ((readfds_local & 1) != 0) {
+#endif /* def FD_SETSIZE */
+		/* sock has input waiting */
+		xprt = xports[sock];
+		/* now receive msgs from xprtprt (support batch calls) */
+		do {
+			if (SVC_RECV(xprt, &msg)) {
+
+				/* now find the exported program and call it */
+				struct svc_callout *s;
+				enum auth_stat why;
+
+				r.rq_xprt = xprt;
+				r.rq_prog = msg.rm_call.cb_prog;
+				r.rq_vers = msg.rm_call.cb_vers;
+				r.rq_proc = msg.rm_call.cb_proc;
+				r.rq_cred = msg.rm_call.cb_cred;
+				/* first authenticate the message */
+				if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
+					svcerr_auth(xprt, why);
+					goto call_done;
+				}
+				/* now match message with a registered service*/
+				prog_found = FALSE;
+				low_vers = 0 - 1;
+				high_vers = 0;
+				for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+					if (s->sc_prog == r.rq_prog) {
+						if (s->sc_vers == r.rq_vers) {
+							(*s->sc_dispatch)(&r, xprt);
+							goto call_done;
+						}  /* found correct version */
+						prog_found = TRUE;
+						if (s->sc_vers < low_vers)
+							low_vers = s->sc_vers;
+						if (s->sc_vers > high_vers)
+							high_vers = s->sc_vers;
+					}   /* found correct program */
+				}
+				/*
+				 * if we got here, the program or version
+				 * is not served ...
+				 */
+				if (prog_found)
+					svcerr_progvers(xprt,
+					low_vers, high_vers);
+				else
+					 svcerr_noprog(xprt);
+				/* Fall through to ... */
+			}
+		call_done:
+			if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+				SVC_DESTROY(xprt);
+				break;
+			}
+		} while (stat == XPRT_MOREREQS);
+	    }
+	}
+}
diff --git a/TBBT/trace_play/rpc/svc.h b/TBBT/trace_play/rpc/svc.h
new file mode 100755
index 0000000..497a6ca
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc.h
@@ -0,0 +1,314 @@
+/*
+ * @(#)svc.h     2.1     97/10/23
+ */
+/* @(#)svc.h	2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __SVC_HEADER__
+#define __SVC_HEADER__
+
+#include "rpc/rpc_msg.h"
+#include "rpc/xdr.h"
+
+/*
+ * This interface must manage two items concerning remote procedure calling:
+ *
+ * 1) An arbitrary number of transport connections upon which rpc requests
+ * are received.  The two most notable transports are TCP and UDP;  they are
+ * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
+ * they in turn call xprt_register and xprt_unregister.
+ *
+ * 2) An arbitrary number of locally registered services.  Services are
+ * described by the following four data: program number, version number,
+ * "service dispatch" function, a transport handle, and a boolean that
+ * indicates whether or not the exported program should be registered with a
+ * local binder service;  if true the program's number and version and the
+ * port number from the transport handle are registered with the binder.
+ * These data are registered with the rpc svc system via svc_register.
+ *
+ * A service's dispatch function is called whenever an rpc request comes in
+ * on a transport.  The request's program and version numbers must match
+ * those of the registered service.  The dispatch function is passed two
+ * parameters, struct svc_req * and SVCXPRT *, defined below.
+ */
+
+enum xprt_stat {
+	XPRT_DIED,
+	XPRT_MOREREQS,
+	XPRT_IDLE
+};
+
+/*
+ * Server side transport handle
+ */
+typedef struct SVCXPRT {
+	int		xp_sock;
+	uint16_t	xp_port;	 /* associated port number */
+	struct xp_ops	*xp_ops;
+#if defined(AIX)
+	size_t		xp_addrlen;	 /* length of remote address */
+#else
+	int		xp_addrlen;	 /* length of remote address */
+#endif
+	struct sockaddr_in xp_raddr;	 /* remote address */
+	struct opaque_auth xp_verf;	 /* raw response verifier */
+	void *		xp_p1;		 /* private */
+	void *		xp_p2;		 /* private */
+} SVCXPRT;
+
+struct xp_ops {
+	bool_t	(*xp_recv)(SVCXPRT *, struct rpc_msg *);
+	enum xprt_stat (*xp_stat)(SVCXPRT *);
+	bool_t	(*xp_getargs)(SVCXPRT *, xdrproc_t, void *);
+	bool_t	(*xp_reply)(SVCXPRT *, struct rpc_msg *);
+	bool_t	(*xp_freeargs)(SVCXPRT *, xdrproc_t, void *);
+	void	(*xp_destroy)(SVCXPRT *);
+};
+/*
+ *  Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Operations defined on an SVCXPRT handle
+ *
+ * SVCXPRT		*xprt;
+ * struct rpc_msg	*msg;
+ * xdrproc_t		 xargs;
+ * void *		 argsp;
+ */
+#define SVC_RECV(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+#define svc_recv(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+
+#define SVC_STAT(xprt)					\
+	(*(xprt)->xp_ops->xp_stat)(xprt)
+#define svc_stat(xprt)					\
+	(*(xprt)->xp_ops->xp_stat)(xprt)
+
+#define SVC_GETARGS(xprt, xargs, argsp)			\
+	(*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+#define svc_getargs(xprt, xargs, argsp)			\
+	(*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+
+#define SVC_REPLY(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+#define svc_reply(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+
+#define SVC_FREEARGS(xprt, xargs, argsp)		\
+	(*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+#define svc_freeargs(xprt, xargs, argsp)		\
+	(*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+
+#define SVC_DESTROY(xprt)				\
+	(*(xprt)->xp_ops->xp_destroy)(xprt)
+#define svc_destroy(xprt)				\
+	(*(xprt)->xp_ops->xp_destroy)(xprt)
+
+
+/*
+ * Service request
+ */
+struct svc_req {
+	uint32_t	rq_prog;	/* service program number */
+	uint32_t	rq_vers;	/* service protocol version */
+	uint32_t	rq_proc;	/* the desired procedure */
+	struct opaque_auth rq_cred;	/* raw creds from the wire */
+	void *		rq_clntcred;	/* read only cooked cred */
+	SVCXPRT	*rq_xprt;		/* associated transport */
+};
+
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ *	SVCXPRT *xprt;
+ *	uint32_t prog;
+ *	uint32_t vers;
+ *	void (*dispatch)();
+ *	int protocol;
+ */
+extern bool_t	svc_register(SVCXPRT *, uint32_t, uint32_t, void (*)(), int);
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ *	uint32_t prog;
+ *	uint32_t vers;
+ */
+extern void	svc_unregister(uint32_t, uint32_t);
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ *	SVCXPRT *xprt;
+ */
+extern void	xprt_register(SVCXPRT *);
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ *	SVCXPRT *xprt;
+ */
+extern void	xprt_unregister(SVCXPRT *);
+
+
+
+
+/*
+ * When the service routine is called, it must first check to see if it
+ * knows about the procedure;  if not, it should call svcerr_noproc
+ * and return.  If so, it should deserialize its arguments via 
+ * SVC_GETARGS (defined above).  If the deserialization does not work,
+ * svcerr_decode should be called followed by a return.  Successful
+ * decoding of the arguments should be followed the execution of the
+ * procedure's code and a call to svc_sendreply.
+ *
+ * Also, if the service refuses to execute the procedure due to too-
+ * weak authentication parameters, svcerr_weakauth should be called.
+ * Note: do not confuse access-control failure with weak authentication!
+ *
+ * NB: In pure implementations of rpc, the caller always waits for a reply
+ * msg.  This message is sent when svc_sendreply is called.  
+ * Therefore pure service implementations should always call
+ * svc_sendreply even if the function logically returns void;  use
+ * xdr.h - xdr_void for the xdr routine.  HOWEVER, tcp based rpc allows
+ * for the abuse of pure rpc via batched calling or pipelining.  In the
+ * case of a batched call, svc_sendreply should NOT be called since
+ * this would send a return message, which is what batching tries to avoid.
+ * It is the service/protocol writer's responsibility to know which calls are
+ * batched and which are not.  Warning: responding to batch calls may
+ * deadlock the caller and server processes!
+ */
+
+extern bool_t	svc_sendreply(SVCXPRT *, xdrproc_t, void *);
+extern void	svcerr_decode(SVCXPRT *);
+extern void	svcerr_weakauth(SVCXPRT *);
+extern void	svcerr_noproc(SVCXPRT *);
+extern void	svcerr_progvers(SVCXPRT *, uint32_t, uint32_t);
+extern void	svcerr_auth(SVCXPRT *, enum auth_stat);
+extern void	svcerr_noprog(SVCXPRT *);
+extern void	svcerr_systemerr(SVCXPRT *);
+    
+/*
+ * Lowest level dispatching -OR- who owns this process anyway.
+ * Somebody has to wait for incoming requests and then call the correct
+ * service routine.  The routine svc_run does infinite waiting; i.e.,
+ * svc_run never returns.
+ * Since another (co-existant) package may wish to selectively wait for
+ * incoming calls or other events outside of the rpc architecture, the
+ * routine svc_getreq is provided.  It must be passed readfds, the
+ * "in-place" results of a select system call (see select, section 2).
+ */
+
+/*
+ * Global keeper of rpc service descriptors in use
+ * dynamic; must be inspected before each call to select 
+ */
+#ifdef FD_SETSIZE
+extern fd_set svc_fdset;
+#define svc_fds svc_fdset.fds_bits[0]	/* compatibility */
+#else
+extern int svc_fds;
+#endif /* def FD_SETSIZE */
+
+/*
+ * a small program implemented by the svc_rpc implementation itself;
+ * also see clnt.h for protocol numbers.
+ */
+extern void rpctest_service();
+
+extern void	svc_getreq(int);
+#ifdef FD_SETSIZE
+extern void	svc_getreqset(fd_set *);/* takes fdset instead of int */
+#else
+extern void	svc_getreqset(int *);
+#endif
+extern void	svc_run(void); 	 /* never returns */
+
+/*
+ * Socket to use on svcxxx_create call to get default socket
+ */
+#define	RPC_ANYSOCK	-1
+
+/*
+ * These are the existing service side transport implementations
+ */
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+extern SVCXPRT *svcraw_create(void);
+
+/*
+ * Udp based rpc.
+ */
+extern SVCXPRT *svcudp_create(int);
+extern SVCXPRT *svcudp_bufcreate(int, uint_t, uint_t);
+
+/*
+ * Tcp based rpc.
+ */
+extern SVCXPRT *svctcp_create(int, uint_t, uint_t);
+
+extern int svcudp_enablecache(SVCXPRT *, uint32_t);
+
+
+#endif /* !__SVC_HEADER__ */
diff --git a/TBBT/trace_play/rpc/svc_auth.c b/TBBT/trace_play/rpc/svc_auth.c
new file mode 100755
index 0000000..2352630
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_auth.c
@@ -0,0 +1,136 @@
+#ifndef lint
+static char sfs_svc_auth_id[] = "@(#)svc_auth.c     2.1     97/10/23";
+#endif
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth.c	2.1 88/08/07 4.0 RPCSRC; from 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * svc_auth_nodes.c, Server-side rpc authenticator interface,
+ * *WITHOUT* DES authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "rpc/rpc.h"
+
+/*
+ * svcauthsw is the bdevsw of server side authentication. 
+ * 
+ * Server side authenticators are called from authenticate by
+ * using the client auth struct flavor field to index into svcauthsw.
+ * The server auth flavors must implement a routine that looks  
+ * like: 
+ * 
+ *	enum auth_stat
+ *	flavorx_auth(rqst, msg)
+ *		register struct svc_req *rqst; 
+ *		register struct rpc_msg *msg;
+ *
+ */
+
+extern enum auth_stat _svcauth_null(struct svc_req *, struct rpc_msg *);
+extern enum auth_stat _svcauth_unix(struct svc_req *, struct rpc_msg *);
+extern enum auth_stat _svcauth_short(struct svc_req *, struct rpc_msg *);
+
+static struct {
+	enum auth_stat (*authenticator)(struct svc_req *, struct rpc_msg *);
+} svcauthsw[] = {
+	_svcauth_null,			/* AUTH_NULL */
+	_svcauth_unix,			/* AUTH_UNIX */
+	_svcauth_short,			/* AUTH_SHORT */
+};
+#define	AUTH_MAX	2		/* HIGHEST AUTH NUMBER */
+
+
+/*
+ * The call rpc message, msg has been obtained from the wire.  The msg contains
+ * the raw form of credentials and verifiers.  authenticate returns AUTH_OK
+ * if the msg is successfully authenticated.  If AUTH_OK then the routine also
+ * does the following things:
+ * set rqst->rq_xprt->verf to the appropriate response verifier;
+ * sets rqst->rq_client_cred to the "cooked" form of the credentials.
+ *
+ * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * its length is set appropriately.
+ *
+ * The caller still owns and is responsible for msg->u.cmb.cred and
+ * msg->u.cmb.verf.  The authentication system retains ownership of
+ * rqst->rq_client_cred, the cooked credentials.
+ *
+ * There is an assumption that any flavour less than AUTH_NULL is
+ * invalid.
+ */
+enum auth_stat
+_authenticate(
+	struct svc_req *rqst,
+	struct rpc_msg *msg)
+{
+	register int cred_flavor;
+
+	rqst->rq_cred = msg->rm_call.cb_cred;
+	rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+	rqst->rq_xprt->xp_verf.oa_length = 0;
+	cred_flavor = rqst->rq_cred.oa_flavor;
+	if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) {
+		return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg));
+	}
+
+	return (AUTH_REJECTEDCRED);
+}
+
+/* ARGSUSED */
+enum auth_stat
+_svcauth_null(
+	struct svc_req *rqst,
+	struct rpc_msg *msg)
+{
+
+	return (AUTH_OK);
+}
diff --git a/TBBT/trace_play/rpc/svc_auth.h b/TBBT/trace_play/rpc/svc_auth.h
new file mode 100755
index 0000000..c765e9f
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_auth.h
@@ -0,0 +1,62 @@
+/*
+ * @(#)svc_auth.h     2.1     97/10/23
+ */
+/* @(#)svc_auth.h	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)svc_auth.h 1.6 86/07/16 SMI      */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ * 
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Server side authenticator
+ */
+extern enum auth_stat _authenticate();
diff --git a/TBBT/trace_play/rpc/svc_auth_unix.c b/TBBT/trace_play/rpc/svc_auth_unix.c
new file mode 100755
index 0000000..83ed327
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_auth_unix.c
@@ -0,0 +1,156 @@
+#ifndef lint
+static char sfs_svc_auth_unix_id[] = "@(#)svc_auth_unix.c     2.1     97/10/23";
+#endif
+/* @(#)svc_auth_unix.c	2.3 88/08/01 4.0 RPCSRC; from 1.28 88/02/08 SMI */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Manassas, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_auth_unix.c
+ * Handles UNIX flavor authentication parameters on the service side of rpc.
+ * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
+ * _svcauth_unix does full blown unix style uid,gid+gids auth,
+ * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
+ * Note: the shorthand has been gutted for efficiency.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "rpc/rpc.h"
+
+/*
+ * Unix longhand authenticator
+ */
+enum auth_stat
+_svcauth_unix(
+	struct svc_req *rqst,
+	struct rpc_msg *msg)
+{
+	enum auth_stat stat;
+	XDR xdrs;
+	struct authunix_parms *aup;
+	int32_t *buf;
+	struct area {
+		struct authunix_parms area_aup;
+		char area_machname[MAX_MACHINE_NAME+1];
+		int area_gids[NGRPS];
+	} *area;
+	uint_t auth_len;
+	int str_len, gid_len;
+	int i;
+
+	area = (struct area *) rqst->rq_clntcred;
+	aup = &area->area_aup;
+	aup->aup_machname = area->area_machname;
+	aup->aup_gids = area->area_gids;
+	auth_len = (uint_t)msg->rm_call.cb_cred.oa_length;
+	xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
+	buf = XDR_INLINE(&xdrs, auth_len);
+	if (buf != NULL) {
+		aup->aup_time = IXDR_GET_LONG(buf);
+		str_len = IXDR_GET_U_LONG(buf);
+		if (str_len > MAX_MACHINE_NAME) {
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+		memmove(aup->aup_machname, (void *)buf, (uint_t)str_len);
+		aup->aup_machname[str_len] = 0;
+		str_len = RNDUP(str_len);
+		buf += str_len / sizeof (int32_t);
+		aup->aup_uid = IXDR_GET_LONG(buf);
+		aup->aup_gid = IXDR_GET_LONG(buf);
+		gid_len = IXDR_GET_U_LONG(buf);
+		if (gid_len > NGRPS) {
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+		aup->aup_len = gid_len;
+		for (i = 0; i < gid_len; i++) {
+			aup->aup_gids[i] = IXDR_GET_LONG(buf);
+		}
+		/*
+		 * five is the smallest unix credentials structure -
+		 * timestamp, hostname len (0), uid, gid, and gids len (0).
+		 */
+		if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
+			(void) printf("bad auth_len gid %d str %d auth %d\n",
+			    gid_len, str_len, auth_len);
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+	} else if (! xdr_authunix_parms(&xdrs, aup)) {
+		xdrs.x_op = XDR_FREE;
+		(void)xdr_authunix_parms(&xdrs, aup);
+		stat = AUTH_BADCRED;
+		goto done;
+	}
+	rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
+	rqst->rq_xprt->xp_verf.oa_length = 0;
+	stat = AUTH_OK;
+done:
+	XDR_DESTROY(&xdrs);
+	return (stat);
+}
+
+
+/*
+ * Shorthand unix authenticator
+ * Looks up longhand in a cache.
+ */
+/*ARGSUSED*/
+enum auth_stat 
+_svcauth_short(
+	struct svc_req *rqst,
+	struct rpc_msg *msg)
+{
+	return (AUTH_REJECTEDCRED);
+}
diff --git a/TBBT/trace_play/rpc/svc_raw.c b/TBBT/trace_play/rpc/svc_raw.c
new file mode 100755
index 0000000..4b85782
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_raw.c
@@ -0,0 +1,196 @@
+#ifndef lint
+static char sfs_svc_raw_id[] = "@(#)svc_raw.c     2.1     97/10/23";
+#endif
+/* @(#)svc_raw.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_raw.c,   This a toy for simple testing and timing.
+ * Interface to create an rpc client and server in the same UNIX process.
+ * This lets us similate rpc and get rpc (round trip) overhead, without
+ * any interference from the kernal.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "rpc/rpc.h"
+
+
+/*
+ * This is the "network" that we will be moving data over
+ */
+static struct svcraw_private {
+	char	_raw_buf[UDPMSGSIZE];
+	SVCXPRT	server;
+	XDR	xdr_stream;
+	char	verf_body[MAX_AUTH_BYTES];
+} *svcraw_private;
+
+static bool_t		svcraw_recv(SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat 	svcraw_stat(SVCXPRT *);
+static bool_t		svcraw_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t		svcraw_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t		svcraw_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void		svcraw_destroy(SVCXPRT *);
+
+static struct xp_ops server_ops = {
+	svcraw_recv,
+	svcraw_stat,
+	svcraw_getargs,
+	svcraw_reply,
+	svcraw_freeargs,
+	svcraw_destroy
+};
+
+SVCXPRT *
+svcraw_create(void)
+{
+	struct svcraw_private *srp = svcraw_private;
+
+	if (srp == 0) {
+		srp = (struct svcraw_private *)calloc(1, sizeof (struct svcraw_private));
+		if (srp == 0)
+			return (0);
+	}
+	srp->server.xp_sock = 0;
+	srp->server.xp_port = 0;
+	srp->server.xp_ops = &server_ops;
+	srp->server.xp_verf.oa_base = srp->verf_body;
+	xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+	return (&srp->server);
+}
+
+/* ARGSUSED */
+static enum xprt_stat
+svcraw_stat(SVCXPRT *x)
+{
+
+	return (XPRT_IDLE);
+}
+
+/* ARGSUSED */
+static bool_t
+svcraw_recv(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+	struct svcraw_private *srp = svcraw_private;
+	XDR *xdrs;
+
+	if (srp == 0)
+		return (0);
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_DECODE;
+	XDR_SETPOS(xdrs, 0);
+	if (! xdr_callmsg(xdrs, msg))
+	       return (FALSE);
+	return (TRUE);
+}
+
+/* ARGSUSED */
+static bool_t
+svcraw_reply(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+	struct svcraw_private *srp = svcraw_private;
+	XDR *xdrs;
+
+	if (srp == 0)
+		return (FALSE);
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, 0);
+	if (! xdr_replymsg(xdrs, msg))
+	       return (FALSE);
+	(void)XDR_GETPOS(xdrs);  /* called just for overhead */
+	return (TRUE);
+}
+
+/* ARGSUSED */
+static bool_t
+svcraw_getargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void *args_ptr)
+{
+	struct svcraw_private *srp = svcraw_private;
+
+	if (srp == 0)
+		return (FALSE);
+	return ((*xdr_args)(&srp->xdr_stream, args_ptr));
+}
+
+/* ARGSUSED */
+static bool_t
+svcraw_freeargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void *args_ptr)
+{ 
+	struct svcraw_private *srp = svcraw_private;
+	XDR *xdrs;
+
+	if (srp == 0)
+		return (FALSE);
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_args)(xdrs, args_ptr));
+} 
+
+/* ARGSUSED */
+static void
+svcraw_destroy(SVCXPRT *x)
+{
+}
diff --git a/TBBT/trace_play/rpc/svc_run.c b/TBBT/trace_play/rpc/svc_run.c
new file mode 100755
index 0000000..0c787b4
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_run.c
@@ -0,0 +1,93 @@
+#ifndef lint
+static char sfs_svc_run_id[] = "@(#)svc_run.c     2.1     97/10/23";
+#endif
+/* @(#)svc_run.c	2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+#include "rpc/rpc.h"
+#include <errno.h>
+
+void
+svc_run(void)
+{
+#ifdef FD_SETSIZE
+	fd_set readfds;
+#else
+	int readfds;
+#endif /* def FD_SETSIZE */
+	extern int errno;
+
+	for (;;) {
+#ifdef FD_SETSIZE
+		readfds = svc_fdset;
+#else
+		readfds = svc_fds;
+#endif /* def FD_SETSIZE */
+		switch (select(_rpc_dtablesize(), &readfds, NULL, NULL,
+			       NULL)) {
+		case -1:
+			if (errno == EINTR) {
+				continue;
+			}
+			perror("svc_run: - select failed");
+			return;
+		case 0:
+			continue;
+		default:
+			svc_getreqset(&readfds);
+		}
+	}
+}
diff --git a/TBBT/trace_play/rpc/svc_simple.c b/TBBT/trace_play/rpc/svc_simple.c
new file mode 100755
index 0000000..ec22a47
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_simple.c
@@ -0,0 +1,171 @@
+#ifndef lint
+static char sfs_svc_simple_id[] = "@(#)svc_simple.c     2.1     97/10/23";
+#endif
+/* @(#)svc_simple.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/* 
+ * svc_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <netdb.h>
+
+static struct proglst {
+	char *(*p_progname)();
+	int  p_prognum;
+	int  p_procnum;
+	xdrproc_t p_inproc, p_outproc;
+	struct proglst *p_nxt;
+} *proglst;
+static void universal(struct svc_req *, SVCXPRT *);
+static SVCXPRT *transp;
+
+registerrpc(
+	int prognum,
+	int versnum,
+	int procnum,
+	char *(*progname)(),
+	xdrproc_t inproc,
+	xdrproc_t outproc)
+{
+	struct proglst *pl;
+	
+	if (procnum == NULLPROC) {
+		(void) fprintf(stderr,
+		    "can't reassign procedure number %d\n", NULLPROC);
+		return (-1);
+	}
+	if (transp == 0) {
+		transp = svcudp_create(RPC_ANYSOCK);
+		if (transp == NULL) {
+			(void) fprintf(stderr, "couldn't create an rpc server\n");
+			return (-1);
+		}
+	}
+	(void) pmap_unset((uint32_t)prognum, (uint32_t)versnum);
+	if (!svc_register(transp, (uint32_t)prognum, (uint32_t)versnum, 
+	    universal, IPPROTO_UDP)) {
+	    	(void) fprintf(stderr, "couldn't register prog %d vers %d\n",
+		    prognum, versnum);
+		return (-1);
+	}
+	pl = (struct proglst *)malloc(sizeof(struct proglst));
+	if (pl == NULL) {
+		(void) fprintf(stderr, "registerrpc: out of memory\n");
+		return (-1);
+	}
+	pl->p_progname = progname;
+	pl->p_prognum = prognum;
+	pl->p_procnum = procnum;
+	pl->p_inproc = inproc;
+	pl->p_outproc = outproc;
+	pl->p_nxt = proglst;
+	proglst = pl;
+	return (0);
+}
+
+static void
+universal(
+	struct svc_req *rqstp,
+	SVCXPRT *transp)
+{
+	int prog, proc;
+	char *outdata;
+	char xdrbuf[UDPMSGSIZE];
+	struct proglst *pl;
+
+	/* 
+	 * enforce "procnum 0 is echo" convention
+	 */
+	if (rqstp->rq_proc == NULLPROC) {
+		if (svc_sendreply(transp, xdr_void, (char *)NULL) == FALSE) {
+			(void) fprintf(stderr, "xxx\n");
+			exit(1);
+		}
+		return;
+	}
+	prog = rqstp->rq_prog;
+	proc = rqstp->rq_proc;
+	for (pl = proglst; pl != NULL; pl = pl->p_nxt)
+		if (pl->p_prognum == prog && pl->p_procnum == proc) {
+			/* decode arguments into a CLEAN buffer */
+			memset(xdrbuf, '\0', sizeof(xdrbuf)); /* required ! */
+			if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
+				svcerr_decode(transp);
+				return;
+			}
+			outdata = (*(pl->p_progname))(xdrbuf);
+			if (outdata == NULL && pl->p_outproc != xdr_void)
+				/* there was an error */
+				return;
+			if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
+				(void) fprintf(stderr,
+				    "trouble replying to prog %d\n",
+				    pl->p_prognum);
+				exit(1);
+			}
+			/* free the decoded arguments */
+			(void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
+			return;
+		}
+	(void) fprintf(stderr, "never registered prog %d\n", prog);
+	exit(1);
+}
+
diff --git a/TBBT/trace_play/rpc/svc_tcp.c b/TBBT/trace_play/rpc/svc_tcp.c
new file mode 100755
index 0000000..2b8b71a
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_tcp.c
@@ -0,0 +1,481 @@
+#ifndef lint
+static char sfs_svc_tcp_id[] = "@(#)svc_tcp.c     2.1     97/10/23";
+#endif
+/* @(#)svc_tcp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_tcp.c, Server side for TCP/IP based RPC. 
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <errno.h>
+
+/*
+ * Ops vector for TCP/IP based rpc service handle
+ */
+static bool_t		svctcp_recv(SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat	svctcp_stat(SVCXPRT *);
+static bool_t		svctcp_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t		svctcp_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t		svctcp_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void		svctcp_destroy(SVCXPRT *);
+static bool_t		svctcp_abortrop(SVCXPRT *, struct rpc_msg *);
+static bool_t		svctcp_abortgop(SVCXPRT *, xdrproc_t, void *);
+
+static struct xp_ops svctcp_op = {
+	svctcp_recv,
+	svctcp_stat,
+	svctcp_getargs,
+	svctcp_reply,
+	svctcp_freeargs,
+	svctcp_destroy
+};
+
+/*
+ * Ops vector for TCP/IP rendezvous handler
+ */
+static bool_t		rendezvous_request(SVCXPRT *xprt, struct rpc_msg *);
+static enum xprt_stat	rendezvous_stat(SVCXPRT *);
+
+static struct xp_ops svctcp_rendezvous_op = {
+	rendezvous_request,
+	rendezvous_stat,
+	svctcp_abortgop,
+	svctcp_abortrop,
+	svctcp_abortgop,
+	svctcp_destroy
+};
+
+static int readtcp(), writetcp();
+static int readtcp(SVCXPRT *, char *, int);
+static int writetcp(SVCXPRT *, char *, int);
+static SVCXPRT *makefd_xprt(int, uint_t, uint_t);
+
+struct tcp_rendezvous { /* kept in xprt->xp_p1 */
+	uint_t sendsize;
+	uint_t recvsize;
+};
+
+struct tcp_conn {  /* kept in xprt->xp_p1 */
+	enum xprt_stat strm_stat;
+	uint32_t x_id;
+	XDR xdrs;
+	char verf_body[MAX_AUTH_BYTES];
+};
+
+/*
+ * Usage:
+ *	xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) tcp based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register).  This routine returns
+ * a NULL if a problem occurred.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svctcp_create
+ * binds it to an arbitrary port.  The routine then starts a tcp
+ * listener on the socket's associated port.  In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since tcp streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svctcp_create(
+	int sock,
+	uint_t sendsize,
+	uint_t recvsize)
+{
+	bool_t madesock = FALSE;
+	SVCXPRT *xprt;
+	struct tcp_rendezvous *r;
+	struct sockaddr_in addr;
+#if defined(AIX) 
+	size_t len;
+#else 
+	int len;
+#endif /* AIX */ 
+ 
+	len = sizeof(struct sockaddr_in);
+
+	if (sock == RPC_ANYSOCK) {
+		if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+			perror("svctcp_.c - udp socket creation problem");
+			return ((SVCXPRT *)NULL);
+		}
+		madesock = TRUE;
+	}
+	memset((char *)&addr, '\0', sizeof (addr));
+	addr.sin_family = AF_INET;
+	if (bindresvport(sock, &addr)) {
+		addr.sin_port = 0;
+		(void)bind(sock, (struct sockaddr *)&addr, len);
+	}
+	if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0)  ||
+	    (listen(sock, 2) != 0)) {
+		perror("svctcp_.c - cannot getsockname or listen");
+		if (madesock)
+		       (void)close(sock);
+		return ((SVCXPRT *)NULL);
+	}
+	r = (struct tcp_rendezvous *)mem_alloc(sizeof(struct tcp_rendezvous));
+	if (r == NULL) {
+		(void) fprintf(stderr, "svctcp_create: out of memory\n");
+		return (NULL);
+	}
+	r->sendsize = sendsize;
+	r->recvsize = recvsize;
+	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+	if (xprt == NULL) {
+		(void) fprintf(stderr, "svctcp_create: out of memory\n");
+		return (NULL);
+	}
+	xprt->xp_p2 = NULL;
+	xprt->xp_p1 = (void *)r;
+	xprt->xp_verf = _null_auth;
+	xprt->xp_ops = &svctcp_rendezvous_op;
+	xprt->xp_port = ntohs(addr.sin_port);
+	xprt->xp_sock = sock;
+	xprt_register(xprt);
+	return (xprt);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcfd_create(
+	int fd,
+	uint_t sendsize,
+	uint_t recvsize)
+{
+
+	return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(
+	int fd,
+	uint_t sendsize,
+	uint_t recvsize)
+{
+	SVCXPRT *xprt;
+	struct tcp_conn *cd;
+ 
+	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+	if (xprt == (SVCXPRT *)NULL) {
+		(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+		goto done;
+	}
+	cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
+	if (cd == (struct tcp_conn *)NULL) {
+		(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+		mem_free((char *) xprt, sizeof(SVCXPRT));
+		xprt = (SVCXPRT *)NULL;
+		goto done;
+	}
+	cd->strm_stat = XPRT_IDLE;
+	xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+	    (void *)xprt, readtcp, writetcp);
+	xprt->xp_p2 = NULL;
+	xprt->xp_p1 = (void *)cd;
+	xprt->xp_verf.oa_base = cd->verf_body;
+	xprt->xp_addrlen = 0;
+	xprt->xp_ops = &svctcp_op;  /* truely deals with calls */
+	xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
+	xprt->xp_sock = fd;
+	xprt_register(xprt);
+    done:
+	return (xprt);
+}
+
+/* ARGSUSED */
+static bool_t
+rendezvous_request(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+	int sock;
+	struct tcp_rendezvous *r;
+	struct sockaddr_in addr;
+#if defined(AIX) 
+        size_t len;
+#else 
+        int len;
+#endif /* AIX */ 
+ 
+	r = (struct tcp_rendezvous *)xprt->xp_p1;
+    again:
+	len = sizeof(struct sockaddr_in);
+	if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
+	    &len)) < 0) {
+		if (errno == EINTR)
+			goto again;
+	       return (FALSE);
+	}
+	/*
+	 * make a new transporter (re-uses xprt)
+	 */
+	xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+	xprt->xp_raddr = addr;
+	xprt->xp_addrlen = len;
+	return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+/* ARGSUSED */
+static enum xprt_stat
+rendezvous_stat(SVCXPRT *x)
+{
+
+	return (XPRT_IDLE);
+}
+
+static void
+svctcp_destroy(
+	SVCXPRT *xprt)
+{
+	struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
+
+	xprt_unregister(xprt);
+	(void)close(xprt->xp_sock);
+	if (xprt->xp_port != 0) {
+		/* a rendezvouser socket */
+		xprt->xp_port = 0;
+	} else {
+		/* an actual connection socket */
+		XDR_DESTROY(&(cd->xdrs));
+	}
+	mem_free((void *)cd, sizeof(struct tcp_conn));
+	mem_free((void *)xprt, sizeof(SVCXPRT));
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = { 35, 0 };
+
+/*
+ * reads data from the tcp conection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ */
+static int
+readtcp(
+	SVCXPRT *xprt,
+	char *buf,
+	int len)
+{
+	int sock = xprt->xp_sock;
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+
+	FD_ZERO(&mask);
+	FD_SET(sock, &mask);
+#else
+	int mask = 1 << sock;
+	int readfds;
+#endif /* def FD_SETSIZE */
+	do {
+		readfds = mask;
+		if (select(_rpc_dtablesize(), &readfds, NULL, NULL, 
+			   &wait_per_try) <= 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			goto fatal_err;
+		}
+#ifdef FD_SETSIZE
+	} while (!FD_ISSET(sock, &readfds));
+#else
+	} while (readfds != mask);
+#endif /* def FD_SETSIZE */
+	if ((len = read(sock, buf, len)) > 0) {
+		return (len);
+	}
+fatal_err:
+	((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+	return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writetcp(
+	SVCXPRT *xprt,
+	char *buf,
+	int len)
+{
+	int i, cnt;
+
+	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+		if ((i = write(xprt->xp_sock, buf, cnt)) < 0) {
+			((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
+			    XPRT_DIED;
+			return (-1);
+		}
+	}
+	return (len);
+}
+
+static enum xprt_stat
+svctcp_stat(
+	SVCXPRT *xprt)
+{
+	struct tcp_conn *cd =
+	    (struct tcp_conn *)(xprt->xp_p1);
+
+	if (cd->strm_stat == XPRT_DIED)
+		return (XPRT_DIED);
+	if (! xdrrec_eof(&(cd->xdrs)))
+		return (XPRT_MOREREQS);
+	return (XPRT_IDLE);
+}
+
+static bool_t
+svctcp_recv(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+	struct tcp_conn *cd =
+	    (struct tcp_conn *)(xprt->xp_p1);
+	XDR *xdrs = &(cd->xdrs);
+
+	xdrs->x_op = XDR_DECODE;
+	(void)xdrrec_skiprecord(xdrs);
+	if (xdr_callmsg(xdrs, msg)) {
+		cd->x_id = msg->rm_xid;
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+static bool_t
+svctcp_getargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void * args_ptr)
+{
+
+	return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
+}
+
+static bool_t
+svctcp_freeargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void * args_ptr)
+{
+	XDR *xdrs =
+	    &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svctcp_reply(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+	struct tcp_conn *cd =
+	    (struct tcp_conn *)(xprt->xp_p1);
+	XDR *xdrs = &(cd->xdrs);
+	bool_t stat;
+
+	xdrs->x_op = XDR_ENCODE;
+	msg->rm_xid = cd->x_id;
+	stat = xdr_replymsg(xdrs, msg);
+	(void)xdrrec_endofrecord(xdrs, TRUE);
+	return (stat);
+}
+
+/* ARGSUSED */
+static bool_t
+svctcp_abortrop(
+	SVCXPRT *x,
+	struct rpc_msg *msg)
+{
+	abort();
+	/* NOTREACHED */
+	return (FALSE);
+}
+
+/* ARGSUSED */
+static bool_t
+svctcp_abortgop(
+	SVCXPRT *x,
+	xdrproc_t argp,
+	void *arg)
+{
+	abort();
+	/* NOTREACHED */
+	return (FALSE);
+}
diff --git a/TBBT/trace_play/rpc/svc_udp.c b/TBBT/trace_play/rpc/svc_udp.c
new file mode 100755
index 0000000..0a801b2
--- /dev/null
+++ b/TBBT/trace_play/rpc/svc_udp.c
@@ -0,0 +1,507 @@
+#ifndef lint
+static char sfs_svc_udp_id[] = "@(#)svc_udp.c     2.1     97/10/23";
+#endif
+/* @(#)svc_udp.c	2.2 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_udp.c,
+ * Server side for UDP/IP based RPC.  (Does some caching in the hopes of
+ * achieving execute-at-most-once semantics.)
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "rpc/rpc.h"
+#include "rpc/osdep.h"
+#include <errno.h>
+
+
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+
+static bool_t		svcudp_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t		svcudp_reply(SVCXPRT *, struct rpc_msg *) ;
+static enum xprt_stat	svcudp_stat(SVCXPRT *);
+static bool_t		svcudp_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t		svcudp_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void		svcudp_destroy(SVCXPRT *);
+
+static struct xp_ops svcudp_op = {
+	svcudp_recv,
+	svcudp_stat,
+	svcudp_getargs,
+	svcudp_reply,
+	svcudp_freeargs,
+	svcudp_destroy
+};
+
+/*
+ * kept in xprt->xp_p2
+ */
+struct svcudp_data {
+	uint_t   su_iosz;	/* byte size of send.recv buffer */
+	uint32_t su_xid;		/* transaction id */
+	XDR	su_xdrs;	/* XDR handle */
+	char	su_verfbody[MAX_AUTH_BYTES];	/* verifier body */
+	char * 	su_cache;	/* cached data, NULL if no cache */
+};
+#define	su_data(xprt)	((struct svcudp_data *)(xprt->xp_p2))
+
+static void cache_set(SVCXPRT *, uint32_t);
+static int cache_get(SVCXPRT *, struct rpc_msg *, char **, uint32_t *);
+
+/*
+ * Usage:
+ *	xprt = svcudp_create(sock);
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcudp_create
+ * binds it to an arbitrary port.  In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ * Once *xprt is initialized, it is registered as a transporter;
+ * see (svc.h, xprt_register).
+ * The routines returns NULL if a problem occurred.
+ */
+SVCXPRT *
+svcudp_bufcreate(
+	int sock,
+	uint_t sendsz,
+	uint_t recvsz)
+{
+	bool_t madesock = FALSE;
+	SVCXPRT *xprt;
+	struct svcudp_data *su;
+	struct sockaddr_in addr;
+#if defined(AIX)
+	size_t len;
+#else
+	int len;
+#endif /* AIX */
+
+	len = sizeof(struct sockaddr_in);
+
+	if (sock == RPC_ANYSOCK) {
+		if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+			perror("svcudp_create: socket creation problem");
+			return ((SVCXPRT *)NULL);
+		}
+		madesock = TRUE;
+	}
+	memset((char *)&addr, '\0', sizeof (addr));
+	addr.sin_family = AF_INET;
+	if (bindresvport(sock, &addr)) {
+		addr.sin_port = 0;
+		(void)bind(sock, (struct sockaddr *)&addr, len);
+	}
+	if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
+		perror("svcudp_create - cannot getsockname");
+		if (madesock)
+			(void)close(sock);
+		return ((SVCXPRT *)NULL);
+	}
+	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+	if (xprt == NULL) {
+		(void)fprintf(stderr, "svcudp_create: out of memory\n");
+		return (NULL);
+	}
+	su = (struct svcudp_data *)mem_alloc(sizeof(struct svcudp_data));
+	if (su == NULL) {
+		(void)fprintf(stderr, "svcudp_create: out of memory\n");
+		return (NULL);
+	}
+	su->su_iosz = ((((sendsz > recvsz) ? sendsz : recvsz) + 3) / 4) * 4;
+	if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
+		(void)fprintf(stderr, "svcudp_create: out of memory\n");
+		return (NULL);
+	}
+	xdrmem_create(
+	    &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE);
+	su->su_cache = NULL;
+	xprt->xp_p2 = (caddr_t)su;
+	xprt->xp_verf.oa_base = su->su_verfbody;
+	xprt->xp_ops = &svcudp_op;
+	xprt->xp_port = ntohs(addr.sin_port);
+	xprt->xp_sock = sock;
+	xprt_register(xprt);
+	return (xprt);
+}
+
+SVCXPRT *
+svcudp_create(
+	int sock)
+{
+
+	return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+svcudp_stat(
+	SVCXPRT *xprt)
+{
+
+	return (XPRT_IDLE); 
+}
+
+static bool_t
+svcudp_recv(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+	struct svcudp_data *su = su_data(xprt);
+	XDR *xdrs = &(su->su_xdrs);
+	int rlen;
+	char *reply;
+	uint32_t replylen;
+
+    again:
+	xprt->xp_addrlen = sizeof(struct sockaddr_in);
+	rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
+	    0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
+	if (rlen == -1 && errno == EINTR)
+		goto again;
+	if (rlen < 4*sizeof(uint32_t))
+		return (FALSE);
+	xdrs->x_op = XDR_DECODE;
+	XDR_SETPOS(xdrs, 0);
+	if (! xdr_callmsg(xdrs, msg))
+		return (FALSE);
+	su->su_xid = msg->rm_xid;
+	if (su->su_cache != NULL) {
+		if (cache_get(xprt, msg, &reply, &replylen)) {
+			(void) sendto(xprt->xp_sock, reply, (int) replylen, 0,
+			  (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen);
+			return (TRUE);
+		}
+	}
+	return (TRUE);
+}
+
+static bool_t
+svcudp_reply(
+	SVCXPRT *xprt, 
+	struct rpc_msg *msg) 
+{
+	struct svcudp_data *su = su_data(xprt);
+	XDR *xdrs = &(su->su_xdrs);
+	int slen;
+	bool_t stat = FALSE;
+
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, 0);
+	msg->rm_xid = su->su_xid;
+	if (xdr_replymsg(xdrs, msg)) {
+		slen = (int)XDR_GETPOS(xdrs);
+		if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
+		    (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
+		    == slen) {
+			stat = TRUE;
+			if (su->su_cache && slen >= 0) {
+				cache_set(xprt, (uint32_t) slen);
+			}
+		}
+	}
+	return (stat);
+}
+
+static bool_t
+svcudp_getargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void *args_ptr)
+{
+
+	return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
+}
+
+static bool_t
+svcudp_freeargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void *args_ptr)
+{
+	XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcudp_destroy(
+	SVCXPRT *xprt)
+{
+	struct svcudp_data *su = su_data(xprt);
+
+	xprt_unregister(xprt);
+	(void)close(xprt->xp_sock);
+	XDR_DESTROY(&(su->su_xdrs));
+	mem_free(rpc_buffer(xprt), su->su_iosz);
+	mem_free((caddr_t)su, sizeof(struct svcudp_data));
+	mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+
+/***********this could be a separate file*********************/
+
+/*
+ * Fifo cache for udp server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define SPARSENESS 4	/* 75% sparse */
+
+#define CACHE_PERROR(msg)	\
+	(void) fprintf(stderr,"%s\n", msg)
+
+#define ALLOC(type, size)	\
+	(type *) mem_alloc((unsigned) (sizeof(type) * (size)))
+
+#define BZERO(addr, type, size)	 \
+	memset((void *) addr, '\0', sizeof(type) * (int) (size)) 
+
+/*
+ * An entry in the cache
+ */
+typedef struct cache_node *cache_ptr;
+struct cache_node {
+	/*
+	 * Index into cache is xid, proc, vers, prog and address
+	 */
+	uint32_t cache_xid;
+	uint32_t cache_proc;
+	uint32_t cache_vers;
+	uint32_t cache_prog;
+	struct sockaddr_in cache_addr;
+	/*
+	 * The cached reply and length
+	 */
+	char * cache_reply;
+	uint32_t cache_replylen;
+	/*
+ 	 * Next node on the list, if there is a collision
+	 */
+	cache_ptr cache_next;	
+};
+
+
+
+/*
+ * The entire cache
+ */
+struct udp_cache {
+	uint32_t uc_size;		/* size of cache */
+	cache_ptr *uc_entries;	/* hash table of entries in cache */
+	cache_ptr *uc_fifo;	/* fifo list of entries in cache */
+	uint32_t uc_nextvictim;	/* points to next victim in fifo list */
+	uint32_t uc_prog;		/* saved program number */
+	uint32_t uc_vers;		/* saved version number */
+	uint32_t uc_proc;		/* saved procedure number */
+	struct sockaddr_in uc_addr; /* saved caller's address */
+};
+
+
+/*
+ * the hashing function
+ */
+#define CACHE_LOC(transp, xid)	\
+ (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))	
+
+
+/*
+ * Enable use of the cache. 
+ * Note: there is no disable.
+ */
+svcudp_enablecache(
+	SVCXPRT *transp,
+	uint32_t size)
+{
+	struct svcudp_data *su = su_data(transp);
+	struct udp_cache *uc;
+
+	if (su->su_cache != NULL) {
+		CACHE_PERROR("enablecache: cache already enabled");
+		return(0);	
+	}
+	uc = ALLOC(struct udp_cache, 1);
+	if (uc == NULL) {
+		CACHE_PERROR("enablecache: could not allocate cache");
+		return(0);
+	}
+	uc->uc_size = size;
+	uc->uc_nextvictim = 0;
+	uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+	if (uc->uc_entries == NULL) {
+		CACHE_PERROR("enablecache: could not allocate cache data");
+		return(0);
+	}
+	BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+	uc->uc_fifo = ALLOC(cache_ptr, size);
+	if (uc->uc_fifo == NULL) {
+		CACHE_PERROR("enablecache: could not allocate cache fifo");
+		return(0);
+	}
+	BZERO(uc->uc_fifo, cache_ptr, size);
+	su->su_cache = (char *) uc;
+	return(1);
+}
+
+
+/*
+ * Set an entry in the cache
+ */
+static void
+cache_set(
+	SVCXPRT *xprt,
+	uint32_t replylen)
+{
+	cache_ptr victim;	
+	cache_ptr *vicp;
+	struct svcudp_data *su = su_data(xprt);
+	struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+	uint_t loc;
+	char *newbuf;
+
+	/*
+ 	 * Find space for the new entry, either by
+	 * reusing an old entry, or by mallocing a new one
+	 */
+	victim = uc->uc_fifo[uc->uc_nextvictim];
+	if (victim != NULL) {
+		loc = CACHE_LOC(xprt, victim->cache_xid);
+		for (vicp = &uc->uc_entries[loc]; 
+		  *vicp != NULL && *vicp != victim; 
+		  vicp = &(*vicp)->cache_next) 
+				;
+		if (*vicp == NULL) {
+			CACHE_PERROR("cache_set: victim not found");
+			return;
+		}
+		*vicp = victim->cache_next;	/* remote from cache */
+		newbuf = victim->cache_reply;
+	} else {
+		victim = ALLOC(struct cache_node, 1);
+		if (victim == NULL) {
+			CACHE_PERROR("cache_set: victim alloc failed");
+			return;
+		}
+		newbuf = mem_alloc(su->su_iosz);
+		if (newbuf == NULL) {
+			CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
+			return;
+		}
+	}
+
+	/*
+	 * Store it away
+	 */
+	victim->cache_replylen = replylen;
+	victim->cache_reply = rpc_buffer(xprt);
+	rpc_buffer(xprt) = newbuf;
+	xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE);
+	victim->cache_xid = su->su_xid;
+	victim->cache_proc = uc->uc_proc;
+	victim->cache_vers = uc->uc_vers;
+	victim->cache_prog = uc->uc_prog;
+	victim->cache_addr = uc->uc_addr;
+	loc = CACHE_LOC(xprt, victim->cache_xid);
+	victim->cache_next = uc->uc_entries[loc];	
+	uc->uc_entries[loc] = victim;
+	uc->uc_fifo[uc->uc_nextvictim++] = victim;
+	uc->uc_nextvictim %= uc->uc_size;
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found
+ */
+static int
+cache_get(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg,
+	char **replyp,
+	uint32_t *replylenp)
+{
+	uint_t loc;
+	cache_ptr ent;
+	struct svcudp_data *su = su_data(xprt);
+	struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+
+#	define EQADDR(a1, a2)	(memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
+
+	loc = CACHE_LOC(xprt, su->su_xid);
+	for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
+		if (ent->cache_xid == su->su_xid &&
+		  ent->cache_proc == uc->uc_proc &&
+		  ent->cache_vers == uc->uc_vers &&
+		  ent->cache_prog == uc->uc_prog &&
+		  EQADDR(ent->cache_addr, uc->uc_addr)) {
+			*replyp = ent->cache_reply;
+			*replylenp = ent->cache_replylen;
+			return(1);
+		}
+	}
+	/*
+	 * Failed to find entry
+	 * Remember a few things so we can do a set later
+	 */
+	uc->uc_proc = msg->rm_call.cb_proc;
+	uc->uc_vers = msg->rm_call.cb_vers;
+	uc->uc_prog = msg->rm_call.cb_prog;
+	uc->uc_addr = xprt->xp_raddr;
+	return(0);
+}
+
diff --git a/TBBT/trace_play/rpc/types.h b/TBBT/trace_play/rpc/types.h
new file mode 100755
index 0000000..0854cc6
--- /dev/null
+++ b/TBBT/trace_play/rpc/types.h
@@ -0,0 +1,111 @@
+/*
+ * @(#)types.h     2.1     97/10/23
+ */
+/* @(#)types.h	2.3 88/08/15 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)types.h 1.18 87/07/24 SMI      */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef __TYPES_RPC_HEADER__
+#define __TYPES_RPC_HEADER__
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#if defined(__INTTYPES_INCLUDED) || defined(_SYS_INT_TYPES_H)
+#define HAVE_INTTYPES
+#endif
+
+#if defined(USE_INTTYPES)
+#include <inttypes.h>
+#else /* USE_INTTYPES */
+#if !defined(HAVE_INTTYPES)
+#define HAVE_INTTYPES
+
+typedef signed char		int8_t;
+typedef short			int16_t;
+typedef int			int32_t;
+
+typedef unsigned char           uint8_t;
+typedef unsigned short          uint16_t;
+typedef unsigned int            uint32_t;
+
+#endif /* !HAVE_INTTYPES */
+
+#endif /* USE_INTTYPES */
+
+#define	bool_t	int32_t
+#define	enum_t	int32_t
+#ifndef FALSE
+#define	FALSE	(0)
+#endif
+#ifndef TRUE
+#define	TRUE	(1)
+#endif
+#define __dontcare__	-1
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define mem_alloc(bsize)	malloc(bsize)
+#define mem_free(ptr, bsize)	free(ptr)
+
+#if defined(NO_T_TYPES)
+typedef unsigned int	uint_t;
+typedef unsigned char	uchar_t;
+#endif
+
+#ifdef notdef
+#ifndef INADDR_LOOPBACK
+#define       INADDR_LOOPBACK         (uint32_t)0x7F000001
+#endif
+#endif
+
+#endif /* ndef __TYPES_RPC_HEADER__ */
diff --git a/TBBT/trace_play/rpc/xdr.c b/TBBT/trace_play/rpc/xdr.c
new file mode 100755
index 0000000..3a1fc88
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr.c
@@ -0,0 +1,685 @@
+#ifndef lint
+static char sfs_xdr_c_id[] = "@(#)xdr.c     2.1     97/10/23";
+#endif
+/* @(#)xdr.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
+#endif
+
+/*
+ * xdr.c, Generic XDR routines implementation.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ *
+ * These are the "generic" xdr routines used to serialize and de-serialize
+ * most common data items.  See xdr.h for more info on the interface to
+ * xdr.
+ */
+#ifndef lint
+static char sfs_clnt_id[] = "@(#)xdr.c     2.1     97/10/23";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+
+/*
+ * constants specific to the xdr "protocol"
+ */
+#define XDR_FALSE	((int32_t) 0)
+#define XDR_TRUE	((int32_t) 1)
+#define LASTUNSIGNED	((uint_t) 0-1)
+
+/*
+ * for unit alignment
+ */
+static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+
+/*
+ * Free a data structure using XDR
+ * Not a filter, but a convenient utility nonetheless
+ */
+void
+xdr_free(
+	xdrproc_t proc,
+	char *objp)
+{
+	XDR x;
+	
+	x.x_op = XDR_FREE;
+	(*proc)(&x, objp);
+}
+
+/*
+ * XDR nothing
+ */
+bool_t
+xdr_void(void)
+{
+
+	return (TRUE);
+}
+
+/*
+ * XDR integers
+ */
+bool_t
+xdr_int(
+	XDR *xdrs,
+	int *ip)
+{
+
+#ifdef lint
+	(void) (xdr_int16_t(xdrs, (int16_t *)ip));
+	return (xdr_int32_t(xdrs, (int32_t *)ip));
+#else
+	if (sizeof (int) == sizeof (int32_t)) {
+		return (xdr_int32_t(xdrs, (int32_t *)ip));
+	} else {
+		return (xdr_int16_t(xdrs, (int16_t *)ip));
+	}
+#endif
+}
+
+/*
+ * XDR unsigned integers
+ */
+bool_t
+xdr_u_int(
+	XDR *xdrs,
+	uint_t *up)
+{
+
+#ifdef lint
+	(void) (xdr_int16_t(xdrs, (int16_t *)up));
+	return (xdr_uint32_t(xdrs, (uint32_t *)up));
+#else
+	if (sizeof (uint_t) == sizeof (uint32_t)) {
+		return (xdr_uint32_t(xdrs, (uint32_t *)up));
+	} else {
+		return (xdr_int16_t(xdrs, (int16_t *)up));
+	}
+#endif
+}
+
+/*
+ * XDR long integers
+ * same as xdr_u_long - open coded to save a proc call!
+ */
+bool_t
+xdr_long(
+	XDR *xdrs,
+	int32_t *lp)
+{
+
+	if (xdrs->x_op == XDR_ENCODE)
+		return (XDR_PUTLONG(xdrs, lp));
+
+	if (xdrs->x_op == XDR_DECODE)
+		return (XDR_GETLONG(xdrs, lp));
+
+	if (xdrs->x_op == XDR_FREE)
+		return (TRUE);
+
+	return (FALSE);
+}
+
+bool_t
+xdr_int32_t(
+	XDR *xdrs,
+	int32_t *lp)
+{
+
+	if (xdrs->x_op == XDR_ENCODE)
+		return (XDR_PUTLONG(xdrs, lp));
+
+	if (xdrs->x_op == XDR_DECODE)
+		return (XDR_GETLONG(xdrs, lp));
+
+	if (xdrs->x_op == XDR_FREE)
+		return (TRUE);
+
+	return (FALSE);
+}
+
+/*
+ * XDR unsigned long integers
+ * same as xdr_long - open coded to save a proc call!
+ */
+bool_t
+xdr_u_long(
+	XDR *xdrs,
+	uint32_t *ulp)
+{
+
+	if (xdrs->x_op == XDR_DECODE)
+		return (XDR_GETLONG(xdrs, (int32_t *)ulp));
+	if (xdrs->x_op == XDR_ENCODE)
+		return (XDR_PUTLONG(xdrs, (int32_t *)ulp));
+	if (xdrs->x_op == XDR_FREE)
+		return (TRUE);
+	return (FALSE);
+}
+
+bool_t
+xdr_uint32_t(
+	XDR *xdrs,
+	uint32_t *ulp)
+{
+
+	if (xdrs->x_op == XDR_DECODE)
+		return (XDR_GETLONG(xdrs, (int32_t *)ulp));
+	if (xdrs->x_op == XDR_ENCODE)
+		return (XDR_PUTLONG(xdrs, (int32_t *)ulp));
+	if (xdrs->x_op == XDR_FREE)
+		return (TRUE);
+	return (FALSE);
+}
+
+/*
+ * XDR short integers
+ */
+bool_t
+xdr_short(
+	XDR *xdrs,
+	int16_t *sp)
+{
+	int32_t l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		l = (int32_t) *sp;
+		return (XDR_PUTLONG(xdrs, &l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, &l)) {
+			return (FALSE);
+		}
+		*sp = (int16_t) l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+bool_t
+xdr_int16_t(
+	XDR *xdrs,
+	int16_t *sp)
+{
+	int32_t l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		l = (int32_t) *sp;
+		return (XDR_PUTLONG(xdrs, &l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, &l)) {
+			return (FALSE);
+		}
+		*sp = (int16_t) l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short(
+	XDR *xdrs,
+	uint16_t *usp)
+{
+	uint32_t l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		l = (uint32_t) *usp;
+		return (XDR_PUTLONG(xdrs, (int32_t *)&l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, (int32_t *)&l)) {
+			return (FALSE);
+		}
+		*usp = (uint16_t) l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+bool_t
+xdr_uint16_t(
+	XDR *xdrs,
+	uint16_t *usp)
+{
+	uint32_t l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		l = (uint32_t) *usp;
+		return (XDR_PUTLONG(xdrs, (int32_t *)&l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, (int32_t *)&l)) {
+			return (FALSE);
+		}
+		*usp = (uint16_t) l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+
+/*
+ * XDR a char
+ */
+bool_t
+xdr_char(
+	XDR *xdrs,
+	char *cp)
+{
+	int i;
+
+	i = (*cp);
+	if (!xdr_int(xdrs, &i)) {
+		return (FALSE);
+	}
+	*cp = i;
+	return (TRUE);
+}
+
+/*
+ * XDR an unsigned char
+ */
+bool_t
+xdr_u_char(
+	XDR *xdrs,
+	uchar_t *cp)
+{
+	uint_t u;
+
+	u = (*cp);
+	if (!xdr_u_int(xdrs, &u)) {
+		return (FALSE);
+	}
+	*cp = u;
+	return (TRUE);
+}
+
+/*
+ * XDR booleans
+ */
+bool_t
+xdr_bool(
+	XDR *xdrs,
+	bool_t *bp)
+{
+	int32_t lb;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		lb = *bp ? XDR_TRUE : XDR_FALSE;
+		return (XDR_PUTLONG(xdrs, &lb));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, &lb)) {
+			return (FALSE);
+		}
+		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR enumerations
+ */
+bool_t
+xdr_enum(
+	XDR *xdrs,
+	enum_t *ep)
+{
+#ifndef lint
+	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
+
+	/*
+	 * enums are treated as ints
+	 */
+	if (sizeof (enum sizecheck) == sizeof (int32_t)) {
+		return (xdr_int32_t(xdrs, (int32_t *)ep));
+	} else if (sizeof (enum sizecheck) == sizeof (int16_t)) {
+		return (xdr_int16_t(xdrs, (int16_t *)ep));
+	} else {
+		return (FALSE);
+	}
+#else
+	(void) (xdr_int16_t(xdrs, (int16_t *)ep));
+	return (xdr_int32_t(xdrs, (int32_t *)ep));
+#endif
+}
+
+/*
+ * XDR opaque data
+ * Allows the specification of a fixed size sequence of opaque bytes.
+ * cp points to the opaque object and cnt gives the byte length.
+ */
+bool_t
+xdr_opaque(
+	XDR *xdrs,
+	void *cp,
+	uint_t cnt)
+{
+	uint_t rndup;
+	static crud[BYTES_PER_XDR_UNIT];
+
+	/*
+	 * if no data we are done
+	 */
+	if (cnt == 0)
+		return (TRUE);
+
+	/*
+	 * round byte count to full xdr units
+	 */
+	rndup = cnt % BYTES_PER_XDR_UNIT;
+	if (rndup > 0)
+		rndup = BYTES_PER_XDR_UNIT - rndup;
+
+	if (xdrs->x_op == XDR_DECODE) {
+		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
+			return (FALSE);
+		}
+		if (rndup == 0)
+			return (TRUE);
+		return (XDR_GETBYTES(xdrs, crud, rndup));
+	}
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
+			return (FALSE);
+		}
+		if (rndup == 0)
+			return (TRUE);
+		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
+	}
+
+	if (xdrs->x_op == XDR_FREE) {
+		return (TRUE);
+	}
+
+	return (FALSE);
+}
+
+/*
+ * XDR counted bytes
+ * *cpp is a pointer to the bytes, *sizep is the count.
+ * If *cpp is NULL maxsize bytes are allocated
+ */
+bool_t
+xdr_bytes(
+	XDR *xdrs,
+	char **cpp,
+	uint_t *sizep,
+	uint_t maxsize)
+{
+	char *sp = *cpp;  /* sp is the actual string pointer */
+	uint_t nodesize;
+
+	/*
+	 * first deal with the length since xdr bytes are counted
+	 */
+	if (! xdr_u_int(xdrs, sizep)) {
+		return (FALSE);
+	}
+	nodesize = *sizep;
+	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
+		return (FALSE);
+	}
+
+	/*
+	 * now deal with the actual bytes
+	 */
+	switch (xdrs->x_op) {
+
+	case XDR_DECODE:
+		if (nodesize == 0) {
+			return (TRUE);
+		}
+		if (sp == NULL) {
+			*cpp = sp = (char *)mem_alloc(nodesize);
+		}
+		if (sp == NULL) {
+			(void) fprintf(stderr, "xdr_bytes: out of memory\n");
+			return (FALSE);
+		}
+		/* fall into ... */
+
+	case XDR_ENCODE:
+		return (xdr_opaque(xdrs, sp, nodesize));
+
+	case XDR_FREE:
+		if (sp != NULL) {
+			mem_free(sp, nodesize);
+			*cpp = NULL;
+		}
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * Implemented here due to commonality of the object.
+ */
+bool_t
+xdr_netobj(
+	XDR *xdrs,
+	struct netobj *np)
+{
+
+	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
+}
+
+/*
+ * XDR a descriminated union
+ * Support routine for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * an entry with a null procedure pointer.  The routine gets
+ * the discriminant value and then searches the array of xdrdiscrims
+ * looking for that value.  It calls the procedure given in the xdrdiscrim
+ * to handle the discriminant.  If there is no specific routine a default
+ * routine may be called.
+ * If there is no specific or default routine an error is returned.
+ */
+bool_t
+xdr_union(
+	XDR *xdrs,
+	enum_t *dscmp,		/* enum to decide which arm to work on */
+	char *unp,		/* the union itself */
+	struct xdr_discrim *choices,	/* [value, xdr proc] for each arm */
+	xdrproc_t dfault)	/* default xdr routine */
+{
+	enum_t dscm;
+
+	/*
+	 * we deal with the discriminator;  it's an enum
+	 */
+	if (! xdr_enum(xdrs, dscmp)) {
+		return (FALSE);
+	}
+	dscm = *dscmp;
+
+	/*
+	 * search choices for a value that matches the discriminator.
+	 * if we find one, execute the xdr routine for that value.
+	 */
+	for (; choices->proc != NULL_xdrproc_t; choices++) {
+		if (choices->value == dscm)
+			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
+	}
+
+	/*
+	 * no match - execute the default xdr routine if there is one
+	 */
+	return ((dfault == NULL_xdrproc_t) ? FALSE :
+	    (*dfault)(xdrs, unp, LASTUNSIGNED));
+}
+
+
+/*
+ * Non-portable xdr primitives.
+ * Care should be taken when moving these routines to new architectures.
+ */
+
+
+/*
+ * XDR null terminated ASCII strings
+ * xdr_string deals with "C strings" - arrays of bytes that are
+ * terminated by a NULL character.  The parameter cpp references a
+ * pointer to storage; If the pointer is null, then the necessary
+ * storage is allocated.  The last parameter is the max allowed length
+ * of the string as specified by a protocol.
+ */
+bool_t
+xdr_string(
+	XDR *xdrs,
+	char **cpp,
+	uint_t maxsize)
+{
+	char *sp = *cpp;  /* sp is the actual string pointer */
+	uint_t size;
+	uint_t nodesize;
+
+	/*
+	 * first deal with the length since xdr strings are counted-strings
+	 */
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+		if (sp == NULL) {
+			return(TRUE);	/* already free */
+		}
+		/* fall through... */
+	case XDR_ENCODE:
+		size = strlen(sp);
+		break;
+	}
+	if (! xdr_u_int(xdrs, &size)) {
+		return (FALSE);
+	}
+	if (size > maxsize) {
+		return (FALSE);
+	}
+	nodesize = size + 1;
+
+	/*
+	 * now deal with the actual bytes
+	 */
+	switch (xdrs->x_op) {
+
+	case XDR_DECODE:
+		if (nodesize == 0) {
+			return (TRUE);
+		}
+		if (sp == NULL)
+			*cpp = sp = (char *)mem_alloc(nodesize);
+		if (sp == NULL) {
+			(void) fprintf(stderr, "xdr_string: out of memory\n");
+			return (FALSE);
+		}
+		sp[size] = 0;
+		/* fall into ... */
+
+	case XDR_ENCODE:
+		return (xdr_opaque(xdrs, sp, size));
+
+	case XDR_FREE:
+		mem_free(sp, nodesize);
+		*cpp = NULL;
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/* 
+ * Wrapper for xdr_string that can be called directly from 
+ * routines like clnt_call
+ */
+bool_t
+xdr_wrapstring(
+	XDR *xdrs,
+	char **cpp)
+{
+	if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
+		return (TRUE);
+	}
+	return (FALSE);
+}
diff --git a/TBBT/trace_play/rpc/xdr.h b/TBBT/trace_play/rpc/xdr.h
new file mode 100755
index 0000000..2ccc5d2
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr.h
@@ -0,0 +1,308 @@
+/*
+ * @(#)xdr.h     2.1     97/10/23
+ */
+
+/* @(#)xdr.h	2.2 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)xdr.h 1.19 87/04/22 SMI      */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __XDR_HEADER__
+#define __XDR_HEADER__
+
+#include <stdio.h>
+
+/*
+ * XDR provides a conventional way for converting between C data
+ * types and an external bit-string representation.  Library supplied
+ * routines provide for the conversion on built-in C data types.  These
+ * routines and utility routines defined here are used to help implement
+ * a type encode/decode routine for each user-defined type.
+ *
+ * Each data type provides a single procedure which takes two arguments:
+ *
+ *	bool_t
+ *	xdrproc(xdrs, argresp)
+ *		XDR *xdrs;
+ *		<type> *argresp;
+ *
+ * xdrs is an instance of a XDR handle, to which or from which the data
+ * type is to be converted.  argresp is a pointer to the structure to be
+ * converted.  The XDR handle contains an operation field which indicates
+ * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
+ *
+ * XDR_DECODE may allocate space if the pointer argresp is null.  This
+ * data can be freed with the XDR_FREE operation.
+ *
+ * We write only one procedure per data type to make it easy
+ * to keep the encode and decode procedures for a data type consistent.
+ * In many cases the same code performs all operations on a user defined type,
+ * because all the hard work is done in the component type routines.
+ * decode as a series of calls on the nested data types.
+ */
+
+/*
+ * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
+ * stream.  XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+	XDR_ENCODE=0,
+	XDR_DECODE=1,
+	XDR_FREE=2
+};
+
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT	(4)
+#define RNDUP(x)  ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
+		    * BYTES_PER_XDR_UNIT)
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or decoded.
+ *
+ * The second argument to the xdrproc_t is a pointer to an opaque pointer.
+ * The opaque pointer generally points to a structure of the data type
+ * to be decoded.  If this pointer is 0, then the type routines should
+ * allocate dynamic storage of the appropriate size and return it.
+ * bool_t	(*xdrproc_t)(XDR *, void **);
+ */
+typedef	bool_t (*xdrproc_t)();
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
+ * and two private fields for the use of the particular impelementation.
+ */
+typedef struct {
+	enum xdr_op	x_op;		/* operation; fast additional param */
+	struct xdr_ops *x_ops;
+	char *	 	x_public;	/* users' data */
+	char * 		x_private;	/* pointer to private data */
+	char *  	x_base;		/* private used for position info */
+	int		x_handy;	/* extra private word */
+} XDR;
+
+struct xdr_ops {
+	/* get a long from underlying stream */
+	bool_t	(*x_getlong)(XDR *, int32_t *);
+	/* put a long to " */
+	bool_t	(*x_putlong)(XDR *, int32_t *);
+	/* get some bytes from " */
+	bool_t	(*x_getbytes)(XDR *, void *, uint_t);
+	/* put some bytes to " */
+	bool_t	(*x_putbytes)(XDR *, void *, uint_t);
+	/* returns bytes off from beginning */
+	uint_t	(*x_getpostn)(XDR *);
+	/* lets you reposition the stream */
+	bool_t  (*x_setpostn)(XDR *, uint_t);
+	/* buf quick ptr to buffered data */
+	int32_t *(*x_inline)(XDR *, uint_t);
+	/* free privates of this xdr_stream */
+	void	(*x_destroy)(XDR *);
+};
+
+/*
+ * Operations defined on a XDR handle
+ *
+ * XDR		*xdrs;
+ * int32_t	*longp;
+ * void * 	 addr;
+ * uint_t	 len;
+ * uint_t	 pos;
+ */
+#define XDR_GETLONG(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+#define xdr_getlong(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+
+#define XDR_PUTLONG(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+#define xdr_putlong(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+
+#define XDR_GETBYTES(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+#define xdr_getbytes(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+
+#define XDR_PUTBYTES(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+#define xdr_putbytes(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+
+#define XDR_GETPOS(xdrs)				\
+	(*(xdrs)->x_ops->x_getpostn)(xdrs)
+#define xdr_getpos(xdrs)				\
+	(*(xdrs)->x_ops->x_getpostn)(xdrs)
+
+#define XDR_SETPOS(xdrs, pos)				\
+	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+#define xdr_setpos(xdrs, pos)				\
+	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+
+#define	XDR_INLINE(xdrs, len)				\
+	(*(xdrs)->x_ops->x_inline)(xdrs, len)
+#define	xdr_inline(xdrs, len)				\
+	(*(xdrs)->x_ops->x_inline)(xdrs, len)
+
+#define	XDR_DESTROY(xdrs)				\
+	if ((xdrs)->x_ops->x_destroy) 			\
+		(*(xdrs)->x_ops->x_destroy)(xdrs)
+#define	xdr_destroy(xdrs)				\
+	if ((xdrs)->x_ops->x_destroy) 			\
+		(*(xdrs)->x_ops->x_destroy)(xdrs)
+
+/*
+ * Support struct for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * a entry with a null procedure pointer.  The xdr_union routine gets
+ * the discriminant value and then searches the array of structures
+ * for a matching value.  If a match is found the associated xdr routine
+ * is called to handle that part of the union.  If there is
+ * no match, then a default routine may be called.
+ * If there is no match and no default routine it is an error.
+ */
+#define NULL_xdrproc_t ((xdrproc_t)0)
+struct xdr_discrim {
+	int	value;
+	xdrproc_t proc;
+};
+
+/*
+ * In-line routines for fast encode/decode of primitve data types.
+ * Caveat emptor: these use single memory cycles to get the
+ * data from the underlying buffer, and will fail to operate
+ * properly if the data is not aligned.  The standard way to use these
+ * is to say:
+ *	if ((buf = XDR_INLINE(xdrs, count)) == NULL)
+ *		return (FALSE);
+ *	<<< macro calls >>>
+ * where ``count'' is the number of bytes of data occupied
+ * by the primitive data types.
+ *
+ * N.B. and frozen for all time: each data type here uses 4 bytes
+ * of external representation.
+ */
+#define IXDR_GET_LONG(buf)		((int32_t)ntohl((uint32_t)*(buf)++))
+#define IXDR_PUT_LONG(buf, v)		(*(buf)++ = (int32_t)htonl((uint32_t)v))
+
+#define IXDR_GET_BOOL(buf)		((bool_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_ENUM(buf, t)		((t)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_LONG(buf)		((uint32_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_SHORT(buf)		((int16_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_SHORT(buf)		((uint16_t)IXDR_GET_LONG(buf))
+
+#define IXDR_PUT_BOOL(buf, v)		IXDR_PUT_LONG((buf), ((int32_t)(v)))
+#define IXDR_PUT_ENUM(buf, v)		IXDR_PUT_LONG((buf), ((int32_t)(v)))
+#define IXDR_PUT_U_LONG(buf, v)		IXDR_PUT_LONG((buf), ((int32_t)(v)))
+#define IXDR_PUT_SHORT(buf, v)		IXDR_PUT_LONG((buf), ((int32_t)(v)))
+#define IXDR_PUT_U_SHORT(buf, v)	IXDR_PUT_LONG((buf), ((int32_t)(v)))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+extern bool_t	xdr_void(void);
+extern bool_t	xdr_int(XDR *, int *);
+extern bool_t	xdr_u_int(XDR *, uint_t *);
+extern bool_t	xdr_long(XDR *, int32_t *);
+extern bool_t	xdr_u_long(XDR *, uint32_t *);
+extern bool_t	xdr_int32_t(XDR *, int32_t *);
+extern bool_t	xdr_uint32_t(XDR *, uint32_t *);
+extern bool_t	xdr_short(XDR *, int16_t *);
+extern bool_t	xdr_u_short(XDR *, uint16_t *);
+extern bool_t	xdr_int16_t(XDR *, int16_t *);
+extern bool_t	xdr_uint16_t(XDR *, uint16_t *);
+extern bool_t	xdr_bool(XDR *, bool_t *);
+extern bool_t	xdr_enum(XDR *, enum_t *);
+extern bool_t	xdr_array(XDR *, void **, uint_t *, uint_t, uint_t, xdrproc_t);
+extern bool_t	xdr_bytes(XDR *, char **cp, uint_t *, uint_t);
+extern bool_t	xdr_opaque(XDR *, void *, uint_t);
+extern bool_t	xdr_string(XDR *, char **cp, uint_t);
+extern bool_t	xdr_union(XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t);
+extern bool_t	xdr_char(XDR *, char *);
+extern bool_t	xdr_u_char(XDR *, uchar_t *);
+extern bool_t	xdr_vector(XDR *, char *, uint_t, uint_t, xdrproc_t);
+extern bool_t	xdr_float(XDR *, float *);
+extern bool_t	xdr_double(XDR *, double *);
+extern bool_t	xdr_reference(XDR *, void **, uint_t, xdrproc_t);
+extern bool_t	xdr_pointer(XDR *, void **, uint_t, xdrproc_t);
+extern bool_t	xdr_wrapstring(XDR *, char **);
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 1024 
+struct netobj {
+	uint_t	n_len;
+	char	*n_bytes;
+};
+typedef struct netobj netobj;
+extern bool_t   xdr_netobj(XDR *, netobj *);
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+extern void   xdrmem_create(XDR *, void *, uint_t, enum xdr_op);
+extern void   xdrstdio_create(XDR *, FILE *, enum xdr_op);
+extern void   xdrrec_create(XDR *, uint_t, uint_t, void *, int (*)(), int (*)());
+extern bool_t xdrrec_endofrecord(XDR *, bool_t);
+extern bool_t xdrrec_skiprecord(XDR *);
+extern bool_t xdrrec_eof(XDR *);
+
+#endif /* !__XDR_HEADER__ */
diff --git a/TBBT/trace_play/rpc/xdr_array.c b/TBBT/trace_play/rpc/xdr_array.c
new file mode 100755
index 0000000..d448022
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr_array.c
@@ -0,0 +1,175 @@
+#ifndef lint
+static char sfs_xdr_array_id[] = "@(#)xdr_array.c     2.1     97/10/23";
+#endif
+/* @(#)xdr_array.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_array.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * arrays.  See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+
+#define LASTUNSIGNED	((uint_t)0-1)
+
+
+/*
+ * XDR an array of arbitrary elements
+ * *addrp is a pointer to the array, *sizep is the number of elements.
+ * If addrp is NULL (*sizep * elsize) bytes are allocated.
+ * elsize is the size (in bytes) of each element, and elproc is the
+ * xdr procedure to call to handle each element of the array.
+ */
+bool_t
+xdr_array(
+	XDR *xdrs,
+	void **addrp,		/* array pointer */
+	uint_t *sizep,		/* number of elements */
+	uint_t maxsize,		/* max numberof elements */
+	uint_t elsize,		/* size in bytes of each element */
+	xdrproc_t elproc)	/* xdr routine to handle each element */
+{
+	uint_t i;
+	char * target = *addrp;
+	uint_t c;  /* the actual element count */
+	bool_t stat = TRUE;
+	uint_t nodesize;
+
+	/* like strings, arrays are really counted arrays */
+	if (! xdr_u_int(xdrs, sizep)) {
+		return (FALSE);
+	}
+	c = *sizep;
+	if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
+		return (FALSE);
+	}
+	nodesize = c * elsize;
+
+	/*
+	 * if we are deserializing, we may need to allocate an array.
+	 * We also save time by checking for a null array if we are freeing.
+	 */
+	if (target == NULL)
+		switch (xdrs->x_op) {
+		case XDR_DECODE:
+			if (c == 0)
+				return (TRUE);
+			*addrp = target = mem_alloc(nodesize);
+			if (target == NULL) {
+				(void) fprintf(stderr, 
+					"xdr_array: out of memory\n");
+				return (FALSE);
+			}
+			memset(target, '\0', nodesize);
+			break;
+
+		case XDR_FREE:
+			return (TRUE);
+	}
+	
+	/*
+	 * now we xdr each element of array
+	 */
+	for (i = 0; (i < c) && stat; i++) {
+		stat = (*elproc)(xdrs, target, LASTUNSIGNED);
+		target += elsize;
+	}
+
+	/*
+	 * the array may need freeing
+	 */
+	if (xdrs->x_op == XDR_FREE) {
+		mem_free(*addrp, nodesize);
+		*addrp = NULL;
+	}
+	return (stat);
+}
+
+/*
+ * xdr_vector():
+ *
+ * XDR a fixed length array. Unlike variable-length arrays,
+ * the storage of fixed length arrays is static and unfreeable.
+ * > basep: base of the array
+ * > size: size of the array
+ * > elemsize: size of each element
+ * > xdr_elem: routine to XDR each element
+ */
+bool_t
+xdr_vector(
+	XDR *xdrs,
+	char *basep,
+	uint_t nelem,
+	uint_t elemsize,
+	xdrproc_t xdr_elem)	
+{
+	uint_t i;
+	char *elptr;
+
+	elptr = basep;
+	for (i = 0; i < nelem; i++) {
+		if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
+			return(FALSE);
+		}
+		elptr += elemsize;
+	}
+	return(TRUE);	
+}
+
diff --git a/TBBT/trace_play/rpc/xdr_float.c b/TBBT/trace_play/rpc/xdr_float.c
new file mode 100755
index 0000000..9048665
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr_float.c
@@ -0,0 +1,288 @@
+#ifndef lint
+static char sfs_xdr_float_id[] = "@(#)xdr_float.c     2.1     97/10/23";
+#endif
+/* @(#)xdr_float.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_float.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "floating point" xdr routines used to (de)serialize
+ * most common data items.  See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+
+/*
+ * NB: Not portable.
+ * This routine works on Suns (Sky / 68000's) and Vaxen.
+ */
+
+#ifdef vax
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct	ieee_single {
+	unsigned int	mantissa: 23;
+	unsigned int	exp     : 8;
+	unsigned int	sign    : 1;
+};
+
+/* Vax single precision floating point */
+struct	vax_single {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS	0x81
+#define IEEE_SNG_BIAS	0x7f
+
+static struct sgl_limits {
+	struct vax_single s;
+	struct ieee_single ieee;
+} sgl_limits[2] = {
+	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
+	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
+	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
+};
+#endif /* vax */
+
+bool_t
+xdr_float(xdrs, fp)
+	register XDR *xdrs;
+	register float *fp;
+{
+#if defined(vax)
+	struct ieee_single is;
+	struct vax_single vs, *vsp;
+	struct sgl_limits *lim;
+	int i;
+#endif
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+#if !defined(vax)
+		return (XDR_PUTLONG(xdrs, (int32_t *)fp));
+#else
+		vs = *((struct vax_single *)fp);
+		for (i = 0, lim = sgl_limits;
+			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+			i++, lim++) {
+			if ((vs.mantissa2 == lim->s.mantissa2) &&
+				(vs.exp == lim->s.exp) &&
+				(vs.mantissa1 == lim->s.mantissa1)) {
+				is = lim->ieee;
+				goto shipit;
+			}
+		}
+		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
+	shipit:
+		is.sign = vs.sign;
+		return (XDR_PUTLONG(xdrs, (int32_t *)&is));
+#endif
+
+	case XDR_DECODE:
+#if !defined(vax)
+		return (XDR_GETLONG(xdrs, (int32_t *)fp));
+#else
+		vsp = (struct vax_single *)fp;
+		if (!XDR_GETLONG(xdrs, (int32_t *)&is))
+			return (FALSE);
+		for (i = 0, lim = sgl_limits;
+			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+			i++, lim++) {
+			if ((is.exp == lim->ieee.exp) &&
+				(is.mantissa == lim->ieee.mantissa)) {
+				*vsp = lim->s;
+				goto doneit;
+			}
+		}
+		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+		vsp->mantissa2 = is.mantissa;
+		vsp->mantissa1 = (is.mantissa >> 16);
+	doneit:
+		vsp->sign = is.sign;
+		return (TRUE);
+#endif
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * This routine works on Suns (Sky / 68000's) and Vaxen.
+ */
+
+#ifdef vax
+/* What IEEE double precision floating point looks like on a Vax */
+struct	ieee_double {
+	unsigned int	mantissa1 : 20;
+	unsigned int	exp       : 11;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 32;
+};
+
+/* Vax double precision floating point */
+struct  vax_double {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+	unsigned int	mantissa3 : 16;
+	unsigned int	mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS	0x81
+#define IEEE_DBL_BIAS	0x3ff
+#define MASK(nbits)	((1 << nbits) - 1)
+
+static struct dbl_limits {
+	struct	vax_double d;
+	struct	ieee_double ieee;
+} dbl_limits[2] = {
+	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
+	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
+	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
+};
+
+#endif /* vax */
+
+
+bool_t
+xdr_double(xdrs, dp)
+	register XDR *xdrs;
+	double *dp;
+{
+	register int32_t *lp;
+#if defined(vax)
+	struct	ieee_double id;
+	struct	vax_double vd;
+	register struct dbl_limits *lim;
+	int i;
+#endif
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+#if !defined(vax)
+		lp = (int32_t *)dp;
+#else
+		vd = *((struct vax_double *)dp);
+		for (i = 0, lim = dbl_limits;
+			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			i++, lim++) {
+			if ((vd.mantissa4 == lim->d.mantissa4) &&
+				(vd.mantissa3 == lim->d.mantissa3) &&
+				(vd.mantissa2 == lim->d.mantissa2) &&
+				(vd.mantissa1 == lim->d.mantissa1) &&
+				(vd.exp == lim->d.exp)) {
+				id = lim->ieee;
+				goto shipit;
+			}
+		}
+		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
+		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
+				(vd.mantissa3 << 13) |
+				((vd.mantissa4 >> 3) & MASK(13));
+	shipit:
+		id.sign = vd.sign;
+		lp = (int32_t *)&id;
+#endif
+		return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+
+	case XDR_DECODE:
+#if !defined(vax)
+		lp = (int32_t *)dp;
+		return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
+#else
+		lp = (int32_t *)&id;
+		if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
+			return (FALSE);
+		for (i = 0, lim = dbl_limits;
+			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			i++, lim++) {
+			if ((id.mantissa2 == lim->ieee.mantissa2) &&
+				(id.mantissa1 == lim->ieee.mantissa1) &&
+				(id.exp == lim->ieee.exp)) {
+				vd = lim->d;
+				goto doneit;
+			}
+		}
+		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+		vd.mantissa1 = (id.mantissa1 >> 13);
+		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
+				(id.mantissa2 >> 29);
+		vd.mantissa3 = (id.mantissa2 >> 13);
+		vd.mantissa4 = (id.mantissa2 << 3);
+	doneit:
+		vd.sign = id.sign;
+		*dp = *((double *)&vd);
+		return (TRUE);
+#endif
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
diff --git a/TBBT/trace_play/rpc/xdr_mem.c b/TBBT/trace_play/rpc/xdr_mem.c
new file mode 100755
index 0000000..6b7fe4d
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr_mem.c
@@ -0,0 +1,205 @@
+#ifndef lint
+static char sfs_xdr_mem_id[] = "@(#)xdr_mem.c     2.1     97/10/23";
+#endif
+/* @(#)xdr_mem.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_mem.h, XDR implementation using memory buffers.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * If you have some data to be interpreted as external data representation
+ * or to be converted to external data representation in a memory buffer,
+ * then this is the package for you.
+ *
+ */
+
+#include <string.h>
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+#include "rpc/osdep.h"
+
+static bool_t	xdrmem_getlong(XDR *, int32_t *);
+static bool_t	xdrmem_putlong(XDR *, int32_t *);
+static bool_t	xdrmem_getbytes(XDR *, void *, uint_t);
+static bool_t	xdrmem_putbytes(XDR *, void *, uint_t);
+static uint_t	xdrmem_getpos(XDR *);
+static bool_t	xdrmem_setpos(XDR *, uint_t);
+static int32_t *xdrmem_inline(XDR *, uint_t);
+static void	xdrmem_destroy(XDR *);
+
+static struct	xdr_ops xdrmem_ops = {
+	xdrmem_getlong,
+	xdrmem_putlong,
+	xdrmem_getbytes,
+	xdrmem_putbytes,
+	xdrmem_getpos,
+	xdrmem_setpos,
+	xdrmem_inline,
+	xdrmem_destroy
+};
+
+/*
+ * The procedure xdrmem_create initializes a stream descriptor for a
+ * memory buffer.  
+ */
+void
+xdrmem_create(
+	XDR *xdrs,
+	void *addr,
+	uint_t size,
+	enum xdr_op op)
+{
+
+	xdrs->x_op = op;
+	xdrs->x_ops = &xdrmem_ops;
+	xdrs->x_private = xdrs->x_base = addr;
+	xdrs->x_handy = size;
+}
+
+/* ARGSUSED */
+static void
+xdrmem_destroy(XDR *xdrs)
+{
+}
+
+static bool_t
+xdrmem_getlong(
+	XDR *xdrs,
+	int32_t *lp)
+{
+
+	if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+		return (FALSE);
+	*lp = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrs->x_private))));
+	xdrs->x_private += sizeof(int32_t);
+	return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong(
+	XDR *xdrs,
+	int32_t *lp)
+{
+
+	if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+		return (FALSE);
+	*(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*lp));
+	xdrs->x_private += sizeof(int32_t);
+	return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(
+	XDR *xdrs,
+	void *addr,
+	uint_t len)
+{
+
+	if ((xdrs->x_handy -= len) < 0)
+		return (FALSE);
+	memmove(addr, xdrs->x_private, len);
+	xdrs->x_private += len;
+	return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(
+	XDR *xdrs,
+	void *addr,
+	uint_t len)
+{
+
+	if ((xdrs->x_handy -= len) < 0)
+		return (FALSE);
+	memmove(xdrs->x_private, addr, len);
+	xdrs->x_private += len;
+	return (TRUE);
+}
+
+static uint_t
+xdrmem_getpos(
+	XDR *xdrs)
+{
+
+	return ((uint_t)xdrs->x_private - (uint_t)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(
+	XDR *xdrs,
+	uint_t pos)
+{
+	char * newaddr = xdrs->x_base + pos;
+	char * lastaddr = xdrs->x_private + xdrs->x_handy;
+
+	if ((int32_t)newaddr > (int32_t)lastaddr)
+		return (FALSE);
+	xdrs->x_private = newaddr;
+	xdrs->x_handy = (int)lastaddr - (int)newaddr;
+	return (TRUE);
+}
+
+static int32_t *
+xdrmem_inline(
+	XDR *xdrs,
+	uint_t len)
+{
+	int32_t *buf = 0;
+
+	if (xdrs->x_handy >= len) {
+		xdrs->x_handy -= len;
+		buf = (int32_t *) xdrs->x_private;
+		xdrs->x_private += len;
+	}
+	return (buf);
+}
diff --git a/TBBT/trace_play/rpc/xdr_rec.c b/TBBT/trace_play/rpc/xdr_rec.c
new file mode 100755
index 0000000..0047c44
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr_rec.c
@@ -0,0 +1,608 @@
+#ifndef lint
+static char sfs_xdr_rec_id[] = "@(#)xdr_rec.c     2.1     97/10/23";
+#endif
+/* @(#)xdr_rec.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
+ * layer above tcp (for rpc's use).
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These routines interface XDRSTREAMS to a tcp/ip connection.
+ * There is a record marking layer between the xdr stream
+ * and the tcp transport level.  A record is composed on one or more
+ * record fragments.  A record fragment is a thirty-two bit header followed
+ * by n bytes of data, where n is contained in the header.  The header
+ * is represented as a htonl(uint32_t).  Thegh order bit encodes
+ * whether or not the fragment is the last fragment of the record
+ * (1 => fragment is last, 0 => more fragments to follow. 
+ * The other 31 bits encode the byte length of the fragment.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+#include "rpc/osdep.h"
+
+static bool_t	xdrrec_getlong(XDR *, int32_t *);
+static bool_t	xdrrec_putlong(XDR *, int32_t *);
+static bool_t	xdrrec_getbytes(XDR *, void *, uint_t);
+static bool_t	xdrrec_putbytes(XDR *, void *, uint_t);
+static uint_t	xdrrec_getpos(XDR *);
+static bool_t	xdrrec_setpos(XDR *, uint_t);
+static int32_t *xdrrec_inline(XDR *, uint_t);
+static void	xdrrec_destroy(XDR *);
+
+static struct  xdr_ops xdrrec_ops = {
+	xdrrec_getlong,
+	xdrrec_putlong,
+	xdrrec_getbytes,
+	xdrrec_putbytes,
+	xdrrec_getpos,
+	xdrrec_setpos,
+	xdrrec_inline,
+	xdrrec_destroy
+};
+
+/*
+ * A record is composed of one or more record fragments.
+ * A record fragment is a two-byte header followed by zero to
+ * 2**32-1 bytes.  The header is treated as a long unsigned and is
+ * encode/decoded to the network via htonl/ntohl.  The low order 31 bits
+ * are a byte count of the fragment.  The highest order bit is a boolean:
+ * 1 => this fragment is the last fragment of the record,
+ * 0 => this fragment is followed by more fragment(s).
+ *
+ * The fragment/record machinery is not general;  it is constructed to
+ * meet the needs of xdr and rpc based on tcp.
+ */
+
+#define LAST_FRAG (0x80000000)
+
+typedef struct rec_strm {
+	void * tcp_handle;
+	void * the_buffer;
+	/*
+	 * out-goung bits
+	 */
+	int (*writeit)();
+	char *out_base;		/* output buffer (points to frag header) */
+	char *out_finger;	/* next output position */
+	char *out_boundry;	/* data cannot up to this address */
+	uint32_t *frag_header;	/* beginning of curren fragment */
+	bool_t frag_sent;	/* true if buffer sent in middle of record */
+	/*
+	 * in-coming bits
+	 */
+	int (*readit)();
+	uint32_t in_size;	/* fixed size of the input buffer */
+	char *in_base;
+	char *in_finger;	/* location of next byte to be had */
+	char *in_boundry;	/* can read up to this location */
+	int32_t fbtbc;		/* fragment bytes to be consumed */
+	bool_t last_frag;
+	uint_t sendsize;
+	uint_t recvsize;
+} RECSTREAM;
+
+
+static uint_t	fix_buf_size(uint_t);
+static bool_t	flush_out(RECSTREAM *, bool_t);
+static bool_t	set_input_fragment(RECSTREAM *);
+static bool_t	skip_input_bytes(RECSTREAM *, int32_t);
+static bool_t	get_input_bytes(RECSTREAM *, char *, int);
+
+/*
+ * Create an xdr handle for xdrrec
+ * xdrrec_create fills in xdrs.  Sendsize and recvsize are
+ * send and recv buffer sizes (0 => use default).
+ * tcp_handle is an opaque handle that is passed as the first parameter to
+ * the procedures readit and writeit.  Readit and writeit are read and
+ * write respectively.   They are like the system
+ * calls expect that they take an opaque handle rather than an fd.
+ */
+void
+xdrrec_create(
+	XDR *xdrs,
+	uint_t sendsize,
+	uint_t recvsize,
+	void * tcp_handle,
+	int (*readit)(),  /* like read, but pass it a tcp_handle, not sock */
+	int (*writeit)())  /* like write, but pass it a tcp_handle, not sock */
+{
+	RECSTREAM *rstrm =
+		(RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
+
+	if (rstrm == NULL) {
+		(void)fprintf(stderr, "xdrrec_create: out of memory\n");
+		/* 
+		 *  This is bad.  Should rework xdrrec_create to 
+		 *  return a handle, and in this case return NULL
+		 */
+		return;
+	}
+	/*
+	 * adjust sizes and allocate buffer quad byte aligned
+	 */
+	rstrm->sendsize = sendsize = fix_buf_size(sendsize);
+	rstrm->recvsize = recvsize = fix_buf_size(recvsize);
+	rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
+	if (rstrm->the_buffer == NULL) {
+		(void)fprintf(stderr, "xdrrec_create: out of memory\n");
+		return;
+	}
+	for (rstrm->out_base = rstrm->the_buffer;
+		(uint_t)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
+		rstrm->out_base++);
+	rstrm->in_base = rstrm->out_base + sendsize;
+	/*
+	 * now the rest ...
+	 */
+	xdrs->x_ops = &xdrrec_ops;
+	xdrs->x_private = (void *)rstrm;
+	rstrm->tcp_handle = tcp_handle;
+	rstrm->readit = readit;
+	rstrm->writeit = writeit;
+	rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
+	rstrm->frag_header = (uint32_t *)rstrm->out_base;
+	rstrm->out_finger += sizeof(uint32_t);
+	rstrm->out_boundry += sendsize;
+	rstrm->frag_sent = FALSE;
+	rstrm->in_size = recvsize;
+	rstrm->in_boundry = rstrm->in_base;
+	rstrm->in_finger = (rstrm->in_boundry += recvsize);
+	rstrm->fbtbc = 0;
+	rstrm->last_frag = TRUE;
+}
+
+
+/*
+ * The reoutines defined below are the xdr ops which will go into the
+ * xdr handle filled in by xdrrec_create.
+ */
+
+static bool_t
+xdrrec_getlong(
+	XDR *xdrs,
+	int32_t *lp)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	int32_t *buflp = (int32_t *)(rstrm->in_finger);
+	int32_t mylong;
+
+	/* first try the inline, fast case */
+	if ((rstrm->fbtbc >= sizeof(int32_t)) &&
+		(((int)rstrm->in_boundry - (int)buflp) >= sizeof(int32_t))) {
+		*lp = (int32_t)ntohl((uint32_t)(*buflp));
+		rstrm->fbtbc -= sizeof(int32_t);
+		rstrm->in_finger += sizeof(int32_t);
+	} else {
+		if (! xdrrec_getbytes(xdrs, (void *)&mylong, sizeof(int32_t)))
+			return (FALSE);
+		*lp = (int32_t)ntohl((uint32_t)mylong);
+	}
+	return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(
+	XDR *xdrs,
+	int32_t *lp)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	int32_t *dest_lp = ((int32_t *)(rstrm->out_finger));
+
+	if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
+		/*
+		 * this case should almost never happen so the code is
+		 * inefficient
+		 */
+		rstrm->out_finger -= sizeof(int32_t);
+		rstrm->frag_sent = TRUE;
+		if (! flush_out(rstrm, FALSE))
+			return (FALSE);
+		dest_lp = ((int32_t *)(rstrm->out_finger));
+		rstrm->out_finger += sizeof(int32_t);
+	}
+	*dest_lp = (int32_t)htonl((uint32_t)(*lp));
+	return (TRUE);
+}
+
+static bool_t  /* must manage buffers, fragments, and records */
+xdrrec_getbytes(
+	XDR *xdrs,
+	void *baddr,
+	uint_t len)
+{
+	char *addr = baddr;
+	RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	int current;
+
+	while (len > 0) {
+		current = rstrm->fbtbc;
+		if (current == 0) {
+			if (rstrm->last_frag)
+				return (FALSE);
+			if (! set_input_fragment(rstrm))
+				return (FALSE);
+			continue;
+		}
+		current = (len < current) ? len : current;
+		if (! get_input_bytes(rstrm, addr, current))
+			return (FALSE);
+		addr += current; 
+		rstrm->fbtbc -= current;
+		len -= current;
+	}
+	return (TRUE);
+}
+
+static bool_t
+xdrrec_putbytes(
+	XDR *xdrs,
+	void *baddr,
+	uint_t len)
+{
+	char *addr = baddr;
+	RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	int current;
+
+	while (len > 0) {
+		current = (uint_t)rstrm->out_boundry - (uint_t)rstrm->out_finger;
+		current = (len < current) ? len : current;
+		memmove(rstrm->out_finger, addr, current);
+		rstrm->out_finger += current;
+		addr += current;
+		len -= current;
+		if (rstrm->out_finger == rstrm->out_boundry) {
+			rstrm->frag_sent = TRUE;
+			if (! flush_out(rstrm, FALSE))
+				return (FALSE);
+		}
+	}
+	return (TRUE);
+}
+
+static uint_t
+xdrrec_getpos(
+	XDR *xdrs)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+	int32_t pos;
+
+	pos = lseek((int)rstrm->tcp_handle, (int32_t) 0, 1);
+	if (pos != -1)
+		switch (xdrs->x_op) {
+
+		case XDR_ENCODE:
+			pos += rstrm->out_finger - rstrm->out_base;
+			break;
+
+		case XDR_DECODE:
+			pos -= rstrm->in_boundry - rstrm->in_finger;
+			break;
+
+		default:
+			pos = (uint_t) -1;
+			break;
+		}
+	return ((uint_t) pos);
+}
+
+static bool_t
+xdrrec_setpos(
+	XDR *xdrs,
+	uint_t pos)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+	uint_t currpos = xdrrec_getpos(xdrs);
+	int delta = currpos - pos;
+	char *newpos;
+
+	if ((int)currpos != -1)
+		switch (xdrs->x_op) {
+
+		case XDR_ENCODE:
+			newpos = rstrm->out_finger - delta;
+			if ((newpos > (char *)(rstrm->frag_header)) &&
+				(newpos < rstrm->out_boundry)) {
+				rstrm->out_finger = newpos;
+				return (TRUE);
+			}
+			break;
+
+		case XDR_DECODE:
+			newpos = rstrm->in_finger - delta;
+			if ((delta < (int)(rstrm->fbtbc)) &&
+				(newpos <= rstrm->in_boundry) &&
+				(newpos >= rstrm->in_base)) {
+				rstrm->in_finger = newpos;
+				rstrm->fbtbc -= delta;
+				return (TRUE);
+			}
+			break;
+		}
+	return (FALSE);
+}
+
+static int32_t *
+xdrrec_inline(
+	XDR *xdrs,
+	uint_t len)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+	int32_t * buf = NULL;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
+			buf = (int32_t *) rstrm->out_finger;
+			rstrm->out_finger += len;
+		}
+		break;
+
+	case XDR_DECODE:
+		if ((len <= rstrm->fbtbc) &&
+			((rstrm->in_finger + len) <= rstrm->in_boundry)) {
+			buf = (int32_t *) rstrm->in_finger;
+			rstrm->fbtbc -= len;
+			rstrm->in_finger += len;
+		}
+		break;
+	}
+	return (buf);
+}
+
+static void
+xdrrec_destroy(
+	XDR *xdrs)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+
+	mem_free(rstrm->the_buffer,
+		rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
+	mem_free((void *)rstrm, sizeof(RECSTREAM));
+}
+
+
+/*
+ * Exported routines to manage xdr records
+ */
+
+/*
+ * Before reading (deserializing from the stream, one should always call
+ * this procedure to guarantee proper record alignment.
+ */
+bool_t
+xdrrec_skiprecord(
+	XDR *xdrs)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+	while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+		if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+			return (FALSE);
+		rstrm->fbtbc = 0;
+		if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+			return (FALSE);
+	}
+	rstrm->last_frag = FALSE;
+	return (TRUE);
+}
+
+/*
+ * Look ahead fuction.
+ * Returns TRUE iff there is no more input in the buffer 
+ * after consuming the rest of the current record.
+ */
+bool_t
+xdrrec_eof(
+	XDR *xdrs)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+	while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+		if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+			return (TRUE);
+		rstrm->fbtbc = 0;
+		if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+			return (TRUE);
+	}
+	if (rstrm->in_finger == rstrm->in_boundry)
+		return (TRUE);
+	return (FALSE);
+}
+
+/*
+ * The client must tell the package when an end-of-record has occurred.
+ * The second paraemters tells whether the record should be flushed to the
+ * (output) tcp stream.  (This let's the package support batched or
+ * pipelined procedure calls.)  TRUE => immmediate flush to tcp connection.
+ */
+bool_t
+xdrrec_endofrecord(
+	XDR *xdrs,
+	bool_t sendnow)
+{
+	RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	uint32_t len;  /* fragment length */
+
+	if (sendnow || rstrm->frag_sent ||
+		((uint32_t)rstrm->out_finger + sizeof(uint32_t) >=
+		(uint32_t)rstrm->out_boundry)) {
+		rstrm->frag_sent = FALSE;
+		return (flush_out(rstrm, TRUE));
+	}
+	len = (uint32_t)(rstrm->out_finger) - (uint32_t)(rstrm->frag_header) -
+	   sizeof(uint32_t);
+	*(rstrm->frag_header) = htonl((uint32_t)len | (uint32_t)LAST_FRAG);
+	rstrm->frag_header = (uint32_t *)rstrm->out_finger;
+	rstrm->out_finger += sizeof(uint32_t);
+	return (TRUE);
+}
+
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(
+	RECSTREAM *rstrm,
+	bool_t eor)
+{
+	uint32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
+	uint32_t len = (uint32_t)(rstrm->out_finger) - 
+		(uint32_t)(rstrm->frag_header) - sizeof(uint32_t);
+
+	*(rstrm->frag_header) = htonl(len | eormask);
+	len = (uint32_t)(rstrm->out_finger) - (uint32_t)(rstrm->out_base);
+	if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
+		!= (int)len)
+		return (FALSE);
+	rstrm->frag_header = (uint32_t *)rstrm->out_base;
+	rstrm->out_finger = (char *)rstrm->out_base + sizeof(uint32_t);
+	return (TRUE);
+}
+
+static bool_t  /* knows nothing about records!  Only about input buffers */
+fill_input_buf(
+	RECSTREAM *rstrm)
+{
+	char *where;
+	uint_t i;
+	int len;
+
+	where = rstrm->in_base;
+	i = (uint_t)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
+	where += i;
+	len = rstrm->in_size - i;
+	if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
+		return (FALSE);
+	rstrm->in_finger = where;
+	where += len;
+	rstrm->in_boundry = where;
+	return (TRUE);
+}
+
+static bool_t  /* knows nothing about records!  Only about input buffers */
+get_input_bytes(
+	RECSTREAM *rstrm,
+	char *addr,
+	int len)
+{
+	int current;
+
+	while (len > 0) {
+		current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
+		if (current == 0) {
+			if (! fill_input_buf(rstrm))
+				return (FALSE);
+			continue;
+		}
+		current = (len < current) ? len : current;
+		memmove(addr, rstrm->in_finger, current);
+		rstrm->in_finger += current;
+		addr += current;
+		len -= current;
+	}
+	return (TRUE);
+}
+
+static bool_t  /* next two bytes of the input stream are treated as a header */
+set_input_fragment(
+	RECSTREAM *rstrm)
+{
+	uint32_t header;
+
+	if (! get_input_bytes(rstrm, (void *)&header, sizeof(header)))
+		return (FALSE);
+	header = (int32_t)ntohl(header);
+	rstrm->last_frag = ((header & (uint32_t)LAST_FRAG) == 0) ? FALSE : TRUE;
+	rstrm->fbtbc = header & (~LAST_FRAG);
+	return (TRUE);
+}
+
+static bool_t  /* consumes input bytes; knows nothing about records! */
+skip_input_bytes(
+	RECSTREAM *rstrm,
+	int32_t cnt)
+{
+	int current;
+
+	while (cnt > 0) {
+		current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
+		if (current == 0) {
+			if (! fill_input_buf(rstrm))
+				return (FALSE);
+			continue;
+		}
+		current = (cnt < current) ? cnt : current;
+		rstrm->in_finger += current;
+		cnt -= current;
+	}
+	return (TRUE);
+}
+
+static uint_t
+fix_buf_size(
+	uint_t s)
+{
+
+	if (s < 100)
+		s = 4000;
+	return (RNDUP(s));
+}
diff --git a/TBBT/trace_play/rpc/xdr_reference.c b/TBBT/trace_play/rpc/xdr_reference.c
new file mode 100755
index 0000000..56fc99c
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr_reference.c
@@ -0,0 +1,156 @@
+#ifndef lint
+static char sfs_xdr_reference_id[] = "@(#)xdr_reference.c     2.1     97/10/23";
+#endif
+/* @(#)xdr_reference.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
+#endif
+
+/*
+ * xdr_reference.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * "pointers".  See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+
+#define LASTUNSIGNED	((uint_t)0-1)
+
+/*
+ * XDR an indirect pointer
+ * xdr_reference is for recursively translating a structure that is
+ * referenced by a pointer inside the structure that is currently being
+ * translated.  pp references a pointer to storage. If *pp is null
+ * the  necessary storage is allocated.
+ * size is the sizeof the referneced structure.
+ * proc is the routine to handle the referenced structure.
+ */
+bool_t
+xdr_reference(
+	XDR *xdrs,
+	void **pp,		/* the pointer to work on */
+	uint_t size,		/* size of the object pointed to */
+	xdrproc_t proc)		/* xdr routine to handle the object */
+{
+	void *loc = *pp;
+	bool_t stat;
+
+	if (loc == NULL)
+		switch (xdrs->x_op) {
+		case XDR_FREE:
+			return (TRUE);
+
+		case XDR_DECODE:
+			*pp = loc = (void *) mem_alloc(size);
+			if (loc == NULL) {
+				(void) fprintf(stderr,
+				    "xdr_reference: out of memory\n");
+				return (FALSE);
+			}
+			memset(loc, '\0', (int)size);
+			break;
+	}
+
+	stat = (*proc)(xdrs, loc, LASTUNSIGNED);
+
+	if (xdrs->x_op == XDR_FREE) {
+		mem_free(loc, size);
+		*pp = NULL;
+	}
+	return (stat);
+}
+
+
+/*
+ * xdr_pointer():
+ *
+ * XDR a pointer to a possibly recursive data structure. This
+ * differs with xdr_reference in that it can serialize/deserialiaze
+ * trees correctly.
+ *
+ *  What's sent is actually a union:
+ *
+ *  union object_pointer switch (boolean b) {
+ *  case TRUE: object_data data;
+ *  case FALSE: void nothing;
+ *  }
+ *
+ * > objpp: Pointer to the pointer to the object.
+ * > obj_size: size of the object.
+ * > xdr_obj: routine to XDR an object.
+ *
+ */
+bool_t
+xdr_pointer(
+	XDR *xdrs,
+	void **objpp,
+	uint_t obj_size,
+	xdrproc_t xdr_obj)
+{
+
+	bool_t more_data;
+
+	more_data = (*objpp != NULL);
+	if (! xdr_bool(xdrs,&more_data)) {
+		return (FALSE);
+	}
+	if (! more_data) {
+		*objpp = NULL;
+		return (TRUE);
+	}
+	return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
+}
diff --git a/TBBT/trace_play/rpc/xdr_stdio.c b/TBBT/trace_play/rpc/xdr_stdio.c
new file mode 100755
index 0000000..8240089
--- /dev/null
+++ b/TBBT/trace_play/rpc/xdr_stdio.c
@@ -0,0 +1,210 @@
+#ifndef lint
+static char sfs_xdr_stdio_id[] = "@(#)xdr_stdio.c     2.1     97/10/23";
+#endif
+/* @(#)xdr_stdio.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_stdio.c, XDR implementation on standard i/o file.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements a XDR on a stdio stream.
+ * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
+ * from the stream.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "rpc/types.h"
+#include "rpc/xdr.h"
+#include "rpc/osdep.h" 
+
+static bool_t	xdrstdio_getlong(XDR *, int32_t *);
+static bool_t	xdrstdio_putlong(XDR *, int32_t *);
+static bool_t	xdrstdio_getbytes(XDR *, void *, uint_t);
+static bool_t	xdrstdio_putbytes(XDR *, void *, uint_t);
+static uint_t	xdrstdio_getpos(XDR *);
+static bool_t	xdrstdio_setpos(XDR *, uint_t);
+static int32_t *xdrstdio_inline(XDR *, uint_t);
+static void	xdrstdio_destroy(XDR *);
+
+/*
+ * Ops vector for stdio type XDR
+ */
+static struct xdr_ops	xdrstdio_ops = {
+	xdrstdio_getlong,	/* deseraialize a long int */
+	xdrstdio_putlong,	/* seraialize a long int */
+	xdrstdio_getbytes,	/* deserialize counted bytes */
+	xdrstdio_putbytes,	/* serialize counted bytes */
+	xdrstdio_getpos,	/* get offset in the stream */
+	xdrstdio_setpos,	/* set offset in the stream */
+	xdrstdio_inline,	/* prime stream for inline macros */
+	xdrstdio_destroy	/* destroy stream */
+};
+
+/*
+ * Initialize a stdio xdr stream.
+ * Sets the xdr stream handle xdrs for use on the stream file.
+ * Operation flag is set to op.
+ */
+void
+xdrstdio_create(
+	XDR *xdrs,
+	FILE *file,
+	enum xdr_op op)
+{
+
+	xdrs->x_op = op;
+	xdrs->x_ops = &xdrstdio_ops;
+	xdrs->x_private = (void *)file;
+	xdrs->x_handy = 0;
+	xdrs->x_base = 0;
+}
+
+/*
+ * Destroy a stdio xdr stream.
+ * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
+ */
+static void
+xdrstdio_destroy(
+	XDR *xdrs)
+{
+	(void)fflush((FILE *)xdrs->x_private);
+	/* xx should we close the file ?? */
+}
+
+static bool_t
+xdrstdio_getlong(
+	XDR *xdrs,
+	int32_t *lp)
+{
+
+	if (fread((void *)lp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
+		return (FALSE);
+	*lp = ntohl(*lp);
+	return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(
+	XDR *xdrs,
+	int32_t *lp)
+{
+
+	int32_t mycopy = htonl(*lp);
+	lp = &mycopy;
+
+	if (fwrite((void *)lp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
+		return (FALSE);
+	return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(
+	XDR *xdrs,
+	void * addr,
+	uint_t len)
+{
+
+	if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+		return (FALSE);
+	return (TRUE);
+}
+
+static bool_t
+xdrstdio_putbytes(
+	XDR *xdrs,
+	void * addr,
+	uint_t len)
+{
+
+	if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+		return (FALSE);
+	return (TRUE);
+}
+
+static uint_t
+xdrstdio_getpos(
+	XDR *xdrs)
+{
+
+	return ((uint_t) ftell((FILE *)xdrs->x_private));
+}
+
+static bool_t
+xdrstdio_setpos(
+	XDR *xdrs,
+	uint_t pos)
+{ 
+
+	return ((fseek((FILE *)xdrs->x_private, (int32_t)pos, 0) < 0) ?
+		FALSE : TRUE);
+}
+
+/* ARGSUSED */
+static int32_t *
+xdrstdio_inline(
+	XDR *xdrs,
+	uint_t len)
+{
+
+	/*
+	 * Must do some work to implement this: must insure
+	 * enough data in the underlying stdio buffer,
+	 * that the buffer is aligned so that we can indirect through a
+	 * int32_t *, and stuff this pointer in xdrs->x_buf.  Doing
+	 * a fread or fwrite to a scratch buffer would defeat
+	 * most of the gains to be had here and require storage
+	 * management on this buffer, so we don't do this.
+	 */
+	return (NULL);
+}
diff --git a/TBBT/trace_play/sem.c b/TBBT/trace_play/sem.c
new file mode 100644
index 0000000..3079f9b
--- /dev/null
+++ b/TBBT/trace_play/sem.c
@@ -0,0 +1,149 @@
+#include <sys/sem.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+
+extern int errno;
+
+#define SEMPERM 0777
+#define TRUE 1
+#define FALSE 0
+
+#define MAX_SEM 50
+struct {
+    int semid;
+    char name[256];
+} semname[MAX_SEM] =
+{
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+/*
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
+*/
+{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}
+} ;
+
+
+/* semaphore operations */
+
+int initsem(key_t key, int value)           /* create a semaphore */
+{
+  int status = 0;
+  int semid;
+
+  if ((semid = semget(key, 1, SEMPERM|IPC_CREAT|IPC_EXCL)) == -1) {
+       if (errno == EEXIST) {
+		printf("semget key %d already exist\n", key);
+	    semid = semget(key, 1, 0);
+	   }
+  } else {
+       status = semctl(semid, 0, SETVAL, value);
+	}
+
+  if (semid == -1 || status == -1) {
+	   printf("%d:\n", getpid());
+       perror("initsem() failed");
+       return (-1);
+  } else
+       return semid;
+}
+
+//int getsem(key_t key, int setval)           /* create a semaphore */
+int getsem(key_t key)           /* create a semaphore */
+{
+  int status = 0;
+  int semid;
+
+  semid = semget(key, 1, 0);
+
+  if (semid == -1 || status == -1) {
+	   printf("%d:\n", getpid());
+       perror("initsem() failed");
+       return (-1);
+  } else
+       return semid;
+}
+
+int waitsem(int semid)           /* wait on a semaphore */
+{
+  struct sembuf p_buf;
+#ifdef NO_SEM
+  return;
+#endif
+
+  p_buf.sem_num = 0;
+  p_buf.sem_op = -1;
+  p_buf.sem_flg = SEM_UNDO;
+
+  if (semop(semid, &p_buf, 1) == -1) {
+	printf("%d:", getpid());
+       perror("waitsem() failed");
+       exit(1);
+  } else
+       return (0);
+}
+
+int postsem(int semid)           /* post to a semaphore */
+{
+  struct sembuf v_buf;
+
+#ifdef NO_SEM
+  return;
+#endif
+
+
+  v_buf.sem_num = 0;
+  v_buf.sem_op = 1;
+  v_buf.sem_flg = SEM_UNDO;
+
+  if (semop(semid, &v_buf, 1) == -1) {
+	printf("%d:", getpid());
+       perror("postsem() failed");
+       exit(1);
+  } else
+       return (0);
+}
+
+void destsem(int semid)          /* destroy a semaphore */
+{
+  semctl(semid, 0, IPC_RMID, 0);
+}
+
+int dest_and_init_sem (key_t key, int value, char * name)
+{
+    int semid;
+    int i;
+    semid = getsem (key);
+    if (semid!=-1)
+        destsem (semid);
+    semid = initsem (key, value);
+    printf ("%s semid %d for key %d value %d \n", name, semid, key, value);
+                                                                                
+    if (semid == 0) {
+        printf ("semid == 0\n");
+        exit(0);
+    }
+                                                                                
+    for (i=0; i<MAX_SEM; i++) {
+        if (semname[i].semid == 0) {
+            semname[i].semid = semid;
+            strcpy(semname[i].name, name);
+            break;
+        }
+    }
+                                                                                
+    if (i==MAX_SEM) {
+        printf ("semname full\n");
+        exit (-1);
+    }
+                                                                                
+    return semid;
+}
+
+
diff --git a/TBBT/trace_play/sfs.1 b/TBBT/trace_play/sfs.1
new file mode 100755
index 0000000..3c89a8a
--- /dev/null
+++ b/TBBT/trace_play/sfs.1
@@ -0,0 +1,842 @@
+.\" @(#)sfs.1  2.1     97/10/23
+.\" See DESCR.SFS file for restrictions
+.\"
+.\" create man page by running 'tbl sfs.1 | nroff -man > sfs.cat'
+.\"
+.TH SFS 1 "5 October 1994"
+.SH NAME
+SFS \- Network File System server benchmark program
+.SH SYNOPSIS
+.B sfs
+[
+.B \-a access_pcnt
+] [
+.B \-A append_pcnt
+]
+.br
+[
+.B \-b blocksz_file
+] [
+.B \-B block_size
+] [
+.B \-d debug_level
+]
+.br
+[
+.B \-D dir_cnt
+] [
+.B \-f file_set_delta
+] [
+.B \-F file_cnt
+] [
+.B \-i
+] [
+.B \-l load
+]
+.br
+[
+.B \-m mix_file
+] [
+.B \-M prime_client_hostname
+]
+.br
+[
+.B \-N client_num
+] [
+.B \-p processes
+] [
+.B \-P
+] [
+.B \-Q
+]
+.br
+[
+.B \-R biod_reads
+] [
+[
+.B \-S symlink_cnt
+] [
+.B \-t time
+] [
+.B \-T
+]
+.br
+[
+.B \-V
+] [
+.B \-W biod_writes
+] [
+.B \-w warmup_time
+] [
+.B \-z
+]
+.br
+[
+.B server:/directory ...
+]
+.LP
+.B sfs3
+[
+.B \-a access_pcnt
+] [
+.B \-A append_pcnt
+]
+.br
+[
+.B \-b blocksz_file
+] [
+.B \-B block_size
+] [
+.B \-d debug_level
+]
+.br
+[
+.B \-D dir_cnt
+] [
+.B \-f file_set_delta
+] [
+.B \-F file_cnt
+] [
+.B \-i
+] [
+.B \-l load
+]
+.br
+[
+.B \-m mix_file
+] [
+.B \-M prime_client_hostname
+]
+.br
+[
+.B \-N client_num
+] [
+.B \-p processes
+] [
+.B \-P
+] [
+.B \-Q
+]
+.br
+[
+.B \-R biod_reads
+] [
+[
+.B \-S symlink_cnt
+] [
+.B \-t time
+] [
+.B \-T
+]
+.br
+[
+.B \-V
+] [
+.B \-W biod_writes
+] [
+.B \-w warmup_time
+] [
+.B \-z
+]
+.br
+[
+.B server:/directory ...
+]
+.SH DESCRIPTION
+Normally,
+.B SFS
+is executed via the
+.B sfs_mgr
+script which controls
+.B SFS
+execution on one or more
+.SM NFS
+client systems using a single user interface.
+.P
+.B SFS
+is a Network File System server benchmark.
+It runs on one or more 
+.SM NFS
+client machines to generate an artificial load
+consisting of a particular mix of
+.SM NFS
+operations on a particular set of files
+residing on the server being tested.
+The benchmark reports the average response time of the
+.SM NFS
+requests in milliseconds for the requested target load.
+The response time is the dependent variable.
+Load can be generated for a specific amount of time,
+or for a specific number of
+.SM NFS
+calls.
+.P
+.B SFS
+can also be used to characterize server performance.
+Nearly all of the major factors that influence NFS performance
+can be controlled using
+.B SFS
+command line arguments. Normally however, only the
+.B \-l load
+option used.
+Other commonly used options include the
+.B \-t time
+,
+.B \-p processes
+,
+.B \-m mix_file
+options.
+The remaining options are used to adjust specific parameters that affect
+.SM NFS
+performance.
+If these options are used, the results produced will be non\-standard,
+and thus, will not be comparable to tests run with other option settings.
+.P
+Normally,
+.B SFS
+is used as a benchmark program to measure the
+.SM NFS
+performance
+of a particular server machine at different load levels.
+In this case,
+the preferred measurement is to make a series of benchmark runs, 
+varying the load factor for each run
+in order to produce a performance/load curve.
+Each point in the curve
+represents the server's response time at a specific load.
+.P
+.B SFS
+generates and transmits
+.SM NFS
+packets over the network to the server directly from the benchmark program,
+without using the client's local NFS service.
+This reduces the effect of the client NFS implementation on results,
+and makes comparison of different servers more client-independent.
+However, not all client implementation effects have been eliminated.
+Since the benchmark does by-pass much of the client NFS implementation
+(including operating system level data caching and write behind),
+.B SFS
+can only be used to measure server performance.
+.P
+Although
+.B SFS
+can be run between a single client and single server pair of machines,
+a more accurate measure of server performance is obtained
+by executing the benchmark on a number of clients simultaneously.
+Not only does this present a more realistic model of
+.SM NFS
+usage, but also improves the chances that maximum performance
+is limited by a lack of resources on the server machine,
+rather than on a single client machine.
+.P
+In order to facilitate running
+.B SFS
+on a number of clients simultaneously,
+an accompanying program called
+.B sfs_mgr
+provides a mechanism to run and synchronize the execution of multiple
+instances of
+.B SFS
+spread across multiple clients and multiple networks
+all generating load to the same
+.SM NFS
+server.
+In general,
+.B sfs_mgr
+should be used to run both single- and multiple-client tests.
+.P
+.B SFS
+employs a number of sub\-processes, each with its own test directory named
+.B ./testdir<n>
+(where <n> is a number from 0 to
+.B processes
+\- 1.)
+A standard set of files is created in the test directory.
+.P
+If multiple
+.B directories
+are specified on the command line, the
+.B SFS
+processes will be evenly distributed among the directories.
+This will produce a balanced load across each of the directories.
+.P
+The mix of
+.SM NFS
+operations generated can be set from a user defined mix file.
+The format of the file consists of a simple format, the first
+line contains the string "SFS MIXFILE VERSION 2" followed by
+each line containing the operation name and the percentage (eg.
+"write 12"). The total percentages must equal 100.
+Operations with not specified will never be called by
+.B SFS.
+.SH SFS OPTIONS
+.TP
+.B \-a access_pcnt
+The percentage of I/O files to access.
+The access percent can be set from 0 to 100 percent.
+The default is 10% access.
+.TP
+.B \-A append_pcnt
+The percentage of write operations that append data to files
+rather than overwriting existing data.
+The append percent can be set from 0 to 100 percent.
+The default is 70% append.
+.TP
+.B \-b blocksz_file
+The name of a file containing a block transfer size distribution specification.
+The format of the file and the default values are discussed below
+under "Block Size Distribution".
+.TP
+.B \-B block_size
+The maximum number of Kilo-bytes (KB) contained in any one data transfer block.
+The valid range of values is from 1 to 8 KB.
+The default maximum is 8 KB per transfer.
+.TP
+.B \-d debug_level
+The debugging level, with higher values producing more debugging output.
+When the benchmark is executed with debugging enabled,
+the results are invalid.
+The debug level must be greater than zero.
+.TP
+.B \-D dir_cnt
+The number of files in each directory, the number of directories varies with
+load load.
+The default is 30 files per directory.
+.TP
+.B \-f file_set_delta
+The percentage change in file set size.
+The change percent can be set from 0 to 100 percent.
+The default is 10% append.
+.TP
+.B \-F file_cnt
+The number of files to be used for read and write operations.
+The file count must be greater than 0.
+The default is 100 files.
+.TP
+.B \-i
+Run the test in interactive mode,
+pausing for user input before starting the test.
+The default setting is to run the test automatically.
+.TP
+.B \-l load
+The number of NFS calls per second to generate from each client machine.
+The load must be greater than the number of processes
+(see the "\-p processes" option).
+The default is to generate 60 calls/sec on each/client.
+.TP
+.B \-m mix_file
+The name of a file containing the operation mix specification.
+The format of the file and the default values are discussed below
+under "Operation Mix".
+.TP
+.B \-p processes
+The number of processes used to generate load on each client machine.
+The number of processes must be greater than 0.
+The default is 4 processes per client.
+.TP
+.B \-P
+Populate the test directories and then exit; don't run the test.
+This option can be used to examine the file set that the benchmark creates.
+The default is to populate the test directories and then
+execute the test automatically.
+.TP
+.B \-Q
+Run NFS over TCP.
+The default is UDP.
+.TP
+.B \-R biod_reads
+The maximum number of asynchronus reads issued to simulate biod behavior.
+The default is 2.
+.TP
+.B \-S symlink_cnt
+The number of symbolic links to be used for symlink operations.
+The symbolic link count must be greater than 0.
+The default is 20 symlinks.
+.TP
+.B \-t time
+The number of seconds to run the benchmark.
+The number of seconds must be greater than 0.
+The default is 300 seconds.
+(Run times less than 300 seconds may produce invalid results.)
+.TP
+.B \-T op_num
+Test a particular
+.SM NFS
+operation by executing it once.
+The valid range of operations is from 1 to 23.
+These values correspond to the procedure number
+for each operation type as defined in the
+.SM NFS
+protocol specification.
+The default is to run the benchmark, with no preliminary operation testing.
+.TP
+.B \-V
+Validate the correctness of the server's
+.SM NFS
+implementation.
+The option verifies the correctness of
+.SM NFS
+operations and data copies.
+The verification takes place immediately before executing the test,
+and does not affect the results reported by the test. 
+The default is not to verify server
+.SM NFS
+operation before beginning the test.
+.TP
+.B \-z
+Generate raw data dump of the individual data points
+for the test run.
+.TP
+.B \-w warmup
+The number of seconds to generate load before starting the timed test run.
+The goal is to reach a steady state and eliminate any variable startup costs,
+before beginning the test.
+The warm up time must be greater than or equal to 0 seconds.
+The default is a 60 second warmup period.
+.TP
+.B \-W biod_writes
+The maximum number of asynchronus writes issued to simulate biod behavior.
+The default is 2.
+.SH MULTI-CLIENT OPTIONS
+.B SFS
+also recognizes options that are only used when executing a multi-client test.
+These options are generated by
+.B sfs_mgr
+and should not be specified by an end-user.
+.TP
+.B \-M prime_client_hostname
+The hostname of the client machine where a multi-client test
+is being controlled from.
+This machine is designated as the "prime client".
+The prime client machine may also be executing the
+.B SFS
+load-generating code. There is no default value.
+.TP
+.B \-N client_num
+The client machine's unique identifier within a multi-client test,
+assigned by the
+.B sfs_mgr
+script.
+There is no default value.
+.\".TP
+.\".B \-R random_number_seed
+.\"The value used by the client to index into a table of random number seeds.
+.\"There is no default value.
+.SH OPERATION MIX
+The
+.B SFS
+default mix of operations for version 2 is:
+.sp
+.TS
+center;
+l l l l l l
+n n n n n n
+l l l l l l
+n n n n n n
+l l l l l l
+n n n n n n.
+null	getattr	setattr	root	lookup	readlink
+0%	26%	1%	0%	36%	7%
+read	wrcache	write	create	remove	rename
+14%	7%	1%	1%	0%	0%
+link	symlink	mkdir	rmdir	readdir	fsstat
+0%	0%	0%	0%	6%	1%
+.TE
+.LP
+The
+.B SFS
+default mix of operations for version 3 is:
+.sp
+.TS
+center;
+l l l l l l
+n n n n n n
+l l l l l l
+n n n n n n
+l l l l l l
+n n n n n n
+l l l l l l
+n n n n n n.
+null	getattr	setattr	lookup	access	readlink
+0%	11%	1%	27%	7%	7%
+read	write	create	mkdir	symlink	mknod
+18%	9%	1%	0%	0%	0%
+remove	rmdir	rename	link	readdir	readdirplus
+1%	0%	0%	0%	2%	9%
+fsstat	fsinfo	pathconf	commit
+1%	0%	0%	5%
+.TE
+.P
+The format of the file consists of a simple format, the first
+line contains the string "SFS MIXFILE VERSION 2" followed by
+each line containing the operation name and the percentage (eg.
+"write 12"). The total percentages must equal 100.
+.SH FILE SET
+The default basic file set used by
+.B SFS
+consists of regular files varying in size from 1KB to 1MB used for read and
+write operations,
+and 20 symbolic links used for symbolic link operations.
+In addition to these, a small number of regular files are created
+and used for non-I/O operations (eg, getattr),
+and a small number of regular, directory, and symlink files may
+be added to this total due to creation operations (eg, mkdir).
+.P
+While these values can be controlled with command line options,
+some file set configurations may produce invalid results.
+If there are not enough files of a particular type,
+the specified mix of operations will not be achieved.
+Too many files of a particular type may produce
+thrashing effects on the server.
+.SH BLOCK SIZE DISTRIBUTION
+The block transfer size distribution is specified by a table of values.
+The first column gives the percent of operations that will be included in a
+any particular specific block transfer.
+The second column gives the number of blocks units that will be transferred.
+Normally the block unit size is 8KB.
+The third column is a boolean specifying
+whether a trailing fragment block should be transferred.
+The fragment size for each transfer is a random multiple of 1 KB,
+up to the block size - 1 KB.
+Two tables are used, one for read operation and one for write operations.
+The following tables give the default distributions
+for the read and write operations.
+.sp
+.TS
+center;
+c s s s
+c s s s
+r r r r
+r r r r
+c s s s
+n n n r.
+Read  - Default Block Transfer Size Distribution Table
+ 
+ 	 	 	resulting transfer
+percent	block count	fragment	(8KB block size)
+ 
+0	0	0	 0%    0 -   7 KB
+85	1	0	85%    8 -  15 KB
+8	2	1	 8%   16 -  23 KB
+4	4	1	 4%   32 -  39 KB
+2	8	1	 2%   64 -  71 KB
+1	16	1	 1%  128 - 135 KB
+.TE
+.sp 2
+.TS
+center;
+c s s s
+c s s s
+r r r r
+r r r r
+c s s s
+n n n r.
+Write  - Default Block Transfer Size Distribution Table
+ 
+ 	 	 	resulting transfer
+percent	block count	fragment	(8KB block size)
+ 
+49	0	1	49%    0 -   7 KB
+36	1	1	36%    8 -  15 KB
+8	2	1	 8%   16 -  23 KB
+4	4	1	 4%   32 -  39 KB
+2	8	1	 2%   64 -  71 KB
+1	16	1	 1%  128 - 135 KB
+.TE
+.P
+A different distribution can be substituted by using the '-b' option.
+The format for the block size distribution file consists of the first
+three columns given above: percent, block count, and fragment.  Read
+and write distribution tables are identified by the keywords "Read" and
+"Write".  An example input file, using the default values, is given below:
+.sp
+.TS
+l s s
+n n n.
+Read
+0	0	0
+85	1	0
+8	2	1
+4	4	1
+2	8	1
+1	16	1
+.TE
+.TS
+l s s
+n n n.
+Write
+49	0	1
+36	1	1
+8	2	1
+4	4	1
+2	8	1
+1	16	1
+.TE
+.P
+A second aspect of the benchmark controlled
+by the block transfer size distribution table is the network data packet size.
+The distribution tables define the relative proportion
+of full block packets to fragment packets.
+For instance, the default tables have been constructed
+to produce a specific distribution of ethernet packet sizes
+for i/o operations by controlling the amount of data in each packet.
+The write packets produced consist of 50% 8-KB packets, and 50% 1-7 KB packets.
+The read packets consist of 90% 8-KB packets, and 10% 1-7 KB packets.
+These figures are determined by multiplying the percentage
+of type of transfer times the number of blocks and fragments generated,
+and adding the totals.
+These computations are performed below
+for the default block size distribution tables:
+.sp
+.TS
+c c c c c
+c c c c c
+n n n n n
+n n n n n
+n n n n n
+n n n n n
+n n n n n
+n n n n n
+r r r l l
+r r r n n
+r r r l l.
+Read	 	 	total	total
+percent	blocks	fragments	blocks	fragments
+0	0	0	0	0
+85	1	0	85	0
+8	2	1	16	8
+4	4	1	16	4
+2	8	1	16	2
+1	16	1	16	1
+ 	 	 	----	-----
+ 	 	 	149	15
+ 	 	 	 90%	  10%
+.TE
+.sp 3
+.TS
+r r r r r
+r r r r r
+n n n n n
+n n n n n
+n n n n n
+n n n n n
+n n n n n
+n n n n n
+r r r l l
+r r r n n
+r r r l l.
+Write	 	 	total	total
+percent	blocks	fragments	blocks	fragments
+49	0	1	0	49
+36	1	1	36	36
+8	2	1	16	8
+4	4	1	16	4
+2	8	1	16	2
+1	16	1	16	1
+ 	 	 	----	------
+ 	 	 	100	100
+ 	 	 	 50%	   50%
+.TE
+.SH USING SFS
+As with all benchmarks,
+.B SFS
+can only provide numbers that are useful
+if the test runs are set up carefully.
+Since it measures server performance,
+the client (or clients) should not limit throughput.
+The goal is to determine how well the server performs.
+Most tests involving a single client will be limited by the client's
+ability to generate load, not by the server's ability to handle more load.
+Whether this is the case can be determined by running the benchmark
+at successively greater load levels and finding the "knee of the curve"
+at which load level the response time begins to increase rapidly.
+Having found the knee of the curve, measurements of CPU utilization,
+disk i/o rates, and network utilization levels should be made in order
+to determine whether the performance bottleneck is due to the client
+or server.
+.P
+For the results reported by
+.B SFS
+to be meaningful, the tests should be run on an isolated network,
+and both the client and server should be as quiescent as possible during tests.
+.P
+High error rates on either the client or server
+can also cause delays due to retransmissions
+of lost or damaged packets.
+.B netstat(8)
+can be used to measure the network error
+and collision rates on the client and server.
+Also
+.B SFS
+reports the number of timed-out
+.SM RPC
+calls that occur during the test as bad calls.
+If the number of bad calls is too great,
+or the specified mix of operations is not achieved,
+.B SFS
+reports that the test run is "Invalid".
+In this case, the reported results should be examined 
+to determine the cause of the errors.
+.P
+To best simulate the effects of
+.SM NFS
+clients on the server, the test
+directories should be set up so that they are on at least two
+disk partitions exported by the server.
+.SM NFS
+operations tend to randomize disk access,
+so putting all of the
+.B SFS
+test directories on a single partition will not show realistic results.
+.P
+On all tests it is a good idea to run the tests repeatedly and compare results.
+If the difference between runs is large,
+the run time of the test should be increased
+until the variance in milliseconds per call is acceptably small.
+If increasing the length of time does not help,
+there may be something wrong with the experimental setup.
+.P
+The numbers generated by
+.B SFS
+are only useful for comparison if the test setup on the client machine
+is the same across different server configurations. 
+Changing the
+.B processes
+or
+.B mix
+parameters will produce numbers that can not be meaningfully compared.
+Changing the number of generator processes may affect the measured response
+time due to context switching or other delays on the client machine,
+while changing the mix of
+.SM NFS
+operations will change the whole nature of the experiment.
+Other changes to the client configuration may also effect the comparability
+of results.
+.P
+To do a comparison of different server configurations, first set up the
+client test directory and do
+.B SFS
+runs at different loads to be sure that the variability is
+reasonably low. Second, run
+.B SFS
+at different loads of interest and
+save the results. Third, change the server configuration (for example,
+add more memory, replace a disk controller, etc.). Finally, run the same
+.B SFS
+loads again and compare the results.
+.SH SEE ALSO
+.P
+The benchmark 
+.B README  
+file contains many pointers to other
+files which provide information concerning SFS.
+.SH ERROR MESSAGES
+.TP 10
+.B "illegal load value"
+The
+.B load
+argument following the
+.B \-l
+flag on the command line is not a positive number.
+.TP
+.B "illegal procs value"
+The
+.B processes
+argument following the
+.B \-p
+flag on the command line is not a positive number.
+.TP
+.B "illegal time value"
+The
+.B time
+argument following the
+.B \-t
+flag on the command line is not a positive number.
+.TP
+.B "bad mix file"
+The
+.B mix
+file argument following the
+.B \-m
+flag on the command line could not be accessed.
+.TP
+.B "can't fork"
+The parent couldn't fork the child processes. This usually results from
+lack of resources, such as memory or swap space.
+.TP
+.PD 0
+.B "can't open log file"
+.TP
+.B "can't stat log"
+.TP
+.B "can't truncate log"
+.TP
+.B "can't write sync file"
+.TP
+.B "can't write log"
+.TP
+.B "can't read log"
+.PD
+A problem occurred during the creation, truncation, reading or writing of the
+synchronization log file. The parent process creates the
+log file in /tmp and uses it to synchronize and communicate with its children.
+.TP
+.PD 0
+.B "can't open test directory"
+.TP
+.B "can't create test directory"
+.TP
+.B "can't cd to test directory"
+.TP
+.B "wrong permissions on test dir"
+.TP
+.B "can't stat testfile"
+.TP
+.B "wrong permissions on testfile"
+.TP
+.B "can't create rename file"
+.TP
+.B "can't create subdir"
+.PD
+A child process had problems creating or checking the contents of its
+test directory. This is usually due to a permission problem (for example
+the test directory was created by a different user) or a full file system.
+.TP
+.PD 0
+.B "op failed: "
+One of the internal pseudo\-NFS operations failed. The name of the operation,
+e.g. read, write, lookup, will be printed along with an indication of the
+nature of the failure.
+.TP
+.B "select failed"
+The select system call returned an unexpected error.
+.SH BUGS
+.P
+.B SFS
+can not be run on non\-NFS file systems.
+.P
+.P
+Shell scripts that execute
+.B SFS
+must catch and ignore SIGUSR1, SIGUSR2, and SIGALRM, (see signal(3)).
+These signals are used to synchronize the test processes.
+If one of these signals is not caught,
+the shell that is running the script will be killed.
+.SH FILES
+.PD 0
+.TP
+.B ./testdir*
+per process test directory
+.TP
+.B /tmp/sfs_log%d
+child process synchronization file
+.TP
+.B /tmp/sfs_CL%d
+client log file
+.TP
+.B /tmp/sfs_PC_sync
+prime client log file
+.TP
+.B /tmp/sfs_res
+prime results log file
+.PD
diff --git a/TBBT/trace_play/sfs3.full_speed b/TBBT/trace_play/sfs3.full_speed
new file mode 100755
index 0000000000000000000000000000000000000000..5237e99301bbf36d98a995526c3757787e6c530d
GIT binary patch
literal 1004158
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
E3lf{3xc~qF

literal 0
HcmV?d00001

diff --git a/TBBT/trace_play/sfs_2_ops.c b/TBBT/trace_play/sfs_2_ops.c
new file mode 100644
index 0000000..f50f353
--- /dev/null
+++ b/TBBT/trace_play/sfs_2_ops.c
@@ -0,0 +1,2131 @@
+#ifndef lint
+static char sfs_c_opsSid[] = "@(#)sfs_2_ops.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_c_ops.c ---------------------
+ *
+ *      RPC routines to implement the NFS protocol.
+ *
+ *.Local Routines
+ *	int op_null(void)
+ *	int op_getattr(void)
+ *	int op_setattr(int)
+ *	int op_nosys(void)
+ *	int op_lookup(void)
+ *	int op_readlink(void)
+ *	int op_read(int)
+ *	int op_write(int, int, int)
+ *	int op_create(void)
+ *	int op_remove(void)
+ *	int op_rename(void)
+ *	int op_link(void)
+ *	int op_symlink(void)
+ *	int op_mkdir(void)
+ *	int op_rmdir(void)
+ *	int op_readdir(void)
+ *	int op_fsstat(void)
+ *
+ *.Revision_History
+ *	20-Apr-92	Wittle		Fix i/o offsets randomization.
+ *	05-Jan-92	Pawlowski	Added hooks in for raw data dump.
+ *      04-Dec-91	Keith		Define string.h for SYSV/SVR4.
+ *	28-Nov-91	Teelucksingh	ANSI C
+ *	01-Aug-91	Santa Wiryaman  fix declaration of sfs_srandom()
+ *					and sfs_random()
+ *	25-Jun-91	Santa Wiryaman  op_rmdir bug fix: when reply==NFS_OK
+ *					Cur_file_ptr->state = Nonexistent
+ *	17-May-90	Richard Bean	Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+/*
+ * --------------------  Local NFS ops function --------------------
+ */
+static int op_null(void);
+static int op_getattr(void);
+static int op_setattr(int);
+static int op_lookup(void);
+static int op_readlink(void);
+static int op_read(int);
+static int op_write(int, int, int);
+static int op_create(void);
+static int op_remove(void);
+static int op_rename(void);
+static int op_link(void);
+static int op_symlink(void);
+static int op_mkdir(void);
+static int op_rmdir(void);
+static int op_readdir(void);
+static int op_fsstat(void);
+static int op_nosys(void);
+static char *nfs2_strerror(int);
+
+/*
+ * --------------------  NFS ops vector --------------------
+ */
+/*
+ * per operation information
+ */
+static sfs_op_type nfsv2_Ops[] = {
+
+/* name      mix   function        op    call  no  req  req  req  results */
+/*           pcnt                 class  targ call pcnt cnt  targ         */
+
+ { "null",        0, op_null,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "getattr",    26, op_getattr,   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "setattr",     1, op_setattr,   Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "root",        0, op_nosys,     Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "lookup",     36, op_lookup,    Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readlink",    7, op_readlink,  Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "read",       14, op_read,      Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "wrcache",     0, op_nosys,     Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "write",       7, op_write,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "create",      1, op_create,    Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "remove",      1, op_remove,    Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rename",      0, op_rename,    Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "link",        0, op_link,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "symlink",     0, op_symlink,   Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "mkdir",       0, op_mkdir,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rmdir",       0, op_rmdir,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdir",     6, op_readdir,   Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsstat",      1, op_fsstat,	   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "access",	  0, op_nosys,	   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "commit",	  0, op_nosys,	   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsinfo",	  0, op_nosys,	   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "mknod",	  0, op_nosys,	   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "pathconf",	  0, op_nosys,	   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdirplus", 0, op_nosys,	   Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "TOTAL",     100, 0,            Lookup,  0,  0,  0.0,  0,   0,  { 0, }}
+};
+
+sfs_op_type *Ops;
+
+/*
+ * --------------------  RPC routines for NFS protocol --------------------
+ */
+
+void
+init_ops(void)
+{ 
+    Ops = nfsv2_Ops;
+    nfs_version = NFS_VERSION;
+} 
+
+/*
+ * The routines below attempt to do over-the-wire operations.
+ * Each op tries to cause one or more of a particular
+ * NFS operation to go over the wire.  OPs return the success
+ * of their NFS call(s).  Each OP records how many calls it
+ * actually made in global data.
+ *
+ * An array of file information is kept for files existing in
+ * the test directory.  File handles, attributes, names, etc
+ * are stored in this array.
+ *
+ */
+
+static int
+op_nosys(void)
+{
+    /*
+     * This is a generic catcher for operations that either don't
+     * exist or were never implemented.  We will be
+     * kind and simply mark it as a bad call.
+     */
+    Ops[TOTAL].results.bad_calls++;
+    return(0);
+
+} /* op_nosys */
+
+
+static int
+op_null(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int 		ret;		/* ret val == call success */
+
+    op_ptr = &Ops[NULLCALL];
+    ret = 0;
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_NULL,
+			xdr_void, (char *)0,
+			xdr_void, (char *)0,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+		    "%s: null_op call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_null */
+
+
+static int
+op_getattr(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    fhandle_t		fh;		/* fh to do op on */
+    attrstat		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[GETATTR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &fh, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_GETATTR,
+			xdr_getattr, (char *) &fh,
+			xdr_getattr, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS_OK) {
+	    Cur_file_ptr->attributes2 = reply.attrstat_u.attributes;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: getattr call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+		    "%s: getattr call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_getattr */
+
+
+/*
+ * perform an RPC setattr operation.  If 'truncate_size' is non-negative,
+ * truncate the file to that size.
+ */
+static int
+op_setattr(
+    int		truncate_size)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    sattrargs		args;
+    attrstat		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[SETATTR];
+    ret = 0;
+
+    /* set up the arguments */
+    args.attributes.mode = 0666;
+    args.attributes.uid = (unsigned int) -1;
+    args.attributes.gid = (unsigned int) -1;
+    args.attributes.size = (unsigned int) -1;
+    args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+    args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+    (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+
+    /* handle file truncations */
+    if (truncate_size >= 0) {
+	if (truncate_size > Cur_file_ptr->attributes2.size)
+	    args.attributes.size = (unsigned int) 0;
+	else
+	    args.attributes.size = (unsigned int) Cur_file_ptr->attributes2.size
+				   - truncate_size;
+    }
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_SETATTR,
+			xdr_setattr, (char *) &args,
+			xdr_setattr, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS_OK) {
+	    Cur_file_ptr->attributes2 = reply.attrstat_u.attributes;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: setattr call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+		    "%s: setattr call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_setattr */
+
+
+static int
+op_lookup(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    diropargs		args;
+    diropres		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[LOOKUP];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    args.name = Cur_filename;
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_LOOKUP,
+			xdr_lookup, (char *) &args,
+			xdr_lookup, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file,
+			NFS_FHSIZE);
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    Cur_file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+            /* We do lookup Nonexistent and this is not an error */
+            if (reply.status != NFSERR_NOENT ||
+                        Cur_file_ptr->state != Nonexistent) {
+	        if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+			"%s: lookup call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	        }
+            }
+
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: lookup call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_lookup */
+
+
+static int
+op_readlink(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    fhandle_t		fh;			/* fh to do op on */
+    readlinkres		reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];
+    int			len;			/* length of symlink data */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[READLINK];
+    ret = 0;
+
+    /* set up the arguments */
+    /*
+     * Note: this fh may be bogus because SYMLINK does
+     * not return a fh ... only a status.  So unless we have
+     * done a LOOKUP on this guy, the fh will probably be bad.
+     * If it is bad it shows up as a symlink error in the results.
+     */
+    (void) memmove((char *) &fh, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+
+    /* Have lower layers fill in the data directly. */
+    reply.readlinkres_u.data = sym_data;
+    len = 0;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_READLINK,
+			xdr_readlink, (char *) &fh,
+			xdr_readlink, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS_OK) {
+	    if (DEBUG_CHILD_RPC) {
+		len = reply.readlinkres_u.len;
+		sym_data[len] = '\0';
+		(void) fprintf(stderr, "%s: READLINK on %s returned %s\n",
+				    sfs_Myname, Cur_filename, sym_data);
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readlink call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+		    "%s: readlink call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readlink */
+
+
+/*
+ * perform an RPC read operation of length 'xfer_size'
+ */
+static int
+op_read(
+    int 			xfer_size)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    int				cur_cnt;
+    int				max_cnt;	/* packet ctrs */
+    char			buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
+    readargs			args;
+    readres			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				size;
+    int				j;
+    int				ret;		/* ret val == call success */
+
+    op_ptr = &Ops[READ];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+
+    /*
+     * Don't allow a read of less than one block size
+     */
+    if (xfer_size < Bytes_per_block)
+	xfer_size = Bytes_per_block;
+
+    /*
+     * randomly choose an offset that is a multiple of the block size
+     * and constrained by making the transfer fit within the file
+     */
+    if (Cur_file_ptr->attributes2.size > xfer_size) {
+	args.offset = Bytes_per_block * (sfs_random() %
+			(((Cur_file_ptr->attributes2.size - xfer_size)
+			/ Bytes_per_block) + 1));
+    } else
+	args.offset = 0;
+
+    /* first read the whole buffers, then the fragment */
+    for (j = 0; j < 2; j++) {
+
+	if (j == 0) {
+	    size = Bytes_per_block;
+	    max_cnt = xfer_size / Bytes_per_block;
+	} else {
+	    /* 1KB - (Kb_per_block -1) KB fragment */
+	    size = xfer_size % Bytes_per_block;
+	    max_cnt = 1;
+	}
+	if (size == 0)
+	    continue;
+
+	/* check our stats to see if this would overflow */
+	if (!Timed_run) {
+	    if (op_ptr->target_calls > 0) {
+		if ((op_ptr->results.good_calls + max_cnt)
+		     > op_ptr->target_calls) {
+		    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+		}
+	    }
+	}
+
+	args.count = size;
+	args.totalcount = size;		/* unused */
+
+	/* Have lower layers fill in the data directly.  */
+	reply.readres_u.reply.data.data_val = buf;
+
+	if (DEBUG_CHILD_RPC) {
+	    (void) fprintf(stderr, "read: %d buffers\n", max_cnt);
+	    (void) fflush(stderr);
+	}
+
+	/* make the call(s) now */
+	for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
+
+	    /* capture length for possible dump */
+	    Dump_length = fh_size(Cur_file_ptr);
+
+	    sfs_gettime(&start);
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_READ,
+				xdr_read, (char *) &args,
+				xdr_read, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+	    sfs_gettime(&stop);
+	    Cur_time = stop;
+
+	    /* capture count and offset for possible dump */
+	    Dump_count = (rpc_stat == RPC_SUCCESS && reply.status == NFS_OK)
+			    ? reply.readres_u.reply.data.data_len : 0;
+	    Dump_offset = args.offset;
+
+	    if (rpc_stat == RPC_SUCCESS) {
+		if (reply.status == NFS_OK) {
+		    Cur_file_ptr->state = Exists;
+		    Cur_file_ptr->attributes2 =
+					reply.readres_u.reply.attributes;
+		    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+		    size = reply.readres_u.reply.data.data_len;
+
+		    if (DEBUG_CHILD_RPC) {
+			(void) fprintf(stderr, "%s: READ %s %d bytes\n",
+					   sfs_Myname, Cur_filename, size);
+			(void) fflush(stderr);
+		    }
+		    args.offset += size;
+		} else {
+		    if (DEBUG_CHILD_ERROR) {
+			 (void) fprintf(stderr,
+				"%s: read call NFS error %s on file %d\n",
+				sfs_Myname, nfs2_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+		    }
+		}
+		sfs_elapsedtime(op_ptr, &start, &stop);
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+		ret++;
+	    } else {
+		if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+			    "%s: read call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+		}
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	    }
+	} /* for reading max_cnt packets */
+    } /* for buffers and fragments */
+    return(ret);
+
+} /* op_read */
+
+
+char *
+init_write_buffer(
+    void)
+{
+    uint32_t *bp;
+    static uint32_t write_buf[DEFAULT_MAX_BUFSIZE / sizeof(uint32_t)];
+    uint32_t *be  = write_buf + (sizeof(write_buf) /
+						sizeof(uint32_t));
+
+    if (write_buf[0] != (uint32_t)0xdeadbeef) {
+        for (bp = write_buf; bp < be; bp++)
+            *bp = (uint32_t)0xdeadbeef;
+    }
+    return (char *)write_buf;
+}
+
+/*
+ * Perform and RPC write operation of length 'xfer_size'.  If 'append_flag'
+ * is true, then write the data to the end of the file.
+ */
+/* ARGSUSED2 */
+static int
+op_write(
+    int			xfer_size,
+    int			append_flag,
+    int			stable)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    static char			*buf = NULL;	/* the data buffer */
+    int				size;		/* size of data write */
+    int				cur_cnt;	/* controls # NFS calls */
+    int				max_cnt;
+    writeargs			args;
+    attrstat			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				j;
+    int				ret;		/* ret val == call success */
+
+    /*
+     * Initialize write buffer to known value
+     */
+    if (buf == NULL) {
+	buf = init_write_buffer();
+    }
+    op_ptr = &Ops[WRITE];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+    args.beginoffset = 0;	/* unused */
+
+    if (append_flag == 1) {
+	args.offset = Cur_file_ptr->attributes2.size;
+    } else {
+	/*
+	 * randomly choose an offset that is a multiple of the block size
+	 * and constrained by making the transfer fit within the file
+	 */
+	if (Cur_file_ptr->attributes2.size > xfer_size) {
+	    args.offset = Bytes_per_block * (sfs_random() %
+			    (((Cur_file_ptr->attributes2.size - xfer_size)
+			    / Bytes_per_block) + 1));
+	} else
+	    args.offset = 0;
+    }
+
+    /* first write the whole buffers, then the fragment */
+    for (j = 0; j < 2; j++) {
+
+	if (j == 0) {
+	    size = Bytes_per_block;
+	    max_cnt = xfer_size / Bytes_per_block;
+	} else {
+	    /* 1KB - (Kb_per_block - 1) KB fragment */
+	    size = xfer_size % Bytes_per_block;
+	    max_cnt = 1;
+	}
+	if (size == 0)
+	    continue;
+
+	args.totalcount = size;	/* unused */
+	args.data.data_len = size;
+	args.data.data_val = buf;
+
+	/* check our stats to see if this would overflow */
+	if (!Timed_run) {
+	    if (op_ptr->target_calls > 0) {
+		if ((op_ptr->results.good_calls + max_cnt)
+		     > op_ptr->target_calls) {
+		    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+		}
+	    }
+	}
+
+	if (DEBUG_CHILD_RPC) {
+	    (void) fprintf(stderr, "write: %d buffers\n", max_cnt);
+	    (void) fflush(stderr);
+	}
+
+	/* make the call(s) now */
+	for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
+
+	    /* capture length for possible dump */
+	    Dump_length = fh_size(Cur_file_ptr);
+
+	    sfs_gettime(&start);
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_WRITE,
+				xdr_write, (char *) &args,
+				xdr_write, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+	    sfs_gettime(&stop);
+	    Cur_time = stop;
+
+	    /* capture count and offset for possible dump */
+	    Dump_count = args.data.data_len;
+	    Dump_offset = args.offset;
+
+	    if (rpc_stat == RPC_SUCCESS) {
+		if (reply.status == NFS_OK) {
+		    Cur_file_ptr->state = Exists;
+		    Cur_file_ptr->attributes2 = reply.attrstat_u.attributes;
+		    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+		    args.offset += size;
+
+		    if (DEBUG_CHILD_RPC) {
+			(void) fprintf(stderr, "%s: WRITE %s %d bytes\n",
+					   sfs_Myname, Cur_filename, size);
+			(void) fflush(stderr);
+		    }
+		} else {
+		    if (DEBUG_CHILD_ERROR) {
+			 (void) fprintf(stderr,
+				"%s: write call NFS error %s on file %d\n",
+				sfs_Myname, nfs2_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+		    }
+		}
+		sfs_elapsedtime(op_ptr, &start, &stop);
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+		ret++;
+	    } else {
+		if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+			    "%s: write call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+		}
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	    }
+	} /* for writing max_cnt packets */
+    } /* for buffers and fragments */
+    return(ret);
+
+} /* op_write */
+
+
+static int
+op_create(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    createargs		args;
+    diropres		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[CREATE];
+    ret = 0;
+
+    /* set up the arguments */
+    args.attributes.mode = (0100000 | 0666);	/* 666 NFREG file */
+    args.attributes.uid = Cur_uid;
+    args.attributes.gid = Cur_gid;
+    args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+    args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+    args.attributes.size = 0;
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    args.where.name = Cur_filename;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_CREATE,
+			xdr_create, (char *) &args,
+			xdr_create, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file,
+			NFS_FHSIZE);
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    Cur_file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: create call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: create call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_create */
+
+
+static int
+op_remove(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    diropargs		args;
+    nfsstat		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[REMOVE];
+    ret = 0;
+
+    /* set up the arguments */
+    args.name = Cur_filename;
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_REMOVE,
+			xdr_remove, (char *) &args,
+			xdr_remove, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply == NFS_OK) {
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: remove call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: remove call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_remove */
+
+
+static int
+op_rename(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target name */
+    renameargs		args;
+    nfsstat		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[RENAME];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.from.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    (void) memmove((char *) &args.to.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+
+    target_fileinfo_ptr = randfh(RENAME, 0, 0, Nonexistent,
+				 Sfs_non_io_file);
+
+    args.from.name = Cur_file_ptr->file_name;
+    (void) sprintf(target_fileinfo_ptr->file_name, Filespec,
+		   target_fileinfo_ptr->unique_num);
+    args.to.name = target_fileinfo_ptr->file_name;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_RENAME,
+			xdr_rename, (char *) &args,
+			xdr_rename, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply == NFS_OK) {
+	    target_fileinfo_ptr->state = Exists;
+	    (void) memmove((char *) &target_fileinfo_ptr->fh2,
+			(char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+	    target_fileinfo_ptr->attributes2 = Cur_file_ptr->attributes2;
+	    target_fileinfo_ptr->size = Cur_file_ptr->size;
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: rename call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: rename call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_rename */
+
+
+static int
+op_link(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target */
+    linkargs		args;
+    nfsstat		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[LINK];
+    ret = 0;
+
+    /* set up the arguments */
+    target_fileinfo_ptr = randfh(LINK, 0, 0, Exists, Sfs_non_io_file);
+    (void) memmove((char *) &args.from, (char *) &target_fileinfo_ptr->fh2,
+			NFS_FHSIZE);
+    (void) memmove((char *) &args.to.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    args.to.name = Cur_filename;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_LINK,
+			xdr_link, (char *) &args,
+			xdr_link, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply == NFS_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &target_fileinfo_ptr->fh2, NFS_FHSIZE);
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    target_fileinfo_ptr->attributes2.nlink++;
+	    Cur_file_ptr->attributes2 = target_fileinfo_ptr->attributes2;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: link call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: link call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_link */
+
+
+static int
+op_symlink(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target file */
+    symlinkargs		args;
+    nfsstat		reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];	/* symlink data */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[SYMLINK];
+    ret = 0;
+
+    /* set up the arguments */
+    target_fileinfo_ptr = randfh(SYMLINK, 0, 0, Exists, Sfs_non_io_file);
+    (void) memmove((char *) &args.from.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    args.from.name = Cur_filename;
+
+    (void) strcpy(sym_data, "./");
+    (void) strcat(sym_data, target_fileinfo_ptr->file_name);
+    args.attributes.size = strlen(sym_data);
+    args.to = sym_data;
+
+    args.attributes.mode = (0120000 | 0777);
+    args.attributes.uid = Cur_uid;
+    args.attributes.gid = Cur_gid;
+    args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+    args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_SYMLINK,
+			xdr_symlink, (char *) &args,
+			xdr_symlink, (char *) &reply,
+			((int)Current_test_phase < (int)Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply == NFS_OK) {
+	    /*
+	     * SYMLINK doesn't return a fh. If we try to
+	     * access this symlink (eg, remove(), readlink())
+	     * before we do a lookup, we won't have a fh to use.
+	     * So, we do a lookup call here.
+	     * If it fails, we fill in what we can.
+	     */
+	    Cur_file_ptr->state = Exists;
+	    if (op_lookup() == 0) {
+		(void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+		Cur_file_ptr->attributes2.type = NFLNK;
+		Cur_file_ptr->attributes2.mode = (0120000|0777);
+		Cur_file_ptr->attributes2.uid = Cur_uid;
+		Cur_file_ptr->attributes2.gid = Cur_gid;
+		Cur_file_ptr->attributes2.atime.seconds =(unsigned int)Cur_time.esec;
+		Cur_file_ptr->attributes2.atime.useconds=(unsigned int)Cur_time.usec;
+		Cur_file_ptr->attributes2.mtime = Cur_file_ptr->attributes2.atime;
+	    } else
+		ret++;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: symlink call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: symlink call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_symlink */
+
+
+static int
+op_mkdir(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    mkdirargs		args;
+    diropres		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[MKDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    args.attributes.mode = (NFSMODE_DIR | 0777);
+    args.attributes.uid = Cur_uid;
+    args.attributes.gid = Cur_gid;
+    args.attributes.size = (unsigned int) 512;
+    args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+    args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+    args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    args.where.name = Cur_filename;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_MKDIR,
+			xdr_mkdir, (char *) &args,
+			xdr_mkdir, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS_OK) {
+	    Cur_file_ptr->state = Empty_dir;
+	    (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file,
+			NFS_FHSIZE);
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    Cur_file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: mkdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: mkdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_mkdir */
+
+
+static int
+op_rmdir(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    diropargs		args;
+    nfsstat		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[RMDIR];
+    ret = 0;
+
+    if (Cur_file_ptr->state != Empty_dir) {
+	     (void) fprintf(stderr, "%s: Attempting to remove non-Empty_dir %d\n",
+		    sfs_Myname, Cur_file_ptr->unique_num);
+    }
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    args.name = Cur_file_ptr->file_name;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_RMDIR,
+			xdr_rmdir, (char *) &args,
+			xdr_rmdir, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply == NFS_OK) {
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: rmdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: rmdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_rmdir */
+
+
+static int
+op_readdir(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    readdirargs		args;
+    readdirres		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    uint_t		i;
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+    nfscookie		cookie;
+    bool_t		hit_eof;
+	/* arbitrary fixed ceiling */
+    int			entry_cnt = SFS_MAXDIRENTS;
+	/* array of entries */
+    entry		entry_stream[SFS_MAXDIRENTS];
+    entry		*entry_ptr;		/* ptr to the dir entry */
+
+    char	name[SFS_MAXNAMLEN];
+	/* array of dir names */
+    char	name_stream[SFS_MAXDIRENTS * SFS_MAXNAMLEN];
+
+
+    /*
+     * 1) need some measure of how many entries are in a directory
+     * currently, we assume SFS_MAXDIRENTS - it should be random
+     * from 0 to MAX for a large MAX we should pre-allocate a buffer for the
+     * returned directory names.
+     * 2) need some measure of how many directory entries to read
+     * during each readdir() call.  Again, we assume SFS_MAXDIRENTS.
+     */
+
+    op_ptr = &Ops[READDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh2,
+			NFS_FHSIZE);
+    (void) memset((char *) args.cookie, '\0', NFS_COOKIESIZE);
+    args.count = DEFAULT_MAX_BUFSIZE;
+
+    /* Have lower layers fill in the data directly.  */
+    reply.readdirres_u.reply.max_entries = entry_cnt;
+    reply.readdirres_u.reply.entries = entry_stream;
+    for (i = 0; i < entry_cnt; i++) {
+	entry_stream[i].name = &name_stream[i * SFS_MAXNAMLEN];
+    }
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_READDIR,
+			xdr_readdir, (char *) &args,
+			xdr_readdir, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS_OK) {
+
+	    if (DEBUG_CHILD_RPC) {
+		hit_eof = reply.readdirres_u.reply.eof;
+		entry_cnt = reply.readdirres_u.reply.max_entries;
+		entry_ptr = reply.readdirres_u.reply.entries;
+		for (i = 0; i < entry_cnt; i++) {
+		    entry_ptr->name[entry_ptr->name_len] ='\0';
+		    (void) strcpy(name, entry_ptr->name);
+		    (void) memmove((char *) cookie,
+					(char *) entry_ptr->cookie,
+					NFS_COOKIESIZE);
+		    (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
+					sfs_Myname, hit_eof, name);
+		    entry_ptr++;
+		}
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs2_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: readdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readdir */
+
+
+/* Beware - op_statfs() collides w/ some other name, use op_fsstat() */
+static int
+op_fsstat(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    fhandle_t		fh;
+    statfsres		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[FSSTAT];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &fh, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC_STATFS,
+			xdr_statfs, (char *) &fh,
+			xdr_statfs, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: fsstat call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_fsstat */
+
+
+/*
+ * These are a set of reliable functions used by the initialization code.
+ */
+
+#define LAD_RETRIABLE(stat) (((stat) == RPC_TIMEDOUT) || ((stat) == RPC_CANTDECODERES))
+
+/*
+ * Reliably lookup a file in the current directory
+ * Return:
+ *	-1	RPC error
+ *	1	File doesn't exist
+ *	0	File exists
+ */
+int
+lad_lookup(sfs_fh_type *file_ptr, char *name)
+{
+    diropargs		args;
+    diropres		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_lookup: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	(void) memmove((char *) &args.dir, (char *) &file_ptr->dir->fh2,
+			NFS_FHSIZE);
+	args.name = name;
+
+	/* make the call */
+	rpc_stat = clnt_call(NFS_client, NFSPROC_LOOKUP,
+			xdr_lookup, (char *) &args,
+			xdr_lookup, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_lookup(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    if (reply.status == NFSERR_NOENT) {
+	return(1);
+    }
+
+    if (reply.status != NFS_OK) {
+	(void) fprintf(stderr, "lad_lookup(%s) NFS call failed : %s\n",
+			name, nfs2_strerror(reply.status));
+	return(-1);
+    }
+
+    file_ptr->state = Exists;
+    (void) memmove((char *) &file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
+    (void) strcpy(file_ptr->file_name, name);
+    file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
+    file_ptr->size = fh_size(file_ptr);
+
+    return(0);
+}
+
+/*
+ * Reliably remove a file in the current directory
+ */
+int
+lad_remove(sfs_fh_type *file_ptr, char *name)
+{
+    diropargs		args;
+    nfsstat		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    int			retried = 0;
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_remove: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does exist
+     */
+    if (file_ptr->attributes2.type == NFDIR)
+	return (lad_rmdir(file_ptr, name));
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.name = name;
+	(void) memmove((char *) &args.dir, (char *) &file_ptr->dir->fh2,
+			NFS_FHSIZE);
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC_REMOVE,
+			xdr_remove, (char *) &args,
+			xdr_remove, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_remove(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply != NFS_OK) {
+	if (reply != NFSERR_NOENT || !retried) {
+	    (void) fprintf(stderr, "lad_remove(%s) NFS call failed : %s\n",
+			name, nfs2_strerror(reply));
+	    return(-1);
+	}
+    }
+
+    file_ptr->state = Nonexistent;
+
+    return(0);
+}
+
+/*
+ * Reliably remove a directory in the current directory
+ */
+int
+lad_rmdir(sfs_fh_type *file_ptr, char *name)
+{
+    diropargs		args;
+    nfsstat		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    int			retried = 0;
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s: lad_rmdir: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does exist and the directory
+     * is empty.
+     */
+    if (file_ptr->attributes2.type != NFDIR)
+	return (lad_remove(file_ptr, name));
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.name = name;
+	(void) memmove((char *) &args.dir, (char *) &file_ptr->dir->fh2,
+			NFS_FHSIZE);
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC_RMDIR,
+			xdr_remove, (char *) &args,
+			xdr_remove, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_rmdir(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply != NFS_OK) {
+	if (reply != NFSERR_NOENT || !retried) {
+	    (void) fprintf(stderr, "lad_rmdir(%s) NFS call failed : %s\n",
+			name, nfs2_strerror(reply));
+	    return(-1);
+	}
+    }
+
+    file_ptr->state = Nonexistent;
+
+    return(0);
+}
+
+/*
+ * Reliably create a symlink in the current directory
+ */
+int
+lad_symlink(sfs_fh_type *file_ptr, char *target, char *name)
+{
+    symlinkargs		args;
+    nfsstat		reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];	/* symlink data */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_symlink: %lx %s -> %s\n", sfs_Myname,
+			(int32_t) file_ptr, name, target);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	(void) memmove((char *) &args.from.dir, (char *) &file_ptr->dir->fh2,
+			NFS_FHSIZE);
+	args.from.name = name;
+
+	(void) strcpy(sym_data, "./");
+	(void) strcat(sym_data, target);
+	args.attributes.size = strlen(sym_data);
+	args.to = sym_data;
+
+	args.attributes.mode = (0120000 | 0777);
+	args.attributes.uid = Cur_uid;
+	args.attributes.gid = Cur_gid;
+	args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+	args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC_SYMLINK,
+			xdr_symlink, (char *) &args,
+			xdr_symlink, (char *) &reply,
+		 	Nfs_timers[Init]);
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_symlink(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply != NFS_OK) {
+	if (reply != NFSERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_symlink(%s, %s) NFS call failed : %s\n",
+			target, name, nfs2_strerror(reply));
+	    return(-1);
+	}
+    }
+
+    /*
+     * SYMLINK doesn't return a fh. If we try to
+     * access this symlink (eg, remove(), readlink())
+     * before we do a lookup, we won't have a fh to use.
+     * So, we do a lookup call here.
+     * If it fails, we fill in what we can.
+     */
+    return (lad_lookup(file_ptr, name));
+}
+
+/*
+ * Reliably create a directory in the current directory
+ */
+int
+lad_mkdir(sfs_fh_type *file_ptr, char *name)
+{
+    mkdirargs		args;
+    diropres		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_mkdir: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.attributes.mode = (NFSMODE_DIR | 0777);
+	args.attributes.uid = Cur_uid;
+	args.attributes.gid = Cur_gid;
+	args.attributes.size = (unsigned int) 512;
+	args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+	args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+	(void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh2,
+			NFS_FHSIZE);
+	args.where.name = name;
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC_MKDIR,
+			xdr_mkdir, (char *) &args,
+			xdr_mkdir, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_mkdir(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (!retried && reply.status == NFSERR_EXIST)
+	return(1);
+
+    if (reply.status != NFS_OK) {
+	if (reply.status != NFSERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_mkdir(%s) NFS call failed : %s\n",
+			name, nfs2_strerror(reply.status));
+	    return(-1);
+	}
+	/*
+	 * If the first mkdir suceeded but the reply as dropped and
+	 * was retransmitted, we still need to lookup the attributes
+	 */
+	if (lad_lookup(file_ptr, name))
+	   return (-1);
+    } else {
+	(void) memmove((char *) &file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file,
+			NFS_FHSIZE);
+	(void) strcpy(file_ptr->file_name, name);
+	file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
+	file_ptr->size = fh_size(file_ptr);
+    }
+    file_ptr->state = Empty_dir;
+
+    return(0);
+}
+
+/*
+ * Reliably write a file in the current directory
+ */
+int
+lad_write(sfs_fh_type *file_ptr, int32_t offset, int32_t length)
+{
+    static char			*buf = NULL;	/* the data buffer */
+    int32_t			size;		/* size of data write */
+    int32_t			cur_cnt;
+    writeargs			args;
+    attrstat			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_write: %lx[%lx] %ld %ld\n",
+			sfs_Myname, (int32_t) file_ptr, (int32_t) file_ptr->dir,
+			offset, length);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does exist
+     * Initialize write buffer to known value
+     */
+    if (buf == NULL) {
+	buf = init_write_buffer();
+    }
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &file_ptr->fh2,
+			NFS_FHSIZE);
+    args.beginoffset = 0;	/* unused */
+    args.offset = offset;
+
+    size = Bytes_per_block;
+    for (cur_cnt = 0; cur_cnt < length; cur_cnt += size) {
+	if ((cur_cnt + size) > length)
+		size = length - cur_cnt;
+
+	if (size == 0)
+	    break;
+
+	args.totalcount = size;	/* unused */
+	args.data.data_len = size;
+	args.data.data_val = buf;
+
+	/* make the call now */
+        /* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_WRITE,
+				xdr_write, (char *) &args,
+				xdr_write, (char *) &reply,
+				Nfs_timers[Init]);
+
+	    if (rpc_stat == RPC_SUCCESS) 
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_write() RPC call failed : %s\n",
+				clnt_sperrno(rpc_stat));
+	    }
+	    if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	    }
+	}
+	if (reply.status != NFS_OK) {
+	    (void) fprintf(stderr, "lad_write() NFS call failed : %s\n",
+			nfs2_strerror(reply.status));
+	    return(-1);
+	}
+	file_ptr->state = Exists;
+	file_ptr->attributes2 = reply.attrstat_u.attributes;
+	file_ptr->size = fh_size(file_ptr);
+	args.offset += size;
+    }
+    return(0);
+}
+
+/*
+ * Reliably create a file in the current directory
+ */
+int
+lad_create(sfs_fh_type *file_ptr, char *name)
+{
+    createargs		args;
+    diropres		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_create: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.attributes.mode = (0100000 | 0666);	/* 666 NFREG file */
+	args.attributes.uid = Cur_uid;
+	args.attributes.gid = Cur_gid;
+	args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+	args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+	args.attributes.size = 0;
+	(void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh2,
+			NFS_FHSIZE);
+	args.where.name = name;
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC_CREATE,
+			xdr_create, (char *) &args,
+			xdr_create, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_create(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (!retried && reply.status == NFSERR_EXIST) {
+	return(1);
+    }
+
+    if (reply.status != NFS_OK) {
+	if (reply.status != NFSERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_create(%s) NFS call failed : %s\n",
+			name, nfs2_strerror(reply.status));
+	    return(-1);
+	}
+	/*
+	 * If the first create suceeded but the reply as dropped and
+	 * was retransmitted, we still need to lookup the attributes
+	 */
+	if (lad_lookup(file_ptr, name))
+	   return (-1);
+    } else {
+	(void) memmove((char *) &file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
+	(void) strcpy(file_ptr->file_name, name);
+	file_ptr->attributes2 = reply.diropres_u.diropres.attributes;
+	file_ptr->size = fh_size(file_ptr);
+    }
+
+    file_ptr->state = Exists;
+    /*
+     * Directories are created as Empty_dir, when a file is created it
+     * becomes an Exists.
+     */
+    file_ptr->dir->state = Exists;
+
+    return(0);
+}
+
+/*
+ * Reliably set the size of a file in the current directory
+ */
+int
+lad_truncate(sfs_fh_type *file_ptr, int32_t size)
+{
+    sattrargs		args;
+    attrstat		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_truncate: %lx[%lx] %ld\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, size);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name already exists
+     */
+    /* CONSTCOND */
+    while (1) {
+	/*
+	 * set up the arguments
+	 * Set the mode and times as well
+	 */
+	args.attributes.mode = 0666;
+	args.attributes.uid = (unsigned int) -1;
+	args.attributes.gid = (unsigned int) -1;
+	args.attributes.size = (unsigned int) -1;
+	args.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+	args.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+	args.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+	(void) memmove((char *) &args.file, (char *) &file_ptr->fh2,
+			NFS_FHSIZE);
+	args.attributes.size = (unsigned int) size;
+
+	/* make the call */
+	rpc_stat = clnt_call(NFS_client, NFSPROC_SETATTR,
+			xdr_setattr, (char *) &args,
+			xdr_setattr, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr,
+				"lad_truncate(%ld) RPC call failed : %s\n",
+				size, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    if (reply.status != NFS_OK) {
+	(void) fprintf(stderr, "lad_truncate(%ld) NFS call failed : %s\n",
+			size, nfs2_strerror(reply.status));
+	return(-1);
+    }
+    file_ptr->attributes2 = reply.attrstat_u.attributes;
+    file_ptr->size = fh_size(file_ptr);
+
+    return(0);
+}
+
+static char *
+nfs2_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFSERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFSERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFSERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFSERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFSERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFSERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFSERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFSERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFSERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFSERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFSERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFSERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFSERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFSERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFSERR_OPNOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFSERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFSERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFSERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFSERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFSERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFSERR_WFLUSH:
+	    (void) strcpy(str, "write cache flushed");
+	    break;
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+/* sfs_c_ops.c */
diff --git a/TBBT/trace_play/sfs_2_vld.c b/TBBT/trace_play/sfs_2_vld.c
new file mode 100644
index 0000000..45e24d9
--- /dev/null
+++ b/TBBT/trace_play/sfs_2_vld.c
@@ -0,0 +1,1747 @@
+#ifndef lint
+static char sfs_c_vldSid[] = "@(#)sfs_2_vld.c 2.1     97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *      Copyright 1991,1992  Legato Systems, Inc.                *
+ *      Copyright 1991,1992  Auspex Systems, Inc.                *
+ *      Copyright 1991,1992  Data General Corporation            *
+ *      Copyright 1991,1992  Digital Equipment Corporation       *
+ *      Copyright 1991,1992  Interphase Corporation              *
+ *      Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ------------------------------ sfs_c_vld.c ---------------------------
+ *
+ * Validation suite for sfs.
+ *
+ *.Exported_routines
+ *      void Validate_ops(int, char **)
+ *
+ *.Local_routines
+ *      void validate_init_rpc()
+ *      void validate_creation(void)
+ *      void validate_attributes(void)
+ *      void validate_read_write(void)
+ *      void validate_rename(void)
+ *      int compare_sattr(char *, char *, sattr *, fattr *)
+ *      int compare_fattr(char *, char *, fattr *, fattr *)
+ *      uint16_t sum(unsigned char *, uint_t)
+ *      void validate_remove(void)
+ *      void validate_cleanup(void)
+ *      void validate_exit(void)
+ *      void verror(int, ValMsgType, char *, ...)
+ *
+ *.Revision History
+ *      04-Dec-91       Keith           Define string.h for SYSV/SVR4.
+ *      25-Jun-91       Wiryaman        Created
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+extern struct hostent	*Server_hostent;
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+
+/* forward definitions for local routines */
+/*
+ * validate options
+ * BATCH        - do complete pass of validation, reporting errors if any
+ * VERBOSE      - prints step-by-step validation actions being performed
+ * INTERACTIVE  - VERBOSE and if any errors encountered, ask to continue
+ *                validation or not.
+ */
+#define VAL_BATCH       1
+#define VAL_VERBOSE     2
+#define VAL_INTERACTIVE 3
+
+typedef enum {
+        I = 1,
+        W = 2,
+        E = 3
+} ValMsgType;
+
+#define NUMREGFILES     7
+#define NUMDIRS         5
+#define NUMLINKS        5
+#define NUMSYMLINKS     5
+#define NUMFILES        NUMREGFILES + NUMDIRS + NUMLINKS + NUMSYMLINKS
+#define NUMFRAGS        8
+
+static void validate_init_rpc(void);
+static void validate_exit(void);
+static void validate_creation(void);
+static void validate_attributes(void);
+static void validate_read_write(void);
+static void validate_rename(void);
+static void validate_remove(void);
+static void validate_cleanup(void);
+static int compare_sattr(char *, char *, sattr *, fattr *);
+static int compare_fattr(char *, char *, fattr *, fattr *);
+static uint16_t sum(unsigned char *, uint_t);
+static void verror(int, ValMsgType, char *, ...);
+
+static void val_op_null(void);
+static void val_op_getattr(fhandle_t *, attrstat *);
+static void val_op_setattr(sattrargs *, attrstat *);
+static void val_op_lookup(diropargs *, diropres *);
+static void val_op_readlink(fhandle_t *, readlinkres *);
+static void val_op_read(readargs *, readres *);
+static void val_op_write(writeargs *, attrstat *);
+static void val_op_create(createargs *, diropres *);
+static void val_op_remove(diropargs *, nfsstat *);
+static void val_op_rename(renameargs *, nfsstat *);
+static void val_op_link(linkargs *, nfsstat *);
+static void val_op_symlink(symlinkargs *, nfsstat *);
+static void val_op_mkdir(mkdirargs *, diropres *);
+static void val_op_rmdir(diropargs *, nfsstat *);
+static void val_op_readdir(readdirargs *, readdirres *);
+static void val_op_statfs(fhandle_t *, statfsres *);
+static void create_tmp_handles(void);
+static void delete_tmp_handles(void);
+
+/*
+ * ----------------------  Static Declarations ----------------------
+ */
+
+int Validate;
+
+static int Validate_errors = 0;
+static char Testdirname[SFS_MAXPATHLEN];    /* test dir component name */
+
+/*
+ * ----------------------  SFS Validation Suite  ----------------------
+ */
+
+void
+Validate_ops(
+    int         argc,
+    char *      argv[])
+{
+    char *      valdir;
+    CLIENT *    mount_client_ptr;
+
+    if (argc > 1) {
+        verror(VAL_BATCH, E, "Can only validate one directory at a time.\n");
+        exit(1);
+    }
+
+    Num_io_files = NUMFILES;
+    Cur_uid = Real_uid;
+    nfs_version = NFS_VERSION;
+
+    if (argc == 0)
+        valdir = ".";
+    else
+        valdir = argv++[0];
+
+    (void) sprintf(Testdirname, "%s/validatedir", valdir);
+
+    do {
+        verror(VAL_BATCH, I, "validating sfs on \"%s\" directory ...\n",
+                valdir);
+
+        init_fileinfo();
+	create_tmp_handles();
+
+        /*
+         * need priv port to do following
+         */
+        mount_client_ptr = lad_getmnt_hand(valdir);
+        if (mount_client_ptr == NULL) {
+            exit(1);
+        }
+        validate_init_rpc();
+
+        /*
+         * should be all done doing priv port stuff
+         */
+        if (setuid(Real_uid) != 0) {
+           (void) fprintf(stderr,"%s: %s%s\n",
+                   sfs_Myname, "cannot perform setuid operation.\n",
+                   "Do `make install` as root.\n");
+        }
+
+        init_mount_point(0, valdir, mount_client_ptr);
+        verror(VAL_VERBOSE, I, "validating null operation ...\n");
+        val_op_null();
+
+        validate_creation();
+        validate_attributes();
+        validate_read_write();
+        validate_rename();
+        validate_remove();
+        argc--;
+        valdir = argv++[0];
+
+        /*
+         * Cleanup mount client handle
+         */
+        clnt_destroy(mount_client_ptr);
+
+	delete_tmp_handles();
+        validate_cleanup();
+
+    } while (argc > 0);
+
+    validate_exit();
+
+} /* Validate_ops */
+
+
+/*
+ * allocate and initialize client handles
+ */
+static void
+validate_init_rpc(void)
+{
+	NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+                                        (uint32_t) NFS_PROGRAM,
+                                        (uint32_t) NFS_VERSION,
+                                        RPC_ANYSOCK, &Nfs_timers[0]);
+ 
+	if (NFS_client == ((CLIENT *) NULL)) { 
+		verror(VAL_BATCH, E, "portmap/nfsd server not responding\n"); 
+		exit(1); 
+	}
+ 
+	NFS_client->cl_auth = authunix_create(lad_hostname, Real_uid,
+                                      Cur_gid, 0, NULL);
+} /* validate_init_rpc */
+
+
+static void
+validate_creation(void)
+{
+    int                 filenum;
+    int                 target_filenum;
+    diropargs           arglp;
+    createargs          argcr;
+    mkdirargs           argmk;
+    linkargs            argln;
+    symlinkargs         argsl;
+    char                sl_target_path[NFS_MAXPATHLEN];
+    diropres            reply;
+    readlinkres         rlreply;
+    char                sym_data[NFS_MAXPATHLEN];
+
+    for (filenum=0; filenum < NUMFILES ; filenum++) {
+
+        Cur_file_ptr = &Io_files[filenum];
+        sfs_gettime(&Cur_time);
+
+        if (filenum < NUMREGFILES) {
+
+            (void) sprintf(Cur_filename, Filespec, filenum);
+
+            /* regular file creation */
+            argcr.attributes.mode= (NFSMODE_REG | 0666);
+            argcr.attributes.uid = Cur_uid;
+            argcr.attributes.gid = Cur_gid;
+            argcr.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+            argcr.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+            argcr.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+            argcr.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+            argcr.attributes.size = 0;
+            (void) memmove((char *) &argcr.where.dir, (char *) &Export_dir.fh2,
+			NFS_FHSIZE);
+            argcr.where.name = Cur_filename;
+
+            verror(VAL_VERBOSE, I, "validating create file %s ...\n",
+					Cur_filename);
+            val_op_create(&argcr, &reply);
+
+            if (reply.status == NFS_OK) {
+                Cur_file_ptr->state = Exists;
+                (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
+                (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+                (void) memmove((char *) &Cur_file_ptr->attributes2,
+				(char *) &reply.diropres_u.diropres.attributes,
+				sizeof(Cur_file_ptr->attributes2));
+                (void) compare_sattr(Ops[CREATE].name, Io_files[filenum].file_name,
+                            &argcr.attributes, &Cur_file_ptr->attributes2);
+            } else {
+                Cur_file_ptr->state = Nonexistent;
+                errno = (int)reply.status;
+                verror(VAL_BATCH, E, "create %s failed: %m\n", Cur_filename);
+                /*
+                 * An error in file creation is fatal, because we use the
+                 * created files to validate the other operations.
+                 */
+                validate_exit();
+            }
+
+        } else if (filenum < NUMREGFILES + NUMDIRS) {
+
+            (void) sprintf(Cur_filename, Dirspec, filenum);
+
+            /* directory creation */
+            argmk.attributes.mode= (NFSMODE_DIR | 0777);
+            argmk.attributes.uid = Cur_uid;
+            argmk.attributes.gid = Cur_gid;
+            argmk.attributes.size = 0xFFFFFFFF;
+            argmk.attributes.atime.seconds = (unsigned int) Cur_time.esec;
+            argmk.attributes.atime.useconds = (unsigned int) Cur_time.usec;
+            argmk.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
+            argmk.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
+            (void) memmove((char *) &argmk.where.dir, (char *) &Export_dir.fh2,
+			NFS_FHSIZE);
+            argmk.where.name = Cur_filename;
+
+            verror(VAL_VERBOSE, I, "validating mkdir %s ...\n", Cur_filename);
+            val_op_mkdir(&argmk, &reply);
+
+            if (reply.status == NFS_OK) {
+                Cur_file_ptr->state = Exists;
+                (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file,
+			NFS_FHSIZE);
+                (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+                (void) memmove((char *) &Cur_file_ptr->attributes2,
+				(char *) &reply.diropres_u.diropres.attributes,
+				sizeof(Cur_file_ptr->attributes2));
+                (void) compare_sattr(Ops[MKDIR].name, Io_files[filenum].file_name,
+                                &argmk.attributes, &Cur_file_ptr->attributes2);
+            } else {
+                Cur_file_ptr->state = Nonexistent;
+                verror(VAL_BATCH, W, "mkdir %s failed:%m\n", Cur_filename);
+            }
+
+        } else if(filenum < NUMREGFILES + NUMDIRS + NUMLINKS ) {
+
+            (void) sprintf(Cur_filename, Filespec, filenum);
+
+            /* hard link creation */
+            target_filenum = NUMFILES-NUMSYMLINKS-1-filenum;
+            (void) memmove((char *) &argln.from,
+			(char *) &Io_files[target_filenum].fh2, NFS_FHSIZE);
+            (void) memmove((char *) &argln.to.dir, (char *) &Export_dir.fh2,
+			NFS_FHSIZE);
+            argln.to.name = Cur_filename;
+
+            verror(VAL_VERBOSE, I, "validating link %s %s ...\n",
+				Io_files[target_filenum].file_name, Cur_filename);
+            val_op_link(&argln, &reply.status);
+
+            if (reply.status == NFS_OK) {
+                Cur_file_ptr->state = Exists;
+                (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &Io_files[target_filenum].fh2,
+			NFS_FHSIZE);
+                (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+                Cur_file_ptr->attributes2 = Io_files[target_filenum].attributes2;
+                Io_files[target_filenum].attributes2.nlink++;
+                Cur_file_ptr->attributes2.nlink++;
+            } else {
+                Cur_file_ptr->state = Nonexistent;
+                verror(VAL_BATCH, W, "link %s failed: %m\n", Cur_filename);
+            }
+
+        } else {
+
+            (void) sprintf(Cur_filename, Symspec, filenum);
+
+            /* symbolic link creation */
+            target_filenum = NUMFILES-1-filenum;
+            (void) memmove((char *) &argsl.from.dir, (char *) &Export_dir.fh2,
+			NFS_FHSIZE);
+            argsl.from.name = Cur_filename;
+            (void) sprintf(sl_target_path,
+                           "./%s", Io_files[target_filenum].file_name);
+            argsl.attributes.size = strlen(sl_target_path);
+            argsl.to = sl_target_path;
+            argsl.attributes.mode = (NFSMODE_LNK | 0777);
+            argsl.attributes.uid = Cur_uid;
+            argsl.attributes.gid = Cur_gid;
+            argsl.attributes.atime.seconds = (unsigned int)Cur_time.esec;
+            argsl.attributes.atime.useconds = (unsigned int)Cur_time.usec;
+            argsl.attributes.mtime.seconds = (unsigned int)Cur_time.esec;
+            argsl.attributes.mtime.useconds = (unsigned int)Cur_time.usec;
+
+            verror(VAL_VERBOSE, I, "validating symlink %s %s ...\n",
+					sl_target_path, Cur_filename);
+            val_op_symlink(&argsl, &reply.status);
+
+            if (reply.status == NFS_OK) {
+                Cur_file_ptr->state = Exists;
+
+                /* do a lookup to get file handle and attributes */
+                (void) memmove((char *) &arglp.dir, (char *) &Export_dir.fh2,
+			NFS_FHSIZE);
+                arglp.name = Cur_filename;
+
+                val_op_lookup(&arglp, &reply);
+
+                if (reply.status == NFS_OK) {
+                    (void) memmove((char *) &Cur_file_ptr->fh2,
+			(char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
+                    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+                    Cur_file_ptr->attributes2 =
+                                        reply.diropres_u.diropres.attributes;
+                    (void) compare_sattr(Ops[SYMLINK].name,
+                                        Io_files[filenum].file_name,
+                                        &argsl.attributes,
+                                        &Cur_file_ptr->attributes2);
+                } else {
+                    verror(VAL_BATCH, W, "lookup %s failed: %m\n",
+						Cur_filename);
+                    continue;
+                }
+
+                /* validate readlink */
+                rlreply.readlinkres_u.data = sym_data;
+
+                verror(VAL_VERBOSE, I, "validating readlink %s ...\n",
+						Cur_filename);
+                val_op_readlink(&Cur_file_ptr->fh2, &rlreply);
+
+                if (rlreply.status == NFS_OK) {
+                    sym_data[rlreply.readlinkres_u.len] = '\0';
+                    if (strcmp(sl_target_path, sym_data)) {
+                        verror(VAL_BATCH, W,
+                            "readlink %s error, result = %s, should be %s\n",
+                            Cur_filename, rlreply.readlinkres_u.data,
+                            sl_target_path);
+                    }
+                } else {
+                    verror(VAL_BATCH, W, "readlink %s failed:%m\n",
+                            Cur_filename);
+                }
+
+            } else {
+                Cur_file_ptr->state = Nonexistent;
+                verror(VAL_BATCH, W, "symlink %s failed: %m\n",
+                        Cur_filename);
+            }
+        }
+    } /* end for each file */
+
+} /* validate_creation */
+
+
+static void
+validate_attributes(void)
+{
+    int                 filenum;
+    diropargs           arglp;
+    diropres            lreply;
+    fhandle_t           fh;
+    sattrargs           argsa;
+    attrstat            areply;
+
+    /* validate fsstat */
+
+    /* validate lookup */
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+        (void) memmove((char *) &arglp.dir, (char *) &Export_dir.fh2,
+			NFS_FHSIZE);
+        arglp.name = Io_files[filenum].file_name;
+
+        verror(VAL_VERBOSE, I, "validating lookup %s ...\n",
+                Io_files[filenum].file_name);
+        val_op_lookup(&arglp, &lreply);
+
+        if (lreply.status == NFS_OK) {
+            if (memcmp((char *) &(Io_files[filenum].fh2),
+                     (char *) &(lreply.diropres_u.diropres.file),
+                        NFS_FHSIZE)) {
+                verror(VAL_BATCH, W, "lookup %s: file handle mismatch\n",
+                        Io_files[filenum].file_name);
+            }
+            (void) compare_fattr(Ops[LOOKUP].name, Io_files[filenum].file_name,
+                          &Io_files[filenum].attributes2,
+                          &lreply.diropres_u.diropres.attributes);
+        } else {
+            verror(VAL_BATCH, W, "lookup %s failed:%m\n",
+                    Io_files[filenum].file_name);
+        }
+    }
+
+    /* validate getattr */
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+        (void) memmove((char *) &fh, (char *) &Io_files[filenum].fh2,
+			NFS_FHSIZE);
+
+        verror(VAL_VERBOSE, I, "validating getattr %s ...\n",
+                Io_files[filenum].file_name);
+        val_op_getattr(&fh, &areply);
+
+        if (areply.status == NFS_OK) {
+            (void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
+                          &Io_files[filenum].attributes2,
+                          &areply.attrstat_u.attributes);
+        } else {
+            verror(VAL_BATCH, W, "getattr %s failed: %m\n",
+                    Io_files[filenum].file_name);
+        }
+    }
+
+    /*validate setattr */
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+        sfs_gettime(&Cur_time);
+        if (filenum >= NUMREGFILES && filenum < NUMREGFILES + NUMDIRS)
+          argsa.attributes.mode= 0777;
+        else
+          argsa.attributes.mode= 0666;
+        argsa.attributes.uid  = 0xFFFFFFFF;
+        argsa.attributes.gid  = 0xFFFFFFFF;
+        argsa.attributes.size = 0xFFFFFFFF;
+        argsa.attributes.atime.seconds =  (unsigned int)Cur_time.esec;
+        argsa.attributes.atime.useconds = (unsigned int)Cur_time.usec;
+        argsa.attributes.mtime.seconds =  (unsigned int)Cur_time.esec;
+        argsa.attributes.mtime.useconds = (unsigned int)Cur_time.usec;
+        (void) memmove((char *) &argsa.file, (char *) &Io_files[filenum].fh2,
+			NFS_FHSIZE);
+
+        verror(VAL_VERBOSE, I, "validating setattr %s ...\n",
+                Io_files[filenum].file_name);
+        val_op_setattr(&argsa, &areply);
+
+        if (areply.status == NFS_OK) {
+            if (argsa.attributes.mode != areply.attrstat_u.attributes.mode){
+                argsa.attributes.mode |=
+                        (Io_files[filenum].attributes2.mode & NFSMODE_FMT);
+                argsa.attributes.mode &= Io_files[filenum].attributes2.mode;
+            }
+            Io_files[filenum].attributes2 = areply.attrstat_u.attributes;
+            (void) compare_sattr(Ops[SETATTR].name, Io_files[filenum].file_name,
+                          &argsa.attributes, &areply.attrstat_u.attributes);
+
+            val_op_getattr(&argsa.file, &areply);
+
+            if (areply.status == NFS_OK) {
+                (void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
+                              &Io_files[filenum].attributes2,
+                              &areply.attrstat_u.attributes);
+            } else {
+                verror(VAL_BATCH, W, "getattr %s failed: %m\n",
+                        Io_files[filenum].file_name);
+            }
+        } else {
+            verror(VAL_BATCH, W, "setattr %s failed: %m\n",
+                    Io_files[filenum].file_name);
+        }
+    }
+
+} /* validate_attributes */
+
+
+static void
+validate_read_write(void)
+{
+    struct {
+        uint16_t  sum;                    /* checksum of data */
+        uint16_t  len;                    /* length of len and data */
+        char            data[DEFAULT_MAX_BUFSIZE - 2 * sizeof(uint16_t)];
+    } block;
+    writeargs           argwr;
+    attrstat            wrreply;
+    readargs            argrd;
+    readres             rdreply;
+    int                 maxblks;
+    int                 maxfiles;
+    uint_t		i;
+    int                 numfiles;
+    int                 filenum;
+    int                 blocknum;
+    readdirargs         argrdir;
+    readdirres          rdirreply;
+    int                 entry_cnt = 9;
+    entry               entry_stream[9];
+    char                name_stream[9 * SFS_MAXNAMLEN];
+
+    /* validate write */
+
+    /* get the maximum number of blocks sfs will write */
+    maxblks = Io_dist_ptr->max_bufs;
+    maxfiles = maxblks > NUMREGFILES ? NUMREGFILES : maxblks;
+
+    /* write maxblks - filenum + 1 blocks to each regular file */
+    argwr.offset = 0;
+    argwr.beginoffset = 0; /* unused */
+    argwr.totalcount = 0; /* unused */
+    argwr.data.data_val = (char *)&block;
+
+    for (blocknum = 0; blocknum <= maxblks ; blocknum++) {
+
+        for (i=0; i < sizeof(block.data); i++)
+            block.data[i] = (char)blocknum;
+
+        for (filenum=0; filenum < maxfiles; filenum++) {
+
+            /* Write fewer blocks to files with higher numbers. */
+            if (blocknum > (maxblks - filenum))
+                break;
+
+            /* set the length field */
+            if (blocknum == (maxblks - filenum)) {
+                block.len = ((maxfiles - filenum) *
+                            (Bytes_per_block/Kb_per_block)) - (sizeof(block.len)
+                             + sizeof(block.sum));
+            } else {
+                block.len = Bytes_per_block - (sizeof(block.len)
+                            + sizeof(block.sum));
+            }
+            block.sum = sum((unsigned char *) &block.len,
+                            block.len + sizeof(block.len));
+
+            (void) memmove((char *) &argwr.file,
+			(char *) &Io_files[filenum].fh2, NFS_FHSIZE);
+            argwr.data.data_len = block.len +
+                                  sizeof(block.len) + sizeof(block.sum);
+
+            verror(VAL_VERBOSE, I,
+                    "validating write %d bytes @ offset %d to %s ...\n",
+                    argwr.data.data_len, argwr.offset,
+                    Io_files[filenum].file_name);
+
+            val_op_write(&argwr, &wrreply);
+
+            if (wrreply.status == NFS_OK) {
+                (void) compare_fattr(Ops[WRITE].name, Io_files[filenum].file_name,
+                              &Io_files[filenum].attributes2,
+                              &wrreply.attrstat_u.attributes);
+                Io_files[filenum].attributes2 = wrreply.attrstat_u.attributes;
+            } else {
+                verror(VAL_BATCH, W, "write %s failed: %m\n",
+                        Io_files[filenum].file_name);
+            }
+        }
+        argwr.offset += Bytes_per_block;
+    }
+
+    /* validate read */
+
+    for (filenum = 0; filenum < maxfiles; filenum++) {
+        (void) memmove((char *) &argrd.file, (char *) &Io_files[filenum].fh2,
+			NFS_FHSIZE);
+        argrd.offset = 0;
+        argrd.count = 0;
+        rdreply.readres_u.reply.data.data_len = 0;
+        maxblks = Io_files[filenum].attributes2.size / Bytes_per_block;
+        for (blocknum = 0; blocknum <= maxblks; blocknum ++) {
+
+            if (argrd.count != rdreply.readres_u.reply.data.data_len) {
+                argrd.count -= rdreply.readres_u.reply.data.data_len;
+                rdreply.readres_u.reply.data.data_val = (char *)&block +
+                                        rdreply.readres_u.reply.data.data_len;
+                blocknum--;
+            } else {
+                if (blocknum < maxblks)
+                    argrd.count = Bytes_per_block;
+                else
+                    argrd.count = (maxfiles - filenum)
+                                  * (Bytes_per_block/Kb_per_block);
+                rdreply.readres_u.reply.data.data_val = (char *)&block;
+            }
+            argrd.totalcount = argrd.count; /* unused */
+
+            verror(VAL_VERBOSE, I,
+                   "validating read %d bytes @ offset %d from %s ...\n",
+                    argrd.count, argrd.offset,
+                    Io_files[filenum].file_name);
+
+            val_op_read(&argrd, &rdreply);
+
+            if (rdreply.status == NFS_OK) {
+                (void) compare_fattr(Ops[READ].name, Io_files[filenum].file_name,
+                              &Io_files[filenum].attributes2,
+                              &rdreply.readres_u.reply.attributes);
+                Io_files[filenum].attributes2 =
+                                        rdreply.readres_u.reply.attributes;
+                argrd.offset += rdreply.readres_u.reply.data.data_len;
+            } else {
+                verror(VAL_BATCH, W, "read %s failed: %m\n",
+                        Io_files[filenum].file_name);
+            }
+
+            if (argrd.count ==
+                (block.sum != sum((unsigned char *) &block.len,
+                                  block.len + sizeof(block.len)))) {
+                verror(VAL_BATCH, W, "read %s checksum mismatch\n",
+                        Io_files[filenum].file_name);
+            }
+        }
+    }
+
+    /* validate readdir */
+    numfiles = 0;
+
+    (void) memmove((char *) &argrdir.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
+    (void) memset((char *) argrdir.cookie, '\0', NFS_COOKIESIZE);
+    argrdir.count = DEFAULT_MAX_BUFSIZE;
+
+    (void) memset((char *) &rdirreply, '\0', sizeof(rdirreply));
+    rdirreply.readdirres_u.reply.max_entries = entry_cnt;
+    rdirreply.readdirres_u.reply.entries = entry_stream;
+    for (i = 0; i < entry_cnt; i++) {
+        entry_stream[i].name = &name_stream[i * SFS_MAXNAMLEN];
+    }
+
+    do {
+        verror(VAL_VERBOSE, I, "validating readdir %d entries of %s ...\n",
+                rdirreply.readdirres_u.reply.max_entries, Testdirname);
+        val_op_readdir(&argrdir, &rdirreply);
+
+        if (rdirreply.status == NFS_OK) {
+            for (i = 0; i < rdirreply.readdirres_u.reply.max_entries; i++) {
+                numfiles++;
+                entry_stream[i].name[entry_stream[i].name_len] = '\0';
+                if (!entry_stream[i].valid) {
+                    verror(VAL_BATCH, W,
+                          "readdir %s error: entry %d (%s) is marked invalid\n",
+                            Testdirname, i, entry_stream[i].name);
+                }
+                if ((!strcmp(entry_stream[i].name, ".")) ||
+                    (!strcmp(entry_stream[i].name, "..")) ) {
+                    numfiles--;
+                    continue;
+                }
+                for (filenum = 0; filenum < NUMFILES; filenum++) {
+                    if (!strcmp(entry_stream[i].name, Io_files[filenum].file_name)) {
+                        if (entry_stream[i].fileid !=
+                                    Io_files[filenum].attributes2.fileid) {
+                            verror(VAL_BATCH, E,
+                                  "readdir %s error: file %s fileid mismatch\n",
+                                    Testdirname, entry_stream[i].name);
+
+                            verror(VAL_BATCH, W,
+                                   "   fileid: got = %d, original = %d\n",
+                                    entry_stream[i].fileid,
+				    Io_files[filenum].attributes2.fileid);
+                        }
+                        break;
+                    }
+                }
+                if (filenum == NUMFILES) {
+                    verror(VAL_BATCH, W,
+               "readdir %s error: file \"%s\" was not created within sfs\n",
+                            Testdirname, entry_stream[i].name);
+                }
+            }
+
+            if (i < entry_cnt && entry_stream[i].valid) {
+                verror(VAL_BATCH, W,
+                        "readdir %s error: valid entries exceeded maximum\n",
+                        Testdirname);
+            }
+
+        } else {
+            verror(VAL_BATCH, W, "readdir %s failed: %m\n", Testdirname);
+        }
+
+        (void) memmove((char *)argrdir.cookie,
+        (char *)entry_stream[rdirreply.readdirres_u.reply.max_entries-1].cookie,
+			NFS_COOKIESIZE);
+
+    } while (rdirreply.readdirres_u.reply.eof == 0);
+
+    if (numfiles != NUMFILES) {
+        verror(VAL_BATCH, W,
+                        "readdir %s error: the number of files found\n\
+does not match with the number of files created within sfs\n", Testdirname);
+    }
+
+} /* validate_read_write */
+
+
+static void
+validate_rename(void)
+{
+    renameargs  argrn;
+    nfsstat     rnreply;
+    int         filenum;
+    char        newname[SFS_MAXNAMLEN];
+    int         rncount = 0;
+
+    (void) memmove((char *) &argrn.from.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
+    (void) memmove((char *) &argrn.to.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
+
+    for (filenum=0; filenum < NUMFILES; filenum++) {
+        if (Io_files[filenum].state != Exists)
+            continue;
+
+        rncount++;
+        (void) sprintf(newname, "n%s", Io_files[filenum].file_name);
+        argrn.from.name = Io_files[filenum].file_name;
+        argrn.to.name = newname;
+
+        verror(VAL_VERBOSE, I, "validating rename %s %s ...\n",
+                argrn.from.name, argrn.to.name);
+
+        val_op_rename(&argrn, &rnreply);
+
+        if (rnreply == NFS_OK) {
+            (void) strcpy(Io_files[filenum].file_name, newname);
+        } else {
+            verror(VAL_BATCH, W, "rename %s to %s failed: %m\n",
+                    Io_files[filenum].file_name, newname);
+        }
+
+    }
+
+    if (!rncount) {
+        verror(VAL_BATCH, E, "validate_rename: no files renamed\n");
+        verror(VAL_BATCH, W, "    due to previous operation error\n");
+    }
+
+} /* validate_rename */
+
+
+static int
+compare_fattr(
+    char *      op,
+    char *      fname,
+    fattr *     attr1,
+    fattr *     attr2)
+{
+    int         ret = TRUE;
+    int         prev_warn = FALSE; /* -1 info warning */
+    int         flag_error = FALSE;
+
+    if (attr1->type != attr2->type) {
+        if (attr1->type == 0xFFFFFFFF) {
+            prev_warn = TRUE;
+            if (ret) {
+                verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                    fname, op);
+            }
+            verror(VAL_BATCH, I, "    type: current = %d, previous =  %d\n",
+                   attr2->type, attr1->type);
+            attr1->type = attr2->type;
+            ret = FALSE;
+        }
+        else {
+                if (ret) {
+                        verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                            fname, op);
+                }
+                verror(VAL_BATCH, E, "    type: current = %d, previous =  %d\n",
+                        attr2->type, attr1->type);
+                ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+    if ((attr1->mode & NFSMODE_MASK) != (attr2->mode & NFSMODE_MASK)) {
+        if (attr1->mode == (unsigned int)0xFFFFFFFF) {
+                prev_warn = TRUE;
+                if (ret) {
+                        verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                                fname, op);
+                }
+                verror(VAL_BATCH, I, "    mode: current = %7o, previous =  %7o\n",
+                        attr2->mode, attr1->mode);
+                attr1->mode =  attr2->mode;
+                ret = FALSE;
+        }
+        else {
+                if (ret) {
+                        verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                            fname, op);
+                }
+                verror(VAL_BATCH, E, "    mode: current = %d, previous =  %d\n",
+                        attr2->mode, attr1->mode);
+                ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+    if (attr1->nlink != attr2->nlink) {
+        if (attr1->nlink == (unsigned int)0xFFFFFFFF) {
+                prev_warn = TRUE;
+                if (ret) {
+                        verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                                fname, op);
+                }
+                verror(VAL_BATCH, I, "    nlink: current = %d, previous =  %d\n",
+                        attr2->nlink, attr1->nlink);
+                attr1->nlink =  attr2->nlink;
+                ret = FALSE;
+        }
+        else {
+                if (ret) {
+                        verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                            fname, op);
+                }
+                verror(VAL_BATCH, E, "    nlink: current = %d, previous =  %d\n",
+                        attr2->nlink, attr1->nlink);
+                ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+
+    /*
+     * Check for user "nobody", UID -2, which may be untranslated from
+     * sixteen-bit two's complement.
+     */
+    if (attr1->uid != attr2->uid && !((attr2->uid == (unsigned int)0xFFFFFFFE ||
+        attr2->uid == 65534) && attr1->uid ==0)) {
+        if (attr1->uid == (unsigned int)0xFFFFFFFF) {
+                prev_warn = TRUE;
+                if (ret) {
+                        verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                                fname, op);
+                }
+                verror(VAL_BATCH, I, "    uid: current = %d, previous =  %d\n",
+                        attr2->uid, attr1->uid);
+                attr1->uid =  attr2->uid;
+                ret = FALSE;
+        }
+        else {
+                if (ret) {
+                        verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                            fname, op);
+                }
+                verror(VAL_BATCH, E, "    uid: current = %d, previous =  %d\n",
+                        attr2->uid, attr1->uid);
+                ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+    if (attr1->gid != attr2->gid && attr2->gid != 0) {
+/*
+    if (attr1->gid != attr2->gid) {
+*/
+        if (attr1->gid == (unsigned int)0xFFFFFFFF) {
+                prev_warn = TRUE;
+                if (ret) {
+                        verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                                fname, op);
+                }
+                verror(VAL_BATCH, I, "    gid: current = %d, previous =  %d\n",
+                        attr2->gid, attr1->gid);
+                attr1->gid =  attr2->gid;
+                ret = FALSE;
+        }
+        else {
+                if (ret) {
+                        verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                            fname, op);
+                }
+                verror(VAL_BATCH, E, "    gid: current = %d, previous =  %d\n",
+                        attr2->gid, attr1->gid);
+                ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+    if (attr1->size != attr2->size) {
+        if (strcmp(op, Ops[WRITE].name)) {
+            if (attr1->size == (unsigned int)0xFFFFFFFF) {
+                prev_warn = TRUE;
+                if (ret) {
+                        verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                                fname, op);
+                }
+                verror(VAL_BATCH, I, "    size: current = %d, previous =  %d\n",
+                        attr2->size, attr1->size);
+                attr1->size =  attr2->size;
+                ret = FALSE;
+            }
+            else {
+                if (ret) {
+                        verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                            fname, op);
+                }
+                verror(VAL_BATCH, E, "    size: current = %d, previous =  %d\n",
+                        attr2->size, attr1->size);
+                ret = FALSE;
+                flag_error = TRUE;
+            }
+        }
+    }
+
+    if (attr1->blocksize != attr2->blocksize) {
+        if (attr1->blocksize == (unsigned int)0xFFFFFFFF) {
+             prev_warn = TRUE;
+             if (ret) {
+                     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                             fname, op);
+             }
+             verror(VAL_BATCH, I, "    blocksize: current = %d, previous =  %d\n",
+                     attr2->blocksize, attr1->blocksize);
+             attr1->blocksize =  attr2->blocksize;
+             ret = FALSE;
+        }
+        else {
+             if (ret) {
+                     verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                         fname, op);
+             }
+             verror(VAL_BATCH, E, "    blocksize: current = %d, previous =  %d\n",
+                     attr2->blocksize, attr1->blocksize);
+             ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+
+    /* compare rdev only if type == NFCHR or NFBLK */
+    if ((attr1->type == NFCHR || attr1->type == NFBLK) &&
+        attr1->rdev != attr2->rdev) {
+        if (attr1->rdev == (unsigned int)0xFFFFFFFF) {
+             prev_warn = TRUE;
+             if (ret) {
+                     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                             fname, op);
+             }
+             verror(VAL_BATCH, I, "    rdev: current = %d, previous =  %d\n",
+                     attr2->rdev, attr1->rdev);
+             attr1->rdev =  attr2->rdev;
+             ret = FALSE;
+        }
+        else {
+             if (ret) {
+                     verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                         fname, op);
+             }
+             verror(VAL_BATCH, E, "    rdev: current = %d, previous =  %d\n",
+                     attr2->rdev, attr1->rdev);
+             ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+
+    /*
+     * The NFS specification does not require that the number of blocks
+     * associated with a file remain constant.  Certain file systems
+     * may pre-allocate more blocks than necessary then trim them
+     * back ("garbage collect") or even blow holes in files that have
+     * all zero blocks.
+     * We must check that we never get back -1.
+     */
+    if (attr1->blocks != attr2->blocks) {
+        if (strcmp(op, Ops[WRITE].name)) {
+            if (attr1->blocks == (unsigned int)0xFFFFFFFF) {
+                 prev_warn = TRUE;
+                 if (ret) {
+                     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                             fname, op);
+                 }
+                verror(VAL_BATCH, I, "    blocks: current = %d, previous =  %d\n",
+                         attr2->blocks, attr1->blocks);
+                 attr1->blocks =  attr2->blocks;
+                 ret = FALSE;
+            }
+        }
+    }
+
+
+    if (attr1->fsid != attr2->fsid) {
+        if (attr1->fsid == (unsigned int)0xFFFFFFFF) {
+             prev_warn = TRUE;
+             if (ret) {
+                     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                             fname, op);
+             }
+             verror(VAL_BATCH, I, "    fsid: current = %d, previous =  %d\n",
+                     attr2->fsid, attr1->fsid);
+             attr1->fsid =  attr2->fsid;
+             ret = FALSE;
+        }
+        else {
+             if (ret) {
+                     verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                         fname, op);
+             }
+             verror(VAL_BATCH, E, "    fsid: current = %d, previous =  %d\n",
+                     attr2->fsid, attr1->fsid);
+             ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+    if (attr1->fileid != attr2->fileid) {
+        if (attr1->fileid == (unsigned int)0xFFFFFFFF) {
+             prev_warn = TRUE;
+             if (ret) {
+                     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+                             fname, op);
+             }
+             verror(VAL_BATCH, I, "    fileid: current = %d, previous =  %d\n",
+                     attr2->fileid, attr1->fileid);
+             attr1->fileid =  attr2->fileid;
+             ret = FALSE;
+        }
+        else {
+             if (ret) {
+                     verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                         fname, op);
+             }
+             verror(VAL_BATCH, E, "    fileid: current = %d, previous =  %d\n",
+                     attr2->fileid, attr1->fileid);
+             ret = FALSE;
+                flag_error = TRUE;
+        }
+    }
+
+    if (prev_warn) {
+        verror(VAL_BATCH, I,
+                "\n        Warning: the previous value of a field is -1,\n");
+        verror(VAL_BATCH, I,
+                "        this resulted from an unused field returned by\n");
+        verror(VAL_BATCH, I,
+                "        the previous operation on this file/directory.\n");
+        verror(VAL_BATCH, I,
+            "        The current value is now stored for future comparison\n\n");
+    }
+
+    if (flag_error)
+        verror(VAL_BATCH, W,"\n");
+
+    return(flag_error);
+
+} /* ckompare_fattr */
+
+
+static int
+compare_sattr(
+    char *      op,
+    char *      fname,
+    sattr *     attr1,
+    fattr *     attr2)
+{
+    int         ret = TRUE;
+    char        msg[80];
+
+    msg[0] = '\0';
+
+    if (attr1->mode != (unsigned int)0xFFFFFFFF &&
+        (attr1->mode & NFSMODE_MASK) != (attr2->mode & NFSMODE_MASK)) {
+        if (ret) {
+            verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                    fname, op);
+
+        }
+        verror(VAL_BATCH, E, "    mode: returned = %7o, specified = %7o\n",
+                attr2->mode, attr1->mode);
+        ret = FALSE;
+    }
+
+    /*
+     * Check for user "nobody", UID -2, which may be untranslated from
+     * sixteen-bit two's complement.
+     */
+    if (attr1->uid != (unsigned int)0xFFFFFFFF && attr1->uid != attr2->uid &&
+		!((attr2->uid == (unsigned int)0xFFFFFFFE ||
+		attr2->uid == 65534) &&
+			attr1->uid == 0)) {
+        if (ret) {
+            verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                    fname, op);
+        }
+        if (attr1->uid == 0)
+            (void) strcat(msg," (is root UID mapped to other UID?)");
+        verror(VAL_BATCH, E, "    uid: returned = %d, specified = %d %s\n",
+                attr2->uid, attr1->uid, msg);
+        ret = FALSE;
+    }
+    if (attr1->gid != (unsigned int)0xFFFFFFFF &&
+			attr1->gid != attr2->gid &&
+			attr2->gid != 0) {
+/*
+   if (attr1->gid != 0xFFFFFFFF && attr1->gid != attr2->gid) {
+*/
+        if (ret) {
+            verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                    fname, op);
+        }
+        verror(VAL_BATCH, E, "    gid: returned = %d, specified = %d\n",
+                attr2->gid, attr1->gid);
+        ret = FALSE;
+    }
+
+    if (attr1->size != (unsigned int)0xFFFFFFFF &&
+			attr1->size != attr2->size) {
+        if (ret) {
+            verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+                    fname, op);
+        }
+        verror(VAL_BATCH, E, "    size: returned = %d, specified = %d\n",
+                attr2->size, attr1->size);
+        ret = FALSE;
+    }
+
+    if (!ret)
+        verror(VAL_BATCH, W,"\n");
+
+    return(ret);
+
+} /* compare_sattr */
+
+
+/*
+ * Return the BSD checksum of buf[0..len-1]
+ */
+static uint16_t
+sum(
+    unsigned char *     buf,
+    uint_t              len)
+{
+    uint16_t      cksum;
+
+    cksum = 0;
+    for (; len--; buf++) {
+        if (cksum & 1)
+            cksum = (cksum >> 1) + 0x8000;
+        else
+            cksum >>= 1;
+        cksum += (uint16_t) *buf;
+        cksum &= 0xFFFF;
+    }
+    return(cksum);
+} /* sum */
+
+
+static void
+validate_remove(void)
+{
+    diropargs   args;
+    nfsstat     reply;
+    diropres    lreply;
+    int         filenum;
+    char *      op;
+
+    (void) memmove((char *) &args.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
+
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+
+        if (Io_files[filenum].state != Exists)
+            continue;
+
+        args.name = Io_files[filenum].file_name;
+
+        if (Io_files[filenum].attributes2.type == NFDIR) {
+            op = Ops[RMDIR].name;
+            verror(VAL_VERBOSE, I, "validating rmdir %s ...\n",
+                    args.name);
+            val_op_rmdir(&args, &reply);
+        } else {
+            op = Ops[REMOVE].name;
+            verror(VAL_VERBOSE, I, "validating remove %s ...\n",
+                    args.name);
+            val_op_remove(&args, &reply);
+        }
+
+        if (reply == NFS_OK) {
+            /* make sure the file is removed from the directory */
+            val_op_lookup(&args, &lreply);
+
+            if (lreply.status == NFSERR_NOENT) {
+                Io_files[filenum].state = Nonexistent;
+            } else if (lreply.status == NFS_OK) {
+                verror(VAL_BATCH, W, "%s %s: file not removed\n",
+                       op, Io_files[filenum].file_name);
+            } else {
+                verror(VAL_BATCH, W, "lookup %s failed: %m\n",
+                       Io_files[filenum].file_name);
+
+            }
+        } else {
+            verror(VAL_BATCH, W, "%s %s failed: %m\n", op,
+                    Io_files[filenum].file_name);
+        }
+
+    }
+
+} /* validate_remove */
+
+
+static void
+validate_cleanup(void)
+{
+    free(Io_files);
+    free(Non_io_files);
+    free(Dirs);
+    free(Symlinks);
+    clnt_destroy(NFS_client);
+
+} /* validate_cleanup */
+
+
+static void
+validate_exit(void)
+{
+    if (!Validate_errors) {
+        verror(VAL_BATCH, I, "validation completed successfully.\n");
+        exit(0);
+    } else {
+        verror(VAL_BATCH, I, "validation terminated with errors\n");
+        exit(1);
+    }
+
+} /* validate_exit */
+
+
+/* PRINTFLIKE3 */
+static void
+verror(
+    int         opt,
+    ValMsgType  msgtype,
+    char *      fmt,
+    ...)
+{
+    va_list	ap;
+    char        buf[1024];
+    char *      bp = buf;
+    char *      fp;
+    int         repeat;
+    char *	sp;
+
+    va_start(ap, fmt);
+
+    /*
+     * Expand the "%m" format character into the descriptive string
+     * for the current value of errno.  Printf handles the other "%"
+     * formatting characters.
+     */
+    if (Validate >= opt) {
+        for (fp = fmt; *fp; fp++) {
+            if (*fp == '%' && fp[1] == 'm') {
+		if ((sp = strerror(errno)) == NULL) {
+                    (void) sprintf(bp, "unknown error %d", errno);
+                } else {
+                    (void) strcpy(bp, sp);
+                }
+                bp = buf + strlen(buf);
+                fp++;
+            } else {
+                *bp++ = *fp;
+            }
+        }
+        *bp = '\0';
+        (void) vprintf(buf, ap);
+    }
+    va_end(ap);
+
+    if (msgtype != I)
+        Validate_errors++;
+
+    if (msgtype == W && Validate == VAL_INTERACTIVE) {
+        repeat = 1;
+        while (repeat) {
+            char ans[80];
+
+            (void) fprintf(stderr, "continue? (y or n)  ");
+            if (!fgets(ans,80,stdin)) {
+                (void) fprintf(stderr, "\n");
+                continue;
+            }
+            if (ans[0] == 'n' || ans[0] == 'N') {
+                validate_exit();
+                exit(1);
+            } else if (ans[0] == 'y' || ans[0] == 'Y') {
+                repeat = 0;
+                break;
+            }
+        }
+    }
+
+} /* verror */
+
+
+static void
+val_op_null(void)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_NULL, 
+	        xdr_void, (char *)0, xdr_void, (char *)0, 
+	        Nfs_timers[Ops[NULLCALL].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "null");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_getattr(fhandle_t *args, attrstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_GETATTR, 
+	    xdr_getattr, (char *)args, xdr_getattr, (char *)reply, 
+	    Nfs_timers[Ops[GETATTR].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "getattr");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_setattr(sattrargs *args, attrstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_SETATTR, 
+	        xdr_setattr, (char *)args, xdr_setattr, (char *)reply, 
+	        Nfs_timers[Ops[SETATTR].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "setattr");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_lookup(diropargs *args, diropres *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_LOOKUP, 
+	        xdr_lookup, (char *)args, xdr_lookup, (char *)reply, 
+	        Nfs_timers[Ops[LOOKUP].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "lookup");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_readlink(fhandle_t *args, readlinkres *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_READLINK, 
+	        xdr_readlink, (char *)args, xdr_readlink, (char *)reply, 
+	        Nfs_timers[Ops[READLINK].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "readlink");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_read(readargs *args, readres *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_READ, 
+	        xdr_read, (char *)args, xdr_read, (char *)reply, 
+	        Nfs_timers[Ops[READ].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "read");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_write(writeargs *args, attrstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client,
+		NFSPROC_WRITE, xdr_write, (char *)args, xdr_write, (char *)reply,
+		Nfs_timers[Ops[WRITE].call_class]);
+
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		    clnt_perror(NFS_client, "write");
+		    Validate_errors++;
+		    validate_exit();
+            }
+	}
+}
+
+static void
+val_op_create(createargs *args, diropres *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client,
+	    NFSPROC_CREATE, xdr_create, (char *)args, xdr_create, (char *)reply, 
+	    Nfs_timers[Ops[CREATE].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "create");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_remove(diropargs *args, nfsstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client,
+		NFSPROC_REMOVE, xdr_remove, (char *)args, xdr_remove, (char *)reply, 
+	        Nfs_timers[Ops[REMOVE].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "remove");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_rename(renameargs *args, nfsstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_RENAME, 
+	        xdr_rename, (char *)args, xdr_rename, (char *)reply, 
+	        Nfs_timers[Ops[RENAME].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "rename");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_link(linkargs *args, nfsstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_LINK, 
+	        xdr_link, (char *)args, xdr_link, (char *)reply, 
+	        Nfs_timers[Ops[LINK].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "link");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_symlink(symlinkargs *args, nfsstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_SYMLINK, 
+	        xdr_symlink, (char *)args, xdr_symlink, (char *)reply, 
+	        Nfs_timers[Ops[SYMLINK].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "symlink");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_mkdir(mkdirargs *args, diropres *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_MKDIR, 
+	        xdr_mkdir, (char *)args, xdr_mkdir, (char *)reply, 
+	        Nfs_timers[Ops[MKDIR].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "mkdir");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_rmdir(diropargs *args, nfsstat *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_RMDIR, 
+	        xdr_rmdir, (char *)args, xdr_rmdir, (char *)reply, 
+	        Nfs_timers[Ops[RMDIR].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "rmdir");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_readdir(readdirargs *args, readdirres *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_READDIR, 
+	        xdr_readdir, (char *)args, xdr_readdir, (char *)reply, 
+	        Nfs_timers[Ops[READDIR].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "readdir");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_statfs(fhandle_t *args, statfsres *reply)
+{
+	int rpc_stat;
+
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC_STATFS, 
+	        xdr_statfs, (char *)args, xdr_statfs, (char *)reply, 
+	        Nfs_timers[Ops[FSSTAT].call_class]);
+            if (rpc_stat == RPC_SUCCESS)
+                break;
+            if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "statfs");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+static void
+create_tmp_handles(void)
+{
+	int filenum;
+	for (filenum = 0; filenum < NUMFILES; filenum++) {
+
+		if(Io_files[filenum].fh_data == (sfs_fh_data *)0)
+		{
+			Io_files[filenum].fh_data = 
+					calloc(1,sizeof(sfs_fh_data));
+			Io_files[filenum].attributes2.type = NFNON;
+			Io_files[filenum].attributes3.type = NF3NON;
+		}
+	}
+}
+
+static void
+delete_tmp_handles()
+{
+	int filenum;
+	for (filenum = 0; filenum < NUMFILES; filenum++) {
+
+		if(Io_files[filenum].fh_data != (sfs_fh_data *)0)
+		{
+			free(Io_files[filenum].fh_data);
+			Io_files[filenum].fh_data=(sfs_fh_data *)0;
+		}
+	}
+}
+
+
+
+
+
+
+
+
diff --git a/TBBT/trace_play/sfs_2_xdr.c b/TBBT/trace_play/sfs_2_xdr.c
new file mode 100644
index 0000000..7c84899
--- /dev/null
+++ b/TBBT/trace_play/sfs_2_xdr.c
@@ -0,0 +1,735 @@
+#ifndef lint
+static char sfs_c_xdrSid[] = "@(#)sfs_2_xdr.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*
+ * -------------------------- sfs_c_xdr.c --------------------------
+ *
+ *      XDR routines for the nfs protocol.
+ *
+ *.Exported_routines
+ *	bool_t xdr_fhstatus(XDR *, struct fhstatus *)
+ *	bool_t xdr_path(XDR *, char **)
+ *	bool_t xdr_fattr(XDR *, fattr *)
+ *	bool_t xdr_sattr(XDR *, sattr *)
+ *	bool_t xdr_null(void)
+ *	bool_t xdr_getattr(XDR *, char *)
+ *	bool_t xdr_setattr(XDR *, char *)
+ *	bool_t xdr_root(void)
+ *	bool_t xdr_lookup(XDR *, char *)
+ *	bool_t xdr_readlink(XDR *, char *)
+ *	bool_t xdr_read(XDR *, char *)
+ *	bool_t xdr_write(XDR *, char *)
+ *	bool_t xdr_create(XDR *, char *)
+ *	bool_t xdr_remove(XDR *, char *)
+ *	bool_t xdr_rename(XDR *, char *)
+ *	bool_t xdr_link(XDR *, char *)
+ *	bool_t xdr_symlink(XDR *, char *)
+ *	bool_t xdr_mkdir(XDR *, char *)
+ *	bool_t xdr_rmdir(XDR *, char *)
+ *	bool_t xdr_readdir(XDR *, char *)
+ *	bool_t xdr_statfs(XDR *, char *)
+ *
+ *.Local_routines
+ *	bool_t xdr_timeval(XDR *, nfstime *)
+ *	bool_t xdr_nfsstat(XDR *, nfsstat *)
+ *	bool_t xdr_ftype(XDR *, ftype *)
+ *	bool_t xdr_diropargs(XDR *, diropargs *)
+ *	bool_t xdr_diropres(XDR *, diropres *)
+ *	bool_t xdr_attrstat(XDR *, attrstat *)
+ *
+ *.Revision_History
+ *      28-NOv-91	Teelucksingh	ANSI C
+ *	25-Jun-91	Santa Wiryaman	Changed return values to TRUE when
+ *					status != NFS_OK.  This way we can
+ *					decode NFS error messages.
+ *	17-May-90	Richard Bean	Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include "sfs_c_def.h"
+
+/*
+ * -----------------------  Forward Definitions  -----------------------
+ */
+
+static bool_t xdr_f_handle(XDR *, fhandle_t *);
+static bool_t xdr_fattr(XDR *, fattr *);
+static bool_t xdr_sattr(XDR *, sattr *);
+static bool_t xdr_timeval(XDR *, nfstime *);
+static bool_t xdr_nfsstat(XDR *, nfsstat *);
+static bool_t xdr_ftype(XDR *, ftype *);
+static bool_t xdr_diropargs(XDR *, diropargs *);
+static bool_t xdr_diropres(XDR *, diropres *);
+static bool_t xdr_attrstat(XDR *, attrstat *);
+
+/*
+ * -----------------------  SFS XDR Routines  -------------------------
+ */
+
+
+static bool_t
+xdr_f_handle(
+    XDR *		xdrs,
+    fhandle_t *		fhandle_ptr)
+{
+    return(xdr_opaque(xdrs, (char *)fhandle_ptr, NFS_FHSIZE));
+}
+
+
+static bool_t
+xdr_timeval(
+    XDR *		xdrs,
+    nfstime *		timeval_ptr)
+{
+    return(xdr_int32_t(xdrs, (int32_t *) &timeval_ptr->seconds) &&
+	   xdr_int32_t(xdrs, (int32_t *) &timeval_ptr->useconds));
+}
+
+
+static bool_t
+xdr_nfsstat(
+    XDR *		xdrs,
+    nfsstat *		nfsstat_ptr)
+{
+    return(xdr_enum(xdrs, (enum_t *) nfsstat_ptr));
+}
+
+
+static bool_t
+xdr_ftype(
+    XDR *		xdrs,
+    ftype *		ftype_ptr)
+{
+    return(xdr_enum(xdrs, (enum_t *) ftype_ptr));
+}
+
+
+bool_t
+xdr_fhstatus(
+    XDR *		xdrs,
+    struct fhstatus *	fhsp)
+{
+    if (!xdr_nfsstat(xdrs, (nfsstat *) &fhsp->fhs_status)) {
+	return(FALSE);
+    }
+    if (fhsp->fhs_status != (int)NFS_OK) {
+	return(TRUE);
+    }
+    return(xdr_f_handle(xdrs, &fhsp->fhs_fh));
+}
+
+
+bool_t
+xdr_path(
+    XDR *		xdrs,
+    char **		pathp)
+{
+    return(xdr_string(xdrs, pathp, NFS_MAXPATHLEN));
+}
+
+
+static bool_t
+xdr_fattr(
+    XDR *		xdrs,
+    fattr *		fattr_ptr)
+{
+    return(xdr_ftype(xdrs, &fattr_ptr->type) &&
+	   xdr_u_int(xdrs, &fattr_ptr->mode) &&
+	   xdr_u_int(xdrs, &fattr_ptr->nlink) &&
+	   xdr_u_int(xdrs, &fattr_ptr->uid) &&
+	   xdr_u_int(xdrs, &fattr_ptr->gid) &&
+	   xdr_u_int(xdrs, &fattr_ptr->size) &&
+	   xdr_u_int(xdrs, &fattr_ptr->blocksize) &&
+	   xdr_u_int(xdrs, &fattr_ptr->rdev) &&
+	   xdr_u_int(xdrs, &fattr_ptr->blocks) &&
+	   xdr_u_int(xdrs, &fattr_ptr->fsid) &&
+	   xdr_u_int(xdrs, &fattr_ptr->fileid) &&
+	   xdr_timeval(xdrs, &fattr_ptr->atime) &&
+	   xdr_timeval(xdrs, &fattr_ptr->mtime) &&
+	   xdr_timeval(xdrs, &fattr_ptr->ctime));
+}
+
+
+static bool_t
+xdr_sattr(
+    XDR *		xdrs,
+    sattr *		sattr_ptr)
+{
+    return(xdr_u_int(xdrs, &sattr_ptr->mode) &&
+	   xdr_u_int(xdrs, &sattr_ptr->uid) &&
+	   xdr_u_int(xdrs, &sattr_ptr->gid) &&
+	   xdr_u_int(xdrs, &sattr_ptr->size) &&
+	   xdr_timeval(xdrs, &sattr_ptr->atime) &&
+	   xdr_timeval(xdrs, &sattr_ptr->mtime));
+}
+
+
+static bool_t
+xdr_diropargs(
+    XDR *		xdrs,
+    diropargs *		dir_args_ptr)
+{
+    return(xdr_f_handle(xdrs, &dir_args_ptr->dir) &&
+	   xdr_path(xdrs, &dir_args_ptr->name));
+}
+
+
+static bool_t
+xdr_diropres(
+    XDR *		xdrs,
+    diropres *		dir_res_ptr)
+{
+    if (!xdr_nfsstat(xdrs, &dir_res_ptr->status)) {
+	return(FALSE);
+    }
+
+    if (dir_res_ptr->status == NFS_OK) {
+	return(xdr_f_handle(xdrs, &dir_res_ptr->diropres_u.diropres.file) &&
+	       xdr_fattr(xdrs, &dir_res_ptr->diropres_u.diropres.attributes));
+    }
+    return(TRUE);
+}
+
+
+static bool_t
+xdr_attrstat(
+    XDR *		xdrs,
+    attrstat *		attrstat_ptr)
+{
+    if (!xdr_nfsstat(xdrs, &attrstat_ptr->status)) {
+	return(FALSE);
+    }
+
+    if (attrstat_ptr->status == NFS_OK) {
+	return(xdr_fattr(xdrs, &attrstat_ptr->attrstat_u.attributes));
+    }
+    return(TRUE);
+}
+
+
+bool_t
+xdr_getattr(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    fhandle_t *		fhandle_ptr;
+    attrstat *		attrstat_ptr;
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    fhandle_ptr = (fhandle_t *) params_ptr;
+	    return(xdr_f_handle(xdrs, fhandle_ptr));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    attrstat_ptr = (attrstat *) params_ptr;
+	    return(xdr_attrstat(xdrs, attrstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_setattr(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    sattrargs *		sattrargs_ptr;
+    attrstat *		attrstat_ptr;
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    sattrargs_ptr = (sattrargs *) params_ptr;
+	    return(xdr_f_handle(xdrs, &sattrargs_ptr->file) &&
+		   xdr_sattr(xdrs, &sattrargs_ptr->attributes));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    attrstat_ptr = (attrstat *) params_ptr;
+	    return(xdr_attrstat(xdrs, attrstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_lookup(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    diropargs *		diropargs_ptr;
+    diropres *		diropres_ptr;
+
+
+    switch(xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    diropargs_ptr = (diropargs *) params_ptr;
+	    return(xdr_f_handle(xdrs, &diropargs_ptr->dir) &&
+		   xdr_path(xdrs, &diropargs_ptr->name));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    diropres_ptr = (diropres *) params_ptr;
+	    return(xdr_diropres(xdrs, diropres_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+bool_t
+xdr_readlink(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    fhandle_t *		fhandle_ptr;
+    readlinkres *	readlinkres_ptr;
+
+    switch(xdrs->x_op) {
+	case XDR_ENCODE:
+	    fhandle_ptr = (fhandle_t *) params_ptr;
+	    return(xdr_f_handle(xdrs, fhandle_ptr));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    readlinkres_ptr = (readlinkres *) params_ptr;
+	    if (!xdr_nfsstat(xdrs, &readlinkres_ptr->status)) {
+		return(FALSE);
+	    }
+	    if (readlinkres_ptr->status != NFS_OK) {
+		return(TRUE);
+	    }
+	    return(xdr_bytes(xdrs, &readlinkres_ptr->readlinkres_u.data,
+			     (unsigned int *)
+			     &readlinkres_ptr->readlinkres_u.len,
+			     (unsigned int) NFS_MAXPATHLEN));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_read(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    readargs *		readargs_ptr;
+    readres *		readres_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    readargs_ptr = (readargs *) params_ptr;
+	    return(xdr_f_handle(xdrs, &readargs_ptr->file) &&
+		   xdr_u_int(xdrs, &readargs_ptr->offset) &&
+		   xdr_u_int(xdrs, &readargs_ptr->count) &&
+		   xdr_u_int(xdrs, &readargs_ptr->totalcount));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    readres_ptr = (readres *) params_ptr;
+	    if (!xdr_nfsstat(xdrs, &readres_ptr->status)) {
+		return(FALSE);
+	    }
+	    if (readres_ptr->status != NFS_OK) {
+		return(TRUE);
+	    }
+	    return(xdr_fattr(xdrs, &readres_ptr->readres_u.reply.attributes) &&
+		   xdr_bytes(xdrs, &readres_ptr->readres_u.reply.data.data_val,
+			     &readres_ptr->readres_u.reply.data.data_len,
+			     (unsigned int) NFS_MAXDATA));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+bool_t
+xdr_write(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    writeargs *		writeargs_ptr;
+    attrstat *		attrstat_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    writeargs_ptr = (writeargs *) params_ptr;
+	    return(xdr_f_handle(xdrs, &writeargs_ptr->file) &&
+		   xdr_u_int(xdrs, &writeargs_ptr->beginoffset) &&
+		   xdr_u_int(xdrs, &writeargs_ptr->offset) &&
+		   xdr_u_int(xdrs, &writeargs_ptr->totalcount) &&
+		   xdr_bytes(xdrs, &writeargs_ptr->data.data_val,
+				   &writeargs_ptr->data.data_len,
+				   (unsigned int) NFS_MAXDATA));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    attrstat_ptr = (attrstat *) params_ptr;
+	    return(xdr_attrstat(xdrs, attrstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_create(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    createargs *	createargs_ptr;
+    diropres *		diropres_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    createargs_ptr = (createargs *) params_ptr;
+	    return(xdr_diropargs(xdrs, &createargs_ptr->where) &&
+		   xdr_sattr(xdrs, &createargs_ptr->attributes));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    diropres_ptr = (diropres *) params_ptr;
+	    return(xdr_diropres(xdrs, diropres_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_remove(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    diropargs *		diropargs_ptr;
+    nfsstat *		nfsstat_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    diropargs_ptr = (diropargs *) params_ptr;
+	    return(xdr_diropargs (xdrs, diropargs_ptr));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    nfsstat_ptr = (nfsstat *) params_ptr;
+	    return(xdr_nfsstat(xdrs, nfsstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_rename(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    renameargs *	renameargs_ptr;
+    nfsstat *		nfsstat_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    renameargs_ptr = (renameargs *) params_ptr;
+	    return(xdr_diropargs(xdrs, &renameargs_ptr->from) &&
+		   xdr_diropargs(xdrs, &renameargs_ptr->to));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    nfsstat_ptr = (nfsstat *) params_ptr;
+	    return(xdr_nfsstat(xdrs, nfsstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_link(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    linkargs *		linkargs_ptr;
+    nfsstat *		nfsstat_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    linkargs_ptr = (linkargs *) params_ptr;
+	    return(xdr_f_handle(xdrs, &linkargs_ptr->from) &&
+		   xdr_diropargs(xdrs, &linkargs_ptr->to));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    nfsstat_ptr = (nfsstat *) params_ptr;
+	    return(xdr_nfsstat(xdrs, nfsstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_symlink(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    symlinkargs *	symlinkargs_ptr;
+    nfsstat *		nfsstat_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    symlinkargs_ptr = (symlinkargs *) params_ptr;
+	    return(xdr_diropargs(xdrs, &symlinkargs_ptr->from) &&
+		   xdr_path(xdrs, &symlinkargs_ptr->to) &&
+		   xdr_sattr(xdrs, &symlinkargs_ptr->attributes));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    nfsstat_ptr = (nfsstat *) params_ptr;
+	    return(xdr_nfsstat(xdrs, nfsstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_mkdir(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    mkdirargs *		mkdirargs_ptr;
+    diropres *		diropres_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    mkdirargs_ptr = (mkdirargs *) params_ptr;
+	    return(xdr_diropargs(xdrs, &mkdirargs_ptr->where) &&
+		   xdr_sattr(xdrs, &mkdirargs_ptr->attributes));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    diropres_ptr = (diropres *) params_ptr;
+	    return(xdr_diropres(xdrs, diropres_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_rmdir(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    diropargs *		diropargs_ptr;
+    nfsstat *		nfsstat_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    diropargs_ptr = (diropargs *) params_ptr;
+	    return(xdr_diropargs(xdrs, diropargs_ptr));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    nfsstat_ptr = (nfsstat *) params_ptr;
+	    return(xdr_nfsstat(xdrs, nfsstat_ptr));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+bool_t
+xdr_readdir(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    readdirargs *	readdirargs_ptr;
+    readdirres *	readdirres_ptr;
+    entry *		entry_ptr;
+    int			n;		/* entry ctr */
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    /* LINTED pointer cast */
+	    readdirargs_ptr = (readdirargs *) params_ptr;
+	    return(xdr_f_handle(xdrs, &readdirargs_ptr->dir) &&
+		   xdr_opaque(xdrs, (char *) readdirargs_ptr->cookie,
+				    NFS_COOKIESIZE) &&
+		   xdr_u_int(xdrs, &readdirargs_ptr->count));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    readdirres_ptr = (readdirres *) params_ptr;
+	    if (!xdr_nfsstat(xdrs, &readdirres_ptr->status)) {
+		return(FALSE);
+	    }
+	    if (readdirres_ptr->status != NFS_OK) {
+		return(TRUE);
+	    }
+
+	    /*
+	     * go thru the stream of entries until hit an invalid one
+	     * or have gotten all the user asked for.
+	     *
+	     * max_entries is read to obtain a maximum.  it is written
+	     * to return how many entries were decoded.
+	     */
+	    entry_ptr = readdirres_ptr->readdirres_u.reply.entries;
+
+	    n = 0;
+	    while (n < readdirres_ptr->readdirres_u.reply.max_entries) {
+		if (!xdr_bool(xdrs, &entry_ptr->valid)) {
+		    return(FALSE);
+		}
+
+		if (!entry_ptr->valid) {
+		    break;
+		}
+
+		if (!xdr_u_int(xdrs, &entry_ptr->fileid)) {
+		    return(FALSE);
+		}
+
+		if (!xdr_uint16_t(xdrs, &entry_ptr->name_len)) {
+		    return(FALSE);
+		}
+
+		if (!xdr_opaque(xdrs, entry_ptr->name, entry_ptr->name_len)) {
+		    return(FALSE);
+		}
+
+		if (!xdr_opaque(xdrs, entry_ptr->cookie, NFS_COOKIESIZE)) {
+		    return(FALSE);
+		}
+
+		n++;
+		entry_ptr++;
+	    } /* while extracting entries */
+
+	    /* If we are at the user's data buffer limit, stop right now.  */
+	    if (n == readdirres_ptr->readdirres_u.reply.max_entries) {
+		return(TRUE);
+	    }
+
+	    /* Return how many entries were gotten for the dirlist */
+	    readdirres_ptr->readdirres_u.reply.max_entries = n;
+
+	    /* check the EOF flag for the dirlist */
+	    if(!xdr_bool(xdrs, &readdirres_ptr->readdirres_u.reply.eof)) {
+		return(FALSE);
+	    }
+
+	    return(TRUE);
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+bool_t
+xdr_statfs(
+    XDR *		xdrs,
+    char *		params_ptr)
+{
+    fhandle_t *		fhandle_ptr;
+    statfsres *		statfsres_ptr;
+
+
+    switch (xdrs->x_op) {
+	case XDR_ENCODE:
+	    fhandle_ptr = (fhandle_t *) params_ptr;
+	    return(xdr_f_handle(xdrs, fhandle_ptr));
+
+	case XDR_DECODE:
+	    /* LINTED pointer cast */
+	    statfsres_ptr = (statfsres *) params_ptr;
+	    if (!xdr_nfsstat(xdrs, &statfsres_ptr->status)) {
+		return(FALSE);
+	    }
+	    if (statfsres_ptr->status != NFS_OK) {
+		return(TRUE);
+	    }
+	    return(xdr_u_int(xdrs, &statfsres_ptr->statfsres_u.reply.tsize) &&
+		   xdr_u_int(xdrs, &statfsres_ptr->statfsres_u.reply.bsize) &&
+		   xdr_u_int(xdrs, &statfsres_ptr->statfsres_u.reply.blocks) &&
+		   xdr_u_int(xdrs, &statfsres_ptr->statfsres_u.reply.bfree) &&
+		   xdr_u_int(xdrs, &statfsres_ptr->statfsres_u.reply.bavail));
+
+	default:
+	    return(FALSE);
+    } /* switch on operation */
+}
+
+
+/* sfs_c_xdr.c */
diff --git a/TBBT/trace_play/sfs_3_ops.c b/TBBT/trace_play/sfs_3_ops.c
new file mode 100644
index 0000000..19aef00
--- /dev/null
+++ b/TBBT/trace_play/sfs_3_ops.c
@@ -0,0 +1,2746 @@
+#ifndef lint
+static char sfs_3_opsSid[] = "@(#)sfs_3_ops.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_3_ops.c ---------------------
+ *
+ *      RPC routines to implement the NFS protocol.
+ *
+ *.Local Routines
+ *	int op_null(void)
+ *	int op_getattr(void)
+ *	int op_setattr(int)
+ *	int op_lookup(void)
+ *	int op_access(void)
+ *	int op_readlink(void)
+ *	int op_read(int)
+ *	int op_write(int, int, stable_how)
+ *	int op_create(void)
+ *	int op_mkdir(void);
+ *	int op_symlink(void);
+ *	int op_mknod(void);
+ *	int op_remove(void);
+ *	int op_rmdir(void);
+ *	int op_rename(void);
+ *	int op_link(void);
+ *	int op_readdir(void);
+ *	int op_readdirplus(void);
+ *	int op_fsstat(void);
+ *	int op_fsinfo(void);
+ *	int op_pathconf(void);
+ *	int op_commit(void);
+ *
+ *.Revision_History
+ *	30-Jun-94	ChakChung Ng	Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+/*
+ * --------------------  Local NFS ops function --------------------
+ */
+static int op_null(void);
+static int op_getattr(void);
+static int op_setattr(int);
+static int op_lookup(void);
+static int op_access(void);
+static int op_readlink(void);
+static int op_read(int);
+static int op_write(int, int, stable_how);
+static int op_create(void);
+static int op_mkdir(void);
+static int op_symlink(void);
+static int op_mknod(void);
+static int op_remove(void);
+static int op_rmdir(void);
+static int op_rename(void);
+static int op_link(void);
+static int op_readdir(void);
+static int op_readdirplus(void);
+static int op_fsstat(void);
+static int op_fsinfo(void);
+static int op_pathconf(void);
+static int op_commit(void);
+static int op_nosys(void);
+static char *nfs3_strerror(int);
+
+
+/*
+ * --------------------  NFS ops vector --------------------
+ */
+/*
+ * per operation information
+ */
+static sfs_op_type nfsv3_Ops[] = {
+
+/* name        mix   function         op    call  no  req  req  req  results */
+/*             pcnt                  class  targ call pcnt cnt  targ         */
+
+ { "null",        0, op_null,        Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "getattr",    11, op_getattr,     Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "setattr",     1, op_setattr,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "root",        0, op_nosys,       Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "lookup",     27, op_lookup,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readlink",    7, op_readlink,    Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "read",       18, op_read,        Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "wrcache",     0, op_nosys,       Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "write",       9, op_write,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "create",      1, op_create,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "remove",      1, op_remove,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rename",      0, op_rename,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "link",        0, op_link,        Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "symlink",     0, op_symlink,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "mkdir",       0, op_mkdir,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rmdir",       0, op_rmdir,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdir",     2, op_readdir,     Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsstat",      1, op_fsstat,	     Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "access",      7, op_access,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "commit",      5, op_commit,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsinfo",      1, op_fsinfo,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "mknod",       0, op_mknod,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "pathconf",    0, op_pathconf,    Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdirplus", 9, op_readdirplus, Read,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "TOTAL",     100, 0,              Lookup,  0,  0,  0.0,  0,   0,  { 0, }}
+};
+
+sfs_op_type *Ops;
+
+/*
+ * --------------------  RPC routines for NFS protocol --------------------
+ */
+
+void
+init_ops(void)
+{
+    Ops = nfsv3_Ops;
+    nfs_version = NFS_V3;
+}
+
+/*
+ * The routines below attempt to do over-the-wire operations.
+ * Each op tries to cause one or more of a particular
+ * NFS operation to go over the wire.  OPs return the success
+ * of their NFS call(s).  Each OP records how many calls it
+ * actually made in global data.
+ *
+ * An array of file information is kept for files existing in
+ * the test directory.  File handles, attributes, names, etc
+ * are stored in this array.
+ *
+ */
+
+/*
+ * Generic catch all for operations not covered by this protocol.
+ */
+static int
+op_nosys(int i)
+{
+	RFS_ASSERT (dep_tab[i].flag == TO_BE_SENT);
+	dep_tab[i].flag = DONE;
+    Ops[TOTAL].results.bad_calls++;
+	if (i==min_index)
+		adjust_min_index ();
+    return(0);
+}
+
+static struct biod_req *
+get_biod_reqp (int dep_tab_index)
+{
+	static int index = 0;
+	int i;
+
+	for (i=0; i<max_biod_reqs; i++, index = (index+1)%max_biod_reqs) {
+		if (biod_reqp[index].in_use == FALSE) {
+			biod_reqp[index].in_use = TRUE;
+			dep_tab[dep_tab_index].biod_index = index;
+			biod_req[index].dep_tab_index = dep_tab_index;
+			return (biod_reqp+index);
+		}
+	}
+}
+
+static int
+op_null(int i)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int 		ret;		/* ret val == call success */
+
+	struct biod_req * reqp;
+	struct ladtime call_timeout;
+
+	if (dep_tab[i].flag == SENT)
+		goto RECEIVE_REPLY;
+
+    op_ptr = &Ops[NULLCALL];
+	reqp = get_biod_reqp(i);
+
+	call_timeout.sec = Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+
+    ret = 0;
+
+    /* make the call */
+    sfs_gettime(&reqp->start);
+	reqp->xid = boid_clnt_call(NFS_client, NFS3PROC_NULL, xdr_void, (char *)0);
+	if (reqp->xid != 0) {
+		reqp->timeout = reqp->start;
+		ADDTIME (reqp->timeout, call_timeout);
+		num_out_reqs++;
+		dep_tab[i].flag = SENT;
+	} else 
+		RFS_ASSERT (0);
+
+	return 0;
+
+RECEIVE_REPLY:
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_NULL,
+			xdr_void, (char *)0, xdr_void, (char *)0,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: null_op call RPC error %d\n",
+						sfs_Myname, rpc_stat);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_null */
+
+
+static int
+op_getattr(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    GETATTR3args	args;		/* fh to do op on */
+    GETATTR3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[GETATTR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
+							sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_GETATTR,
+			xdr_GETATTR3args, (char *) &args,
+			xdr_GETATTR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: getattr call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: getattr call RPC error %d on file %d\n",
+		    	sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_getattr */
+
+
+/*
+ * perform an RPC setattr operation.  If 'truncate_size' is non-negative,
+ * truncate the file to that size.
+ */
+static int
+op_setattr(
+    int		truncate_size)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    SETATTR3args	args;
+    SETATTR3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[SETATTR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
+							sizeof (nfs_fh3));
+    args.new_attributes.mode.set_it = TRUE;
+    args.new_attributes.mode.mode = (uint32_t) 0666;
+    args.new_attributes.uid.set_it = FALSE;
+    args.new_attributes.uid.uid = (uint32_t) -1;
+    args.new_attributes.gid.set_it = FALSE;
+    args.new_attributes.gid.gid = (uint32_t) -1;
+    args.new_attributes.size.set_it = FALSE;
+    args.new_attributes.size.size._p._u = (uint32_t) ~0;
+    args.new_attributes.size.size._p._l = (uint32_t) -1;
+    args.new_attributes.atime.set_it = TRUE;
+    args.new_attributes.atime.atime.seconds = Cur_time.esec;
+    args.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+    args.new_attributes.mtime.set_it = TRUE;
+    args.new_attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+    args.guard.check = FALSE;
+
+    /* handle file truncations */
+    if (truncate_size >= 0) {
+	args.new_attributes.size.set_it = TRUE;
+	args.new_attributes.size.size._p._u = (uint32_t) 0;
+	if (truncate_size > Cur_file_ptr->attributes3.size._p._l)
+	    args.new_attributes.size.size._p._l = (uint32_t) 0;
+	else
+	    args.new_attributes.size.size._p._l =
+		(uint32_t) Cur_file_ptr->attributes3.size._p._l -
+								truncate_size;
+    }
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR,
+			xdr_SETATTR3args, (char *) &args,
+			xdr_SETATTR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_wcc.after.attr,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: setattr call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: setattr call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_setattr */
+
+
+static int
+op_lookup(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[LOOKUP];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.what.dir, (char *) &Cur_file_ptr->dir->fh3,
+							sizeof (nfs_fh3));
+    args.what.name = Cur_filename;
+    (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.object,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes.attr,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    /* We do lookup Nonexistent and this is not an error */
+	    if (reply.status != NFS3ERR_NOENT ||
+			Cur_file_ptr->state != Nonexistent) {
+	        if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+			"%s: lookup call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	        }
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: lookup call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_lookup */
+
+
+static int
+op_access(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    ACCESS3args		args;
+    ACCESS3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[ACCESS];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->dir->fh3,
+				sizeof (nfs_fh3));
+    args.access = ACCESS3_MODIFY;
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_ACCESS,
+			xdr_ACCESS3args, (char *) &args,
+			xdr_ACCESS3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes.attr,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: access call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: access call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_access */
+
+
+static int
+op_readlink(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    READLINK3args	args;			/* the args */
+    READLINK3res	reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[READLINK];
+    ret = 0;
+
+    /* set up the arguments */
+    /*
+     * Note: this symlink may be bogus because SYMLINK does
+     * not return a symlink ... only a status.  So unless we have
+     * done a LOOKUP on this guy, the symlink will probably be bad.
+     * If it is bad it shows up as a symlink error in the results.
+     */
+    (void) memmove((char *) &args.symlink,
+			(char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    /* Have lower layers fill in the data directly. */
+    reply.resok.data = sym_data;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_READLINK,
+			xdr_READLINK3args, (char *) &args,
+			xdr_READLINK3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    if (DEBUG_CHILD_RPC) {
+		(void) fprintf(stderr, "%s: READLINK on %s returned %s\n",
+				    sfs_Myname, Cur_filename, sym_data);
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readlink call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: readlink call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readlink */
+
+
+/*
+ * perform an RPC read operation of length 'xfer_size'
+ */
+static int
+op_read(
+    int 			xfer_size)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    int				cur_cnt;
+    int				max_cnt;	/* packet ctrs */
+    char			buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
+    READ3args			args;
+    READ3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				size;
+    int				j;
+    int				ret;		/* ret val == call success */
+
+    op_ptr = &Ops[READ];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file,
+			(char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    /*
+     * Don't allow a read of less than one block size
+     */
+    if (xfer_size < Bytes_per_block)
+	xfer_size = Bytes_per_block;
+
+    /*
+     * randomly choose an offset that is a multiple of the block size
+     * and constrained by making the transfer fit within the file
+     */
+    args.offset._p._u = 0;
+    if (Cur_file_ptr->attributes3.size._p._l > xfer_size)
+	args.offset._p._l = Bytes_per_block * (sfs_random() %
+			(((Cur_file_ptr->attributes3.size._p._l - xfer_size)
+			/ Bytes_per_block) + 1));
+    else
+	args.offset._p._l = 0;
+
+    /* Have lower layers fill in the data directly.  */
+    reply.resok.data.data_len = 0;
+    reply.resok.data.data_val = buf;
+
+    /* first read the whole buffers, then the fragment */
+    for (j = 0; j < 2; j++) {
+
+	if (j == 0) {
+	    size = Bytes_per_block;
+	    max_cnt = xfer_size / Bytes_per_block;
+	} else {
+	    /* 1KB - (Kb_per_block -1) KB fragment */
+	    size = xfer_size % Bytes_per_block;
+	    max_cnt = 1;
+	}
+	if (size == 0)
+	    continue;
+
+	/* check our stats to see if this would overflow */
+	if (!Timed_run) {
+	    if (op_ptr->target_calls > 0) {
+		if ((op_ptr->results.good_calls + max_cnt)
+		     > op_ptr->target_calls) {
+		    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+		}
+	    }
+	}
+
+	args.count = size;
+
+	if (DEBUG_CHILD_RPC) {
+	    (void) fprintf(stderr, "read: %d buffers\n", max_cnt);
+	    (void) fflush(stderr);
+	}
+
+	/* make the call(s) now */
+	for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
+
+	    /* capture length for possible dump */
+	    Dump_length = fh_size(Cur_file_ptr);
+ 
+	    sfs_gettime(&start);
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_READ,
+				xdr_READ3args, (char *) &args,
+				xdr_READ3res, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+	    sfs_gettime(&stop);
+	    Cur_time = stop;
+
+	    /* capture count and offset for possible dump */
+	    Dump_count = (rpc_stat == RPC_SUCCESS && reply.status == NFS3_OK)
+			    ? reply.resok.data.data_len : 0;
+	    Dump_offset = args.offset._p._l;
+
+	    if (rpc_stat == RPC_SUCCESS) {
+		if (reply.status == NFS3_OK) {
+		    Cur_file_ptr->state = Exists;
+		    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.file_attributes.attr,
+				sizeof (Cur_file_ptr->attributes3));
+		    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+		    size = reply.resok.data.data_len;
+
+		    if (DEBUG_CHILD_RPC) {
+			(void) fprintf(stderr, "%s: READ %s %d bytes\n",
+					   sfs_Myname, Cur_filename, size);
+			(void) fflush(stderr);
+		    }
+		    args.offset._p._l += size;
+		} else {
+		    if (DEBUG_CHILD_ERROR) {
+			 (void) fprintf(stderr,
+				"%s: read call NFS error %s on file %d\n",
+					sfs_Myname,
+					nfs3_strerror(reply.status),
+					Cur_file_ptr->unique_num);
+		    }
+		}
+		sfs_elapsedtime(op_ptr, &start, &stop);
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+		ret++;
+	    } else {
+		if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+				"%s: read call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+		}
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	    }
+	} /* for reading max_cnt packets */
+    } /* for buffers and fragments */
+    return(ret);
+
+} /* op_read */
+
+char *
+init_write_buffer(
+    void)
+{
+    uint32_t *bp;
+    static uint32_t write_buf[DEFAULT_MAX_BUFSIZE / sizeof(uint32_t)];
+    uint32_t *be  = write_buf + (sizeof(write_buf) /
+							sizeof(uint32_t));
+
+    if (write_buf[0] != (uint32_t)0xdeadbeef) {
+        for (bp = write_buf; bp < be; bp++)
+            *bp = (uint32_t)0xdeadbeef;
+    }
+    return (char *)write_buf;
+}
+
+
+/*
+ * Perform and RPC write operation of length 'xfer_size'.  If 'append_flag'
+ * is true, then write the data to the end of the file.
+ *
+ * If the stab_flag is set to UNSTABLE we issue the requests and then
+ * issue a op_commit to sync the data.
+ */
+static int
+op_write(
+    int			xfer_size,
+    int			append_flag,
+    stable_how		stab_flag)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    static char			*buf = NULL;	/* the data buffer */
+    unsigned int		size;		/* size of data write */
+    int				cur_cnt;	/* controls # NFS calls */
+    int				max_cnt;
+    WRITE3args			args;
+    WRITE3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				j;
+    int				ret;		/* ret val == call success */
+
+    /*
+     * For now we treat DATA_SYNC to be the same as FILE_SYNC.
+     */
+    if (stab_flag == DATA_SYNC)
+	stab_flag = FILE_SYNC;
+
+    /*
+     * Initialize write buffer to known value
+     */
+    if (buf == NULL) {
+	buf = init_write_buffer();
+    }
+
+    op_ptr = &Ops[WRITE];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
+		sizeof (nfs_fh3));
+    args.offset._p._u = 0;
+    if (append_flag == 1) {
+	args.offset._p._l = Cur_file_ptr->attributes3.size._p._l;
+    } else {
+	/*
+	 * randomly choose an offset that is a multiple of the block size
+	 * and constrained by making the transfer fit within the file
+	 */
+	if (Cur_file_ptr->attributes3.size._p._l > xfer_size) {
+	    args.offset._p._l = Bytes_per_block * (sfs_random() %
+			    (((Cur_file_ptr->attributes3.size._p._l - xfer_size)
+			    / Bytes_per_block) + 1));
+	} else
+	    args.offset._p._l = 0;
+    }
+
+    /* stab_flag has to be set in op() in sfs_3_chd.c */
+    args.stable = stab_flag;
+
+    /* first write the whole buffers, then the fragment */
+    for (j = 0; j < 2; j++) {
+
+	if (j == 0) {
+	    size = Bytes_per_block;
+	    max_cnt = xfer_size / Bytes_per_block;
+	} else {
+	    /* 1KB - (Kb_per_block - 1) KB fragment */
+	    size = xfer_size % Bytes_per_block;
+	    max_cnt = 1;
+	}
+	if (size == 0)
+	    continue;
+
+	args.count = size;
+	args.data.data_len = size;
+	args.data.data_val = buf;
+
+	/* check our stats to see if this would overflow */
+	if (!Timed_run) {
+	    if (op_ptr->target_calls > 0) {
+		if ((op_ptr->results.good_calls + max_cnt)
+		     > op_ptr->target_calls) {
+		    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+		}
+	    }
+	}
+
+	if (DEBUG_CHILD_RPC) {
+	    (void) fprintf(stderr, "write: %d buffers\n", max_cnt);
+	    (void) fflush(stderr);
+	}
+
+	/* make the call(s) now */
+	for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
+
+	    if (DEBUG_CHILD_RPC) {
+(void) fprintf(stderr, "%s: WRITE %s offset %u count %lu stable %d\n",
+sfs_Myname, Cur_filename, args.offset._p._l, args.count, args.stable);
+		(void) fflush(stderr);
+	    }
+
+	    /* capture length for possible dump */
+	    Dump_length = fh_size(Cur_file_ptr);
+ 
+	    sfs_gettime(&start);
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE,
+				xdr_WRITE3args, (char *) &args,
+				xdr_WRITE3res, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+	    sfs_gettime(&stop);
+	    Cur_time = stop;
+
+	    /* capture count and offset for possible dump */
+	    Dump_count = args.data.data_len;
+	    Dump_offset = args.offset._p._l;
+
+	    if (rpc_stat == RPC_SUCCESS) {
+		if (reply.status == NFS3_OK) {
+		    Cur_file_ptr->state = Exists;
+		    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.file_wcc.after.attr,
+				sizeof (Cur_file_ptr->attributes3));
+		    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+		    args.offset._p._l += size;
+
+		    if (DEBUG_CHILD_RPC) {
+			(void) fprintf(stderr, "%s: WRITE %s %d bytes\n",
+					   sfs_Myname, Cur_filename, size);
+			(void) fflush(stderr);
+		    }
+		} else {
+		    if (DEBUG_CHILD_ERROR) {
+			 (void) fprintf(stderr,
+				"%s: write call NFS error %s on file %d\n",
+				sfs_Myname, nfs3_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+		    }
+		}
+		sfs_elapsedtime(op_ptr, &start, &stop);
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+		ret++;
+	    } else {
+		if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+				"%s: write call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+		}
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	    }
+	} /* for writing max_cnt packets */
+    } /* for buffers and fragments */
+
+    /*
+     * If we have not gotten an error and we were asked for an async write
+     * send a commit operation.
+     */
+    if (ret && stab_flag != FILE_SYNC)
+	ret += op_commit();
+
+    return(ret);
+
+} /* op_write */
+
+
+static int
+op_create(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    CREATE3args		args;
+    CREATE3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[CREATE];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.how.mode = UNCHECKED;
+    args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.mode.mode = (NFSMODE_REG | 0666);
+    args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
+    args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
+    args.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.atime.atime.seconds = Cur_time.esec;
+    args.how.createhow3_u.obj_attributes.atime.atime.nseconds =
+						Cur_time.usec * 1000;
+    args.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
+						Cur_time.usec * 1000;
+    args.how.createhow3_u.obj_attributes.size.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.size.size._p._u = (uint32_t) 0;
+    args.how.createhow3_u.obj_attributes.size.size._p._l = (uint32_t) 0;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE,
+			xdr_CREATE3args, (char *) &args,
+			xdr_CREATE3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.obj.handle,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.obj_attributes.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: create call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: create call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_create */
+
+
+static int
+op_mkdir(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    MKDIR3args		args;
+    MKDIR3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[MKDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.attributes.mode.set_it = TRUE;
+    args.attributes.mode.mode = (NFSMODE_DIR | 0777);
+    args.attributes.uid.set_it = TRUE;
+    args.attributes.uid.uid = Cur_uid;
+    args.attributes.gid.set_it = TRUE;
+    args.attributes.gid.gid = Cur_gid;
+    args.attributes.size.set_it = TRUE;
+    args.attributes.size.size._p._u = 0;
+    args.attributes.size.size._p._l = 512;
+    args.attributes.atime.set_it = TRUE;
+    args.attributes.atime.atime.seconds = Cur_time.esec;
+    args.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+    args.attributes.mtime.set_it = TRUE;
+    args.attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR,
+			xdr_MKDIR3args, (char *) &args,
+			xdr_MKDIR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+            Cur_file_ptr->state = Empty_dir;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.obj.handle,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.obj_attributes.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: mkdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: mkdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_mkdir */
+
+
+static int
+op_symlink(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target file */
+    SYMLINK3args	args;
+    SYMLINK3res		reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];	/* symlink data */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[SYMLINK];
+    ret = 0;
+
+    /* set up the arguments */
+    target_fileinfo_ptr = randfh(SYMLINK, 0, 0, Exists, Sfs_non_io_file);
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+
+    (void) strcpy(sym_data, "./");
+    (void) strcat(sym_data, target_fileinfo_ptr->file_name);
+    args.symlink.symlink_attributes.size.set_it = TRUE;
+    args.symlink.symlink_attributes.size.size._p._u = (uint32_t) 0;
+    args.symlink.symlink_attributes.size.size._p._l = strlen(sym_data);
+    args.symlink.symlink_data = sym_data;
+
+    args.symlink.symlink_attributes.mode.set_it = TRUE;
+    args.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
+    args.symlink.symlink_attributes.uid.set_it = TRUE;
+    args.symlink.symlink_attributes.uid.uid = Cur_uid;
+    args.symlink.symlink_attributes.gid.set_it = TRUE;
+    args.symlink.symlink_attributes.gid.gid = Cur_gid;
+    args.symlink.symlink_attributes.atime.set_it = TRUE;
+    args.symlink.symlink_attributes.atime.atime.seconds = Cur_time.esec;
+    args.symlink.symlink_attributes.atime.atime.nseconds =
+						Cur_time.usec * 1000;
+    args.symlink.symlink_attributes.mtime.set_it = TRUE;
+    args.symlink.symlink_attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.symlink.symlink_attributes.mtime.mtime.nseconds =
+						Cur_time.usec * 1000;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK,
+			xdr_SYMLINK3args, (char *) &args,
+			xdr_SYMLINK3res, (char *) &reply,
+			((int)Current_test_phase < (int)Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    /*
+	     * SYMLINK doesn't return a fh. If we try to access this symlink
+	     * (eg, remove(), readlink()) before we do a lookup, we won't have
+	     * a fh to use. So, we do a lookup call here. If it fails, we fill
+	     * in what we can.
+	     */
+	    Cur_file_ptr->state = Exists;
+	    if (op_lookup() == 0) {
+		(void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+		Cur_file_ptr->attributes3.type = NF3LNK;
+		Cur_file_ptr->attributes3.mode = (NFSMODE_LNK|0777);
+		Cur_file_ptr->attributes3.uid = Cur_uid;
+		Cur_file_ptr->attributes3.gid = Cur_gid;
+		Cur_file_ptr->attributes3.atime.seconds = Cur_time.esec;
+		Cur_file_ptr->attributes3.atime.nseconds =
+							Cur_time.usec * 1000;
+		Cur_file_ptr->attributes3.mtime =
+			Cur_file_ptr->attributes3.atime;
+	    } else
+		ret++;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: symlink call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: symlink call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_symlink */
+
+
+static int
+op_mknod(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    MKNOD3args		args;
+    MKNOD3res		reply;
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[MKNOD];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.what.type = NF3FIFO;
+    args.what.mknoddata3_u.pipe_attributes.mode.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mode.mode = (NFSMODE_FIFO | 0777);
+    args.what.mknoddata3_u.pipe_attributes.uid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.uid.uid = Cur_uid;
+    args.what.mknoddata3_u.pipe_attributes.gid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.gid.gid = Cur_gid;
+    args.what.mknoddata3_u.pipe_attributes.size.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._u = (uint32_t) 0;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._l =
+							(uint32_t) 512;
+    args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.seconds =
+							Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.nseconds =
+							Cur_time.usec * 1000;
+    args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.seconds =
+								Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.nseconds =
+							Cur_time.usec * 1000;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_MKNOD,
+			xdr_MKNOD3args, (char *) &args,
+			xdr_MKNOD3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.obj.handle,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.obj_attributes.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: mknod call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: mknod call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_mknod */
+
+
+static int
+op_remove(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    REMOVE3args		args;
+    REMOVE3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[REMOVE];
+    ret = 0;
+
+    /* set up the arguments */
+    args.object.name = Cur_filename;
+    (void) memmove((char *) &args.object.dir,(char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE,
+			xdr_REMOVE3args, (char *) &args,
+			xdr_REMOVE3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+				"%s: remove call NFS error %s on file %d\n",
+				sfs_Myname, nfs3_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: remove call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_remove */
+
+
+static int
+op_rmdir(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    RMDIR3args		args;
+    RMDIR3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[RMDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.object.name = Cur_file_ptr->file_name;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR,
+			xdr_RMDIR3args, (char *) &args,
+			xdr_RMDIR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+				"%s: rmdir call NFS error %s on file %d\n",
+				sfs_Myname, nfs3_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: rmdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_rmdir */
+
+
+static int
+op_rename(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target name */
+    RENAME3args		args;
+    RENAME3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[RENAME];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.from.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    (void) memmove((char *) &args.to.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    target_fileinfo_ptr = randfh(RENAME, 0, 0, Nonexistent,
+				 Sfs_non_io_file);
+
+    args.from.name = Cur_file_ptr->file_name;
+    (void) sprintf(target_fileinfo_ptr->file_name, Filespec,
+		   target_fileinfo_ptr->unique_num);
+    args.to.name = target_fileinfo_ptr->file_name;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
+			xdr_RENAME3args, (char *) &args,
+			xdr_RENAME3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    target_fileinfo_ptr->state = Exists;
+	    (void) memmove((char *) &target_fileinfo_ptr->fh3,
+			(char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+	    target_fileinfo_ptr->attributes3 = Cur_file_ptr->attributes3;
+	    target_fileinfo_ptr->size = fh_size(Cur_file_ptr);
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: rename call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: rename call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_rename */
+
+
+static int
+op_link(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target */
+    LINK3args		args;
+    LINK3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[LINK];
+    ret = 0;
+
+    /* set up the arguments */
+    target_fileinfo_ptr = randfh(LINK, 0, 0, Exists, Sfs_non_io_file);
+    (void) memmove((char *) &args.file, (char *) &target_fileinfo_ptr->fh3,
+		sizeof (nfs_fh3));
+    (void) memmove((char *) &args.link.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.link.name = Cur_filename;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LINK,
+			xdr_LINK3args, (char *) &args,
+			xdr_LINK3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &target_fileinfo_ptr->fh3,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    target_fileinfo_ptr->attributes3.nlink++;
+	    Cur_file_ptr->attributes3 = target_fileinfo_ptr->attributes3;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: link call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: link call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_link */
+
+
+static int
+op_readdir(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    READDIR3args	args;
+    READDIR3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			i;
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+    bool_t		hit_eof;
+	/* array of entries */
+    entry3		entry_stream[SFS_MAXDIRENTS];
+    entry3		*entries;		/* ptr to the dir entry */
+
+    op_ptr = &Ops[READDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
+    (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+    args.count = DEFAULT_MAX_BUFSIZE;
+
+    /* Have lower layers fill in the data directly.  */
+    (void) memset((char *) &reply, '\0', sizeof (reply));
+    (void) memset((char *) entry_stream, '\0',
+					sizeof (entry3) * SFS_MAXDIRENTS);
+    reply.resok.count = SFS_MAXDIRENTS;
+    reply.resok.reply.entries = entry_stream;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIR,
+			xdr_READDIR3args, (char *) &args,
+			xdr_READDIR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+
+	    if (DEBUG_CHILD_RPC) {
+		hit_eof = reply.resok.reply.eof;
+		entries = reply.resok.reply.entries;
+		for (i = 0; i < reply.resok.count; i++) {
+		    (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
+				    sfs_Myname, hit_eof, entries[i].name);
+		}
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+				"%s: readdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readdir */
+
+
+static int
+op_readdirplus(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    READDIRPLUS3args	args;
+    READDIRPLUS3res	reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			i;
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+    bool_t		hit_eof;
+	/* array of entries */
+    entryplus3		entry_stream[SFS_MAXDIRENTS];
+    entryplus3		*entries;
+
+    op_ptr = &Ops[READDIRPLUS];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
+    (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+    (void) memset((char *) entry_stream, '\0',
+				sizeof (entryplus3) * SFS_MAXDIRENTS);
+    args.dircount = DEFAULT_MAX_BUFSIZE;
+    args.maxcount = DEFAULT_MAX_BUFSIZE;
+
+    /* Have lower layers fill in the data directly.  */
+    reply.resok.count = SFS_MAXDIRENTS;
+    reply.resok.reply.entries = entry_stream;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIRPLUS,
+			xdr_READDIRPLUS3args, (char *) &args,
+			xdr_READDIRPLUS3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+
+	    if (DEBUG_CHILD_RPC) {
+		hit_eof = reply.resok.reply.eof;
+		entries = reply.resok.reply.entries;
+		for (i = 0; i < reply.resok.count; i++) {
+		    (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
+				    sfs_Myname, hit_eof, entries[i].name);
+		}
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+				"%s: readdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readdirplus */
+
+
+static int
+op_fsstat(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    FSSTAT3args		args;
+    FSSTAT3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[FSSTAT];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.fsroot, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_FSSTAT,
+			xdr_FSSTAT3args, (char *) &args,
+			xdr_FSSTAT3args, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: fsstat call RPC error %d\n",
+						sfs_Myname, rpc_stat);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_fsstat */
+
+
+static int
+op_fsinfo(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    FSINFO3args		args;
+    FSINFO3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[FSINFO];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.fsroot, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_FSINFO,
+			xdr_FSINFO3args, (char *) &args,
+			xdr_FSINFO3args, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: fsinfo call RPC error %d\n",
+						sfs_Myname, rpc_stat);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_fsinfo */
+
+
+static int
+op_pathconf(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    PATHCONF3args	args;
+    PATHCONF3res	reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[PATHCONF];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_PATHCONF,
+			xdr_PATHCONF3args, (char *) &args,
+			xdr_PATHCONF3args, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: pathconf call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_pathconf */
+
+
+static int
+op_commit(void)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    int32_t			size;		/* size of data write */
+    COMMIT3args			args;
+    COMMIT3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				ret;		/* ret val == call success */
+
+    op_ptr = &Ops[COMMIT];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
+		sizeof (nfs_fh3));
+    args.offset._p._u = args.offset._p._l = (uint32_t) 0;
+    args.count = Cur_file_ptr->attributes3.size._p._l;
+    size = args.count;
+
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT,
+				xdr_COMMIT3args, (char *) &args,
+				xdr_COMMIT3res, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.file_wcc.after.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+
+	    if (DEBUG_CHILD_RPC) {
+		(void) fprintf(stderr, "%s: WRITE %s %ld bytes\n",
+					   sfs_Myname, Cur_filename, size);
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: write call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: write call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+
+    return(ret);
+
+} /* op_commit */
+
+
+#define LAD_RETRIABLE(stat) (((stat) == RPC_TIMEDOUT) || ((stat) == RPC_CANTDECODERES))
+
+/*
+ * Reliably lookup a file in the current directory
+ * Return:
+ *	-1	RPC error
+ *	1	File doesn't exist
+ *	0	File exists
+ */
+int
+lad_lookup(sfs_fh_type *file_ptr, char *name)
+{
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_lookup: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+        (void) memmove((char *) &args.what.dir, (char *) &file_ptr->dir->fh3,
+							sizeof (nfs_fh3));
+	args.what.name = name;
+        (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+	/* make the call */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_lookup(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    if (reply.status == NFS3ERR_NOENT) {
+	return(1);
+    }
+
+    if (reply.status != NFS3_OK) {
+	(void) fprintf(stderr, "lad_lookup(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	return(-1);
+    }
+
+    file_ptr->state = Exists;
+    (void) memmove((char *) &file_ptr->fh3,
+			(char *) &reply.resok.object,
+			sizeof (nfs_fh3));
+    (void) strcpy(file_ptr->file_name, name);
+    (void) memmove((char *) &file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes.attr,
+				sizeof (file_ptr->attributes3));
+    file_ptr->size = fh_size(file_ptr);
+    return(0);
+}
+
+/*
+ * Reliably remove a file in the current directory
+ */
+int
+lad_remove(sfs_fh_type *file_ptr, char *name)
+{
+    REMOVE3args         args;
+    REMOVE3res          reply;          /* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does exist
+     */
+    if (file_ptr->attributes3.type == NF3DIR)
+	return (lad_rmdir(file_ptr, name));
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_remove: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.object.name = name;
+	(void) memmove((char *) &args.object.dir, (char *) &file_ptr->dir->fh3,
+			sizeof(nfs_fh3));
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE,
+                        xdr_REMOVE3args, (char *) &args,
+                        xdr_REMOVE3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_remove(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_NOENT || !retried) {
+	    (void) fprintf(stderr, "lad_remove(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+    }
+
+    file_ptr->state = Nonexistent;
+
+    return(0);
+}
+
+/*
+ * Reliably remove a directory in the current directory
+ */
+int
+lad_rmdir(sfs_fh_type *file_ptr, char *name)
+{
+    RMDIR3args          args;
+    RMDIR3res           reply;          /* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does exist and is empty
+     */
+    if (file_ptr->attributes3.type != NF3DIR)
+	return (lad_remove(file_ptr, name));
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_rmdir: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.object.name = name;
+        (void) memmove((char *) &args.object.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR,
+                        xdr_RMDIR3args, (char *) &args,
+                        xdr_RMDIR3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_rmdir(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_NOENT || !retried) {
+	    (void) fprintf(stderr, "lad_rmdir(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+    }
+
+    file_ptr->state = Nonexistent;
+
+    return(0);
+}
+
+/*
+ * Reliably create a symlink in the current directory
+ */
+int
+lad_symlink(sfs_fh_type *file_ptr, char *target, char *name)
+{
+    SYMLINK3args        args;
+    SYMLINK3res         reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];	/* symlink data */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_symlink: %lx[%lx] %s -> %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name, target);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+         (void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+         args.where.name = name;
+
+	(void) strcpy(sym_data, "./");
+	(void) strcat(sym_data, target);
+	args.symlink.symlink_attributes.size.set_it = TRUE;
+	args.symlink.symlink_attributes.size.size._p._u = (uint32_t) 0;
+	args.symlink.symlink_attributes.size.size._p._l = strlen(sym_data);
+	args.symlink.symlink_data = sym_data;
+
+	args.symlink.symlink_attributes.mode.set_it = TRUE;
+	args.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
+	args.symlink.symlink_attributes.uid.set_it = TRUE;
+	args.symlink.symlink_attributes.uid.uid = Cur_uid;
+	args.symlink.symlink_attributes.gid.set_it = TRUE;
+	args.symlink.symlink_attributes.gid.gid = Cur_gid;
+	args.symlink.symlink_attributes.atime.set_it = TRUE;
+	args.symlink.symlink_attributes.atime.atime.seconds = Cur_time.esec;
+	args.symlink.symlink_attributes.atime.atime.nseconds =
+                                                Cur_time.usec * 1000;
+	args.symlink.symlink_attributes.mtime.set_it = TRUE;
+	args.symlink.symlink_attributes.mtime.mtime.seconds = Cur_time.esec;
+	args.symlink.symlink_attributes.mtime.mtime.nseconds =
+                                                Cur_time.usec * 1000;
+
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK,
+                        xdr_SYMLINK3args, (char *) &args,
+                        xdr_SYMLINK3res, (char *) &reply,
+		 	Nfs_timers[Init]);
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_symlink(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_symlink(%s, %s) NFS call failed : %s\n",
+			target, name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+    }
+
+    /*
+     * SYMLINK may not return a fh. If we try to
+     * access this symlink (eg, remove(), readlink())
+     * before we do a lookup, we won't have a fh to use.
+     * So, we do a lookup call here.
+     * If it fails, we fill in what we can.
+     */  
+    return (lad_lookup(file_ptr, name));
+}
+
+/*
+ * Reliably create a directory in the current directory
+ */
+int
+lad_mkdir(sfs_fh_type *file_ptr, char *name)
+{
+    MKDIR3args          args;
+    MKDIR3res           reply;                  /* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_mkdir: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+ 	(void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+	args.where.name = name;
+	args.attributes.mode.set_it = TRUE;
+	args.attributes.mode.mode = (NFSMODE_DIR | 0777);
+	args.attributes.uid.set_it = TRUE;
+	args.attributes.uid.uid = Cur_uid;
+	args.attributes.gid.set_it = TRUE;
+	args.attributes.gid.gid = Cur_gid;
+	args.attributes.size.set_it = TRUE;
+	args.attributes.size.size._p._u = 0;
+	args.attributes.size.size._p._l = 512;
+	args.attributes.atime.set_it = TRUE;
+	args.attributes.atime.atime.seconds = Cur_time.esec;
+	args.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+	args.attributes.mtime.set_it = TRUE;
+	args.attributes.mtime.mtime.seconds = Cur_time.esec;
+	args.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR,
+                        xdr_MKDIR3args, (char *) &args,
+                        xdr_MKDIR3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_mkdir(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (!retried && reply.status == NFS3ERR_EXIST)
+	return(1);
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_mkdir(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+	/*
+	 * If the first mkdir suceeded but the reply as dropped and
+	 * was retransmitted, we still need to lookup the attributes
+	 */
+	if (lad_lookup(file_ptr, name))
+	   return (-1);
+    } else {
+	(void) memmove((char *) &file_ptr->fh3,
+                   (char *) &reply.resok.obj.handle,
+                   sizeof (nfs_fh3));
+	(void) strcpy(file_ptr->file_name, name);
+	(void) memmove((char *) &file_ptr->attributes3,
+                   (char *) &reply.resok.obj_attributes.attr,
+                   sizeof(file_ptr->attributes3));
+	file_ptr->size = fh_size(file_ptr);
+    }
+    file_ptr->state = Empty_dir;
+
+    return(0);
+}
+
+/*
+ * Reliably commit a file
+ */
+static int
+lad_commit(sfs_fh_type *file_ptr)
+{
+    COMMIT3args			args;
+    COMMIT3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_commit: %lx[%lx]\n",
+			sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir);
+	(void) fflush(stderr);
+    }
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &file_ptr->fh3,
+		sizeof (nfs_fh3));
+    args.offset._p._u = args.offset._p._l = (uint32_t) 0;
+    args.count = file_ptr->attributes3.size._p._l;
+
+    /* CONSTCOND */
+    while (1) {
+        rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT,
+				xdr_COMMIT3args, (char *) &args,
+				xdr_COMMIT3res, (char *) &reply,
+			 	Nfs_timers[Init]);
+        if (rpc_stat == RPC_SUCCESS) 
+	    break;
+        if (rpc_stat != RPC_TIMEDOUT) {
+	    (void) fprintf(stderr, "lad_commit() RPC call failed : %s\n",
+				clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    return(0);
+}
+
+/*
+ * Reliably write a file in the current directory
+ */
+int
+lad_write(sfs_fh_type *file_ptr, int32_t offset, int32_t length)
+{
+    static char			*buf = NULL;	/* the data buffer */
+    int32_t			size;		/* size of data write */
+    int32_t			cur_cnt;
+    WRITE3args                  args;
+    WRITE3res                   reply;          /* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    int				async = 1;
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_write: %lx[%lx] %ld %ld\n",
+			sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, offset, length);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does exist
+     * Initialize write buffer to known value
+     */
+    if (buf == NULL) {
+	buf = init_write_buffer();
+    }
+
+    /*
+     * If a short file write don't bother with the commit, just write sync.
+     */
+    if (length <= Bytes_per_block)
+	async = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &file_ptr->fh3,
+                sizeof (nfs_fh3));
+    args.offset._p._u = 0;
+    args.offset._p._l = offset;
+    if (async)
+	    args.stable = UNSTABLE;
+    else
+	    args.stable = FILE_SYNC;
+
+    size = Bytes_per_block;
+    for (cur_cnt = 0; cur_cnt < length; cur_cnt += size) {
+	if ((cur_cnt + size) > length)
+		size = length - cur_cnt;
+
+	if (size == 0)
+	    break;
+
+	args.count = size;
+	args.data.data_len = size;
+	args.data.data_val = buf;
+
+	/* make the call now */
+        /* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE,
+                                xdr_WRITE3args, (char *) &args,
+                                xdr_WRITE3res, (char *) &reply,
+				Nfs_timers[Init]);
+
+	    if (rpc_stat == RPC_SUCCESS) 
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_write() RPC call failed : %s\n",
+				clnt_sperrno(rpc_stat));
+	    }
+	    if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	    }
+	}
+	if (reply.status != NFS3_OK) {
+	    (void) fprintf(stderr, "lad_write() NFS call failed : %s\n",
+			nfs3_strerror(reply.status));
+	    return(-1);
+	}
+	file_ptr->state = Exists;
+        (void) memmove((char *) &file_ptr->attributes3,
+                                (char *) &reply.resok.file_wcc.after.attr,
+                                sizeof (file_ptr->attributes3));
+	file_ptr->size = fh_size(file_ptr);
+
+        args.offset._p._l += size;
+    }
+
+    if (async)
+	(void) lad_commit(file_ptr);
+    return(0);
+}
+
+/*
+ * Reliably create a file in the current directory
+ */
+int
+lad_create(sfs_fh_type *file_ptr, char *name)
+{
+    CREATE3args         args;
+    CREATE3res          reply;                  /* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_create: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	(void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+	args.where.name = name;
+	args.how.mode = UNCHECKED;
+	args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.mode.mode = (NFSMODE_REG | 0666);
+	args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
+	args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
+	args.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.atime.atime.seconds =
+						Cur_time.esec;
+	args.how.createhow3_u.obj_attributes.atime.atime.nseconds =
+                                                Cur_time.usec * 1000;
+	args.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.mtime.mtime.seconds =
+						Cur_time.esec;
+	args.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
+                                                Cur_time.usec * 1000;
+	args.how.createhow3_u.obj_attributes.size.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.size.size._p._u =
+						(uint32_t) 0;
+	args.how.createhow3_u.obj_attributes.size.size._p._l =
+						(uint32_t) 0;
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE,
+                        xdr_CREATE3args, (char *) &args,
+                        xdr_CREATE3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_create(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (!retried && reply.status == NFS3ERR_EXIST) {
+	return(1);
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_create(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+        /*
+         * If the first create suceeded but the reply as dropped and
+         * was retransmitted, we still need to lookup the attributes
+         */
+        if (lad_lookup(file_ptr, name))
+           return (-1);
+    } else {
+	(void) memmove((char *) &file_ptr->fh3,
+                   (char *) &reply.resok.obj.handle,
+                   sizeof (nfs_fh3));
+	(void) strcpy(file_ptr->file_name, name);
+	(void) memmove((char *) &file_ptr->attributes3,
+                   (char *) &reply.resok.obj_attributes.attr,
+                   sizeof(file_ptr->attributes3));
+	file_ptr->size = fh_size(file_ptr);
+    }
+
+    file_ptr->state = Exists;
+    /*
+     * Directories are created as Empty_dir, when a file is created it
+     * becomes an Exists.
+     */
+    file_ptr->dir->state = Exists;
+
+    return(0);
+}
+
+/*
+ * Reliably set the size of a file in the current directory
+ */
+int
+lad_truncate(sfs_fh_type *file_ptr, int32_t size)
+{
+    SETATTR3args        args;
+    SETATTR3res         reply;          /* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+
+    /*
+     * This function presumes that the file name already exists
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_truncate: %lx[%lx] %ld\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, size);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/*
+	 * set up the arguments
+	 * Set the mode and times as well
+	 */
+	(void) memmove((char *) &args.object, (char *) &file_ptr->fh3,
+                                                        sizeof (nfs_fh3));
+	args.new_attributes.mode.set_it = TRUE;
+	args.new_attributes.mode.mode = (uint32_t) 0666;
+	args.new_attributes.uid.set_it = FALSE;
+	args.new_attributes.uid.uid = (uint32_t) -1;
+	args.new_attributes.gid.set_it = FALSE;
+	args.new_attributes.gid.gid = (uint32_t) -1;
+	args.new_attributes.size.set_it = TRUE;
+	args.new_attributes.size.size._p._u = 0;
+	args.new_attributes.size.size._p._l = size;
+	args.new_attributes.atime.set_it = TRUE;
+	args.new_attributes.atime.atime.seconds = Cur_time.esec;
+	args.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+	args.new_attributes.mtime.set_it = TRUE;
+	args.new_attributes.mtime.mtime.seconds = Cur_time.esec;
+	args.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+	args.guard.check = FALSE;
+
+	/* make the call */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR,
+                        xdr_SETATTR3args, (char *) &args,
+                        xdr_SETATTR3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void)fprintf(stderr,
+				"lad_truncate(%ld) RPC call failed : %s\n",
+				size, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    if (reply.status != NFS3_OK) {
+	(void) fprintf(stderr, "lad_truncate(%ld) NFS call failed : %s\n",
+			size, nfs3_strerror(reply.status));
+	return(-1);
+    }
+    (void) memmove(&file_ptr->attributes3,
+                   &reply.resok.obj_wcc.after.attr,
+                   sizeof (file_ptr->attributes3));
+    file_ptr->size = fh_size(file_ptr);
+
+    return(0);
+}
+
+static char *
+nfs3_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS3_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFS3ERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFS3ERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFS3ERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFS3ERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFS3ERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFS3ERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFS3ERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFS3ERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFS3ERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFS3ERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFS3ERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFS3ERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFS3ERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFS3ERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFS3ERR_MLINK:
+	    (void) strcpy(str, "Too many links");
+	    break;
+	case NFS3ERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFS3ERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFS3ERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFS3ERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFS3ERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFS3ERR_BADHANDLE:
+	    (void) strcpy(str, "Bad file handle");
+	    break;
+	case NFS3ERR_NOT_SYNC:
+	    (void) strcpy(str, "Not sync write");
+	    break;
+	case NFS3ERR_BAD_COOKIE:
+	    (void) strcpy(str, "Bad cookie");
+	    break;
+	case NFS3ERR_NOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFS3ERR_TOOSMALL:
+	    (void) strcpy(str, "Value too small");
+	    break;
+	case NFS3ERR_SERVERFAULT:
+	    (void) strcpy(str, "Server fault");
+	    break;
+	case NFS3ERR_BADTYPE:
+	    (void) strcpy(str, "Bad type");
+	    break;
+	case NFS3ERR_JUKEBOX:
+	    (void) strcpy(str, "Jukebox");
+	    break;
+	case NFS3ERR_RFS_TIMEOUT:
+		(void) strcpy(str, "RFS timeout");
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+
+/* sfs_3_ops.c */
diff --git a/TBBT/trace_play/sfs_3_ops.c.org b/TBBT/trace_play/sfs_3_ops.c.org
new file mode 100644
index 0000000..57cbb57
--- /dev/null
+++ b/TBBT/trace_play/sfs_3_ops.c.org
@@ -0,0 +1,2701 @@
+#ifndef lint
+static char sfs_3_opsSid[] = "@(#)sfs_3_ops.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_3_ops.c ---------------------
+ *
+ *      RPC routines to implement the NFS protocol.
+ *
+ *.Local Routines
+ *	int op_null(void)
+ *	int op_getattr(void)
+ *	int op_setattr(int)
+ *	int op_lookup(void)
+ *	int op_access(void)
+ *	int op_readlink(void)
+ *	int op_read(int)
+ *	int op_write(int, int, stable_how)
+ *	int op_create(void)
+ *	int op_mkdir(void);
+ *	int op_symlink(void);
+ *	int op_mknod(void);
+ *	int op_remove(void);
+ *	int op_rmdir(void);
+ *	int op_rename(void);
+ *	int op_link(void);
+ *	int op_readdir(void);
+ *	int op_readdirplus(void);
+ *	int op_fsstat(void);
+ *	int op_fsinfo(void);
+ *	int op_pathconf(void);
+ *	int op_commit(void);
+ *
+ *.Revision_History
+ *	30-Jun-94	ChakChung Ng	Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+/*
+ * --------------------  Local NFS ops function --------------------
+ */
+static int op_null(void);
+static int op_getattr(void);
+static int op_setattr(int);
+static int op_lookup(void);
+static int op_access(void);
+static int op_readlink(void);
+static int op_read(int);
+static int op_write(int, int, stable_how);
+static int op_create(void);
+static int op_mkdir(void);
+static int op_symlink(void);
+static int op_mknod(void);
+static int op_remove(void);
+static int op_rmdir(void);
+static int op_rename(void);
+static int op_link(void);
+static int op_readdir(void);
+static int op_readdirplus(void);
+static int op_fsstat(void);
+static int op_fsinfo(void);
+static int op_pathconf(void);
+static int op_commit(void);
+static int op_nosys(void);
+static char *nfs3_strerror(int);
+
+
+/*
+ * --------------------  NFS ops vector --------------------
+ */
+/*
+ * per operation information
+ */
+static sfs_op_type nfsv3_Ops[] = {
+
+/* name        mix   function         op    call  no  req  req  req  results */
+/*             pcnt                  class  targ call pcnt cnt  targ         */
+
+ { "null",        0, op_null,        Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "getattr",    11, op_getattr,     Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "setattr",     1, op_setattr,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "root",        0, op_nosys,       Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "lookup",     27, op_lookup,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readlink",    7, op_readlink,    Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "read",       18, op_read,        Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "wrcache",     0, op_nosys,       Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "write",       9, op_write,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "create",      1, op_create,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "remove",      1, op_remove,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rename",      0, op_rename,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "link",        0, op_link,        Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "symlink",     0, op_symlink,     Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "mkdir",       0, op_mkdir,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "rmdir",       0, op_rmdir,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdir",     2, op_readdir,     Read,    0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsstat",      1, op_fsstat,	     Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "access",      7, op_access,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "commit",      5, op_commit,      Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "fsinfo",      1, op_fsinfo,      Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "mknod",       0, op_mknod,       Write,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "pathconf",    0, op_pathconf,    Lookup,  0,  0,  0.0,  0,   0,  { 0, }},
+ { "readdirplus", 9, op_readdirplus, Read,   0,  0,  0.0,  0,   0,  { 0, }},
+ { "TOTAL",     100, 0,              Lookup,  0,  0,  0.0,  0,   0,  { 0, }}
+};
+
+sfs_op_type *Ops;
+
+/*
+ * --------------------  RPC routines for NFS protocol --------------------
+ */
+
+void
+init_ops(void)
+{
+    Ops = nfsv3_Ops;
+    nfs_version = NFS_V3;
+}
+
+/*
+ * The routines below attempt to do over-the-wire operations.
+ * Each op tries to cause one or more of a particular
+ * NFS operation to go over the wire.  OPs return the success
+ * of their NFS call(s).  Each OP records how many calls it
+ * actually made in global data.
+ *
+ * An array of file information is kept for files existing in
+ * the test directory.  File handles, attributes, names, etc
+ * are stored in this array.
+ *
+ */
+
+/*
+ * Generic catch all for operations not covered by this protocol.
+ */
+static int
+op_nosys(void)
+{
+    Ops[TOTAL].results.bad_calls++;
+    return(0);
+}
+
+static int
+op_null(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int 		ret;		/* ret val == call success */
+
+    op_ptr = &Ops[NULLCALL];
+    ret = 0;
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_NULL,
+			xdr_void, (char *)0, xdr_void, (char *)0,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: null_op call RPC error %d\n",
+						sfs_Myname, rpc_stat);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_null */
+
+
+static int
+op_getattr(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    GETATTR3args	args;		/* fh to do op on */
+    GETATTR3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[GETATTR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
+							sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_GETATTR,
+			xdr_GETATTR3args, (char *) &args,
+			xdr_GETATTR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: getattr call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: getattr call RPC error %d on file %d\n",
+		    	sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_getattr */
+
+
+/*
+ * perform an RPC setattr operation.  If 'truncate_size' is non-negative,
+ * truncate the file to that size.
+ */
+static int
+op_setattr(
+    int		truncate_size)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    SETATTR3args	args;
+    SETATTR3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[SETATTR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
+							sizeof (nfs_fh3));
+    args.new_attributes.mode.set_it = TRUE;
+    args.new_attributes.mode.mode = (uint32_t) 0666;
+    args.new_attributes.uid.set_it = FALSE;
+    args.new_attributes.uid.uid = (uint32_t) -1;
+    args.new_attributes.gid.set_it = FALSE;
+    args.new_attributes.gid.gid = (uint32_t) -1;
+    args.new_attributes.size.set_it = FALSE;
+    args.new_attributes.size.size._p._u = (uint32_t) ~0;
+    args.new_attributes.size.size._p._l = (uint32_t) -1;
+    args.new_attributes.atime.set_it = TRUE;
+    args.new_attributes.atime.atime.seconds = Cur_time.esec;
+    args.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+    args.new_attributes.mtime.set_it = TRUE;
+    args.new_attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+    args.guard.check = FALSE;
+
+    /* handle file truncations */
+    if (truncate_size >= 0) {
+	args.new_attributes.size.set_it = TRUE;
+	args.new_attributes.size.size._p._u = (uint32_t) 0;
+	if (truncate_size > Cur_file_ptr->attributes3.size._p._l)
+	    args.new_attributes.size.size._p._l = (uint32_t) 0;
+	else
+	    args.new_attributes.size.size._p._l =
+		(uint32_t) Cur_file_ptr->attributes3.size._p._l -
+								truncate_size;
+    }
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR,
+			xdr_SETATTR3args, (char *) &args,
+			xdr_SETATTR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_wcc.after.attr,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: setattr call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: setattr call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_setattr */
+
+
+static int
+op_lookup(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[LOOKUP];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.what.dir, (char *) &Cur_file_ptr->dir->fh3,
+							sizeof (nfs_fh3));
+    args.what.name = Cur_filename;
+    (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.object,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes.attr,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    /* We do lookup Nonexistent and this is not an error */
+	    if (reply.status != NFS3ERR_NOENT ||
+			Cur_file_ptr->state != Nonexistent) {
+	        if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+			"%s: lookup call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	        }
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: lookup call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_lookup */
+
+
+static int
+op_access(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    ACCESS3args		args;
+    ACCESS3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[ACCESS];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->dir->fh3,
+				sizeof (nfs_fh3));
+    args.access = ACCESS3_MODIFY;
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_ACCESS,
+			xdr_ACCESS3args, (char *) &args,
+			xdr_ACCESS3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes.attr,
+				sizeof (Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: access call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: access call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_access */
+
+
+static int
+op_readlink(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    READLINK3args	args;			/* the args */
+    READLINK3res	reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[READLINK];
+    ret = 0;
+
+    /* set up the arguments */
+    /*
+     * Note: this symlink may be bogus because SYMLINK does
+     * not return a symlink ... only a status.  So unless we have
+     * done a LOOKUP on this guy, the symlink will probably be bad.
+     * If it is bad it shows up as a symlink error in the results.
+     */
+    (void) memmove((char *) &args.symlink,
+			(char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    /* Have lower layers fill in the data directly. */
+    reply.resok.data = sym_data;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_READLINK,
+			xdr_READLINK3args, (char *) &args,
+			xdr_READLINK3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    if (DEBUG_CHILD_RPC) {
+		(void) fprintf(stderr, "%s: READLINK on %s returned %s\n",
+				    sfs_Myname, Cur_filename, sym_data);
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readlink call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: readlink call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readlink */
+
+
+/*
+ * perform an RPC read operation of length 'xfer_size'
+ */
+static int
+op_read(
+    int 			xfer_size)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    int				cur_cnt;
+    int				max_cnt;	/* packet ctrs */
+    char			buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
+    READ3args			args;
+    READ3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				size;
+    int				j;
+    int				ret;		/* ret val == call success */
+
+    op_ptr = &Ops[READ];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file,
+			(char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    /*
+     * Don't allow a read of less than one block size
+     */
+    if (xfer_size < Bytes_per_block)
+	xfer_size = Bytes_per_block;
+
+    /*
+     * randomly choose an offset that is a multiple of the block size
+     * and constrained by making the transfer fit within the file
+     */
+    args.offset._p._u = 0;
+    if (Cur_file_ptr->attributes3.size._p._l > xfer_size)
+	args.offset._p._l = Bytes_per_block * (sfs_random() %
+			(((Cur_file_ptr->attributes3.size._p._l - xfer_size)
+			/ Bytes_per_block) + 1));
+    else
+	args.offset._p._l = 0;
+
+    /* Have lower layers fill in the data directly.  */
+    reply.resok.data.data_len = 0;
+    reply.resok.data.data_val = buf;
+
+    /* first read the whole buffers, then the fragment */
+    for (j = 0; j < 2; j++) {
+
+	if (j == 0) {
+	    size = Bytes_per_block;
+	    max_cnt = xfer_size / Bytes_per_block;
+	} else {
+	    /* 1KB - (Kb_per_block -1) KB fragment */
+	    size = xfer_size % Bytes_per_block;
+	    max_cnt = 1;
+	}
+	if (size == 0)
+	    continue;
+
+	/* check our stats to see if this would overflow */
+	if (!Timed_run) {
+	    if (op_ptr->target_calls > 0) {
+		if ((op_ptr->results.good_calls + max_cnt)
+		     > op_ptr->target_calls) {
+		    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+		}
+	    }
+	}
+
+	args.count = size;
+
+	if (DEBUG_CHILD_RPC) {
+	    (void) fprintf(stderr, "read: %d buffers\n", max_cnt);
+	    (void) fflush(stderr);
+	}
+
+	/* make the call(s) now */
+	for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
+
+	    /* capture length for possible dump */
+	    Dump_length = fh_size(Cur_file_ptr);
+ 
+	    sfs_gettime(&start);
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_READ,
+				xdr_READ3args, (char *) &args,
+				xdr_READ3res, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+	    sfs_gettime(&stop);
+	    Cur_time = stop;
+
+	    /* capture count and offset for possible dump */
+	    Dump_count = (rpc_stat == RPC_SUCCESS && reply.status == NFS3_OK)
+			    ? reply.resok.data.data_len : 0;
+	    Dump_offset = args.offset._p._l;
+
+	    if (rpc_stat == RPC_SUCCESS) {
+		if (reply.status == NFS3_OK) {
+		    Cur_file_ptr->state = Exists;
+		    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.file_attributes.attr,
+				sizeof (Cur_file_ptr->attributes3));
+		    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+		    size = reply.resok.data.data_len;
+
+		    if (DEBUG_CHILD_RPC) {
+			(void) fprintf(stderr, "%s: READ %s %d bytes\n",
+					   sfs_Myname, Cur_filename, size);
+			(void) fflush(stderr);
+		    }
+		    args.offset._p._l += size;
+		} else {
+		    if (DEBUG_CHILD_ERROR) {
+			 (void) fprintf(stderr,
+				"%s: read call NFS error %s on file %d\n",
+					sfs_Myname,
+					nfs3_strerror(reply.status),
+					Cur_file_ptr->unique_num);
+		    }
+		}
+		sfs_elapsedtime(op_ptr, &start, &stop);
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+		ret++;
+	    } else {
+		if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+				"%s: read call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+		}
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	    }
+	} /* for reading max_cnt packets */
+    } /* for buffers and fragments */
+    return(ret);
+
+} /* op_read */
+
+char *
+init_write_buffer(
+    void)
+{
+    uint32_t *bp;
+    static uint32_t write_buf[DEFAULT_MAX_BUFSIZE / sizeof(uint32_t)];
+    uint32_t *be  = write_buf + (sizeof(write_buf) /
+							sizeof(uint32_t));
+
+    if (write_buf[0] != (uint32_t)0xdeadbeef) {
+        for (bp = write_buf; bp < be; bp++)
+            *bp = (uint32_t)0xdeadbeef;
+    }
+    return (char *)write_buf;
+}
+
+
+/*
+ * Perform and RPC write operation of length 'xfer_size'.  If 'append_flag'
+ * is true, then write the data to the end of the file.
+ *
+ * If the stab_flag is set to UNSTABLE we issue the requests and then
+ * issue a op_commit to sync the data.
+ */
+static int
+op_write(
+    int			xfer_size,
+    int			append_flag,
+    stable_how		stab_flag)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    static char			*buf = NULL;	/* the data buffer */
+    unsigned int		size;		/* size of data write */
+    int				cur_cnt;	/* controls # NFS calls */
+    int				max_cnt;
+    WRITE3args			args;
+    WRITE3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				j;
+    int				ret;		/* ret val == call success */
+
+    /*
+     * For now we treat DATA_SYNC to be the same as FILE_SYNC.
+     */
+    if (stab_flag == DATA_SYNC)
+	stab_flag = FILE_SYNC;
+
+    /*
+     * Initialize write buffer to known value
+     */
+    if (buf == NULL) {
+	buf = init_write_buffer();
+    }
+
+    op_ptr = &Ops[WRITE];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
+		sizeof (nfs_fh3));
+    args.offset._p._u = 0;
+    if (append_flag == 1) {
+	args.offset._p._l = Cur_file_ptr->attributes3.size._p._l;
+    } else {
+	/*
+	 * randomly choose an offset that is a multiple of the block size
+	 * and constrained by making the transfer fit within the file
+	 */
+	if (Cur_file_ptr->attributes3.size._p._l > xfer_size) {
+	    args.offset._p._l = Bytes_per_block * (sfs_random() %
+			    (((Cur_file_ptr->attributes3.size._p._l - xfer_size)
+			    / Bytes_per_block) + 1));
+	} else
+	    args.offset._p._l = 0;
+    }
+
+    /* stab_flag has to be set in op() in sfs_3_chd.c */
+    args.stable = stab_flag;
+
+    /* first write the whole buffers, then the fragment */
+    for (j = 0; j < 2; j++) {
+
+	if (j == 0) {
+	    size = Bytes_per_block;
+	    max_cnt = xfer_size / Bytes_per_block;
+	} else {
+	    /* 1KB - (Kb_per_block - 1) KB fragment */
+	    size = xfer_size % Bytes_per_block;
+	    max_cnt = 1;
+	}
+	if (size == 0)
+	    continue;
+
+	args.count = size;
+	args.data.data_len = size;
+	args.data.data_val = buf;
+
+	/* check our stats to see if this would overflow */
+	if (!Timed_run) {
+	    if (op_ptr->target_calls > 0) {
+		if ((op_ptr->results.good_calls + max_cnt)
+		     > op_ptr->target_calls) {
+		    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+		}
+	    }
+	}
+
+	if (DEBUG_CHILD_RPC) {
+	    (void) fprintf(stderr, "write: %d buffers\n", max_cnt);
+	    (void) fflush(stderr);
+	}
+
+	/* make the call(s) now */
+	for (cur_cnt = 0; cur_cnt < max_cnt; cur_cnt++) {
+
+	    if (DEBUG_CHILD_RPC) {
+(void) fprintf(stderr, "%s: WRITE %s offset %u count %lu stable %d\n",
+sfs_Myname, Cur_filename, args.offset._p._l, args.count, args.stable);
+		(void) fflush(stderr);
+	    }
+
+	    /* capture length for possible dump */
+	    Dump_length = fh_size(Cur_file_ptr);
+ 
+	    sfs_gettime(&start);
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE,
+				xdr_WRITE3args, (char *) &args,
+				xdr_WRITE3res, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+	    sfs_gettime(&stop);
+	    Cur_time = stop;
+
+	    /* capture count and offset for possible dump */
+	    Dump_count = args.data.data_len;
+	    Dump_offset = args.offset._p._l;
+
+	    if (rpc_stat == RPC_SUCCESS) {
+		if (reply.status == NFS3_OK) {
+		    Cur_file_ptr->state = Exists;
+		    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &reply.resok.file_wcc.after.attr,
+				sizeof (Cur_file_ptr->attributes3));
+		    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+		    args.offset._p._l += size;
+
+		    if (DEBUG_CHILD_RPC) {
+			(void) fprintf(stderr, "%s: WRITE %s %d bytes\n",
+					   sfs_Myname, Cur_filename, size);
+			(void) fflush(stderr);
+		    }
+		} else {
+		    if (DEBUG_CHILD_ERROR) {
+			 (void) fprintf(stderr,
+				"%s: write call NFS error %s on file %d\n",
+				sfs_Myname, nfs3_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+		    }
+		}
+		sfs_elapsedtime(op_ptr, &start, &stop);
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+		ret++;
+	    } else {
+		if (DEBUG_CHILD_ERROR) {
+		     (void) fprintf(stderr,
+				"%s: write call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+		}
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	    }
+	} /* for writing max_cnt packets */
+    } /* for buffers and fragments */
+
+    /*
+     * If we have not gotten an error and we were asked for an async write
+     * send a commit operation.
+     */
+    if (ret && stab_flag != FILE_SYNC)
+	ret += op_commit();
+
+    return(ret);
+
+} /* op_write */
+
+
+static int
+op_create(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    CREATE3args		args;
+    CREATE3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[CREATE];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.how.mode = UNCHECKED;
+    args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.mode.mode = (NFSMODE_REG | 0666);
+    args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
+    args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
+    args.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.atime.atime.seconds = Cur_time.esec;
+    args.how.createhow3_u.obj_attributes.atime.atime.nseconds =
+						Cur_time.usec * 1000;
+    args.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
+						Cur_time.usec * 1000;
+    args.how.createhow3_u.obj_attributes.size.set_it = TRUE;
+    args.how.createhow3_u.obj_attributes.size.size._p._u = (uint32_t) 0;
+    args.how.createhow3_u.obj_attributes.size.size._p._l = (uint32_t) 0;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE,
+			xdr_CREATE3args, (char *) &args,
+			xdr_CREATE3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.obj.handle,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.obj_attributes.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: create call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: create call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_create */
+
+
+static int
+op_mkdir(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    MKDIR3args		args;
+    MKDIR3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[MKDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.attributes.mode.set_it = TRUE;
+    args.attributes.mode.mode = (NFSMODE_DIR | 0777);
+    args.attributes.uid.set_it = TRUE;
+    args.attributes.uid.uid = Cur_uid;
+    args.attributes.gid.set_it = TRUE;
+    args.attributes.gid.gid = Cur_gid;
+    args.attributes.size.set_it = TRUE;
+    args.attributes.size.size._p._u = 0;
+    args.attributes.size.size._p._l = 512;
+    args.attributes.atime.set_it = TRUE;
+    args.attributes.atime.atime.seconds = Cur_time.esec;
+    args.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+    args.attributes.mtime.set_it = TRUE;
+    args.attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR,
+			xdr_MKDIR3args, (char *) &args,
+			xdr_MKDIR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+            Cur_file_ptr->state = Empty_dir;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.obj.handle,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.obj_attributes.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: mkdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: mkdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_mkdir */
+
+
+static int
+op_symlink(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target file */
+    SYMLINK3args	args;
+    SYMLINK3res		reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];	/* symlink data */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[SYMLINK];
+    ret = 0;
+
+    /* set up the arguments */
+    target_fileinfo_ptr = randfh(SYMLINK, 0, 0, Exists, Sfs_non_io_file);
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+
+    (void) strcpy(sym_data, "./");
+    (void) strcat(sym_data, target_fileinfo_ptr->file_name);
+    args.symlink.symlink_attributes.size.set_it = TRUE;
+    args.symlink.symlink_attributes.size.size._p._u = (uint32_t) 0;
+    args.symlink.symlink_attributes.size.size._p._l = strlen(sym_data);
+    args.symlink.symlink_data = sym_data;
+
+    args.symlink.symlink_attributes.mode.set_it = TRUE;
+    args.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
+    args.symlink.symlink_attributes.uid.set_it = TRUE;
+    args.symlink.symlink_attributes.uid.uid = Cur_uid;
+    args.symlink.symlink_attributes.gid.set_it = TRUE;
+    args.symlink.symlink_attributes.gid.gid = Cur_gid;
+    args.symlink.symlink_attributes.atime.set_it = TRUE;
+    args.symlink.symlink_attributes.atime.atime.seconds = Cur_time.esec;
+    args.symlink.symlink_attributes.atime.atime.nseconds =
+						Cur_time.usec * 1000;
+    args.symlink.symlink_attributes.mtime.set_it = TRUE;
+    args.symlink.symlink_attributes.mtime.mtime.seconds = Cur_time.esec;
+    args.symlink.symlink_attributes.mtime.mtime.nseconds =
+						Cur_time.usec * 1000;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK,
+			xdr_SYMLINK3args, (char *) &args,
+			xdr_SYMLINK3res, (char *) &reply,
+			((int)Current_test_phase < (int)Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    /*
+	     * SYMLINK doesn't return a fh. If we try to access this symlink
+	     * (eg, remove(), readlink()) before we do a lookup, we won't have
+	     * a fh to use. So, we do a lookup call here. If it fails, we fill
+	     * in what we can.
+	     */
+	    Cur_file_ptr->state = Exists;
+	    if (op_lookup() == 0) {
+		(void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+		Cur_file_ptr->attributes3.type = NF3LNK;
+		Cur_file_ptr->attributes3.mode = (NFSMODE_LNK|0777);
+		Cur_file_ptr->attributes3.uid = Cur_uid;
+		Cur_file_ptr->attributes3.gid = Cur_gid;
+		Cur_file_ptr->attributes3.atime.seconds = Cur_time.esec;
+		Cur_file_ptr->attributes3.atime.nseconds =
+							Cur_time.usec * 1000;
+		Cur_file_ptr->attributes3.mtime =
+			Cur_file_ptr->attributes3.atime;
+	    } else
+		ret++;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: symlink call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: symlink call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_symlink */
+
+
+static int
+op_mknod(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    MKNOD3args		args;
+    MKNOD3res		reply;
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[MKNOD];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.where.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.where.name = Cur_filename;
+    args.what.type = NF3FIFO;
+    args.what.mknoddata3_u.pipe_attributes.mode.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mode.mode = (NFSMODE_FIFO | 0777);
+    args.what.mknoddata3_u.pipe_attributes.uid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.uid.uid = Cur_uid;
+    args.what.mknoddata3_u.pipe_attributes.gid.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.gid.gid = Cur_gid;
+    args.what.mknoddata3_u.pipe_attributes.size.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._u = (uint32_t) 0;
+    args.what.mknoddata3_u.pipe_attributes.size.size._p._l =
+							(uint32_t) 512;
+    args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.seconds =
+							Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.atime.atime.nseconds =
+							Cur_time.usec * 1000;
+    args.what.mknoddata3_u.pipe_attributes.atime.set_it = TRUE;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.seconds =
+								Cur_time.esec;
+    args.what.mknoddata3_u.pipe_attributes.mtime.mtime.nseconds =
+							Cur_time.usec * 1000;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_MKNOD,
+			xdr_MKNOD3args, (char *) &args,
+			xdr_MKNOD3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &reply.resok.obj.handle,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.obj_attributes.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: mknod call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: mknod call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_mknod */
+
+
+static int
+op_remove(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    REMOVE3args		args;
+    REMOVE3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[REMOVE];
+    ret = 0;
+
+    /* set up the arguments */
+    args.object.name = Cur_filename;
+    (void) memmove((char *) &args.object.dir,(char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE,
+			xdr_REMOVE3args, (char *) &args,
+			xdr_REMOVE3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+				"%s: remove call NFS error %s on file %d\n",
+				sfs_Myname, nfs3_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: remove call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_remove */
+
+
+static int
+op_rmdir(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    RMDIR3args		args;
+    RMDIR3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[RMDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.object.name = Cur_file_ptr->file_name;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR,
+			xdr_RMDIR3args, (char *) &args,
+			xdr_RMDIR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+				"%s: rmdir call NFS error %s on file %d\n",
+				sfs_Myname, nfs3_strerror(reply.status),
+				Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: rmdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_rmdir */
+
+
+static int
+op_rename(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target name */
+    RENAME3args		args;
+    RENAME3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[RENAME];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.from.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    (void) memmove((char *) &args.to.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    target_fileinfo_ptr = randfh(RENAME, 0, 0, Nonexistent,
+				 Sfs_non_io_file);
+
+    args.from.name = Cur_file_ptr->file_name;
+    (void) sprintf(target_fileinfo_ptr->file_name, Filespec,
+		   target_fileinfo_ptr->unique_num);
+    args.to.name = target_fileinfo_ptr->file_name;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
+			xdr_RENAME3args, (char *) &args,
+			xdr_RENAME3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    target_fileinfo_ptr->state = Exists;
+	    (void) memmove((char *) &target_fileinfo_ptr->fh3,
+			(char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+	    target_fileinfo_ptr->attributes3 = Cur_file_ptr->attributes3;
+	    target_fileinfo_ptr->size = fh_size(Cur_file_ptr);
+	    Cur_file_ptr->state = Nonexistent;
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: rename call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: rename call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_rename */
+
+
+static int
+op_link(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    sfs_fh_type		*target_fileinfo_ptr;	/* target */
+    LINK3args		args;
+    LINK3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+
+    op_ptr = &Ops[LINK];
+    ret = 0;
+
+    /* set up the arguments */
+    target_fileinfo_ptr = randfh(LINK, 0, 0, Exists, Sfs_non_io_file);
+    (void) memmove((char *) &args.file, (char *) &target_fileinfo_ptr->fh3,
+		sizeof (nfs_fh3));
+    (void) memmove((char *) &args.link.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.link.name = Cur_filename;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LINK,
+			xdr_LINK3args, (char *) &args,
+			xdr_LINK3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->fh3,
+			(char *) &target_fileinfo_ptr->fh3,
+			sizeof (nfs_fh3));
+	    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+	    target_fileinfo_ptr->attributes3.nlink++;
+	    Cur_file_ptr->attributes3 = target_fileinfo_ptr->attributes3;
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: link call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: link call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_link */
+
+
+static int
+op_readdir(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    READDIR3args	args;
+    READDIR3res		reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			i;
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+    bool_t		hit_eof;
+	/* array of entries */
+    entry3		entry_stream[SFS_MAXDIRENTS];
+    entry3		*entries;		/* ptr to the dir entry */
+
+    op_ptr = &Ops[READDIR];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
+    (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+    args.count = DEFAULT_MAX_BUFSIZE;
+
+    /* Have lower layers fill in the data directly.  */
+    (void) memset((char *) &reply, '\0', sizeof (reply));
+    (void) memset((char *) entry_stream, '\0',
+					sizeof (entry3) * SFS_MAXDIRENTS);
+    reply.resok.count = SFS_MAXDIRENTS;
+    reply.resok.reply.entries = entry_stream;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIR,
+			xdr_READDIR3args, (char *) &args,
+			xdr_READDIR3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+
+	    if (DEBUG_CHILD_RPC) {
+		hit_eof = reply.resok.reply.eof;
+		entries = reply.resok.reply.entries;
+		for (i = 0; i < reply.resok.count; i++) {
+		    (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
+				    sfs_Myname, hit_eof, entries[i].name);
+		}
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+				"%s: readdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readdir */
+
+
+static int
+op_readdirplus(void)
+{
+    sfs_op_type		*op_ptr;		/* per operation info */
+    READDIRPLUS3args	args;
+    READDIRPLUS3res	reply;			/* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			i;
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;			/* ret val == call success */
+    bool_t		hit_eof;
+	/* array of entries */
+    entryplus3		entry_stream[SFS_MAXDIRENTS];
+    entryplus3		*entries;
+
+    op_ptr = &Ops[READDIRPLUS];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.dir, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+    args.cookie._p._l = args.cookie._p._u = (uint32_t) 0;
+    (void) memset((char *) args.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+    (void) memset((char *) entry_stream, '\0',
+				sizeof (entryplus3) * SFS_MAXDIRENTS);
+    args.dircount = DEFAULT_MAX_BUFSIZE;
+    args.maxcount = DEFAULT_MAX_BUFSIZE;
+
+    /* Have lower layers fill in the data directly.  */
+    reply.resok.count = SFS_MAXDIRENTS;
+    reply.resok.reply.entries = entry_stream;
+
+    /* make the call now */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIRPLUS,
+			xdr_READDIRPLUS3args, (char *) &args,
+			xdr_READDIRPLUS3res, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+
+	    if (DEBUG_CHILD_RPC) {
+		hit_eof = reply.resok.reply.eof;
+		entries = reply.resok.reply.entries;
+		for (i = 0; i < reply.resok.count; i++) {
+		    (void) fprintf(stderr, "%s:READDIR (eof=%d) entry %s\n",
+				    sfs_Myname, hit_eof, entries[i].name);
+		}
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: readdir call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+				"%s: readdir call RPC error %d on file %d\n",
+		    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_readdirplus */
+
+
+static int
+op_fsstat(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    FSSTAT3args		args;
+    FSSTAT3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[FSSTAT];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.fsroot, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_FSSTAT,
+			xdr_FSSTAT3args, (char *) &args,
+			xdr_FSSTAT3args, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: fsstat call RPC error %d\n",
+						sfs_Myname, rpc_stat);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_fsstat */
+
+
+static int
+op_fsinfo(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    FSINFO3args		args;
+    FSINFO3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[FSINFO];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.fsroot, (char *) &Cur_file_ptr->dir->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_FSINFO,
+			xdr_FSINFO3args, (char *) &args,
+			xdr_FSINFO3args, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: fsinfo call RPC error %d\n",
+						sfs_Myname, rpc_stat);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_fsinfo */
+
+
+static int
+op_pathconf(void)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    PATHCONF3args	args;
+    PATHCONF3res	reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+    int			ret;		/* ret val == call success */
+
+    op_ptr = &Ops[PATHCONF];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.object, (char *) &Cur_file_ptr->fh3,
+		sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_PATHCONF,
+			xdr_PATHCONF3args, (char *) &args,
+			xdr_PATHCONF3args, (char *) &reply,
+			(Current_test_phase < Warmup_phase)
+				 ? Nfs_timers[Init]
+				 : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr,
+			"%s: pathconf call RPC error %d on file %d\n",
+			sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+    return(ret);
+
+} /* op_pathconf */
+
+
+static int
+op_commit(void)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    int32_t			size;		/* size of data write */
+    COMMIT3args			args;
+    COMMIT3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    struct ladtime		start;
+    struct ladtime		stop;
+    int				ret;		/* ret val == call success */
+
+    op_ptr = &Ops[COMMIT];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &Cur_file_ptr->fh3,
+		sizeof (nfs_fh3));
+    args.offset._p._u = args.offset._p._l = (uint32_t) 0;
+    args.count = Cur_file_ptr->attributes3.size._p._l;
+    size = args.count;
+
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT,
+				xdr_COMMIT3args, (char *) &args,
+				xdr_COMMIT3res, (char *) &reply,
+				(Current_test_phase < Warmup_phase)
+				     ? Nfs_timers[Init]
+				     : Nfs_timers[op_ptr->call_class]);
+    sfs_gettime(&stop);
+    Cur_time = stop;
+
+    if (rpc_stat == RPC_SUCCESS) {
+	if (reply.status == NFS3_OK) {
+	    Cur_file_ptr->state = Exists;
+	    (void) memmove((char *) &Cur_file_ptr->attributes3,
+			(char *) &reply.resok.file_wcc.after.attr,
+			sizeof(Cur_file_ptr->attributes3));
+	    Cur_file_ptr->size = fh_size(Cur_file_ptr);
+
+	    if (DEBUG_CHILD_RPC) {
+		(void) fprintf(stderr, "%s: WRITE %s %ld bytes\n",
+					   sfs_Myname, Cur_filename, size);
+		(void) fflush(stderr);
+	    }
+	} else {
+	    if (DEBUG_CHILD_ERROR) {
+		 (void) fprintf(stderr,
+			"%s: write call NFS error %s on file %d\n",
+			sfs_Myname, nfs3_strerror(reply.status),
+			Cur_file_ptr->unique_num);
+	    }
+	}
+	sfs_elapsedtime(op_ptr, &start, &stop);
+	op_ptr->results.good_calls++;
+	Ops[TOTAL].results.good_calls++;
+	ret++;
+    } else {
+	if (DEBUG_CHILD_ERROR) {
+	     (void) fprintf(stderr, "%s: write call RPC error %d on file %d\n",
+			    sfs_Myname, rpc_stat, Cur_file_ptr->unique_num);
+	}
+	op_ptr->results.bad_calls++;
+	Ops[TOTAL].results.bad_calls++;
+    }
+
+    return(ret);
+
+} /* op_commit */
+
+
+#define LAD_RETRIABLE(stat) (((stat) == RPC_TIMEDOUT) || ((stat) == RPC_CANTDECODERES))
+
+/*
+ * Reliably lookup a file in the current directory
+ * Return:
+ *	-1	RPC error
+ *	1	File doesn't exist
+ *	0	File exists
+ */
+int
+lad_lookup(sfs_fh_type *file_ptr, char *name)
+{
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_lookup: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+        (void) memmove((char *) &args.what.dir, (char *) &file_ptr->dir->fh3,
+							sizeof (nfs_fh3));
+	args.what.name = name;
+        (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+	/* make the call */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_lookup(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    if (reply.status == NFS3ERR_NOENT) {
+	return(1);
+    }
+
+    if (reply.status != NFS3_OK) {
+	(void) fprintf(stderr, "lad_lookup(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	return(-1);
+    }
+
+    file_ptr->state = Exists;
+    (void) memmove((char *) &file_ptr->fh3,
+			(char *) &reply.resok.object,
+			sizeof (nfs_fh3));
+    (void) strcpy(file_ptr->file_name, name);
+    (void) memmove((char *) &file_ptr->attributes3,
+				(char *) &reply.resok.obj_attributes.attr,
+				sizeof (file_ptr->attributes3));
+    file_ptr->size = fh_size(file_ptr);
+    return(0);
+}
+
+/*
+ * Reliably remove a file in the current directory
+ */
+int
+lad_remove(sfs_fh_type *file_ptr, char *name)
+{
+    REMOVE3args         args;
+    REMOVE3res          reply;          /* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does exist
+     */
+    if (file_ptr->attributes3.type == NF3DIR)
+	return (lad_rmdir(file_ptr, name));
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_remove: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.object.name = name;
+	(void) memmove((char *) &args.object.dir, (char *) &file_ptr->dir->fh3,
+			sizeof(nfs_fh3));
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE,
+                        xdr_REMOVE3args, (char *) &args,
+                        xdr_REMOVE3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_remove(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_NOENT || !retried) {
+	    (void) fprintf(stderr, "lad_remove(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+    }
+
+    file_ptr->state = Nonexistent;
+
+    return(0);
+}
+
+/*
+ * Reliably remove a directory in the current directory
+ */
+int
+lad_rmdir(sfs_fh_type *file_ptr, char *name)
+{
+    RMDIR3args          args;
+    RMDIR3res           reply;          /* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does exist and is empty
+     */
+    if (file_ptr->attributes3.type != NF3DIR)
+	return (lad_remove(file_ptr, name));
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_rmdir: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	args.object.name = name;
+        (void) memmove((char *) &args.object.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR,
+                        xdr_RMDIR3args, (char *) &args,
+                        xdr_RMDIR3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_rmdir(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_NOENT || !retried) {
+	    (void) fprintf(stderr, "lad_rmdir(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+    }
+
+    file_ptr->state = Nonexistent;
+
+    return(0);
+}
+
+/*
+ * Reliably create a symlink in the current directory
+ */
+int
+lad_symlink(sfs_fh_type *file_ptr, char *target, char *name)
+{
+    SYMLINK3args        args;
+    SYMLINK3res         reply;			/* the reply */
+    char		sym_data[NFS_MAXPATHLEN];	/* symlink data */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_symlink: %lx[%lx] %s -> %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name, target);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+         (void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+         args.where.name = name;
+
+	(void) strcpy(sym_data, "./");
+	(void) strcat(sym_data, target);
+	args.symlink.symlink_attributes.size.set_it = TRUE;
+	args.symlink.symlink_attributes.size.size._p._u = (uint32_t) 0;
+	args.symlink.symlink_attributes.size.size._p._l = strlen(sym_data);
+	args.symlink.symlink_data = sym_data;
+
+	args.symlink.symlink_attributes.mode.set_it = TRUE;
+	args.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
+	args.symlink.symlink_attributes.uid.set_it = TRUE;
+	args.symlink.symlink_attributes.uid.uid = Cur_uid;
+	args.symlink.symlink_attributes.gid.set_it = TRUE;
+	args.symlink.symlink_attributes.gid.gid = Cur_gid;
+	args.symlink.symlink_attributes.atime.set_it = TRUE;
+	args.symlink.symlink_attributes.atime.atime.seconds = Cur_time.esec;
+	args.symlink.symlink_attributes.atime.atime.nseconds =
+                                                Cur_time.usec * 1000;
+	args.symlink.symlink_attributes.mtime.set_it = TRUE;
+	args.symlink.symlink_attributes.mtime.mtime.seconds = Cur_time.esec;
+	args.symlink.symlink_attributes.mtime.mtime.nseconds =
+                                                Cur_time.usec * 1000;
+
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK,
+                        xdr_SYMLINK3args, (char *) &args,
+                        xdr_SYMLINK3res, (char *) &reply,
+		 	Nfs_timers[Init]);
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_symlink(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_symlink(%s, %s) NFS call failed : %s\n",
+			target, name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+    }
+
+    /*
+     * SYMLINK may not return a fh. If we try to
+     * access this symlink (eg, remove(), readlink())
+     * before we do a lookup, we won't have a fh to use.
+     * So, we do a lookup call here.
+     * If it fails, we fill in what we can.
+     */  
+    return (lad_lookup(file_ptr, name));
+}
+
+/*
+ * Reliably create a directory in the current directory
+ */
+int
+lad_mkdir(sfs_fh_type *file_ptr, char *name)
+{
+    MKDIR3args          args;
+    MKDIR3res           reply;                  /* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_mkdir: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+ 	(void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+	args.where.name = name;
+	args.attributes.mode.set_it = TRUE;
+	args.attributes.mode.mode = (NFSMODE_DIR | 0777);
+	args.attributes.uid.set_it = TRUE;
+	args.attributes.uid.uid = Cur_uid;
+	args.attributes.gid.set_it = TRUE;
+	args.attributes.gid.gid = Cur_gid;
+	args.attributes.size.set_it = TRUE;
+	args.attributes.size.size._p._u = 0;
+	args.attributes.size.size._p._l = 512;
+	args.attributes.atime.set_it = TRUE;
+	args.attributes.atime.atime.seconds = Cur_time.esec;
+	args.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+	args.attributes.mtime.set_it = TRUE;
+	args.attributes.mtime.mtime.seconds = Cur_time.esec;
+	args.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR,
+                        xdr_MKDIR3args, (char *) &args,
+                        xdr_MKDIR3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_mkdir(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (!retried && reply.status == NFS3ERR_EXIST)
+	return(1);
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_mkdir(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+	/*
+	 * If the first mkdir suceeded but the reply as dropped and
+	 * was retransmitted, we still need to lookup the attributes
+	 */
+	if (lad_lookup(file_ptr, name))
+	   return (-1);
+    } else {
+	(void) memmove((char *) &file_ptr->fh3,
+                   (char *) &reply.resok.obj.handle,
+                   sizeof (nfs_fh3));
+	(void) strcpy(file_ptr->file_name, name);
+	(void) memmove((char *) &file_ptr->attributes3,
+                   (char *) &reply.resok.obj_attributes.attr,
+                   sizeof(file_ptr->attributes3));
+	file_ptr->size = fh_size(file_ptr);
+    }
+    file_ptr->state = Empty_dir;
+
+    return(0);
+}
+
+/*
+ * Reliably commit a file
+ */
+static int
+lad_commit(sfs_fh_type *file_ptr)
+{
+    COMMIT3args			args;
+    COMMIT3res			reply;		/* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_commit: %lx[%lx]\n",
+			sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir);
+	(void) fflush(stderr);
+    }
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &file_ptr->fh3,
+		sizeof (nfs_fh3));
+    args.offset._p._u = args.offset._p._l = (uint32_t) 0;
+    args.count = file_ptr->attributes3.size._p._l;
+
+    /* CONSTCOND */
+    while (1) {
+        rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT,
+				xdr_COMMIT3args, (char *) &args,
+				xdr_COMMIT3res, (char *) &reply,
+			 	Nfs_timers[Init]);
+        if (rpc_stat == RPC_SUCCESS) 
+	    break;
+        if (rpc_stat != RPC_TIMEDOUT) {
+	    (void) fprintf(stderr, "lad_commit() RPC call failed : %s\n",
+				clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    return(0);
+}
+
+/*
+ * Reliably write a file in the current directory
+ */
+int
+lad_write(sfs_fh_type *file_ptr, int32_t offset, int32_t length)
+{
+    static char			*buf = NULL;	/* the data buffer */
+    int32_t			size;		/* size of data write */
+    int32_t			cur_cnt;
+    WRITE3args                  args;
+    WRITE3res                   reply;          /* the reply */
+    enum clnt_stat		rpc_stat;	/* result from RPC call */
+    int				async = 1;
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_write: %lx[%lx] %ld %ld\n",
+			sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, offset, length);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * This function presumes that the file name does exist
+     * Initialize write buffer to known value
+     */
+    if (buf == NULL) {
+	buf = init_write_buffer();
+    }
+
+    /*
+     * If a short file write don't bother with the commit, just write sync.
+     */
+    if (length <= Bytes_per_block)
+	async = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args.file, (char *) &file_ptr->fh3,
+                sizeof (nfs_fh3));
+    args.offset._p._u = 0;
+    args.offset._p._l = offset;
+    if (async)
+	    args.stable = UNSTABLE;
+    else
+	    args.stable = FILE_SYNC;
+
+    size = Bytes_per_block;
+    for (cur_cnt = 0; cur_cnt < length; cur_cnt += size) {
+	if ((cur_cnt + size) > length)
+		size = length - cur_cnt;
+
+	if (size == 0)
+	    break;
+
+	args.count = size;
+	args.data.data_len = size;
+	args.data.data_val = buf;
+
+	/* make the call now */
+        /* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE,
+                                xdr_WRITE3args, (char *) &args,
+                                xdr_WRITE3res, (char *) &reply,
+				Nfs_timers[Init]);
+
+	    if (rpc_stat == RPC_SUCCESS) 
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_write() RPC call failed : %s\n",
+				clnt_sperrno(rpc_stat));
+	    }
+	    if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	    }
+	}
+	if (reply.status != NFS3_OK) {
+	    (void) fprintf(stderr, "lad_write() NFS call failed : %s\n",
+			nfs3_strerror(reply.status));
+	    return(-1);
+	}
+	file_ptr->state = Exists;
+        (void) memmove((char *) &file_ptr->attributes3,
+                                (char *) &reply.resok.file_wcc.after.attr,
+                                sizeof (file_ptr->attributes3));
+	file_ptr->size = fh_size(file_ptr);
+
+        args.offset._p._l += size;
+    }
+
+    if (async)
+	(void) lad_commit(file_ptr);
+    return(0);
+}
+
+/*
+ * Reliably create a file in the current directory
+ */
+int
+lad_create(sfs_fh_type *file_ptr, char *name)
+{
+    CREATE3args         args;
+    CREATE3res          reply;                  /* the reply */
+    enum clnt_stat	rpc_stat;		/* result from RPC call */
+    int			retried = 0;
+
+    /*
+     * This function presumes that the file name does not already exist
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_create: %lx[%lx] %s\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, name);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/* set up the arguments */
+	(void) memmove((char *) &args.where.dir, (char *) &file_ptr->dir->fh3,
+                sizeof (nfs_fh3));
+	args.where.name = name;
+	args.how.mode = UNCHECKED;
+	args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.mode.mode = (NFSMODE_REG | 0666);
+	args.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
+	args.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
+	args.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.atime.atime.seconds =
+						Cur_time.esec;
+	args.how.createhow3_u.obj_attributes.atime.atime.nseconds =
+                                                Cur_time.usec * 1000;
+	args.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.mtime.mtime.seconds =
+						Cur_time.esec;
+	args.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
+                                                Cur_time.usec * 1000;
+	args.how.createhow3_u.obj_attributes.size.set_it = TRUE;
+	args.how.createhow3_u.obj_attributes.size.size._p._u =
+						(uint32_t) 0;
+	args.how.createhow3_u.obj_attributes.size.size._p._l =
+						(uint32_t) 0;
+
+	/* make the call now */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE,
+                        xdr_CREATE3args, (char *) &args,
+                        xdr_CREATE3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void) fprintf(stderr, "lad_create(%s) RPC call failed : %s\n",
+				name, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+	retried++;
+    }
+
+    if (!retried && reply.status == NFS3ERR_EXIST) {
+	return(1);
+    }
+
+    if (reply.status != NFS3_OK) {
+	if (reply.status != NFS3ERR_EXIST || !retried) {
+	    (void) fprintf(stderr, "lad_create(%s) NFS call failed : %s\n",
+			name, nfs3_strerror(reply.status));
+	    return(-1);
+	}
+        /*
+         * If the first create suceeded but the reply as dropped and
+         * was retransmitted, we still need to lookup the attributes
+         */
+        if (lad_lookup(file_ptr, name))
+           return (-1);
+    } else {
+	(void) memmove((char *) &file_ptr->fh3,
+                   (char *) &reply.resok.obj.handle,
+                   sizeof (nfs_fh3));
+	(void) strcpy(file_ptr->file_name, name);
+	(void) memmove((char *) &file_ptr->attributes3,
+                   (char *) &reply.resok.obj_attributes.attr,
+                   sizeof(file_ptr->attributes3));
+	file_ptr->size = fh_size(file_ptr);
+    }
+
+    file_ptr->state = Exists;
+    /*
+     * Directories are created as Empty_dir, when a file is created it
+     * becomes an Exists.
+     */
+    file_ptr->dir->state = Exists;
+
+    return(0);
+}
+
+/*
+ * Reliably set the size of a file in the current directory
+ */
+int
+lad_truncate(sfs_fh_type *file_ptr, int32_t size)
+{
+    SETATTR3args        args;
+    SETATTR3res         reply;          /* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+
+    /*
+     * This function presumes that the file name already exists
+     */
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "%s:lad_truncate: %lx[%lx] %ld\n", sfs_Myname,
+			(int32_t) file_ptr, (int32_t) file_ptr->dir, size);
+	(void) fflush(stderr);
+    }
+
+    /* CONSTCOND */
+    while (1) {
+	/*
+	 * set up the arguments
+	 * Set the mode and times as well
+	 */
+	(void) memmove((char *) &args.object, (char *) &file_ptr->fh3,
+                                                        sizeof (nfs_fh3));
+	args.new_attributes.mode.set_it = TRUE;
+	args.new_attributes.mode.mode = (uint32_t) 0666;
+	args.new_attributes.uid.set_it = FALSE;
+	args.new_attributes.uid.uid = (uint32_t) -1;
+	args.new_attributes.gid.set_it = FALSE;
+	args.new_attributes.gid.gid = (uint32_t) -1;
+	args.new_attributes.size.set_it = TRUE;
+	args.new_attributes.size.size._p._u = 0;
+	args.new_attributes.size.size._p._l = size;
+	args.new_attributes.atime.set_it = TRUE;
+	args.new_attributes.atime.atime.seconds = Cur_time.esec;
+	args.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+	args.new_attributes.mtime.set_it = TRUE;
+	args.new_attributes.mtime.mtime.seconds = Cur_time.esec;
+	args.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+	args.guard.check = FALSE;
+
+	/* make the call */
+	rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR,
+                        xdr_SETATTR3args, (char *) &args,
+                        xdr_SETATTR3res, (char *) &reply,
+			Nfs_timers[Init]);
+
+	if (rpc_stat == RPC_SUCCESS) 
+		break;
+	if (rpc_stat != RPC_TIMEDOUT) {
+		(void)fprintf(stderr,
+				"lad_truncate(%ld) RPC call failed : %s\n",
+				size, clnt_sperrno(rpc_stat));
+	}
+	if (!LAD_RETRIABLE(rpc_stat)) {
+		return(-1);
+	}
+    }
+
+    if (reply.status != NFS3_OK) {
+	(void) fprintf(stderr, "lad_truncate(%ld) NFS call failed : %s\n",
+			size, nfs3_strerror(reply.status));
+	return(-1);
+    }
+    (void) memmove(&file_ptr->attributes3,
+                   &reply.resok.obj_wcc.after.attr,
+                   sizeof (file_ptr->attributes3));
+    file_ptr->size = fh_size(file_ptr);
+
+    return(0);
+}
+
+static char *
+nfs3_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS3_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFS3ERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFS3ERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFS3ERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFS3ERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFS3ERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFS3ERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFS3ERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFS3ERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFS3ERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFS3ERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFS3ERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFS3ERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFS3ERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFS3ERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFS3ERR_MLINK:
+	    (void) strcpy(str, "Too many links");
+	    break;
+	case NFS3ERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFS3ERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFS3ERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFS3ERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFS3ERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFS3ERR_BADHANDLE:
+	    (void) strcpy(str, "Bad file handle");
+	    break;
+	case NFS3ERR_NOT_SYNC:
+	    (void) strcpy(str, "Not sync write");
+	    break;
+	case NFS3ERR_BAD_COOKIE:
+	    (void) strcpy(str, "Bad cookie");
+	    break;
+	case NFS3ERR_NOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFS3ERR_TOOSMALL:
+	    (void) strcpy(str, "Value too small");
+	    break;
+	case NFS3ERR_SERVERFAULT:
+	    (void) strcpy(str, "Server fault");
+	    break;
+	case NFS3ERR_BADTYPE:
+	    (void) strcpy(str, "Bad type");
+	    break;
+	case NFS3ERR_JUKEBOX:
+	    (void) strcpy(str, "Jukebox");
+	    break;
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+
+/* sfs_3_ops.c */
diff --git a/TBBT/trace_play/sfs_3_vld.c b/TBBT/trace_play/sfs_3_vld.c
new file mode 100644
index 0000000..8ede891
--- /dev/null
+++ b/TBBT/trace_play/sfs_3_vld.c
@@ -0,0 +1,2126 @@
+#ifndef lint
+static char sfs_3_vldSid[] = "@(#)sfs_3_vld.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *      Copyright 1991,1992  Legato Systems, Inc.                *
+ *      Copyright 1991,1992  Auspex Systems, Inc.                *
+ *      Copyright 1991,1992  Data General Corporation            *
+ *      Copyright 1991,1992  Digital Equipment Corporation       *
+ *      Copyright 1991,1992  Interphase Corporation              *
+ *      Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ------------------------------ sfs_3_vld.c ---------------------------
+ *
+ * Validation suite for sfs.
+ *
+ *.Exported_routines
+ *      void Validate_ops(int, char **)
+ *
+ *.Local_routines
+ *      void validate_init_rpc()
+ *      void validate_creation(void)
+ *      void validate_attributes(void)
+ *      void validate_read_write(void)
+ *      void validate_rename(void)
+ *      int compare_sattr(char *, char *, sattr3 *, fattr3 *)
+ *      int compare_fattr(char *, char *, fattr3 *, fattr3 *)
+ *      uint16_t sum(unsigned char *, int)
+ *      void validate_remove(void)
+ *      void validate_cleanup(void)
+ *      void validate_exit(void)
+ *      void verror(int, ValMsgType, char *, ...)
+ *
+ *.Revision History
+ *	11-Jul-94	ChakChung Ng	Created
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+ 
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "sfs_c_def.h"
+
+extern struct hostent   *Server_hostent;
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+
+/* forward definitions for local routines */
+/*
+ * validate options
+ * BATCH 	- do complete pass of validation, reporting errors if any
+ * VERBOSE	- prints step-by-step validation actions being performed
+ * INTERACTIVE	- VERBOSE and if any errors encountered, ask to continue
+ *		  validation or not.
+ */
+#define	VAL_BATCH	1
+#define VAL_VERBOSE	2
+#define	VAL_INTERACTIVE	3
+
+typedef enum {
+	I = 1,
+	W = 2,
+	E = 3
+} ValMsgType;
+
+#define NUMREGFILES	21
+#define NUMDIRS		10
+#define NUMLINKS	10
+#define NUMSYMLINKS	10
+#define NUMFILES	NUMREGFILES + NUMDIRS + NUMLINKS + NUMSYMLINKS
+#define NUMFRAGS	8
+
+static void val_op_null(void);
+static void val_op_getattr(GETATTR3args *, GETATTR3res *);
+static void val_op_setattr(SETATTR3args *, SETATTR3res *);
+static void val_op_lookup(LOOKUP3args *, LOOKUP3res *);
+static void val_op_access(ACCESS3args *, ACCESS3res *);
+static void val_op_readlink(READLINK3args *, READLINK3res *);
+static void val_op_read(READ3args *, READ3res *);
+static void val_op_write(WRITE3args *, WRITE3res *);
+static void val_op_create(CREATE3args *, CREATE3res *);
+static void val_op_mkdir(MKDIR3args *, MKDIR3res *);
+static void val_op_symlink(SYMLINK3args *, SYMLINK3res *);
+static void val_op_mknod(MKNOD3args *, MKNOD3res *);
+static void val_op_remove(REMOVE3args *, REMOVE3res *);
+static void val_op_rmdir(RMDIR3args *, RMDIR3res *);
+static void val_op_rename(RENAME3args *, RENAME3res *);
+static void val_op_link(LINK3args *, LINK3res *);
+static void val_op_readdir(READDIR3args *, READDIR3res *);
+static void val_op_readdirplus(READDIRPLUS3args *, READDIRPLUS3res *);
+static void val_op_fsstat(FSSTAT3args *, FSSTAT3res *);
+static void val_op_fsinfo(FSINFO3args *, FSINFO3res *);
+static void val_op_pathconf(PATHCONF3args *, PATHCONF3res *);
+static void val_op_commit(COMMIT3args *, COMMIT3res *);
+
+static void validate_init_rpc(void);
+static void validate_exit(void);
+static void validate_creation(void);
+static void validate_attributes(void);
+static void validate_read_write(void);
+static void validate_rename(void);
+static void validate_remove(void);
+static void validate_cleanup(void);
+static int compare_sattr(char *, char *, sattr3 *, fattr3 *);
+static int compare_fattr(char *, char *, fattr3 *, fattr3 *);
+static uint16_t sum(unsigned char *, int);
+static void verror(int, ValMsgType, char *, ...);
+static void create_3tmp_handles(void);
+static void delete_3tmp_handles(void);
+
+/*
+ * ----------------------  Static Declarations ----------------------
+ */
+
+int Validate;
+
+static int Validate_errors = 0;
+static char Testdirname[SFS_MAXPATHLEN];    /* test dir component name */
+/*
+ * packed structure to keep track of file status
+ */
+struct sfs_fileinfo {
+    int file_found:1,   /* file has been found */
+        file_is_dup:1,  /* file has a duplicate */
+        pad:30;         /* pad the rest */
+};
+
+typedef struct sfs_fileinfo sfs_fileinfo;
+/*
+ * This vector is used for readdirplus validation currently, but could be
+ * extended to keep track of other interesting pieces of information.
+ */
+static sfs_fileinfo check_files[NUMFILES];
+
+/*
+ * ----------------------  SFS Validation Suite  ----------------------
+ */
+
+/*
+ * XXXXX Must make sure that we validate that all servers return back
+ * XXXXX All optional values
+ */
+void
+Validate_ops(
+    int         argc,
+    char *      argv[])
+{
+    char *      valdir;
+    CLIENT *    mount_client_ptr;
+    int i;
+
+    if (argc > 1) {
+	verror(VAL_BATCH, E, "Can only validate one directory at a time.\n");
+	exit(1);
+    }
+
+    Num_io_files = NUMFILES;
+    Cur_uid = Real_uid;
+    nfs_version = NFS_V3;
+
+    if (argc == 0)
+	valdir = ".";
+    else
+	valdir = argv++[0];
+
+    (void) sprintf(Testdirname, "%s/validatedir", valdir);
+
+    do {
+	verror(VAL_BATCH, I, "validating sfs on \"%s\" directory ...\n",
+		valdir);
+
+	init_fileinfo();
+	create_3tmp_handles();
+
+	/*
+	 * need priv port to do following
+	 */
+	mount_client_ptr = lad_getmnt_hand(valdir);
+	if (mount_client_ptr == NULL) {
+	    exit(1);
+	}
+	validate_init_rpc();
+
+	/*
+	 * should be all done doing priv port stuff
+	 */
+	if (setuid(Real_uid) != 0) {
+	   (void) fprintf(stderr,"%s: %s%s\n",
+		   sfs_Myname, "cannot perform setuid operation.\n",
+		   "Do `make install` as root.\n");
+	}
+
+	init_mount_point(0, valdir, mount_client_ptr);
+
+        /*
+         * initialize the check_file array
+         */
+        (void) memset((void *) check_files, '\0', sizeof(check_files));
+
+	verror(VAL_VERBOSE, I, "validating null operation ...\n");
+	val_op_null();
+
+	validate_creation();
+	validate_attributes();
+	validate_read_write();
+	validate_rename();
+	validate_remove();
+	argc--;
+	valdir = argv++[0];
+
+	/*
+	 * Cleanup mount client handle
+	 */
+	clnt_destroy(mount_client_ptr);
+
+	delete_3tmp_handles();
+	validate_cleanup();
+    } while (argc > 0);
+
+    validate_exit();
+
+} /* Validate_ops */
+
+
+/*
+ * allocate and initialize client handles
+ */
+static void
+validate_init_rpc(void)
+{
+	NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+                                        (uint32_t) NFS_PROGRAM,
+                                        (uint32_t) NFS_V3,
+                                        RPC_ANYSOCK, &Nfs_timers[0]);
+
+	if (NFS_client == ((CLIENT *) NULL)) { 
+		    verror(VAL_BATCH, E,
+				"portmap/nfsd server not responding\n"); 
+		    exit(1); 
+	}
+ 
+	NFS_client->cl_auth = authunix_create(lad_hostname, Real_uid,
+                                      Cur_gid, 0, NULL);
+} /* validate_init_rpc */
+
+
+static void
+validate_creation(void)
+{
+    int                 filenum;
+    int                 target_filenum;
+    CREATE3args		argcr;
+    CREATE3res		repcr;
+    MKDIR3args		argmk;
+    MKDIR3res		repmk;
+    LINK3args		argln;
+    LINK3res		repln;
+    SYMLINK3args	argsl;
+    SYMLINK3res		repsl;
+    LOOKUP3args		arglp;
+    LOOKUP3res		replp;
+    READLINK3args	argrl;
+    READLINK3res	reprl;
+    char                sl_target_path[NFS_MAXPATHLEN];
+    char                sym_data[NFS_MAXPATHLEN];
+
+    for (filenum=0; filenum < NUMFILES ; filenum++) {
+
+	Cur_file_ptr = &Io_files[filenum];
+	sfs_gettime(&Cur_time);
+
+	if (filenum < NUMREGFILES) {
+
+	    (void) sprintf(Cur_filename, Filespec, filenum);
+
+	    /* regular file creation */
+	    (void) memmove((char *) &argcr.where.dir, (char *) &Export_dir.fh3,
+				sizeof (nfs_fh3));
+	    argcr.where.name = Cur_filename;
+	    argcr.how.mode = UNCHECKED;
+	    argcr.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
+	    argcr.how.createhow3_u.obj_attributes.mode.mode =
+							(NFSMODE_REG | 0666);
+	    argcr.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
+	    argcr.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
+	    argcr.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
+	    argcr.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
+	    argcr.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
+	    argcr.how.createhow3_u.obj_attributes.atime.atime.seconds =
+							Cur_time.esec;
+	    argcr.how.createhow3_u.obj_attributes.atime.atime.nseconds =
+							Cur_time.usec * 1000;
+	    argcr.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
+	    argcr.how.createhow3_u.obj_attributes.mtime.mtime.seconds =
+							Cur_time.esec;
+	    argcr.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
+			                                Cur_time.usec * 1000;
+	    argcr.how.createhow3_u.obj_attributes.size.set_it = TRUE;
+	    argcr.how.createhow3_u.obj_attributes.size.size._p._u =
+							(uint32_t) 0;
+	    argcr.how.createhow3_u.obj_attributes.size.size._p._l =
+							(uint32_t) 0;
+
+	    (void) memset((char *) &repcr.resok.obj.handle, '\0',
+							sizeof (nfs_fh3));
+	    verror(VAL_VERBOSE, I, "validating create file %s ...\n",
+		    Cur_filename);
+	    val_op_create(&argcr, &repcr);
+
+	    if (repcr.status == NFS3_OK) {
+		Cur_file_ptr->state = Exists;
+		(void) memmove((char *) &Cur_file_ptr->fh3,
+				(char *) &repcr.resok.obj.handle,
+				sizeof (nfs_fh3));
+		(void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+		(void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &repcr.resok.obj_attributes.attr,
+				sizeof(Cur_file_ptr->attributes3));
+		(void) compare_sattr(Ops[CREATE].name, Io_files[filenum].file_name,
+					&argcr.how.createhow3_u.obj_attributes,
+					&Cur_file_ptr->attributes3);
+	    } else {
+		Cur_file_ptr->state = Nonexistent;
+		errno = (int)repcr.status;
+		verror(VAL_BATCH, E, "create %s failed: %m\n",
+			  Cur_filename);
+		/*
+		 * An error in file creation is fatal, because we use the
+		 * created files to validate the other operations.
+		 */
+		validate_exit();
+	    }
+
+	} else if (filenum < NUMREGFILES + NUMDIRS) {
+
+	    (void) sprintf(Cur_filename, Dirspec, filenum - NUMREGFILES);
+
+	    /* directory creation */
+	    (void) memmove((char *) &argmk.where.dir, (char *) &Export_dir.fh3,
+			sizeof (nfs_fh3));
+	    argmk.where.name = Cur_filename;
+	    argmk.attributes.mode.set_it = TRUE;
+	    argmk.attributes.mode.mode = (NFSMODE_DIR | 0777);
+	    argmk.attributes.uid.set_it = TRUE;
+	    argmk.attributes.uid.uid = Cur_uid;
+	    argmk.attributes.gid.set_it = TRUE;
+	    argmk.attributes.gid.gid = Cur_gid;
+	    argmk.attributes.size.set_it = FALSE;
+	    argmk.attributes.size.size._p._u = (uint32_t) 0;
+	    argmk.attributes.size.size._p._l = (uint32_t) 0;
+	    argmk.attributes.atime.set_it = TRUE;
+	    argmk.attributes.atime.atime.seconds = Cur_time.esec;
+	    argmk.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+	    argmk.attributes.mtime.set_it = TRUE;
+	    argmk.attributes.mtime.mtime.seconds = Cur_time.esec;
+	    argmk.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+
+	    (void) memset((char *) &repmk.resok.obj.handle, '\0', sizeof (nfs_fh3));
+	    verror(VAL_VERBOSE, I, "validating mkdir %s ...\n", Cur_filename);
+	    val_op_mkdir(&argmk, &repmk);
+
+	    if (repmk.status == NFS3_OK) {
+		Cur_file_ptr->state = Exists;
+		(void) memmove((char *) &Cur_file_ptr->fh3,
+				(char *) &repmk.resok.obj.handle,
+				sizeof (nfs_fh3));
+		(void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+		(void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &repmk.resok.obj_attributes.attr,
+				sizeof(Cur_file_ptr->attributes3));
+		(void) compare_sattr(Ops[MKDIR].name, Io_files[filenum].file_name,
+			        &argmk.attributes, &Cur_file_ptr->attributes3);
+	    } else {
+		Cur_file_ptr->state = Nonexistent;
+		verror(VAL_BATCH, W, "mkdir %s failed:%m\n", Cur_filename);
+	    }
+
+	} else if (filenum < NUMREGFILES + NUMDIRS + NUMLINKS ) {
+
+	    (void) sprintf(Cur_filename, Filespec, filenum - NUMDIRS);
+
+	    /* hard link creation */
+	    target_filenum = NUMFILES-NUMSYMLINKS-1-filenum;
+	    (void) memmove((char *) &argln.file,
+			(char *) &Io_files[target_filenum].fh3,
+			sizeof (nfs_fh3));
+	    (void) memmove((char *) &argln.link.dir, (char *) &Export_dir.fh3,
+			sizeof (nfs_fh3));
+	    argln.link.name = Cur_filename;
+
+	    verror(VAL_VERBOSE, I, "validating link %s %s ...\n",
+		    Io_files[target_filenum].file_name, Cur_filename);
+	    val_op_link(&argln, &repln);
+
+	    if (repln.status == NFS3_OK) {
+		Cur_file_ptr->state = Exists;
+		(void) memmove((char *) &Cur_file_ptr->fh3,
+				(char *) &Io_files[target_filenum].fh3,
+				sizeof (nfs_fh3));
+		(void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+		Cur_file_ptr->attributes3 = Io_files[target_filenum].attributes3;
+		Io_files[target_filenum].attributes3.nlink++;
+		Cur_file_ptr->attributes3.nlink++;
+	    } else {
+		Cur_file_ptr->state = Nonexistent;
+		verror(VAL_BATCH, W, "link %s failed: %m\n", Cur_filename);
+		exit(1);
+	    }
+
+	} else {
+
+	    (void) sprintf(Cur_filename, Symspec, filenum -
+					(NUMREGFILES + NUMDIRS + NUMLINKS));
+
+	    /* symbolic link creation */
+	    target_filenum = NUMFILES-1-filenum;
+	    (void) memmove((char *) &argsl.where.dir, (char *) &Export_dir.fh3,
+			sizeof (nfs_fh3));
+	    argsl.where.name = Cur_filename;
+	    (void) sprintf(sl_target_path,
+			   "./%s", Io_files[target_filenum].file_name);
+	    argsl.symlink.symlink_attributes.size.set_it = TRUE;
+	    argsl.symlink.symlink_attributes.size.size._p._u =
+					(uint32_t) 0;
+	    argsl.symlink.symlink_attributes.size.size._p._l =
+					(uint32_t) strlen(sl_target_path);
+	    argsl.symlink.symlink_data = sl_target_path;
+	    argsl.symlink.symlink_attributes.mode.set_it = TRUE;
+	    argsl.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
+	    argsl.symlink.symlink_attributes.uid.set_it = TRUE;
+	    argsl.symlink.symlink_attributes.uid.uid = Cur_uid;
+	    argsl.symlink.symlink_attributes.gid.set_it = TRUE;
+	    argsl.symlink.symlink_attributes.gid.gid = Cur_gid;
+	    argsl.symlink.symlink_attributes.atime.set_it = TRUE;
+	    argsl.symlink.symlink_attributes.atime.atime.seconds =
+							Cur_time.esec;
+	    argsl.symlink.symlink_attributes.atime.atime.nseconds =
+							Cur_time.usec * 1000;
+	    argsl.symlink.symlink_attributes.mtime.set_it = TRUE;
+	    argsl.symlink.symlink_attributes.mtime.mtime.seconds =
+							Cur_time.esec;
+	    argsl.symlink.symlink_attributes.mtime.mtime.nseconds =
+							Cur_time.usec * 1000;
+
+	    verror(VAL_VERBOSE, I, "validating symlink %s %s ...\n",
+		    sl_target_path, Cur_filename);
+	    val_op_symlink(&argsl, &repsl);
+
+	    if (repsl.status == NFS3_OK) {
+		Cur_file_ptr->state = Exists;
+
+		/* do a lookup to get file handle and attributes */
+		(void) memmove((char *) &arglp.what.dir, (char *) &Export_dir.fh3,
+				sizeof (nfs_fh3));
+		arglp.what.name = Cur_filename;
+		(void) memset((char *) &replp.resok.object, '\0', sizeof (nfs_fh3));
+
+		val_op_lookup(&arglp, &replp);
+
+		if (replp.status == NFS3_OK) {
+		    (void) memmove((char *) &Cur_file_ptr->fh3,
+				(char *) &replp.resok.object,
+				sizeof (nfs_fh3));
+		    (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
+		    (void) memmove((char *) &Cur_file_ptr->attributes3,
+				(char *) &replp.resok.obj_attributes.attr,
+				sizeof (Cur_file_ptr->attributes3));
+		    (void) compare_sattr(Ops[SYMLINK].name,
+			                Io_files[filenum].file_name,
+			                &argsl.symlink.symlink_attributes,
+			                &Cur_file_ptr->attributes3);
+		} else {
+		    verror(VAL_BATCH, W, "lookup %s failed: %m\n",
+			    Cur_filename);
+		    continue;
+		}
+
+		/* validate readlink */
+		(void) memmove((char *) &argrl.symlink,
+				(char *) &Cur_file_ptr->fh3,
+				sizeof (nfs_fh3));
+		reprl.resok.data = sym_data;
+
+		verror(VAL_VERBOSE, I, "validating readlink %s ...\n",
+			Cur_filename);
+		val_op_readlink(&argrl, &reprl);
+
+		if (reprl.status == NFS3_OK) {
+		    if (strcmp(sl_target_path, sym_data)) {
+			verror(VAL_BATCH, W,
+			    "readlink %s error, result = %s, should be %s\n",
+			    Cur_filename, reprl.resok.data,
+			    sl_target_path);
+		    }
+		} else {
+		    verror(VAL_BATCH, W, "readlink %s failed:%m\n",
+			    Cur_filename);
+		}
+
+	    } else {
+		Cur_file_ptr->state = Nonexistent;
+		verror(VAL_BATCH, W, "symlink %s failed: %m\n", Cur_filename);
+	    }
+	}
+    } /* end for each file */
+
+} /* validate_creation */
+
+
+static void
+validate_attributes(void)
+{
+    int                 filenum;
+    LOOKUP3args		arglp;
+    LOOKUP3res		replp;
+    GETATTR3args	argga;
+    GETATTR3res		repga;
+    SETATTR3args	argsa;
+    SETATTR3res		repsa;
+
+    /* validate fsstat */
+
+    /* validate lookup */
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+	(void) memmove((char *) &arglp.what.dir, (char *) &Export_dir.fh3,
+			sizeof (nfs_fh3));
+	arglp.what.name = Io_files[filenum].file_name;
+	(void) memset((char *) &replp.resok.object, '\0', sizeof (nfs_fh3));
+
+	verror(VAL_VERBOSE, I, "validating lookup %s ...\n",
+		Io_files[filenum].file_name);
+	val_op_lookup(&arglp, &replp);
+
+	if (replp.status == NFS3_OK) {
+	    if (memcmp((char *) &(Io_files[filenum].fh3),
+		     (char *) &(replp.resok.object), sizeof (nfs_fh3))) {
+		verror(VAL_BATCH, W, "lookup %s: file handle mismatch\n",
+				Io_files[filenum].file_name);
+		exit(1);
+	    }
+	    (void) compare_fattr(Ops[LOOKUP].name, Io_files[filenum].file_name,
+					&Io_files[filenum].attributes3,
+					&replp.resok.obj_attributes.attr);
+	} else {
+	    verror(VAL_BATCH, W, "lookup %s failed:%m\n",
+		    Io_files[filenum].file_name);
+	}
+    }
+
+    /* validate getattr */
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+	(void) memmove((char *) &argga.object,
+			(char *) &Io_files[filenum].fh3,
+			sizeof (nfs_fh3));
+
+	verror(VAL_VERBOSE, I, "validating getattr %s ...\n",
+		Io_files[filenum].file_name);
+	val_op_getattr(&argga, &repga);
+
+	if (repga.status == NFS3_OK) {
+	    (void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
+			  &Io_files[filenum].attributes3,
+			  &repga.resok.obj_attributes);
+	} else {
+	    verror(VAL_BATCH, W, "getattr %s failed: %m\n",
+		    Io_files[filenum].file_name);
+	}
+    }
+
+    /*validate setattr */
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+	sfs_gettime(&Cur_time);
+	(void) memmove((char *) &argsa.object,
+			(char *) &Io_files[filenum].fh3,
+			sizeof (nfs_fh3));
+	argsa.new_attributes.mode.set_it = TRUE;
+	if (filenum >= NUMREGFILES && filenum < NUMREGFILES + NUMDIRS)
+	  argsa.new_attributes.mode.mode = 0777;
+	else
+	  argsa.new_attributes.mode.mode = 0666;
+	argsa.new_attributes.uid.set_it = FALSE;
+	argsa.new_attributes.uid.uid = 0;
+	argsa.new_attributes.gid.set_it = FALSE;
+	argsa.new_attributes.gid.gid = 0;
+	argsa.new_attributes.size.set_it = FALSE;
+	argsa.new_attributes.size.size._p._u = 0;
+	argsa.new_attributes.size.size._p._l = 0;
+	argsa.new_attributes.atime.set_it = TRUE;
+	argsa.new_attributes.atime.atime.seconds = Cur_time.esec;
+	argsa.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
+	argsa.new_attributes.mtime.set_it = TRUE;
+	argsa.new_attributes.mtime.mtime.seconds = Cur_time.esec;
+	argsa.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
+	argsa.guard.check = FALSE;
+
+	verror(VAL_VERBOSE, I, "validating setattr %s ...\n",
+				Io_files[filenum].file_name);
+	val_op_setattr(&argsa, &repsa);
+
+	if (repsa.status == NFS3_OK) {
+	    (void) memmove((char *) &Io_files[filenum].attributes3,
+				(char *) &repsa.resok.obj_wcc.after.attr,
+				sizeof (Io_files[filenum].attributes3));
+	    (void) compare_sattr(Ops[SETATTR].name, Io_files[filenum].file_name,
+			&argsa.new_attributes, &repsa.resok.obj_wcc.after.attr);
+
+	    (void) memmove((char *) &argga.object,
+				(char *) &Io_files[filenum].fh3,
+				sizeof (nfs_fh3));
+
+	    val_op_getattr(&argga, &repga);
+
+	    if (repga.status == NFS3_OK) {
+		(void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
+						&Io_files[filenum].attributes3,
+						&repga.resok.obj_attributes);
+	    } else {
+		verror(VAL_BATCH, W, "getattr %s failed: %m\n",
+			Io_files[filenum].file_name);
+	    }
+	} else {
+	    verror(VAL_BATCH, W, "setattr %s failed: %m\n",
+		    Io_files[filenum].file_name);
+	    exit(1);
+	}
+    }
+
+} /* validate_attributes */
+
+#define WAITFOREOF 1
+/*
+ * need to check if readdirplus returns a reasonable amount of data.
+ */
+static void
+val_rddirplus_retsize(uint32_t dircount, uint32_t maxcount,
+                      READDIRPLUS3resok *rp)
+{
+    entryplus3 *esp;
+    static int eof_wait = 0;
+    int i;
+    int size = 0;
+    int tsize = 0;
+    int msize = 0;
+    double mpcnt = 0;
+
+    esp = rp->reply.entries;
+
+    for (i = 0; i < rp->count; i++) {
+            size += sizeof(esp[i].fileid);
+            size += strlen(esp[i].name) * sizeof(char);
+            size += sizeof(esp[i].cookie);
+            tsize += sizeof(esp[i].name_attributes);
+            tsize += sizeof(esp[i].name_handle.handle_follows);
+            tsize += esp[i].name_handle.handle.fh3_length * sizeof(char);
+    }
+
+    msize = size + tsize;
+    mpcnt = (double) msize / (double) maxcount * 100;
+
+    if (rp->reply.eof) {
+        verror(VAL_VERBOSE, I, "readdirplus on %s returned EOF.\n"
+    "\treceived %d bytes of directory information and %d bytes including\n"
+    "\tpost op attributes and filehandle.\n",
+               Testdirname, size, msize);
+    } else if (mpcnt < 80) {
+    	eof_wait++;
+        if (eof_wait > WAITFOREOF) {
+            verror(VAL_BATCH, E,
+    "readdirplus on %s did not return a reasonable amount of data.\n"
+    "\treceived %d bytes. should receive close to %d bytes.\n",
+		   Testdirname, msize, maxcount);
+	} else {
+	    verror(VAL_VERBOSE, I, "readdirplus on %s did not return EOF.\n"
+    "\treceived %d bytes of directory information and %d bytes including\n"
+    "\tpost op attributes and filehandle.\n",
+		   Testdirname, size, msize);
+	}
+    } else {
+        verror(VAL_VERBOSE, I, "readdirplus on %s did not return EOF.\n"
+    "\treceived %d bytes of directory information and %d bytes including\n"
+    "\tpost op attributes and filehandle.\n",
+               Testdirname, size, msize);
+    }    
+}
+
+static void
+validate_read_write(void)
+{
+    struct {
+	uint16_t  sum;                    /* checksum of data */
+	uint16_t  len;                    /* length of len and data */
+	char            data[DEFAULT_MAX_BUFSIZE - 2 * sizeof(uint16_t)];
+    } block;
+    WRITE3args		argwr;
+    WRITE3res		repwr;
+    READ3args		argrd;
+    READ3res		reprd;
+    READDIR3args	argdr;
+    READDIR3res		repdr;
+    READDIRPLUS3args    argdrp;
+    READDIRPLUS3res     repdrp;
+    int                 maxblks;
+    int                 maxfiles;
+    int                 i;
+    int                 numfiles;
+    int                 filenum;
+    int                 blocknum;
+    entry3              entry_stream[SFS_MAXDIRENTS];
+    entryplus3          entryplus_stream[SFS_MAXDIRENTS];
+
+    /* validate write */
+
+    /* get the maximum number of blocks sfs will write */
+    maxblks = Io_dist_ptr->max_bufs;
+    maxfiles = maxblks > NUMREGFILES ? NUMREGFILES : maxblks;
+
+    /* write maxblks - filenum + 1 blocks to each regular file */
+    argwr.offset._p._u = argwr.offset._p._l = (uint32_t) 0;
+    argwr.stable = FILE_SYNC;
+    argwr.data.data_val = (char *)&block;
+
+    for (blocknum = 0; blocknum <= maxblks ; blocknum++) {
+
+	for (i=0; i < sizeof(block.data); i++)
+	    block.data[i] = (char)blocknum;
+
+	for (filenum=0; filenum < maxfiles; filenum++) {
+	    /* Write fewer blocks to files with higher numbers. */
+	    if (blocknum > (maxblks - filenum))
+		break;
+
+	    /* set the length field */
+	    if (blocknum == (maxblks - filenum)) {
+		block.len = ((maxfiles - filenum) *
+		        (Bytes_per_block/Kb_per_block)) - (sizeof(block.len) + 
+							   sizeof(block.sum));
+		/*
+                 * XXX - write kludge.
+                 *
+                 * Writes must be less than 8K in
+                 * size or else the checksum will incur a buffer overflow
+                 */
+                block.len = (block.len % DEFAULT_MAX_BUFSIZE) -
+                        (sizeof(block.len) + sizeof(block.sum));
+	    } else {
+		block.len = Bytes_per_block - (sizeof(block.len)
+			    + sizeof(block.sum));
+	    }
+	    block.sum = sum((unsigned char *) &block.len,
+			    (int)(block.len + sizeof(block.len)));
+
+	    (void) memmove((char *) &argwr.file,
+				(char *) &Io_files[filenum].fh3,
+				sizeof (nfs_fh3));
+	    argwr.data.data_len = block.len +
+			          sizeof(block.len) + sizeof(block.sum);
+	    argwr.count = argwr.data.data_len;
+
+	    verror(VAL_VERBOSE, I,
+		    "validating write %d bytes @ offset %lu to %s ...\n",
+		    argwr.data.data_len, argwr.offset._p._l,
+		    Io_files[filenum].file_name);
+
+	    val_op_write(&argwr, &repwr);
+
+	    if (repwr.status == NFS3_OK) {
+		(void) compare_fattr(Ops[WRITE].name, Io_files[filenum].file_name,
+			      &Io_files[filenum].attributes3,
+			      &repwr.resok.file_wcc.after.attr);
+		Io_files[filenum].attributes3 = repwr.resok.file_wcc.after.attr;
+                /*
+                 * XXX-bookeeping kludge.
+                 *
+                 * Need to update hardlink attributes, so readdirplus vali-
+                 * dation doesn't barf.  This is necessary because setattr was
+                 * validated on all the test files and the attributes in
+                 * Io_files[] were updated accordingly.  Since the write
+                 * op has been validated on just the regular files, we have to
+                 * make sure that the corresponding indexes in Io_files[] that
+                 * point to the hard links reflect the current file attributes.
+                 */
+                if (filenum < NUMLINKS) {
+                    Io_files[NUMREGFILES+NUMDIRS+NUMLINKS-1-filenum].attributes3 = Io_files[filenum].attributes3;
+                }
+
+	    } else {
+		verror(VAL_BATCH, W, "write %s failed: %m\n",
+			Io_files[filenum].file_name);
+	    }
+	}
+	argwr.offset._p._l += Bytes_per_block;
+    }
+
+    /* validate read */
+
+    for (filenum = 0; filenum < maxfiles; filenum++) {
+	(void) memmove((char *) &argrd.file,
+			(char *) &Io_files[filenum].fh3,
+			sizeof (nfs_fh3));
+	argrd.offset._p._u = argrd.offset._p._l = (uint32_t) 0;
+	argrd.count = 0;
+	reprd.resok.data.data_len = 0;
+	maxblks = Io_files[filenum].attributes3.size._p._l / Bytes_per_block;
+	for (blocknum = 0; blocknum <= maxblks; blocknum ++) {
+
+	    if (argrd.count != reprd.resok.data.data_len) {
+		argrd.count -= reprd.resok.data.data_len;
+		reprd.resok.data.data_val = (char *)&block +
+			                reprd.resok.data.data_len;
+		blocknum--;
+	    } else {
+		if (blocknum < maxblks)
+		    argrd.count = Bytes_per_block;
+		else
+		    argrd.count = (maxfiles - filenum)
+			          * (Bytes_per_block/Kb_per_block);
+		reprd.resok.data.data_val = (char *)&block;
+	    }
+
+	    verror(VAL_VERBOSE, I,
+		   "validating read %lu bytes @ offset %lu from %s ...\n",
+		    argrd.count, argrd.offset._p._l,
+		    Io_files[filenum].file_name);
+
+	    val_op_read(&argrd, &reprd);
+
+	    if (reprd.status == NFS3_OK) {
+		(void) compare_fattr(Ops[READ].name, Io_files[filenum].file_name,
+			      &Io_files[filenum].attributes3,
+			      &reprd.resok.file_attributes.attr);
+		Io_files[filenum].attributes3 = reprd.resok.file_attributes.attr;
+		argrd.offset._p._l += reprd.resok.data.data_len;
+	    } else {
+		verror(VAL_BATCH, W, "read %s failed: %m\n",
+			Io_files[filenum].file_name);
+	    }
+
+	    if ((argrd.count ==
+		(block.sum != sum((unsigned char *) &block.len,
+			          (int)(block.len + sizeof(block.len)))))) {
+		verror(VAL_BATCH, W, "read %s checksum mismatch\n",
+			Io_files[filenum].file_name);
+	    }
+	}
+    }
+
+    /* validate readdir */
+    (void) memmove((char *) &argdr.dir, (char *) &Export_dir.fh3,
+			sizeof (nfs_fh3));
+    argdr.cookie._p._l = argdr.cookie._p._u = (uint32_t) 0;
+    (void) memset((char *) argdr.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+    argdr.count = DEFAULT_MAX_BUFSIZE;
+
+    do {
+        (void) memset((char *) entry_stream, '\0', sizeof (entry3) * SFS_MAXDIRENTS);
+        (void) memset((char *) &repdr, '\0', sizeof(repdr));
+        repdr.resok.count = SFS_MAXDIRENTS;
+        repdr.resok.reply.entries = entry_stream;
+	verror(VAL_VERBOSE, I, "validating readdir on %s ...\n", Testdirname);
+	val_op_readdir(&argdr, &repdr);
+
+
+	if (repdr.status == NFS3_OK) {
+            for (i = 0; i < repdr.resok.count; i++) {
+                for (filenum = 0; filenum < NUMFILES; filenum++) {
+                    if (!strcmp(entry_stream[i].name, Io_files[filenum].file_name)) {                        if (entry_stream[i].fileid._p._l !=
+                                    Io_files[filenum].attributes3.fileid._p._l) {
+                            verror(VAL_BATCH, E,
+                                "readdir %s error: file %s fileid mismatch\n",
+                                Testdirname, entry_stream[i].name);
+                            verror(VAL_BATCH, W,
+                                "   fileid: got = %lu, original = %lu\n",
+                                entry_stream[i].fileid._p._l,
+                                Io_files[filenum].attributes3.fileid._p._l);
+                        }
+                        /*
+                         * mark file as either found or dup
+                         */
+                        if (check_files[filenum].file_found &&
+                            !check_files[filenum].file_is_dup)
+                                check_files[filenum].file_is_dup = 1;
+                        else
+                                check_files[filenum].file_found = 1;
+                        break;
+                    }
+                }
+            }
+        } else {
+            verror(VAL_BATCH, W, "readdir %s failed: %m\n", Testdirname);
+        }
+
+	argdr.cookie = entry_stream[repdr.resok.count-1].cookie;
+
+    } while (repdr.resok.reply.eof == 0);
+
+    /*
+     * check if any known files have not been found
+     */
+    for (i = 0; i < NUMFILES; i++) {
+        if (!check_files[i].file_found)
+                verror(VAL_BATCH, E,
+                       "readdir %s error: file %s not found\n",
+                       Testdirname, Io_files[i].file_name);
+        else {
+                if (check_files[i].file_is_dup)
+                    verror(VAL_BATCH, E,
+              "readdir %s error: file %s returned more than once\n",
+                           Testdirname, Io_files[i].file_name);
+        }
+    }
+
+    /* validate readdirplus */
+    (void) memset((void *) check_files, '\0', sizeof(check_files));
+
+    argdrp.cookie._p._l = argdrp.cookie._p._u = (uint32_t) 0;
+    (void) memmove((char *) &argdrp.dir, (char *) &Export_dir.fh3,
+                   sizeof (nfs_fh3));
+    (void) memset((char *) argdrp.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
+    /*
+     * We validate readdirplus with dircount and maxcount both set at 8K.
+     * This is not the most efficient way, but this is how readdirplus is
+     * called in SFS.  With the numbers set as such, maxcount becomes the
+     * bottleneck and we will not get 8K worth of directory info.  What we
+     * should get is 8K worth which includes directory info plus post_op_
+     * attributes and filehandle.
+     */
+    argdrp.dircount = DEFAULT_MAX_BUFSIZE;
+    argdrp.maxcount = DEFAULT_MAX_BUFSIZE;
+    do {
+        (void) memset((char *) entryplus_stream, '\0',
+                      sizeof (entryplus_stream));
+
+        (void) memset((char *) &repdrp, '\0', sizeof(repdrp));
+        repdrp.resok.count = SFS_MAXDIRENTS;
+        repdrp.resok.reply.entries = entryplus_stream;
+
+        verror(VAL_VERBOSE, I, "validating readdirplus on %s ...\n",
+                Testdirname);
+        val_op_readdirplus(&argdrp, &repdrp);
+
+        if (repdrp.status == NFS3_OK) {
+            verror(VAL_VERBOSE, I, "readdirplus found %d entries in %s...\n",
+                   repdrp.resok.count, Testdirname);
+            val_rddirplus_retsize(argdrp.dircount, argdrp.maxcount,
+                                  &repdrp.resok);
+            for (i = 0; i < repdrp.resok.count; i++) {
+                for (filenum = 0; filenum < NUMFILES; filenum++) {
+                    if (!strcmp(entryplus_stream[i].name,
+                                Io_files[filenum].file_name)) {
+                        if (entryplus_stream[i].fileid._p._l !=
+                            Io_files[filenum].attributes3.fileid._p._l) {
+                            verror(VAL_BATCH, E,
+                        "readdirplus %s error: file %s fileid mismatch\n",
+                                   Testdirname, entryplus_stream[i].name);
+                            verror(VAL_BATCH, W,
+                                "   fileid: got = %lu, original = %lu\n",
+                                   entryplus_stream[i].fileid._p._l,
+                                   Io_files[filenum].attributes3.fileid._p._l);
+                        }
+
+                        /*
+                         * mark file as either found or dup
+                         */
+                        if (check_files[filenum].file_found &&
+                            !check_files[filenum].file_is_dup)
+                                check_files[filenum].file_is_dup = 1;
+                        else
+                                check_files[filenum].file_found = 1;
+
+			/*
+                         * check to make sure post op attributes and
+                         * file handle are returned.
+                         */
+                        if (!entryplus_stream[i].name_attributes.attributes)
+                                verror(VAL_BATCH, E,
+                "readdirplus %s warning: did not receive post op attributes for file %s\n\n",
+                                       Testdirname, entryplus_stream[i].name);
+                        else
+                            (void) compare_fattr(Ops[READDIRPLUS].name,
+                                                 Io_files[filenum].file_name,
+                                                 &Io_files[filenum].attributes3,                                                 &entryplus_stream[i].name_attributes.attr);
+
+                        if (!entryplus_stream[i].name_handle.handle_follows)
+                                verror(VAL_BATCH, E,
+                "readdirplus %s warning: did not receive file handle for file %s\n\n",
+                                       Testdirname, entryplus_stream[i].name);
+                        else
+                            if (memcmp((void *) &Io_files[filenum].fh3.fh3_u.data,
+                                       (void *) &entryplus_stream[i].name_handle.handle.fh3_u.data, Io_files[filenum].fh3.fh3_length) != 0)
+                                   verror(VAL_BATCH, E,
+                "readdirplus %s error: file %s, filehandles do not match\n\n",
+                                          Testdirname, entryplus_stream[i].name);
+                        break;
+                    }
+                }
+            }
+        } else {
+            verror(VAL_BATCH, W, "readdirplus %s failed: %m\n", Testdirname);
+        }
+        argdrp.cookie = entryplus_stream[repdrp.resok.count-1].cookie;
+
+    } while (repdrp.resok.reply.eof == 0);
+    /*
+     * check if any known files have not been found
+     */
+    for (i = 0; i < NUMFILES; i++) {
+        if (!check_files[i].file_found)
+                verror(VAL_BATCH, E,
+                       "readdirplus %s error: file %s not found\n",
+                       Testdirname, Io_files[i].file_name);
+        else {
+                if (check_files[i].file_is_dup)
+                    verror(VAL_BATCH, E,
+              "readdirplus %s error: file %s returned more than once\n",
+                           Testdirname, Io_files[i].file_name);
+        }
+    }   
+} /* validate_read_write */
+
+
+static void
+validate_rename(void)
+{
+    RENAME3args argrn;
+    RENAME3res  reprn;
+    int         filenum;
+    char        newname[SFS_MAXNAMLEN];
+    int         rncount = 0;
+
+    (void) memmove((char *) &argrn.from.dir, (char *) &Export_dir.fh3,
+			sizeof (nfs_fh3));
+    (void) memmove((char *) &argrn.to.dir, (char *) &Export_dir.fh3,
+		sizeof (nfs_fh3));
+
+    for (filenum=0; filenum < NUMFILES; filenum++) {
+	if (Io_files[filenum].state != Exists)
+	    continue;
+
+	rncount++;
+	(void) sprintf(newname, "n%s", Io_files[filenum].file_name);
+	argrn.from.name = Io_files[filenum].file_name;
+	argrn.to.name = newname;
+
+	verror(VAL_VERBOSE, I, "validating rename %s %s ...\n",
+		argrn.from.name, argrn.to.name);
+
+	val_op_rename(&argrn, &reprn);
+
+	if (reprn.status == NFS3_OK) {
+	    (void) strcpy(Io_files[filenum].file_name, newname);
+	} else {
+	    verror(VAL_BATCH, W, "rename %s to %s failed: %m\n",
+		    Io_files[filenum].file_name, newname);
+	}
+
+    }
+
+    if (!rncount) {
+	verror(VAL_BATCH, E, "validate_rename: no files renamed\n");
+	verror(VAL_BATCH, W, "    due to previous operation error\n");
+    }
+
+} /* validate_rename */
+
+
+static int
+compare_fattr(
+    char *      op,
+    char *      fname,
+    fattr3 *     attr1,
+    fattr3 *     attr2)
+{
+    int         ret = TRUE;
+    int         prev_warn = FALSE; /* -1 info warning */
+    int         flag_error = FALSE;
+
+    if (attr1->type != attr2->type) {
+	if (attr1->type == 0xFFFFFFFF) {
+	    prev_warn = TRUE;
+	    if (ret) {
+		verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+		    fname, op);
+	    }
+	    verror(VAL_BATCH, I, "    type: current = %d, previous =  %d\n",
+		   attr2->type, attr1->type);
+	    attr1->type = attr2->type;
+	    ret = FALSE;
+	}
+	else {
+		if (ret) {
+			verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			    fname, op);
+		}
+		verror(VAL_BATCH, E, "    type: current = %d, previous =  %d\n",
+			attr2->type, attr1->type);
+		ret = FALSE;
+		flag_error = TRUE;
+	}
+    }
+
+    if ((attr1->mode & NFSMODE_MASK) != (attr2->mode & NFSMODE_MASK)) {
+	if (attr1->mode == (unsigned int)0xFFFFFFFF) {
+		prev_warn = TRUE;
+		if (ret) {
+			verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			        fname, op);
+		}
+		verror(VAL_BATCH, I, "    mode: current = %7lo, previous =  %7lo\n",
+			attr2->mode, attr1->mode);
+		attr1->mode =  attr2->mode;
+		ret = FALSE;
+	}
+	else {
+		if (ret) {
+			verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			    fname, op);
+		}
+		verror(VAL_BATCH, E, "    mode: current = %7lo, previous =  %7lo\n",
+                        attr2->mode, attr1->mode);
+		ret = FALSE;
+		flag_error = TRUE;
+	}
+    }
+
+    if (attr1->nlink != attr2->nlink) {
+	if (attr1->nlink == (unsigned int)0xFFFFFFFF) {
+		prev_warn = TRUE;
+		if (ret) {
+			verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			        fname, op);
+		}
+		verror(VAL_BATCH, I,
+			"    nlink: current = %lu, previous =  %lu\n",
+			attr2->nlink, attr1->nlink);
+		ret = FALSE;
+		attr1->nlink =  attr2->nlink;
+	}
+	else {
+		if (ret) {
+			verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			    fname, op);
+		}
+		verror(VAL_BATCH, E,
+			"    nlink: current = %lu, previous =  %lu\n",
+			attr2->nlink, attr1->nlink);
+		ret = FALSE;
+		flag_error = TRUE;
+	}
+    }
+
+
+    /*
+     * Check for user "nobody", UID -2, which may be untranslated from
+     * sixteen-bit two's complement.
+     */
+    if (attr1->uid != attr2->uid && !((attr2->uid == (unsigned int)0xFFFFFFFE ||
+	attr2->uid == 65534) && attr1->uid ==0)) {
+	if (attr1->uid == (unsigned int)0xFFFFFFFF) {
+		prev_warn = TRUE;
+		if (ret) {
+			verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			        fname, op);
+		}
+		verror(VAL_BATCH, I,
+			"    uid: current = %lu, previous =  %lu\n",
+			attr2->uid, attr1->uid);
+		attr1->uid =  attr2->uid;
+		ret = FALSE;
+	}
+	else {
+		if (ret) {
+			verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			    fname, op);
+		}
+		verror(VAL_BATCH, E,
+			"    uid: current = %lu, previous =  %lu\n",
+			attr2->uid, attr1->uid);
+		ret = FALSE;
+		flag_error = TRUE;
+	}
+    }
+
+    if (attr1->gid != attr2->gid && attr2->gid != 0) {
+/*
+    if (attr1->gid != attr2->gid) {
+*/
+	if (attr1->gid == (unsigned int)0xFFFFFFFF) {
+		prev_warn = TRUE;
+		if (ret) {
+			verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			        fname, op);
+		}
+		verror(VAL_BATCH, I,
+			"    gid: current = %lu, previous =  %lu\n",
+			attr2->gid, attr1->gid);
+		attr1->gid =  attr2->gid;
+		ret = FALSE;
+	}
+	else {
+		if (ret) {
+			verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			    fname, op);
+		}
+		verror(VAL_BATCH, E,
+			"    gid: current = %lu, previous =  %lu\n",
+			attr2->gid, attr1->gid);
+		ret = FALSE;
+		flag_error = TRUE;
+	}
+    }
+
+    if (attr1->size._p._l != attr2->size._p._l) {
+	if (strcmp(op, Ops[WRITE].name)) {
+	    if (attr1->size._p._l == (unsigned int)0xFFFFFFFF) {
+		prev_warn = TRUE;
+		if (ret) {
+			verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			        fname, op);
+		}
+		verror(VAL_BATCH, I,
+			"    size: current = %lu, previous =  %lu\n",
+			attr2->size._p._l, attr1->size._p._l);
+		attr1->size._p._l =  attr2->size._p._l;
+		ret = FALSE;
+	    }
+	    else {
+		if (ret) {
+			verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			    fname, op);
+		}
+		verror(VAL_BATCH, E,
+			"    size: current = %lu, previous =  %lu\n",
+			attr2->size._p._l, attr1->size._p._l);
+		ret = FALSE;
+		flag_error = TRUE;
+	    }
+	}
+    }
+
+    /* compare rdev only if type == NFCHR or NFBLK */
+    if ((attr1->type == NF3CHR || attr1->type == NF3BLK) &&
+			(attr1->rdev.specdata1 != attr2->rdev.specdata1 ||
+			attr1->rdev.specdata2 != attr2->rdev.specdata2)) {
+	if (attr1->rdev.specdata1 == (unsigned int)0xFFFFFFFF) {
+	     prev_warn = TRUE;
+	     if (ret) {
+		     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			     fname, op);
+	     }
+	     verror(VAL_BATCH, I,
+			"    rdev: current = %lu %lu, previous =  %lu %lu\n",
+			attr2->rdev.specdata1, attr2->rdev.specdata2,
+			attr1->rdev.specdata1, attr1->rdev.specdata2);
+	     attr1->rdev.specdata1 =  attr2->rdev.specdata1;
+	     attr1->rdev.specdata2 =  attr2->rdev.specdata2;
+	     ret = FALSE;
+	}
+	else {
+	     if (ret) {
+		     verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			 fname, op);
+	     }
+	     verror(VAL_BATCH, E,
+			"    rdev: current = %lu %lu, previous =  %lu %lu\n",
+			attr2->rdev.specdata1, attr2->rdev.specdata2,
+			attr1->rdev.specdata1, attr1->rdev.specdata2);
+	     ret = FALSE;
+	     flag_error = TRUE;
+	}
+    }
+
+    if (attr1->fsid._p._l != attr2->fsid._p._l) {
+	if (attr1->fsid._p._l == (unsigned int)0xFFFFFFFF) {
+	     prev_warn = TRUE;
+	     if (ret) {
+		     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			     fname, op);
+	     }
+	     verror(VAL_BATCH, I, "    fsid: current = %lu, previous =  %lu\n",
+		     attr2->fsid._p._l, attr1->fsid._p._l);
+	     attr1->fsid._p._l =  attr2->fsid._p._l;
+	     ret = FALSE;
+	}
+	else {
+	     if (ret) {
+		     verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			 fname, op);
+	     }
+	     verror(VAL_BATCH, E, "    fsid: current = %lu, previous =  %lu\n",
+		     attr2->fsid._p._l, attr1->fsid._p._l);
+	     ret = FALSE;
+		flag_error = TRUE;
+	}
+    }
+
+    if (attr1->fileid._p._l != attr2->fileid._p._l) {
+	if (attr1->fileid._p._l == (unsigned int)0xFFFFFFFF) {
+	     prev_warn = TRUE;
+	     if (ret) {
+		     verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
+			     fname, op);
+	     }
+	     verror(VAL_BATCH, I,
+			"    fileid: current = %lu, previous =  %lu\n",
+			attr2->fileid._p._l, attr1->fileid._p._l);
+	     attr1->fileid._p._l =  attr2->fileid._p._l;
+	     ret = FALSE;
+	}
+	else {
+	     if (ret) {
+		     verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+			 fname, op);
+	     }
+	     verror(VAL_BATCH, E,
+			"    fileid: current = %lu, previous =  %lu\n",
+		     attr2->fileid._p._l, attr1->fileid._p._l);
+	     ret = FALSE;
+		flag_error = TRUE;
+	}
+    }
+
+    if (prev_warn) {
+	verror(VAL_BATCH, I,
+		"\n        Warning: the previous value of a field is -1,\n");
+	verror(VAL_BATCH, I,
+		"        this resulted from an unused field returned by\n");
+	verror(VAL_BATCH, I,
+		"        the previous operation on this file/directory.\n");
+	verror(VAL_BATCH, I,
+	    "        The current value is now stored for future comparison\n\n");
+    }
+
+    if (flag_error)
+	verror(VAL_BATCH, W,"\n");
+
+    return(flag_error);
+
+} /* ckompare_fattr */
+
+
+uint32_t sattr_types[8] =	{
+			  0000000,		/* NF3NON */
+			  0100000,		/* NF3REG */
+			  0040000,		/* NF3DIR */
+			  0060000,		/* NF3BLK */
+			  0020000,		/* NF3CHR */
+			  0120000,		/* NF3LNK */
+			  0140000,		/* NF3SOCK */
+			  0010000 };		/* NF3FIFO */
+static int
+compare_sattr(
+    char *      op,
+    char *      fname,
+    sattr3 *    attr1,
+    fattr3 *    attr2)
+{
+    int         ret = TRUE;
+    char        msg[80];
+
+    msg[0] = '\0';
+
+#ifdef notyet
+    if (attr1->mode.mode.set_it == TRUE &&
+	(((attr1->mode.mode & NFSTYPE_FMT) != sattr_types[attr2->type]) &&
+	((attr1->mode.mode & NFSTYPE_FMT) != sattr_types[0]) ||
+	((attr1->mode.mode & NFSMODE_FMT) != (attr2->mode & NFSMODE_FMT)))) {
+	if (ret) {
+	    verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+						fname, op);
+
+	}
+	verror(VAL_BATCH, E, "    mode: returned = %7o, specified = %7o\n",
+				attr1->mode.mode, attr2->mode);
+	ret = FALSE;
+    }
+#endif
+
+    /*
+     * Check for user "nobody", UID -2, which may be untranslated from
+     * sixteen-bit two's complement.
+     */
+    if (attr1->uid.set_it == TRUE && attr1->uid.uid != attr2->uid &&
+                        !((attr2->uid == (unsigned int)0xFFFFFFFE ||
+						attr2->uid == 65534) &&
+						attr1->uid.uid == 0)) {
+	if (ret) {
+	    verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+						fname, op);
+	}
+	if (attr1->uid.uid == 0)
+	    (void) strcat(msg," (is root UID mapped to other UID?)");
+	verror(VAL_BATCH, E, "    uid: returned = %lu, specified = %lu %s\n",
+				attr2->uid, attr1->uid.uid, msg);
+	ret = FALSE;
+    }
+
+    if (attr1->gid.set_it == TRUE && attr1->gid.gid != attr2->gid &&
+							attr2->gid != 0) {
+/*
+   if (attr1->gid.set_it == TRUE && attr1->gid != attr2->gid) {
+*/
+	if (ret) {
+	    verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+		    fname, op);
+	}
+	verror(VAL_BATCH, E, "    gid: returned = %lu, specified = %lu\n",
+		attr2->gid, attr1->gid.gid);
+	ret = FALSE;
+    }
+
+    if (attr1->size.set_it == TRUE &&
+				attr1->size.size._p._l != attr2->size._p._l) {
+	if (ret) {
+	    verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
+		    fname, op);
+	}
+	verror(VAL_BATCH, E, "    size: returned = %lu, specified = %lu\n",
+		attr2->size._p._l, attr1->size.size._p._l);
+	ret = FALSE;
+    }
+
+    if (!ret)
+	verror(VAL_BATCH, W,"\n");
+
+    return(ret);
+
+} /* compare_sattr */
+
+
+/*
+ * Return the BSD checksum of buf[0..len-1]
+ */
+static uint16_t
+sum(
+    unsigned char *     buf,
+    int                 len)
+{
+    uint16_t      cksum;
+
+    cksum = 0;
+    for (; len--; buf++) {
+	if (cksum & 01)
+	    cksum = (cksum >> 1) + 0x8000;
+	else
+	    cksum >>= 1;
+	cksum += (uint16_t) *buf;
+	cksum &= 0xFFFF;
+    }
+    return(cksum);
+
+} /* sum */
+
+
+static void
+validate_remove(void)
+{
+    REMOVE3args	argrm;
+    REMOVE3res	reprm;
+    RMDIR3args	argrd;
+    RMDIR3res	reprd;
+    LOOKUP3args	arglp;
+    LOOKUP3res	replp;
+    nfsstat3	reply;
+    int         filenum;
+    char *      op;
+
+    for (filenum = 0; filenum < NUMFILES; filenum++) {
+
+	if (Io_files[filenum].state != Exists)
+	    continue;
+
+	if (Io_files[filenum].attributes3.type == NF3DIR) {
+	    op = Ops[RMDIR].name;
+	    verror(VAL_VERBOSE, I, "validating rmdir %s ...\n",
+		    Io_files[filenum].file_name);
+
+	    (void) memmove((char *) &argrd.object.dir,
+				(char *) &Export_dir.fh3,
+				sizeof (nfs_fh3));
+	    argrd.object.name = Io_files[filenum].file_name;
+	    val_op_rmdir(&argrd, &reprd);
+	    reply = reprd.status;
+	} else {
+	    op = Ops[REMOVE].name;
+	    verror(VAL_VERBOSE, I, "validating remove %s ...\n",
+		    Io_files[filenum].file_name);
+
+	    (void) memmove((char *) &argrm.object.dir, (char *) &Export_dir.fh3,
+				sizeof (nfs_fh3));
+	    argrm.object.name = Io_files[filenum].file_name;
+	    val_op_remove(&argrm, &reprm);
+	    reply = reprm.status;
+	}
+
+	if (reply == NFS3_OK) {
+	    /* make sure the file is removed from the directory */
+	    (void) memmove((char *) &arglp.what.dir, (char *) &Export_dir.fh3,
+				sizeof (nfs_fh3));
+	    arglp.what.name = Io_files[filenum].file_name;
+	    val_op_lookup(&arglp, &replp);
+
+	    if (replp.status == NFS3ERR_NOENT) {
+		Io_files[filenum].state = Nonexistent;
+	    } else if (replp.status == NFS3_OK) {
+		verror(VAL_BATCH, W, "%s %s: file not removed\n",
+		       op, Io_files[filenum].file_name);
+	    } else {
+		verror(VAL_BATCH, W, "lookup %s failed: %m\n",
+		       Io_files[filenum].file_name);
+
+	    }
+	} else {
+	    verror(VAL_BATCH, W, "%s %s failed: %m\n", op,
+		    Io_files[filenum].file_name);
+	}
+
+    }
+
+} /* validate_remove */
+
+
+static void
+validate_cleanup(void)
+{
+    free(Io_files);
+    free(Non_io_files);
+    free(Dirs);
+    free(Symlinks);
+    clnt_destroy(NFS_client);
+} /* validate_cleanup */
+
+
+static void
+validate_exit(void)
+{
+    if (!Validate_errors) {
+	verror(VAL_BATCH, I, "validation completed successfully.\n");
+	exit(0);
+    } else {
+	verror(VAL_BATCH, I, "validation terminated with errors\n");
+	exit(1);
+    }
+
+} /* validate_exit */
+
+
+/* PRINTFLIKE3 */ 
+static void
+verror(
+    int         opt,
+    ValMsgType  msgtype,
+    char *      fmt,
+    ...)
+{
+    va_list	ap;
+    char        buf[1024];
+    char *      bp = buf;
+    char *      fp;
+    char *      sp;
+    int         repeat;
+
+    va_start(ap, fmt);
+
+    /*
+     * Expand the "%m" format character into the descriptive string
+     * for the current value of errno.  Printf handles the other "%"
+     * formatting characters.
+     */
+    if (Validate >= opt) {
+	for (fp = fmt; *fp; fp++) {
+	    if (*fp == '%' && fp[1] == 'm') {
+		if ((sp = strerror(errno)) == NULL) {
+		    (void) sprintf(bp, "unknown error %d", errno);
+		} else {
+		    (void) strcpy(bp, sp);
+		}
+		bp = buf + strlen(buf);
+		fp++;
+	    } else {
+		*bp++ = *fp;
+	    }
+	}
+	*bp = '\0';
+	(void) vfprintf(stderr, buf, ap);
+    }
+    va_end(ap);
+
+    if (msgtype != I)
+	Validate_errors++;
+
+    if (msgtype == W && Validate == VAL_INTERACTIVE) {
+	repeat = 1;
+	while (repeat) {
+	    char ans[80];
+
+	    (void) fprintf(stderr, "continue? (y or n)  ");
+	    if (!fgets(ans,80,stdin)) {
+		(void) fprintf(stderr, "\n");
+		continue;
+	    }
+	    if (ans[0] == 'n' || ans[0] == 'N') {
+		validate_exit();
+		exit(1);
+	    } else if (ans[0] == 'y' || ans[0] == 'Y') {
+		repeat = 0;
+		break;
+	    }
+	}
+    }
+
+} /* verror */
+
+
+static void
+val_op_null(void)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_NULL, 
+	        xdr_void, (char *)0, xdr_void, (char *)0, 
+	        Nfs_timers[Ops[NULLCALL].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "null");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_getattr(GETATTR3args *args, GETATTR3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_GETATTR, 
+	        xdr_GETATTR3args, (char *)args, xdr_GETATTR3res, (char *)reply, 
+	        Nfs_timers[Ops[GETATTR].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "getattr");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_setattr(SETATTR3args *args, SETATTR3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR, 
+	        xdr_SETATTR3args, (char *)args, xdr_SETATTR3res, (char *)reply, 
+	        Nfs_timers[Ops[SETATTR].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "setattr");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_lookup(LOOKUP3args *args, LOOKUP3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP, 
+	        xdr_LOOKUP3args, (char *)args, xdr_LOOKUP3res, (char *)reply, 
+	        Nfs_timers[Ops[LOOKUP].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "lookup");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_access(ACCESS3args *args, ACCESS3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_ACCESS, 
+	        xdr_ACCESS3args, (char *)args, xdr_ACCESS3res, (char *)reply, 
+	        Nfs_timers[Ops[ACCESS].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "access");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_readlink(READLINK3args *args, READLINK3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_READLINK, 
+	        xdr_READLINK3args, (char *)args, xdr_READLINK3res, (char *)reply, 
+	        Nfs_timers[Ops[READLINK].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "readlink");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_read(READ3args *args, READ3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_READ, 
+	        xdr_READ3args, (char *)args, xdr_READ3res, (char *)reply, 
+	        Nfs_timers[Ops[READ].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "read");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_write(WRITE3args *args, WRITE3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE, 
+	        xdr_WRITE3args, (char *)args, xdr_WRITE3res, (char *)reply, 
+	        Nfs_timers[Ops[WRITE].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "write");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_create(CREATE3args *args, CREATE3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE, 
+	        xdr_CREATE3args, (char *)args, xdr_CREATE3res, (char *)reply, 
+	        Nfs_timers[Ops[CREATE].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "create");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_mkdir(MKDIR3args *args, MKDIR3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR, 
+	        xdr_MKDIR3args, (char *)args, xdr_MKDIR3res, (char *)reply, 
+	        Nfs_timers[Ops[MKDIR].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "mkdir");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_symlink(SYMLINK3args *args, SYMLINK3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK, 
+	        xdr_SYMLINK3args, (char *)args, xdr_SYMLINK3res, (char *)reply, 
+	        Nfs_timers[Ops[SYMLINK].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "symlink");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_mknod(MKNOD3args *args, MKNOD3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_MKNOD, 
+	        xdr_MKNOD3args, (char *)args, xdr_MKNOD3res, (char *)reply, 
+	        Nfs_timers[Ops[MKNOD].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "mknod");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_remove(REMOVE3args *args, REMOVE3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE, 
+	        xdr_REMOVE3args, (char *)args, xdr_REMOVE3res, (char *)reply, 
+	        Nfs_timers[Ops[REMOVE].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "remove");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_rmdir(RMDIR3args *args, RMDIR3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR, 
+	        xdr_RMDIR3args, (char *)args, xdr_RMDIR3res, (char *)reply, 
+	        Nfs_timers[Ops[RMDIR].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "rmdir");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_rename(RENAME3args *args, RENAME3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME, 
+	        xdr_RENAME3args, (char *)args, xdr_RENAME3res, (char *)reply, 
+	        Nfs_timers[Ops[RENAME].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "rename");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_link(LINK3args *args, LINK3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_LINK, 
+	        xdr_LINK3args, (char *)args, xdr_LINK3res, (char *)reply, 
+	        Nfs_timers[Ops[LINK].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, 
+		    "link");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_readdir(READDIR3args *args, READDIR3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIR, 
+	        xdr_READDIR3args, (char *)args, xdr_READDIR3res, (char *)reply, 
+	        Nfs_timers[Ops[READDIR].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "readdir");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client,
+	        NFSPROC3_READDIRPLUS, xdr_READDIRPLUS3args, (char *)args, 
+	        xdr_READDIRPLUS3res, (char *)reply, 
+	        Nfs_timers[Ops[READDIRPLUS].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client,
+		    "readdirplus");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_fsstat(FSSTAT3args *args, FSSTAT3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_FSSTAT, 
+	        xdr_FSSTAT3args, (char *)args, xdr_FSSTAT3res, (char *)reply, 
+	        Nfs_timers[Ops[FSSTAT].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "fsstat");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_fsinfo(FSINFO3args *args, FSINFO3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_FSINFO, 
+	        xdr_FSINFO3args, (char *)args, xdr_FSINFO3res, (char *)reply, 
+	        Nfs_timers[Ops[FSINFO].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "fsinfo");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_pathconf(PATHCONF3args *args, PATHCONF3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_PATHCONF, 
+	        xdr_PATHCONF3args, (char *)args, xdr_PATHCONF3res, (char *)reply, 
+	        Nfs_timers[Ops[PATHCONF].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "pathconf");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+val_op_commit(COMMIT3args *args, COMMIT3res *reply)
+{
+	int rpc_stat;
+ 
+	/* CONSTCOND */
+	while (1) {
+	    rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT, 
+		xdr_COMMIT3args, (char *)args, xdr_COMMIT3res, (char *)reply, 
+		Nfs_timers[Ops[COMMIT].call_class]);
+	    if (rpc_stat == RPC_SUCCESS)
+		break;
+	    if (rpc_stat != RPC_TIMEDOUT) {
+		clnt_perror(NFS_client, "commit");
+		Validate_errors++;
+		validate_exit();
+	    }
+	}
+}
+
+static void
+create_3tmp_handles(void)
+{
+	int filenum;
+	for (filenum = 0; filenum < NUMFILES; filenum++) {
+
+		if(Io_files[filenum].fh_data == (sfs_fh_data *)0)
+		{
+			Io_files[filenum].fh_data = 
+					calloc(1,sizeof(sfs_fh_data));
+			Io_files[filenum].attributes2.type = NFNON;
+			Io_files[filenum].attributes3.type = NF3NON;
+		}
+	}
+}
+
+static void
+delete_3tmp_handles(void)
+{
+	int filenum;
+	for (filenum = 0; filenum < NUMFILES; filenum++) {
+
+		if(Io_files[filenum].fh_data != (sfs_fh_data *)0)
+		{
+			free(Io_files[filenum].fh_data);
+			Io_files[filenum].fh_data= (sfs_fh_data *)0;
+		}
+	}
+}
+/* sfs_3_vld.c */
diff --git a/TBBT/trace_play/sfs_3_xdr.c b/TBBT/trace_play/sfs_3_xdr.c
new file mode 100644
index 0000000..01a69fb
--- /dev/null
+++ b/TBBT/trace_play/sfs_3_xdr.c
@@ -0,0 +1,1720 @@
+#ifndef lint
+static char sfs_3_xdrSid[] = "@(#)sfs_3_xdr.c 2.1     97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *              6585 Merchant Place, Suite 100
+ *              Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*
+ * -------------------------- sfs_3_xdr.c --------------------------
+ *
+ *      XDR routines for the nfs protocol.
+ *
+ *.Exported_routines
+ *	xdr_GETATTR3args(XDR *, GETATTR3args *)
+ *	xdr_GETATTR3res(XDR *, GETATTR3res *)
+ *	xdr_SETATTR3args(XDR *, SETATTR3args *)
+ *	xdr_SETATTR3res(XDR *, SETATTR3res *)
+ *	xdr_LOOKUP3args(XDR *, LOOKUP3args *)
+ *	xdr_LOOKUP3res(XDR *, LOOKUP3res *)
+ *	xdr_ACCESS3args(XDR *, ACCESS3args *)
+ *	xdr_ACCESS3res(XDR *, ACCESS3res *)
+ *	xdr_READLINK3args(XDR *, READLINK3args *)
+ *	xdr_READLINK3res(XDR *, READLINK3res *)
+ *	xdr_READ3args(XDR *, READ3args *)
+ *	xdr_READ3res(XDR *, READ3res *)
+ *	xdr_WRITE3args(XDR *, WRITE3args *)
+ *	xdr_WRITE3res(XDR *, WRITE3res *)
+ *	xdr_CREATE3args(XDR *, CREATE3args *)
+ *	xdr_CREATE3res(XDR *, CREATE3res *)
+ *	xdr_MKDIR3args(XDR *, MKDIR3args *)
+ *	xdr_MKDIR3res(XDR *, MKDIR3res *)
+ *	xdr_SYMLINK3args(XDR *, SYMLINK3args *)
+ *	xdr_SYMLINK3res(XDR *, SYMLINK3res *)
+ *	xdr_MKNOD3args(XDR *, MKNOD3args *)
+ *	xdr_MKNOD3res(XDR *, MKNOD3res *)
+ *	xdr_REMOVE3args(XDR *, REMOVE3args *)
+ *	xdr_REMOVE3res(XDR *, REMOVE3res *)
+ *	xdr_RMDIR3args(XDR *, RMDIR3args *)
+ *	xdr_RMDIR3res(XDR *, RMDIR3res *)
+ *	xdr_RENAME3args(XDR *, RENAME3args *)
+ *	xdr_RENAME3res(XDR *, RENAME3res *)
+ *	xdr_LINK3args(XDR *, LINK3args *)
+ *	xdr_LINK3res(XDR *, LINK3res *)
+ *	xdr_READDIR3args(XDR *, READDIR3args *)
+ *	xdr_READDIR3res(XDR *, READDIR3res *)
+ *	xdr_READDIRPLUS3args(XDR *, READDIRPLUS3args *)
+ *	xdr_READDIRPLUS3res(XDR *, READDIRPLUS3res *)
+ *	xdr_FSSTAT3args(XDR *, FSSTAT3args *)
+ *	xdr_FSSTAT3res(XDR *, FSSTAT3res *)
+ *	xdr_FSINFO3args(XDR *, FSINFO3args *)
+ *	xdr_FSINFO3res(XDR *, FSINFO3res *)
+ *	xdr_PATHCONF3args(XDR *, PATHCONF3args *)
+ *	xdr_PATHCONF3res(XDR *, PATHCONF3res *)
+ *	xdr_COMMIT3args(XDR *, COMMIT3args *)
+ *	xdr_COMMIT3res(XDR *, COMMIT3res *)
+ *	xdr_mntres3(XDR *, mountres3 *)
+ *
+ *.Local_routines
+ *	xdr_string3(XDR *, char **, unsigned int)
+ *	xdr_filename3(XDR *, filename3 *)
+ *	xdr_nfspath3(XDR *, nfspath3 *)
+ *	xdr_nfs_uint64_t(XDR *, nfs_uint64_t *)
+ *	xdr_cookieverf3(XDR *, cookieverf3)
+ *	xdr_createverf3(XDR *, createverf3)
+ *	xdr_writeverf3(XDR *, writeverf3)
+ *	xdr_nfs_fh3(XDR *, nfs_fh3 *)
+ *	xdr_diropargs3(XDR *, diropargs3 *)
+ *	xdr_nfstime3(XDR *, nfstime3 *)
+ *	xdr_specdata3(XDR *, specdata3 *)
+ *	xdr_nfsstat3(XDR *, nfsstat3 *)
+ *	xdr_ftype3(XDR *, ftype3 *)
+ *	xdr_fattr3(XDR *, fattr3 *)
+ *	xdr_post_op_attr(XDR *, post_op_attr *)
+ *	xdr_wcc_attr(XDR *, wcc_attr *)
+ *	xdr_pre_op_attr(XDR *, pre_op_attr *)
+ *	xdr_wcc_data(XDR *, wcc_data *)
+ *	xdr_post_op_fh3(XDR *, post_op_fh3 *)
+ *	xdr_time_how(XDR *, time_how *)
+ *	xdr_set_mode3(XDR *, set_mode3 *)
+ *	xdr_set_uid3(XDR *, set_uid3 *)
+ *	xdr_set_gid3(XDR *, set_gid3 *)
+ *	xdr_set_size3(XDR *, set_size3 *)
+ *	xdr_set_atime(XDR *, set_atime *)
+ *	xdr_set_mtime(XDR *, set_mtime *)
+ *	xdr_sattr3(XDR *, sattr3 *)
+ *	xdr_GETATTR3resok(XDR *, GETATTR3resok *)
+ *	xdr_sattrguard3(XDR *, sattrguard3 *)
+ *	xdr_SETATTR3resok(XDR *, SETATTR3resok *)
+ *	xdr_SETATTR3resfail(XDR *, SETATTR3resfail *)
+ *	xdr_LOOKUP3resok(XDR *, LOOKUP3resok *)
+ *	xdr_LOOKUP3resfail(XDR *, LOOKUP3resfail *)
+ *	xdr_ACCESS3resok(XDR *, ACCESS3resok *)
+ *	xdr_ACCESS3resfail(XDR *, ACCESS3resfail *)
+ *	xdr_READLINK3resok(XDR *, READLINK3resok *)
+ *	xdr_READLINK3resfail(XDR *, READLINK3resfail *)
+ *	xdr_READ3resok(XDR *, READ3resok *)
+ *	xdr_READ3resfail(XDR *, READ3resfail *)
+ *	xdr_stable_how(XDR *, stable_how *)
+ *	xdr_WRITE3resok(XDR *, WRITE3resok *)
+ *	xdr_WRITE3resfail(XDR *, WRITE3resfail *)
+ *	xdr_createmode3(XDR *, createmode3 *)
+ *	xdr_createhow3(XDR *, createhow3 *)
+ *	xdr_CREATE3resok(XDR *, CREATE3resok *)
+ *	xdr_CREATE3resfail(XDR *, CREATE3resfail *)
+ *	xdr_MKDIR3resok(XDR *, MKDIR3resok *)
+ *	xdr_MKDIR3resfail(XDR *, MKDIR3resfail *)
+ *	xdr_symlinkdata3(XDR *, symlinkdata3 *)
+ *	xdr_SYMLINK3resok(XDR *, SYMLINK3resok *)
+ *	xdr_SYMLINK3resfail(XDR *, SYMLINK3resfail *)
+ *	xdr_devicedata3(XDR *, devicedata3 *)
+ *	xdr_mknoddata3(XDR *, mknoddata3 *)
+ *	xdr_MKNOD3resok(XDR *, MKNOD3resok *)
+ *	xdr_MKNOD3resfail(XDR *, MKNOD3resfail *)
+ *	xdr_REMOVE3resok(XDR *, REMOVE3resok *)
+ *	xdr_REMOVE3resfail(XDR *, REMOVE3resfail *)
+ *	xdr_RMDIR3resok(XDR *, RMDIR3resok *)
+ *	xdr_RMDIR3resfail(XDR *, RMDIR3resfail *)
+ *	xdr_RENAME3resok(XDR *, RENAME3resok *)
+ *	xdr_RENAME3resfail(XDR *, RENAME3resfail *)
+ *	xdr_LINK3resok(XDR *, LINK3resok *)
+ *	xdr_LINK3resfail(XDR *, LINK3resfail *)
+ *	xdr_getdirlist(XDR *, READDIR3resok *)
+ *	xdr_READDIR3resok(XDR *, READDIR3resok *)
+ *	xdr_READDIR3resfail(XDR *, READDIR3resfail *)
+ *	xdr_getdirpluslist(XDR *, READDIRPLUS3resok *)
+ *	xdr_READDIRPLUS3resok(XDR *, READDIRPLUS3resok *)
+ *	xdr_READDIRPLUS3resfail(XDR *, READDIRPLUS3resfail *)
+ *	xdr_FSSTAT3resok(XDR *, FSSTAT3resok *)
+ *	xdr_FSSTAT3resfail(XDR *, FSSTAT3resfail *)
+ *	xdr_FSINFO3resok(XDR *, FSINFO3resok *)
+ *	xdr_FSINFO3resfail(XDR *, FSINFO3resfail *)
+ *	xdr_PATHCONF3resok(XDR *, PATHCONF3resok *)
+ *	xdr_PATHCONF3resfail(XDR *, PATHCONF3resfail *)
+ *	xdr_COMMIT3resok(XDR *, COMMIT3resok *)
+ *	xdr_COMMIT3resfail(XDR *, COMMIT3resfail *)
+ *
+ *.Revision_History
+ *      28-Jun-94	ChakChung Ng	Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include "sfs_c_def.h"
+
+/*
+ * -----------------------  SFS XDR Routines  -------------------------
+ */
+
+/*
+ * xdr_string3 deals with "C strings" - arrays of bytes that are terminated by
+ * a NULL character.  The parameter cpp references a pointer to storage. If the
+ * pointer is null, then necessary storage is allocated.  The last parameter is
+ * the max allowed length of the string as allowed by the system.  The NFS
+ * Version 3 protocol does not place limits on strings, but the implementation
+ * needs to place a reasonable limit to avoid problems.
+ */
+
+static bool_t
+xdr_string3(
+    XDR *		xdrs,
+    char **		cpp,
+    unsigned int	maxsize)
+{
+	char *sp;
+	unsigned int size, nodesize;
+
+	/*
+	 * first deal with the length since xdr strings are counted-strings
+	 */
+	sp = *cpp;
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+		if (sp == NULL || sp == nfs3nametoolong)
+			return(TRUE);  /* already free */
+		/* FALLTHROUGH */
+	case XDR_ENCODE:
+		size = strlen(sp);
+		break;
+	}
+
+	if (!xdr_u_int(xdrs, &size))
+		return(FALSE);
+
+	/*
+	 * now deal with the actual bytes
+	 */
+	switch (xdrs->x_op) {
+	case XDR_DECODE:
+		if (size > maxsize) {
+			int xskp = (((((int)size) + 3) / 4) * 4);
+
+			*cpp = nfs3nametoolong;
+			if ((xdrs->x_handy -= xskp) < 0)
+				return(FALSE);
+			xdrs->x_private += xskp;
+			return(TRUE);
+		}
+		nodesize = size + 1;
+		if (nodesize == 0)
+			return(TRUE);
+		if (sp == NULL) {
+			sp = (char *)malloc(nodesize);
+			*cpp = sp;
+			if (sp == NULL)
+				return(FALSE);
+		}
+		sp[size] = 0;	/* 0 through size-1 are original string */
+		/* FALLTHROUGH */
+	case XDR_ENCODE:
+		return(xdr_opaque(xdrs, sp, size));
+	case XDR_FREE:
+		nodesize = size + 1;
+		mem_free((caddr_t)sp, nodesize);
+		*cpp = NULL;
+		return(TRUE);
+	}
+
+	return(FALSE);
+}
+
+static bool_t
+xdr_filename3(
+    XDR *		xdrs,
+    filename3 *		objp)
+{
+
+	return(xdr_string3(xdrs, objp, NFS_MAXNAMLEN));
+}
+
+static bool_t
+xdr_nfspath3(
+    XDR *		xdrs,
+    nfspath3 *		objp)
+{
+
+	return(xdr_string3(xdrs, objp, NFS_MAXPATHLEN));
+}
+
+static bool_t
+xdr_nfs_uint64_t(
+    XDR			*xdrs,
+    nfs_uint64_t *	objp)
+{
+	return(xdr_int(xdrs, (int *)&objp->_p._u) &&
+					xdr_int(xdrs, (int *)&objp->_p._l));
+}
+
+static bool_t
+xdr_cookieverf3(
+    XDR *		xdrs,
+    cookieverf3		objp)
+{
+	return(xdr_opaque(xdrs, objp, NFS3_COOKIEVERFSIZE));
+}
+
+static bool_t
+xdr_createverf3(
+    XDR *		xdrs,
+    createverf3		objp)
+{
+	return(xdr_opaque(xdrs, objp, NFS3_CREATEVERFSIZE));
+}
+
+static bool_t
+xdr_writeverf3(
+    XDR *		xdrs,
+    writeverf3		objp)
+{
+	return(xdr_opaque(xdrs, objp, NFS3_WRITEVERFSIZE));
+}
+
+static bool_t
+xdr_nfs_fh3(
+    XDR *		xdrs,
+    nfs_fh3 *		objp)
+{
+	if (!xdr_u_int(xdrs, &objp->fh3_length))
+		return(FALSE);
+
+	if (objp->fh3_length > NFS3_FHSIZE)
+		return(FALSE);
+	if (xdrs->x_op == XDR_DECODE || xdrs->x_op == XDR_ENCODE)
+		return(xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length));
+
+	if (xdrs->x_op == XDR_FREE)
+		return(TRUE);
+
+	return(FALSE);
+}
+
+static bool_t
+xdr_diropargs3(
+    XDR *		xdrs,
+    diropargs3 *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->dir))
+		return(xdr_filename3(xdrs, &objp->name));
+	return(FALSE);
+}
+
+static bool_t
+xdr_nfstime3(
+    XDR *		xdrs,
+    nfstime3 *		objp)
+{
+	if (xdr_uint32_t(xdrs, &objp->seconds))
+		return(xdr_uint32_t(xdrs, &objp->nseconds));
+	return(FALSE);
+}
+
+static bool_t
+xdr_specdata3(
+    XDR *		xdrs,
+    specdata3 *		objp)
+{
+	if (xdr_uint32_t(xdrs, &objp->specdata1))
+		return(xdr_uint32_t(xdrs, &objp->specdata2));
+	return(FALSE);
+}
+
+static bool_t
+xdr_nfsstat3(
+    XDR *		xdrs,
+    nfsstat3 *		objp)
+{
+	return(xdr_enum(xdrs, (enum_t *)objp));
+}
+
+static bool_t
+xdr_ftype3(
+    XDR *		xdrs,
+    ftype3 *		objp)
+{
+	return(xdr_enum(xdrs, (enum_t *)objp));
+}
+
+static bool_t
+xdr_fattr3(
+    XDR *		xdrs,
+    fattr3 *		objp)
+{
+	if (!xdr_ftype3(xdrs, &objp->type))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->mode))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->nlink))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->uid))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->gid))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->size))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->used))
+		return(FALSE);
+	if (!xdr_specdata3(xdrs, &objp->rdev))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->fsid))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->fileid))
+		return(FALSE);
+	if (!xdr_nfstime3(xdrs, &objp->atime))
+		return(FALSE);
+	if (!xdr_nfstime3(xdrs, &objp->mtime))
+		return(FALSE);
+	if (!xdr_nfstime3(xdrs, &objp->ctime))
+		return(FALSE);
+	return(TRUE);
+}
+ 
+static bool_t
+xdr_post_op_attr(
+    XDR *		xdrs,
+    post_op_attr *	objp)
+{
+	if (!xdr_bool(xdrs, &objp->attributes))
+		return(FALSE);
+	switch (objp->attributes) {
+	case TRUE:	return(xdr_fattr3(xdrs, &objp->attr));
+	case FALSE:	return(TRUE);
+	default:	return(FALSE);
+	}
+}
+
+static bool_t
+xdr_wcc_attr(
+    XDR *		xdrs,
+    wcc_attr *		objp)
+{
+	if (xdr_nfs_uint64_t(xdrs, &objp->size) &&
+					xdr_nfstime3(xdrs, &objp->mtime))
+		return(xdr_nfstime3(xdrs, &objp->ctime));
+	return(FALSE);
+}
+
+static bool_t
+xdr_pre_op_attr(
+    XDR *		xdrs,
+    pre_op_attr *	objp)
+{
+	if (!xdr_bool(xdrs, &objp->attributes))
+		return(FALSE);
+	switch (objp->attributes) {
+	case TRUE:	return(xdr_wcc_attr(xdrs, &objp->attr));
+	case FALSE:	return(TRUE);
+	default:	return(FALSE);
+	}
+}
+ 
+static bool_t
+xdr_wcc_data(
+    XDR *		xdrs,
+    wcc_data *		objp)
+{
+	if (xdr_pre_op_attr(xdrs, &objp->before))
+		return(xdr_post_op_attr(xdrs, &objp->after));
+	return(FALSE);
+}
+ 
+static bool_t
+xdr_post_op_fh3(
+    XDR *		xdrs,
+    post_op_fh3 *	objp)
+{
+	if (!xdr_bool(xdrs, &objp->handle_follows))
+		return(FALSE);
+	switch (objp->handle_follows) {
+	case TRUE:	return(xdr_nfs_fh3(xdrs, &objp->handle));
+	case FALSE:	return(TRUE);
+	default:  	return(FALSE);
+	}
+}	
+ 
+static bool_t
+xdr_time_how(
+    XDR *		xdrs,
+    time_how *		objp)
+{
+	return(xdr_enum(xdrs, (enum_t *)objp));
+}
+
+static bool_t
+xdr_set_mode3(
+    XDR *		xdrs,
+    set_mode3 *		objp)
+{
+	if (!xdr_bool(xdrs, &objp->set_it))
+		return(FALSE);
+	if (objp->set_it == TRUE)
+		return(xdr_uint32_t(xdrs, &objp->mode));
+	return(TRUE);
+}	
+ 
+static bool_t
+xdr_set_uid3(
+    XDR *		xdrs,
+    set_uid3 *		objp)
+{
+	if (!xdr_bool(xdrs, &objp->set_it))
+		return(FALSE);
+	if (objp->set_it == TRUE)
+		return(xdr_uint32_t(xdrs, &objp->uid));
+	return(TRUE);
+}	
+ 
+static bool_t
+xdr_set_gid3(
+    XDR *		xdrs,
+    set_gid3 *		objp)
+{
+	if (!xdr_bool(xdrs, &objp->set_it))
+		return(FALSE);
+	if (objp->set_it == TRUE)
+		return(xdr_uint32_t(xdrs, &objp->gid));
+	return(TRUE);
+}
+
+static bool_t
+xdr_set_size3(
+    XDR *		xdrs,
+    set_size3 *		objp)
+{
+	if (!xdr_bool(xdrs, &objp->set_it))
+		return(FALSE);
+	if (objp->set_it == TRUE)
+		return(xdr_nfs_uint64_t(xdrs, &objp->size));
+	return(TRUE);
+}
+
+static bool_t
+xdr_set_atime(
+    XDR *		xdrs,
+    set_atime *		objp)
+{
+	if (!xdr_time_how(xdrs, &objp->set_it))
+		return(FALSE);
+	if (objp->set_it == SET_TO_CLIENT_TIME)
+		return(xdr_nfstime3(xdrs, &objp->atime));
+	return(TRUE);
+}
+
+static bool_t
+xdr_set_mtime(
+    XDR *		xdrs,
+    set_mtime *		objp)
+{
+	if (!xdr_time_how(xdrs, &objp->set_it))
+		return(FALSE);
+	if (objp->set_it == SET_TO_CLIENT_TIME)
+		return(xdr_nfstime3(xdrs, &objp->mtime));
+	return(TRUE);
+}
+
+static bool_t
+xdr_sattr3(
+    XDR *		xdrs,
+    sattr3 *		objp)
+{
+	if (xdr_set_mode3(xdrs, &objp->mode) &&
+					xdr_set_uid3(xdrs, &objp->uid) &&
+					xdr_set_gid3(xdrs, &objp->gid) &&
+					xdr_set_size3(xdrs, &objp->size) &&
+					xdr_set_atime(xdrs, &objp->atime))
+		return(xdr_set_mtime(xdrs, &objp->mtime));
+	return(FALSE);
+}
+
+
+bool_t
+xdr_GETATTR3args(
+    XDR *		xdrs,
+    GETATTR3args *	objp)
+{
+	return(xdr_nfs_fh3(xdrs, &objp->object));
+}
+
+static bool_t
+xdr_GETATTR3resok(
+    XDR *		xdrs,
+    GETATTR3resok *	objp)
+{
+	return(xdr_fattr3(xdrs, &objp->obj_attributes));
+}
+
+bool_t
+xdr_GETATTR3res(
+    XDR *		xdrs,
+    GETATTR3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_GETATTR3resok(xdrs, &objp->resok));
+	return(TRUE);
+}
+
+
+static bool_t
+xdr_sattrguard3(
+    XDR *		xdrs,
+    sattrguard3 *	objp)
+{
+	if (!xdr_bool(xdrs, &objp->check))
+		return(FALSE);
+	switch (objp->check) {
+	case TRUE:	return(xdr_nfstime3(xdrs, &objp->obj_ctime));
+	case FALSE:	return(TRUE);
+	default:	return(FALSE);
+	}
+}
+
+bool_t
+xdr_SETATTR3args(
+    XDR *		xdrs,
+    SETATTR3args *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->object) &&
+				xdr_sattr3(xdrs, &objp->new_attributes))
+		return(xdr_sattrguard3(xdrs, &objp->guard));
+	return(FALSE);
+}
+
+static bool_t
+xdr_SETATTR3resok(
+    XDR *		xdrs,
+    SETATTR3resok *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->obj_wcc));
+}
+
+static bool_t
+xdr_SETATTR3resfail(
+    XDR *		xdrs,
+    SETATTR3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->obj_wcc));
+}
+
+bool_t
+xdr_SETATTR3res(
+    XDR *		xdrs,
+    SETATTR3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_SETATTR3resok(xdrs, &objp->resok));
+	return(xdr_SETATTR3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_LOOKUP3args(
+    XDR *		xdrs,
+    LOOKUP3args *	objp)
+{
+	return(xdr_diropargs3(xdrs, &objp->what));
+}
+ 
+static bool_t
+xdr_LOOKUP3resok(
+    XDR *		xdrs,
+    LOOKUP3resok *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->object) &&
+				xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(xdr_post_op_attr(xdrs, &objp->dir_attributes));
+	return(FALSE);
+}
+ 
+static bool_t
+xdr_LOOKUP3resfail(
+    XDR *		xdrs,
+    LOOKUP3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->dir_attributes));
+}
+ 
+bool_t
+xdr_LOOKUP3res(
+    XDR *		xdrs,
+    LOOKUP3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_LOOKUP3resok(xdrs, &objp->resok));
+	return(xdr_LOOKUP3resfail(xdrs, &objp->resfail));
+}	
+ 
+
+bool_t
+xdr_ACCESS3args(
+    XDR *		xdrs,
+    ACCESS3args *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->object))
+		return(xdr_uint32_t(xdrs, &objp->access));
+	return(FALSE);
+}
+
+static bool_t
+xdr_ACCESS3resok(
+    XDR *		xdrs,
+    ACCESS3resok *	objp)
+{
+	if (xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(xdr_uint32_t(xdrs, &objp->access));
+	return(FALSE);
+}
+
+static bool_t
+xdr_ACCESS3resfail(
+    XDR *		xdrs,
+    ACCESS3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->obj_attributes));
+}
+
+bool_t
+xdr_ACCESS3res(
+    XDR *		xdrs,
+    ACCESS3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_ACCESS3resok(xdrs, &objp->resok));
+	return(xdr_ACCESS3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_READLINK3args(
+    XDR *		xdrs,
+    READLINK3args *	objp)
+{
+	return(xdr_nfs_fh3(xdrs, &objp->symlink));
+}
+
+static bool_t
+xdr_READLINK3resok(
+    XDR *		xdrs,
+    READLINK3resok *	objp)
+{
+	if (xdr_post_op_attr(xdrs, &objp->symlink_attributes))
+		return(xdr_nfspath3(xdrs, &objp->data));
+	return(FALSE);
+}
+
+static bool_t
+xdr_READLINK3resfail(
+    XDR *		xdrs,
+    READLINK3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->symlink_attributes));
+}
+ 
+bool_t
+xdr_READLINK3res(
+    XDR *		xdrs,
+    READLINK3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_READLINK3resok(xdrs, &objp->resok));
+	return(xdr_READLINK3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_READ3args(
+    XDR *		xdrs,
+    READ3args *		objp)
+{
+ 
+	if (xdr_nfs_fh3(xdrs, &objp->file) &&
+					xdr_nfs_uint64_t(xdrs, &objp->offset))
+		return(xdr_uint32_t(xdrs, &objp->count));
+	return(FALSE);
+}
+
+static bool_t
+xdr_READ3resok(
+    XDR *		xdrs,
+    READ3resok *	objp)
+{
+	if (xdr_post_op_attr(xdrs, &objp->file_attributes) &&
+					xdr_uint32_t(xdrs, &objp->count) &&
+					xdr_bool(xdrs, &objp->eof))
+		return(xdr_bytes(xdrs, (char **)&objp->data.data_val,
+					(unsigned int *)&objp->data.data_len,
+					~0));
+	return(FALSE);
+}
+
+static bool_t
+xdr_READ3resfail(
+    XDR *		xdrs,
+    READ3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->file_attributes));
+}
+
+bool_t
+xdr_READ3res(
+    XDR *		xdrs,
+    READ3res *		objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_READ3resok(xdrs, &objp->resok));
+	return(xdr_READ3resfail(xdrs, &objp->resfail));
+}
+
+
+static bool_t
+xdr_stable_how(
+    XDR *		xdrs,
+    stable_how *	objp)
+{
+	return(xdr_enum(xdrs, (enum_t *)objp));
+}
+
+bool_t
+xdr_WRITE3args(
+    XDR *		xdrs,
+    WRITE3args *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->file) &&
+					xdr_nfs_uint64_t(xdrs, &objp->offset) &&
+					xdr_uint32_t(xdrs, &objp->count) &&
+					xdr_stable_how(xdrs, &objp->stable))
+		return(xdr_bytes(xdrs, (char **)&objp->data.data_val,
+					(unsigned int *)&objp->data.data_len,
+					~0));
+	return(FALSE);
+}
+
+static bool_t
+xdr_WRITE3resok(
+    XDR *		xdrs,
+    WRITE3resok *	objp)
+{
+	if (xdr_wcc_data(xdrs, &objp->file_wcc) &&
+					xdr_uint32_t(xdrs, &objp->count) &&
+					xdr_stable_how(xdrs, &objp->committed))
+		return(xdr_writeverf3(xdrs, objp->verf));
+	return(FALSE);
+}
+
+static bool_t
+xdr_WRITE3resfail(
+    XDR *		xdrs,
+    WRITE3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->file_wcc));
+}
+
+bool_t
+xdr_WRITE3res(
+    XDR *		xdrs,
+    WRITE3res *		objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_WRITE3resok(xdrs, &objp->resok));
+	return(xdr_WRITE3resfail(xdrs, &objp->resfail));
+}
+
+
+static bool_t
+xdr_createmode3(
+    XDR *		xdrs,
+    createmode3 *	objp)
+{
+	return(xdr_enum(xdrs, (enum_t *)objp));
+}
+
+static bool_t
+xdr_createhow3(
+    XDR *		xdrs,
+    createhow3 *	objp)
+{
+	if (!xdr_createmode3(xdrs, &objp->mode))
+		return(FALSE);
+	switch (objp->mode) {
+	case UNCHECKED:
+	case GUARDED:
+		return(xdr_sattr3(xdrs, &objp->createhow3_u.obj_attributes));
+	case EXCLUSIVE:
+		return(xdr_createverf3(xdrs, objp->createhow3_u.verf));
+	default:
+		return(FALSE);
+	}
+}
+
+bool_t
+xdr_CREATE3args(
+    XDR *		xdrs,
+    CREATE3args *	objp)
+{
+	if (xdr_diropargs3(xdrs, &objp->where))
+		return(xdr_createhow3(xdrs, &objp->how));
+	return(FALSE);
+}
+
+static bool_t
+xdr_CREATE3resok(
+    XDR *		xdrs,
+    CREATE3resok *	objp)
+{
+	if (xdr_post_op_fh3(xdrs, &objp->obj) &&
+				xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+	return(FALSE);
+}
+
+static bool_t
+xdr_CREATE3resfail(
+    XDR *		xdrs,
+    CREATE3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+bool_t
+xdr_CREATE3res(
+    XDR *		xdrs,
+    CREATE3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_CREATE3resok(xdrs, &objp->resok));
+	return(xdr_CREATE3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_MKDIR3args(
+    XDR *		xdrs,
+    MKDIR3args *	objp)
+{
+	if (xdr_diropargs3(xdrs, &objp->where))
+		return(xdr_sattr3(xdrs, &objp->attributes));
+	return(FALSE);
+}
+
+static bool_t
+xdr_MKDIR3resok(
+    XDR *		xdrs,
+    MKDIR3resok *	objp)
+{
+	if (xdr_post_op_fh3(xdrs, &objp->obj) &&
+				xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+	return(FALSE);
+}
+
+static bool_t
+xdr_MKDIR3resfail(
+    XDR *		xdrs,
+    MKDIR3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+bool_t
+xdr_MKDIR3res(
+    XDR *		xdrs,
+    MKDIR3res *		objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_MKDIR3resok(xdrs, &objp->resok));
+	return(xdr_MKDIR3resfail(xdrs, &objp->resfail));
+}
+
+
+static bool_t
+xdr_symlinkdata3(
+    XDR *		xdrs,
+    symlinkdata3 *	objp)
+{
+	if (xdr_sattr3(xdrs, &objp->symlink_attributes))
+		return(xdr_nfspath3(xdrs, &objp->symlink_data));
+	return(FALSE);
+}
+
+bool_t
+xdr_SYMLINK3args(
+    XDR *		xdrs,
+    SYMLINK3args *	objp)
+{
+	if (xdr_diropargs3(xdrs, &objp->where))
+		return(xdr_symlinkdata3(xdrs, &objp->symlink));
+	return(FALSE);
+}
+
+static bool_t
+xdr_SYMLINK3resok(
+    XDR *		xdrs,
+    SYMLINK3resok *	objp)
+{
+	if (xdr_post_op_fh3(xdrs, &objp->obj) &&
+				xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+	return(FALSE);
+}
+
+static bool_t
+xdr_SYMLINK3resfail(
+    XDR *		xdrs,
+    SYMLINK3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+bool_t
+xdr_SYMLINK3res(
+    XDR *		xdrs,
+    SYMLINK3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_SYMLINK3resok(xdrs, &objp->resok));
+	return(xdr_SYMLINK3resfail(xdrs, &objp->resfail));
+}
+
+
+static bool_t
+xdr_devicedata3(
+    XDR *		xdrs,
+    devicedata3 *	objp)
+{
+	if (xdr_sattr3(xdrs, &objp->dev_attributes))
+		return(xdr_specdata3(xdrs, &objp->spec));
+	return(FALSE);
+}
+
+static bool_t
+xdr_mknoddata3(
+    XDR *		xdrs,
+    mknoddata3 *	objp)
+{
+	if (!xdr_ftype3(xdrs, &objp->type))
+		return(FALSE);
+	switch (objp->type) {
+	case NF3CHR:
+	case NF3BLK:
+		if (!xdr_devicedata3(xdrs, &objp->mknoddata3_u.device))
+			return(FALSE);
+		break;
+	case NF3SOCK:
+	case NF3FIFO:
+		if (!xdr_sattr3(xdrs, &objp->mknoddata3_u.pipe_attributes))
+			return(FALSE);
+		break;
+	}
+	return(TRUE);
+}
+
+bool_t
+xdr_MKNOD3args(
+    XDR *		xdrs,
+    MKNOD3args *	objp)
+{
+	if (xdr_diropargs3(xdrs, &objp->where))
+		return(xdr_mknoddata3(xdrs, &objp->what));
+	return(FALSE);
+}
+
+static bool_t
+xdr_MKNOD3resok(
+    XDR *		xdrs,
+    MKNOD3resok *	objp)
+{
+	if (xdr_post_op_fh3(xdrs, &objp->obj) &&
+				xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+	return(FALSE);
+}
+
+static bool_t
+xdr_MKNOD3resfail(
+    XDR *		xdrs,
+    MKNOD3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+bool_t
+xdr_MKNOD3res(
+    XDR *		xdrs,
+    MKNOD3res *		objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_MKNOD3resok(xdrs, &objp->resok));
+	return(xdr_MKNOD3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_REMOVE3args(
+    XDR *		xdrs,
+    REMOVE3args *	objp)
+{
+	return(xdr_diropargs3(xdrs, &objp->object));
+}
+
+static bool_t
+xdr_REMOVE3resok(
+    XDR *		xdrs,
+    REMOVE3resok *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+static bool_t
+xdr_REMOVE3resfail(
+    XDR *		xdrs,
+    REMOVE3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+bool_t
+xdr_REMOVE3res(
+    XDR *		xdrs,
+    REMOVE3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_REMOVE3resok(xdrs, &objp->resok));
+	return(xdr_REMOVE3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_RMDIR3args(
+    XDR *		xdrs,
+    RMDIR3args *	objp)
+{
+	return(xdr_diropargs3(xdrs, &objp->object));
+}
+
+static bool_t
+xdr_RMDIR3resok(
+    XDR *		xdrs,
+    RMDIR3resok *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+static bool_t
+xdr_RMDIR3resfail(
+    XDR *		xdrs,
+    RMDIR3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->dir_wcc));
+}
+
+bool_t
+xdr_RMDIR3res(
+    XDR *		xdrs,
+    RMDIR3res *		objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_RMDIR3resok(xdrs, &objp->resok));
+	return(xdr_RMDIR3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_RENAME3args(
+    XDR *		xdrs,
+    RENAME3args *	objp)
+{
+	if (xdr_diropargs3(xdrs, &objp->from))
+		return(xdr_diropargs3(xdrs, &objp->to));
+	return(FALSE);
+}
+
+static bool_t
+xdr_RENAME3resok(
+    XDR *		xdrs,
+    RENAME3resok *	objp)
+{
+	if (xdr_wcc_data(xdrs, &objp->fromdir_wcc))
+		return(xdr_wcc_data(xdrs, &objp->todir_wcc));
+	return(FALSE);
+}
+
+static bool_t
+xdr_RENAME3resfail(
+    XDR *		xdrs,
+    RENAME3resfail *	objp)
+{
+	if (xdr_wcc_data(xdrs, &objp->fromdir_wcc))
+		return(xdr_wcc_data(xdrs, &objp->todir_wcc));
+	return(FALSE);
+}
+
+bool_t
+xdr_RENAME3res(
+    XDR *		xdrs,
+    RENAME3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_RENAME3resok(xdrs, &objp->resok));
+	return(xdr_RENAME3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_LINK3args(
+    XDR *		xdrs,
+    LINK3args *		objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->file))
+		return(xdr_diropargs3(xdrs, &objp->link));
+	return(FALSE);
+}
+
+static bool_t
+xdr_LINK3resok(
+    XDR *		xdrs,
+    LINK3resok *	objp)
+{
+	if (xdr_post_op_attr(xdrs, &objp->file_attributes))
+		return(xdr_wcc_data(xdrs, &objp->linkdir_wcc));
+	return(FALSE);
+}
+
+static bool_t
+xdr_LINK3resfail(
+    XDR *		xdrs,
+    LINK3resfail *	objp)
+{
+	if (xdr_post_op_attr(xdrs, &objp->file_attributes))
+		return(xdr_wcc_data(xdrs, &objp->linkdir_wcc));
+	return(FALSE);
+}
+
+bool_t
+xdr_LINK3res(
+    XDR *		xdrs,
+    LINK3res *		objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_LINK3resok(xdrs, &objp->resok));
+	return(xdr_LINK3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_READDIR3args(
+    XDR *		xdrs,
+    READDIR3args *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->dir) &&
+					xdr_nfs_uint64_t(xdrs, &objp->cookie) &&
+					xdr_cookieverf3(xdrs, objp->cookieverf))
+		return(xdr_uint32_t(xdrs, &objp->count));
+	return(FALSE);
+}
+
+#define	roundtoint(x)	(((x) + sizeof (int) - 1) & ~(sizeof (int) - 1))
+
+/*
+ * DECODE ONLY
+ */
+static bool_t
+xdr_getdirlist(
+    XDR *		xdrs,
+    READDIR3resok *	objp)
+{
+	register int	i;
+	bool_t		valid;
+	unsigned int	namlen;
+	char		name[SFS_MAXNAMLEN];
+	nfs_uint64_t	fileid, cookie;
+	entry3		*dp;
+
+	i = 0;
+	dp = objp->reply.entries;
+	for (;;) {
+		if (!xdr_bool(xdrs, &valid))
+			return(FALSE);
+		if (!valid)
+			break;
+		if (!xdr_nfs_uint64_t(xdrs, &fileid) ||
+						!xdr_u_int(xdrs, &namlen))
+			return(FALSE);
+		if (namlen >= SFS_MAXNAMLEN)
+			namlen = SFS_MAXNAMLEN - 1;
+		if (!xdr_opaque(xdrs, name, namlen) ||
+					!xdr_nfs_uint64_t(xdrs, &cookie))
+			return(FALSE);
+		name[namlen] = '\0';
+		if (i < SFS_MAXDIRENTS) {
+		    dp[i].fileid = fileid;
+		    (void)memmove(dp[i].name, name, (namlen+1));
+		    dp[i].cookie = cookie;
+		    i++;
+		}
+	}
+	objp->count = i;
+	if (!xdr_bool(xdrs, &objp->reply.eof))
+		return(FALSE);
+	return(TRUE);
+}
+
+static bool_t
+xdr_READDIR3resok(
+    XDR *		xdrs,
+    READDIR3resok *	objp)
+{
+	if (!xdr_post_op_attr(xdrs, &objp->dir_attributes))
+		return(FALSE);
+	if (!xdr_cookieverf3(xdrs, objp->cookieverf))
+		return(FALSE);
+	if (xdrs->x_op == XDR_DECODE)
+		return(xdr_getdirlist(xdrs, objp));
+	return(TRUE);
+}
+
+static bool_t
+xdr_READDIR3resfail(
+    XDR *		xdrs,
+    READDIR3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->dir_attributes));
+}
+
+bool_t
+xdr_READDIR3res(
+    XDR *		xdrs,
+    READDIR3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_READDIR3resok(xdrs, &objp->resok));
+	return(xdr_READDIR3resfail(xdrs, &objp->resfail));
+}
+
+bool_t
+xdr_READDIRPLUS3args(
+    XDR *		xdrs,
+    READDIRPLUS3args *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->dir) &&
+				xdr_nfs_uint64_t(xdrs, &objp->cookie) &&
+				xdr_cookieverf3(xdrs, objp->cookieverf) &&
+				xdr_uint32_t(xdrs, &objp->dircount))
+		return(xdr_uint32_t(xdrs, &objp->maxcount));
+	return(FALSE);
+}
+
+/*
+ * copy post_op_attr from s2 to s1
+ */
+static void
+copy_post_op_attr(post_op_attr *s1, post_op_attr *s2)
+{
+	s1->attributes = s2->attributes;
+	(void) memmove((void *) &s1->attr, (void *) &s2->attr,
+		       sizeof (fattr3));
+}
+
+/*
+ * copy post_op_fh3 from s2 to s1
+ */
+static void
+copy_post_op_fh3(post_op_fh3 *s1, post_op_fh3 *s2)
+{
+	s1->handle_follows = s2->handle_follows;
+	(void) memmove((void *) &s1->handle, (void *) &s2->handle,
+		       sizeof (nfs_fh3));
+}
+		
+/*
+ * DECODE ONLY
+ */
+static bool_t
+xdr_getdirpluslist(
+    XDR *		xdrs,
+    READDIRPLUS3resok *	objp)
+{
+	register int	i;
+	bool_t		valid;
+	unsigned int	namlen;
+	char		name[SFS_MAXNAMLEN];
+	nfs_uint64_t	fileid, cookie;
+	entryplus3	*dp;
+	post_op_attr	at;
+	post_op_fh3	fh;
+
+	i = 0;
+	dp = objp->reply.entries;
+	for (;;) {
+		if (!xdr_bool(xdrs, &valid))
+			return(FALSE);
+		if (!valid)
+			break;
+		if (!xdr_nfs_uint64_t(xdrs, &fileid) ||
+					!xdr_u_int(xdrs, &namlen))
+			return(FALSE);
+		if (namlen >= SFS_MAXNAMLEN)
+			namlen = SFS_MAXNAMLEN - 1;
+		if (!xdr_opaque(xdrs, name, namlen) ||
+					!xdr_nfs_uint64_t(xdrs, &cookie))
+			return(FALSE);
+		name[namlen] = '\0';
+		if (!xdr_post_op_attr(xdrs, &at))
+			return(FALSE);
+		if (!xdr_post_op_fh3(xdrs, &fh))
+			return(FALSE);
+		if (i < SFS_MAXDIRENTS) {
+		    dp[i].fileid = fileid;
+		    (void)memmove(dp[i].name, name, (namlen+1));
+		    dp[i].cookie = cookie;
+		    copy_post_op_attr(&dp[i].name_attributes, &at);
+		    copy_post_op_fh3(&dp[i].name_handle, &fh);
+		    i++;
+		}
+	}
+
+	objp->count = i;
+	if (!xdr_bool(xdrs, &objp->reply.eof))
+		return(FALSE);
+	return(TRUE);
+}
+
+static bool_t
+xdr_READDIRPLUS3resok(
+    XDR *		xdrs,
+    READDIRPLUS3resok *	objp)
+{
+
+	if (!xdr_post_op_attr(xdrs, &objp->dir_attributes))
+		return(FALSE);
+	if (!xdr_cookieverf3(xdrs, objp->cookieverf))
+		return(FALSE);
+	if (xdrs->x_op == XDR_DECODE)
+		return(xdr_getdirpluslist(xdrs, objp));
+	return(TRUE);
+}
+
+static bool_t
+xdr_READDIRPLUS3resfail(
+    XDR *			xdrs,
+    READDIRPLUS3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->dir_attributes));
+}
+
+bool_t
+xdr_READDIRPLUS3res(
+    XDR *		xdrs,
+    READDIRPLUS3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_READDIRPLUS3resok(xdrs, &objp->resok));
+	return(xdr_READDIRPLUS3resfail(xdrs, &objp->resfail));
+}
+
+bool_t
+xdr_FSSTAT3args(
+    XDR *		xdrs,
+    FSSTAT3args *	objp)
+{
+	return(xdr_nfs_fh3(xdrs, &objp->fsroot));
+}
+
+static bool_t
+xdr_FSSTAT3resok(
+    XDR *		xdrs,
+    FSSTAT3resok *	objp)
+{
+	if (!xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->tbytes))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->fbytes))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->abytes))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->tfiles))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->ffiles))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->afiles))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->invarsec))
+		return(FALSE);
+	return(TRUE);
+}
+
+static bool_t
+xdr_FSSTAT3resfail(
+    XDR *		xdrs,
+    FSSTAT3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->obj_attributes));
+}
+
+bool_t
+xdr_FSSTAT3res(
+    XDR *		xdrs,
+    FSSTAT3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_FSSTAT3resok(xdrs, &objp->resok));
+	return(xdr_FSSTAT3resfail(xdrs, &objp->resfail));
+}
+
+bool_t
+xdr_FSINFO3args(
+    XDR *		xdrs,
+    FSINFO3args *	objp)
+{
+	return(xdr_nfs_fh3(xdrs, &objp->fsroot));
+}
+
+static bool_t
+xdr_FSINFO3resok(
+    XDR *		xdrs,
+    FSINFO3resok *	objp)
+{
+	if (!xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->rtmax))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->rtpref))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->rtmult))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->wtmax))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->wtpref))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->wtmult))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->dtpref))
+		return(FALSE);
+	if (!xdr_nfs_uint64_t(xdrs, &objp->maxfilesize))
+		return(FALSE);
+	if (!xdr_nfstime3(xdrs, &objp->time_delta))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->properties))
+		return(FALSE);
+	return(TRUE);
+}
+
+static bool_t
+xdr_FSINFO3resfail(
+    XDR *		xdrs,
+    FSINFO3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->obj_attributes));
+}
+
+bool_t
+xdr_FSINFO3res(
+    XDR *		xdrs,
+    FSINFO3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_FSINFO3resok(xdrs, &objp->resok));
+	return(xdr_FSINFO3resfail(xdrs, &objp->resfail));
+}
+
+bool_t
+xdr_PATHCONF3args(
+    XDR *		xdrs,
+    PATHCONF3args *	objp)
+{
+	return(xdr_nfs_fh3(xdrs, &objp->object));
+}
+
+static bool_t
+xdr_PATHCONF3resok(
+    XDR *		xdrs,
+    PATHCONF3resok *	objp)
+{
+	if (!xdr_post_op_attr(xdrs, &objp->obj_attributes))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->link_max))
+		return(FALSE);
+	if (!xdr_uint32_t(xdrs, &objp->name_max))
+		return(FALSE);
+	if (!xdr_bool(xdrs, &objp->no_trunc))
+		return(FALSE);
+	if (!xdr_bool(xdrs, &objp->chown_restricted))
+		return(FALSE);
+	if (!xdr_bool(xdrs, &objp->case_insensitive))
+		return(FALSE);
+	if (!xdr_bool(xdrs, &objp->case_preserving))
+		return(FALSE);
+	return(TRUE);
+}
+
+static bool_t
+xdr_PATHCONF3resfail(
+    XDR *		xdrs,
+    PATHCONF3resfail *	objp)
+{
+	return(xdr_post_op_attr(xdrs, &objp->obj_attributes));
+}
+
+bool_t
+xdr_PATHCONF3res(
+    XDR *		xdrs,
+    PATHCONF3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_PATHCONF3resok(xdrs, &objp->resok));
+	return(xdr_PATHCONF3resfail(xdrs, &objp->resfail));
+}
+
+bool_t
+xdr_COMMIT3args(
+    XDR *		xdrs,
+    COMMIT3args *	objp)
+{
+	if (xdr_nfs_fh3(xdrs, &objp->file) &&
+					xdr_nfs_uint64_t(xdrs, &objp->offset))
+		return(xdr_uint32_t(xdrs, &objp->count));
+	return(FALSE);
+}
+
+static bool_t
+xdr_COMMIT3resok(
+    XDR *		xdrs,
+    COMMIT3resok *	objp)
+{
+	if (xdr_wcc_data(xdrs, &objp->file_wcc))
+		return(xdr_writeverf3(xdrs, objp->verf));
+	return(FALSE);
+}
+
+static bool_t
+xdr_COMMIT3resfail(
+    XDR *		xdrs,
+    COMMIT3resfail *	objp)
+{
+	return(xdr_wcc_data(xdrs, &objp->file_wcc));
+}
+
+bool_t
+xdr_COMMIT3res(
+    XDR *		xdrs,
+    COMMIT3res *	objp)
+{
+	if (!xdr_nfsstat3(xdrs, &objp->status))
+		return(FALSE);
+	if (objp->status == NFS3_OK)
+		return(xdr_COMMIT3resok(xdrs, &objp->resok));
+	return(xdr_COMMIT3resfail(xdrs, &objp->resfail));
+}
+
+
+bool_t
+xdr_dirpath(
+    XDR *		xdrs,
+    dirpath *		objp)
+{
+	return(xdr_string(xdrs, objp, MNTPATHLEN));
+}
+
+static bool_t
+xdr_fhandle3(
+    XDR *		xdrs,
+    fhandle3 *		objp)
+{
+	return(xdr_bytes(xdrs, (char **) &objp->fhandle3_val,
+				(unsigned int *) &objp->fhandle3_len, NFS3_FHSIZE));
+}
+
+static bool_t
+xdr_mntres3_ok(
+    XDR *		xdrs,
+    mntres3_ok *	objp)
+{
+	if (xdr_fhandle3(xdrs, &objp->fhandle)) {
+		return(xdr_array(xdrs,
+			(void **) &objp->auth_flavors.auth_flavors_val,
+			(unsigned int *) &objp->auth_flavors.auth_flavors_len,
+			~0, sizeof (int), (xdrproc_t) xdr_int));
+	}
+	return(FALSE);
+}
+
+bool_t
+xdr_mntres3(
+    XDR *		xdrs,
+    mountres3 *		objp)
+{
+	if (!xdr_enum(xdrs, (enum_t *) &objp->fhs_status))
+		return(FALSE);
+	if (objp->fhs_status == MNT_OK)
+		return(xdr_mntres3_ok(xdrs, &objp->mntres3_u.mntinfo));
+	return(TRUE);
+}
+/* sfs_3_xdr.c */
diff --git a/TBBT/trace_play/sfs_c_bio.c b/TBBT/trace_play/sfs_c_bio.c
new file mode 100644
index 0000000..ed35c42
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_bio.c
@@ -0,0 +1,1023 @@
+#ifndef lint
+static char sfs_c_bioSid[] = "@(#)sfs_c_bio.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*
+ * ---------------------- sfs_c_bio.c ---------------------
+ *
+ *	Routines that attempt to simulate biod behavior
+ *
+ *	The routines contained here model biod behavior.  Simply call
+ *	biod_init() to replace regular calls to op_read() and op_write()
+ *	with calls to op_biod_read() and op_biod_write().  The variables
+ *	max_out_writes and max_out_reads control the maximum number of
+ *	outstanding writes and reads respectively.
+ *
+ *.Exported Routines
+ *	int	biod_init(int, int);
+ *	void	biod_turn_on(void);
+ *	void	op_biod_write(int, int, int);
+ *	void	op_biod_read(int);
+ *
+ *.Local Routines
+ *	uint32_t	biod_clnt_call(CLIENT *, uint32_t,
+ *						xdrproc_t, void *);
+ *	struct biod_req	*biod_get_reply(CLIENT *, xdrproc_t,
+ *						void *, struct timeval *);
+ *	int		biod_poll_wait(CLIENT *, uint32_t);
+ *
+ *.Revision_History
+ *	03-May-94	Robinson
+ *				History now kept in SCCS
+ *	03-Mar-92	0.1.0 Corbin
+ *					Added biod behavior
+ */
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "rfs_c_def.h"
+
+/*
+ * Information associated with outstanding read/write requests
+ */
+#ifndef RFS
+struct biod_req {
+    uint32_t		xid;		/* RPC transmission ID	*/
+    bool_t		in_use;			/* Indicates if the entry is in use */
+	int	dep_tab_index;			/* corresponding index in dep_tab */
+    unsigned int	count;		/* Count saved for Dump routines */
+    unsigned int	offset;		/* Offset saved for Dump routines */
+    struct ladtime	start;		/* Time RPC call was made */
+    struct ladtime	stop;		/* Time RPC reply was received */
+    struct ladtime	timeout;	/* Time RPC call will time out */
+};
+#endif
+
+/*
+ * ----------------------  Static Declarations  ----------------------
+ */
+
+static int	max_out_writes;
+static int	max_out_reads;
+int	max_biod_reqs = 0;
+struct biod_req *biod_reqp;
+
+/* forward definitions for local functions */
+extern uint32_t	biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
+static struct biod_req *biod_get_reply(CLIENT *, xdrproc_t,
+						void *, struct timeval *);
+extern int	biod_poll_wait(CLIENT *, uint32_t);
+
+static int op_biod_write(int, int, int);
+static int op_biod_read(int);
+
+/*
+ * ----------------------  BIOD Support Routines  ----------------------
+ */
+
+/*
+ * biod_init()
+ *
+ * This function is called during the initialization phase. It performs
+ * the following tasks:
+ *	- Allocate memory to hold outstanding biod request information
+ *
+ * Returns 0 for OK, -1 for failure
+ */
+int
+biod_init(
+    int			out_writes,
+    int			out_reads)
+{
+    // RFS max_out_writes = MAXIMUM(1, out_writes);
+    // RFS max_out_reads = MAXIMUM(1, out_reads);
+    // RFS max_biod_reqs = MAXIMUM(out_writes, out_reads);
+	max_biod_reqs = MAX_OUTSTANDING_REQ;	// RFS
+
+    biod_reqp = (struct biod_req *) calloc(max_biod_reqs,
+					   sizeof (struct biod_req));
+    if (biod_reqp == (struct biod_req *)0) {
+	(void) fprintf(stderr, "%s: biod_init calloc failed.\n", sfs_Myname);
+	(void) fflush(stderr);
+	return (-1);
+    }
+
+    return (0);
+} /* biod_init */
+
+#ifndef RFS
+
+/*
+ *	- Change the operation functions for reads and writes to use the
+ *	  biod routines. This step should be done last to allow callers
+ *	  to still run with the old op functions if the biod initialization
+ *	  fails.
+ */
+void
+biod_turn_on(void)
+{
+    Ops[WRITE].funct = op_biod_write;
+    Ops[READ].funct = op_biod_read;
+}
+
+#endif
+
+/*
+ * biod_term()
+ *
+ * This function is called during the termination phase to free any resources
+ * allocated by the biod_init() routine. It performs the following tasks:
+ *	- Frees memory associated with outstanding biod request information
+ *	- Frees the biod client handle
+ */
+void
+biod_term(void)
+{
+    if (max_biod_reqs) {
+	free(biod_reqp);
+    }
+} /* biod_term */
+
+#ifndef RFS
+/*
+ * Perform and RPC biod style write operation of length 'xfer_size'.
+ * If 'append_flag' is true, then write the data to the end of the file.
+ */
+static int
+op_biod_write(
+    int			xfer_size,
+    int			append_flag,
+    int			stab_flag)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    static char		*buf = NULL;	/* the data buffer */
+    unsigned int	size;		/* size of data write */
+    int			max_cnt;
+    attrstat		reply2;		/* the reply */
+    writeargs		args2;
+    WRITE3res		reply3;		/* the reply */
+    WRITE3args		args3;
+    struct ladtime	curr_time;
+    struct ladtime	tmp_time;
+    struct ladtime	call_timeout;
+    struct biod_req	*reqp;
+    int			ret;		/* ret val == call success */
+    int			num_out_reqs;	/* # of outstanding writes */
+    int			i;
+    int			error;
+    int32_t		offset;
+    static int		calls = 0;
+
+    calls++;
+
+    if (nfs_version != NFS_VERSION && nfs_version != NFS_V3)
+	return (0);
+
+    /*
+     * Initialize write buffer to known value
+     */  
+    if (buf == NULL) {
+        buf = init_write_buffer();
+    }
+
+
+    /*
+     * For now we treat DATA_SYNC to be the same as FILE_SYNC.
+     * If it is not a V3 op then it must always be stable
+     */  
+    if (stab_flag == DATA_SYNC || nfs_version != NFS_V3)
+        stab_flag = FILE_SYNC;
+
+    op_ptr = &Ops[WRITE];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args2.file, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+    (void) memmove((char *) &args3.file, (char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    args2.beginoffset = 0;	/* unused */
+
+    if (append_flag == 1) {
+	args2.offset = Cur_file_ptr->attributes2.size;
+	args3.offset = Cur_file_ptr->attributes3.size;
+    } else {
+	if (fh_size(Cur_file_ptr) > xfer_size) {
+	    offset = Bytes_per_block * (sfs_random() %
+			    (((fh_size(Cur_file_ptr) - xfer_size)
+			    / Bytes_per_block) + 1));
+	    args2.offset = offset;
+	    args3.offset._p._u = 0;
+	    args3.offset._p._l = offset;
+	} else {
+	    args2.offset = 0;
+	    args3.offset._p._u = args3.offset._p._l = 0;
+	}
+    }
+
+    size = Bytes_per_block;
+    args2.totalcount = size;	/* unused */
+    args2.data.data_len = size;
+    args2.data.data_val = buf;
+    args3.data.data_len = size;
+    args3.data.data_val = buf;
+    args3.count = size;
+    args3.stable = stab_flag;
+
+    /* Calculate the number of NFS writes required */
+    max_cnt = xfer_size / Bytes_per_block;
+    if ((xfer_size % Bytes_per_block) != 0) {
+	max_cnt++;
+    }
+
+    /* check our stats to see if this would overflow */
+    if (!Timed_run) {
+	if (op_ptr->target_calls > 0 &&
+	   (op_ptr->results.good_calls + max_cnt) > op_ptr->target_calls) {
+	    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+	}
+    }
+
+    if (DEBUG_CHILD_OPS) {
+	(void) fprintf(stderr, "write: %d buffers xfer_size %d\n",
+			  max_cnt, xfer_size);
+	(void) fflush(stderr);
+    }
+
+    /* Mark all request slots as not in use */
+    for (reqp = biod_reqp, i = 0; i < max_biod_reqs; i++, reqp++) {
+	reqp->in_use = FALSE;
+    }
+
+    if (Current_test_phase < Warmup_phase) {
+	call_timeout.sec = Nfs_timers[Init].tv_sec;
+	call_timeout.usec = Nfs_timers[Init].tv_usec;
+    } else {
+	call_timeout.sec = Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+    }
+
+    /* capture length for possible dump */
+    Dump_length = fh_size(Cur_file_ptr);
+ 
+    /* make the call(s) now */
+    num_out_reqs = 0;
+    while (xfer_size > 0 || num_out_reqs > 0) {
+	/*
+	 * Send out calls async until either the maximum number of outstanding
+	 * requests has been reached or there are no more requests to make.
+	 */
+	while (num_out_reqs < max_out_writes && xfer_size > 0) {
+
+	    /* find an empty write request slot */
+	    for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    break;
+		}
+	    }
+
+	    if (xfer_size < size) {
+		size = xfer_size;
+		args2.data.data_len = xfer_size;
+		args2.totalcount = xfer_size;		/* unused */
+		args3.data.data_len = xfer_size;
+		args3.count = xfer_size;
+	    }
+	    xfer_size -= size;
+
+	    sfs_gettime(&reqp->start);
+	    if (nfs_version == NFS_V3) {
+		    reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC3_WRITE,
+					xdr_WRITE3args, (char *) &args3);
+		    if (reqp->xid != 0) {
+			/* capture count and offset for possible dump */
+			reqp->count = args3.data.data_len;
+			reqp->offset = args3.offset._p._l;
+			reqp->timeout = reqp->start;
+			ADDTIME(reqp->timeout, call_timeout);
+			reqp->in_use = TRUE;
+			num_out_reqs++;
+	    	    }
+	    }
+	    if (nfs_version == NFS_VERSION) {
+		    reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC_WRITE,
+					xdr_write, (char *) &args2);
+		    if (reqp->xid != 0) {
+			/* capture count and offset for possible dump */
+			reqp->count = args2.data.data_len;
+			reqp->offset = args2.offset;
+			reqp->timeout = reqp->start;
+			ADDTIME(reqp->timeout, call_timeout);
+			reqp->in_use = TRUE;
+			num_out_reqs++;
+	    	    }
+	    }
+	    if (DEBUG_CHILD_BIOD) {
+		(void) fprintf (stderr,
+"[%d]:Biod write started xid %x start (%d.%06d) timeo (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec);
+	    }
+
+	    args2.offset += size;
+	    args3.offset._p._l += size;
+	    if (biod_poll_wait(NFS_client, 0) > 0) {
+		break;
+	    }
+	} /* while can make an async call */
+
+	/*
+	 * Process replies while there is data on the socket buffer.
+	 * Just do polls on the select, no sleeping occurs in this loop.
+	 */
+	do {
+	    error = biod_poll_wait(NFS_client, 0);
+	    switch (error) {
+		case -1:
+		    if (errno == EINTR) {
+			error = 1;
+			continue;
+		    }
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf(stderr, "%s:[%d]: biod_poll_wait error\n",
+					   sfs_Myname, calls);
+			(void) fflush(stderr);
+		    }
+		    break;
+
+		case 0:
+		    break;
+
+
+		default:
+		    if (nfs_version == NFS_VERSION)
+			    reqp = biod_get_reply(NFS_client, xdr_write,
+					  (char *) &reply2,
+					  &Nfs_timers[op_ptr->call_class]);
+		    if (nfs_version == NFS_V3)
+			    reqp = biod_get_reply(NFS_client, xdr_WRITE3res,
+					  (char *) &reply3,
+					  &Nfs_timers[op_ptr->call_class]);
+
+		    /*
+		     * If biod_get_reply returns NULL then we got an RPC
+		     * level error, probably a dropped fragment or the
+		     * remains of a previous partial request.
+		     */
+		    if (reqp == (struct biod_req *)NULL) {
+			error = 0;
+			break;
+		    }
+
+		    /*
+		     * We have a valid response, check if procedure completed
+		     * correctly.
+		     */
+		    if ((nfs_version == NFS_VERSION &&
+			 reply2.status == NFS_OK) ||
+			 (nfs_version == NFS_V3 && reply3.status == NFS3_OK)) {
+			Cur_file_ptr->state = Exists;
+			/*
+			 * In updating attributes we may get replies out
+			 * of order.  We blindly update the attributes
+			 * which may cause old attributes to be stored.
+			 * XXX We should check for old attributes.
+			 */
+		        if (nfs_version == NFS_VERSION)
+			    Cur_file_ptr->attributes2 =
+					reply2.attrstat_u.attributes;
+		        if (nfs_version == NFS_V3)
+			    Cur_file_ptr->attributes3 =
+					reply3.res_u.ok.file_wcc.after.attr;
+			if (DEBUG_CHILD_RPC) {
+			    (void) fprintf(stderr,
+					"%s: WRITE %s %d bytes offset %d \n",
+					sfs_Myname, Cur_filename,
+					reqp->count, reqp->offset);
+			    (void) fflush(stderr);
+			}
+
+			/* capture count and offset for possible dump */
+			Dump_count = reqp->count;
+			Dump_offset = reqp->offset;
+			sfs_elapsedtime(op_ptr, &reqp->start, &reqp->stop);
+			op_ptr->results.good_calls++;
+			Ops[TOTAL].results.good_calls++;
+			ret++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+		        if (DEBUG_CHILD_BIOD) {
+			    (void) fprintf (stderr,
+"[%d]:Biod write succeded xid %x start (%d.%06d) timeo (%d.%06d) stop (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec,
+				reqp->stop.sec, reqp->stop.usec);
+			}
+		    } else {
+			op_ptr->results.bad_calls++;
+			Ops[TOTAL].results.bad_calls++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+		        if (DEBUG_CHILD_BIOD) {
+			    (void) fprintf (stderr,
+"[%d]:Biod write failed xid %x start (%d.%06d) timeo (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec);
+
+			    (void) fprintf(stderr,
+				    "[%d]:BIOD WRITE FAILED: xid %x",
+				    calls, reqp->xid);
+
+			    if (nfs_version == NFS_VERSION)
+			        (void) fprintf(stderr, "  status %d",
+								reply2.status);
+			    if (nfs_version == NFS_V3)
+			        (void) fprintf(stderr, "  status %d",
+								reply3.status);
+			    (void) fprintf(stderr, "\n");
+			}
+		    }
+		    break;
+	    }
+	} while (error > 0 && num_out_reqs > 0);
+
+	/* Scan for replies that have timed out */
+	if (num_out_reqs > 0) {
+	    sfs_gettime(&curr_time);
+	    for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (reqp->timeout.sec < curr_time.sec ||
+		    (reqp->timeout.sec == curr_time.sec &&
+		    reqp->timeout.usec < curr_time.usec)) {
+
+		    op_ptr->results.bad_calls++;
+		    Ops[TOTAL].results.bad_calls++;
+		    reqp->in_use = FALSE;
+		    num_out_reqs--;
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf (stderr,
+"[%d]:Biod write timed out %x start (%d.%06d) timeo (%d.%06d) now (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec,
+				curr_time.sec, curr_time.usec);
+			if (biod_poll_wait(NFS_client, 0) > 0) {
+			   (void) fprintf(stderr,
+				"[%d]:BIOD WRITE TIMEOUT - data on input queue!\n", calls);
+			}
+		    }
+		}
+	    }
+	}
+
+	/*
+	 * We go to sleep waiting for a reply if all the requests have
+	 * been sent and there are outstanding requests, or we cannot
+	 * send any more requests.
+	 */
+	if ((xfer_size <= 0 && num_out_reqs > 0) ||
+	    num_out_reqs == max_out_writes) {
+	    /*
+	     * Find the next outstanding request that will timeout
+	     * and take a time differential to use for the poll timeout.
+	     * If the differential is less than zero, then we go to the
+	     * top of the loop. Note that we are not picky on errors
+	     * returned by select, after the sleep we return to the top
+	     * of the loop so extensive error/status checking is not
+	     * needed.
+	     */
+	    tmp_time.sec = 0;
+	    tmp_time.usec = 0;
+	    for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (tmp_time.sec == 0 ||
+		    (reqp->timeout.sec < tmp_time.sec ||
+		     (reqp->timeout.sec == tmp_time.sec &&
+		      reqp->timeout.usec < tmp_time.usec))) {
+		    
+		     tmp_time = reqp->timeout;
+		}
+	    }
+	    if (tmp_time.sec == 0 && tmp_time.usec == 0)
+		continue;
+	    sfs_gettime(&curr_time);
+	    SUBTIME(tmp_time, curr_time);
+	    (void) biod_poll_wait(NFS_client,
+					tmp_time.sec * 1000000 + tmp_time.usec);
+	}
+    } /* while not done */
+
+ 
+    /*
+     * If we have not gotten an error and we were asked for an async write
+     * send a commit operation.
+     */  
+    if (ret && stab_flag != FILE_SYNC)
+	ret += (*Ops[COMMIT].funct)();
+
+    return (ret);
+
+} /* op_biod_write */
+
+
+/*
+ * perform an RPC read operation of length 'xfer_size'
+ */
+static int
+op_biod_read(
+    int 			xfer_size)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    int				max_cnt;	/* packet ctrs */
+    char			buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
+    readargs			args2;
+    readres			reply2;		/* the reply */
+    READ3args			args3;
+    READ3res			reply3;		/* the reply */
+    int				size;
+    struct ladtime		curr_time;
+    struct ladtime		call_timeout;
+    struct ladtime		tmp_time;
+    struct biod_req		*reqp;
+    int				ret;		/* ret val == call success */
+    int				num_out_reqs;	/* # of outstanding writes */
+    int				i;
+    int				error;
+    int32_t			offset;
+    static int		calls = 0;
+
+    calls++;
+
+    if (nfs_version != NFS_VERSION && nfs_version != NFS_V3)
+	return (0);
+
+    op_ptr = &Ops[READ];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args2.file, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+    (void) memmove((char *) &args3.file, (char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    /*
+     * Don't allow a read of less than one block size
+     */
+    if (xfer_size < Bytes_per_block)
+        xfer_size = Bytes_per_block;
+ 
+
+    /* Calculate the number of NFS reads required */
+    max_cnt = xfer_size / Bytes_per_block;
+    if ((xfer_size % Bytes_per_block) != 0) {
+	    max_cnt++;
+    }
+
+    /* check our stats to see if this would overflow */
+    if (!Timed_run) {
+	if (op_ptr->target_calls > 0 &&
+	    (op_ptr->results.good_calls + max_cnt) > op_ptr->target_calls) {
+	    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+	}
+    }
+
+    args2.offset = 0;
+    args3.offset._p._l = args3.offset._p._u = 0;
+
+    /*
+     * randomly choose an offset that is a multiple of the block size
+     * and constrained by making the transfer fit within the file
+     */
+    if (fh_size(Cur_file_ptr) > xfer_size) {
+	offset = Bytes_per_block * (sfs_random() %
+			    (((fh_size(Cur_file_ptr) - xfer_size)
+			    / Bytes_per_block) + 1));
+	args2.offset = offset;
+	args3.offset._p._u = 0;
+	args3.offset._p._l = offset;
+    }
+
+    size = Bytes_per_block;
+    args2.count = size;
+    args3.count = size;
+    args2.totalcount = size;	/* unused */
+
+    /* Have lower layers fill in the data directly.  */
+    reply2.readres_u.reply.data.data_val = buf;
+    reply3.res_u.ok.data.data_val = buf;
+
+    if (DEBUG_CHILD_OPS) {
+	(void) fprintf(stderr, "read: %d buffers xfer_size %d\n",
+			  max_cnt, xfer_size);
+	(void) fflush(stderr);
+    }
+
+    /* Mark all request slots as not in use */
+    for (reqp = biod_reqp, i = 0; i < max_biod_reqs; i++, reqp++) {
+	reqp->in_use = FALSE;
+    }
+
+    if (Current_test_phase < Warmup_phase) {
+	call_timeout.sec = Nfs_timers[Init].tv_sec;
+	call_timeout.usec = Nfs_timers[Init].tv_usec;
+    } else {
+	call_timeout.sec = Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+    }
+
+    /* capture length for possible dump */
+    Dump_length = fh_size(Cur_file_ptr);
+
+    /* make the call(s) now */
+    num_out_reqs = 0;
+    while (xfer_size > 0 || num_out_reqs > 0) {
+	/*
+	 * Send out calls async until either the maximum number of outstanding
+	 * requests has been reached or there are no more requests to make.
+	 */
+	while (num_out_reqs < max_out_reads && xfer_size > 0) {
+
+	    /* find an empty read request slot */
+	    for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    break;
+		}
+	    }
+
+	    if (xfer_size < size) {
+		size = xfer_size;
+		args2.count = xfer_size;
+		args3.count = xfer_size;
+		args2.totalcount = xfer_size;		/* unused */
+	    }
+	    xfer_size -= size;
+
+	    sfs_gettime(&reqp->start);
+	    if (nfs_version == NFS_VERSION) {
+		reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC_READ,
+					xdr_read, (char *) &args2);
+		if (reqp->xid != 0) {
+		    /* capture count and offset for possible dump */
+		    reqp->count = args2.count;
+		    reqp->offset = args2.offset;
+		    reqp->timeout = reqp->start;
+		    ADDTIME(reqp->timeout, call_timeout);
+		    reqp->in_use = TRUE;
+		    num_out_reqs++;
+		}
+	    } else if (nfs_version == NFS_V3) {
+		reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC3_READ,
+					xdr_READ3args, (char *) &args3);
+		if (reqp->xid != 0) {
+		    /* capture count and offset for possible dump */
+		    reqp->count = args3.count;
+		    reqp->offset = args3.offset._p._l;
+		    reqp->timeout = reqp->start;
+		    ADDTIME(reqp->timeout, call_timeout);
+		    reqp->in_use = TRUE;
+		    num_out_reqs++;
+		}
+	    }
+
+	    args2.offset += size;
+	    args3.offset._p._l += size;
+	    if (biod_poll_wait(NFS_client, 0) > 0) {
+		break;
+	    }
+	} /* while can make an async call */
+
+	/*
+	 * Process replies while there is data on the socket buffer.
+	 * Just do polls on the select, no sleeping occurs in this loop.
+	 */
+	do {
+	    error = biod_poll_wait(NFS_client, 0);
+	    switch (error) {
+		case -1:
+		    if (errno == EINTR) {
+			error = 1;
+			continue;
+		    }
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf(stderr,
+					"%s:[%d]: biod_poll_wait error\n",
+					sfs_Myname, calls);
+			(void) fflush(stderr);
+		    }
+		    break;
+
+		case 0:
+		    break;
+
+
+		default:
+		    if (nfs_version == NFS_VERSION)
+		        reqp = biod_get_reply(NFS_client, xdr_read,
+					  (char *) &reply2,
+					  &Nfs_timers[op_ptr->call_class]);
+		    if (nfs_version == NFS_V3)
+		        reqp = biod_get_reply(NFS_client, xdr_READ3res,
+					  (char *) &reply3,
+					  &Nfs_timers[op_ptr->call_class]);
+
+		    /*
+		     * If biod_get_reply returns NULL then we got an RPC
+		     * level error, probably a dropped fragment or the
+		     * remains of a previous partial request.
+		     */
+		    if (reqp == (struct biod_req *)NULL) {
+			error = 0;
+			break;
+		    }
+
+		    /*
+		     * We have a valid response, check if procedure completed
+		     * correctly.
+		     */
+		    if ((nfs_version == NFS_VERSION &&
+						reply2.status == NFS_OK) ||
+			 (nfs_version == NFS_V3 &&
+						reply3.status == NFS3_OK)) {
+			Cur_file_ptr->state = Exists;
+			if (DEBUG_CHILD_RPC) {
+			    (void) fprintf(stderr, "%s: READ %s %d bytes offset %d\n",
+			    	   sfs_Myname, Cur_filename, reqp->count, reqp->offset);
+			    (void) fflush(stderr);
+			}
+			/*
+			 * In updating attributes we may get replies out
+			 * of order.  We blindly update the attributes
+			 * which may cause old attributes to be stored.
+			 * XXX We should check for old attributes.
+			 */
+			if (nfs_version == NFS_VERSION) {
+			    Cur_file_ptr->attributes2 =
+					reply2.readres_u.reply.attributes;
+			    /* capture count and offset for possible dump */
+			    Dump_count = reply2.readres_u.reply.data.data_len;
+			}
+			if (nfs_version == NFS_V3) {
+			    Cur_file_ptr->attributes3 =
+					reply3.res_u.ok.file_attributes.attr;
+			    /* capture count and offset for possible dump */
+			    Dump_count = reply3.res_u.ok.data.data_len;
+			}
+
+			Dump_offset = reqp->offset;
+			sfs_elapsedtime(op_ptr, &reqp->start, &reqp->stop);
+			op_ptr->results.good_calls++;
+			Ops[TOTAL].results.good_calls++;
+			ret++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+		    } else {
+			op_ptr->results.bad_calls++;
+			Ops[TOTAL].results.bad_calls++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+
+			if (DEBUG_CHILD_BIOD) {
+			    (void) fprintf(stderr,
+				    "[%d]:BIOD READ FAILED: xid %x",
+				    calls, reqp->xid);
+
+			    if (nfs_version == NFS_VERSION)
+			        (void) fprintf(stderr, "  status %d",
+								reply2.status);
+			    if (nfs_version == NFS_V3)
+			        (void) fprintf(stderr, "  status %d",
+								reply3.status);
+			    (void) fprintf(stderr, "\n");
+			}
+		    }
+		    break;
+	    } /* switch */
+	} while (error > 0 && num_out_reqs > 0);
+
+	/* Scan for replies that have timed out */
+	if (num_out_reqs > 0) {
+	    sfs_gettime(&curr_time);
+	    for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (reqp->timeout.sec < curr_time.sec ||
+		    (reqp->timeout.sec == curr_time.sec &&
+		     reqp->timeout.usec < curr_time.usec)) {
+
+		    op_ptr->results.bad_calls++;
+		    Ops[TOTAL].results.bad_calls++;
+		    reqp->in_use = FALSE;
+		    num_out_reqs--;
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf (stderr,
+"[%d]:Biod read timed out %x (%d.%06d) now (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->timeout.sec, reqp->timeout.usec,
+				curr_time.sec, curr_time.usec);
+			if (biod_poll_wait(NFS_client, 0) > 0) {
+			   (void) fprintf(stderr,
+				"[%d]:BIOD READ TIMEOUT - data on input queue!\n", calls);
+			}
+		    }
+		}
+	    }
+	}
+
+	/*
+	 * We go to sleep waiting for a reply if all the requests have
+	 * been sent and there are outstanding requests, or we cannot
+	 * send any more requests.
+	 */
+	if ((xfer_size <= 0 && num_out_reqs > 0) ||
+	    num_out_reqs == max_out_reads) {
+	    /*
+	     * Find the next outstanding request that will timeout
+	     * and take a time differential to use for the poll timeout.
+	     * If the differential is less than zero, then we go to the
+	     * top of the loop. Note that we are not picky on errors
+	     * returned by select, after the sleep we return to the top
+	     * of the loop so extensive error/status checking is not
+	     * needed.
+	     */
+	    tmp_time.sec = 0;
+	    tmp_time.usec = 0;
+	    for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (tmp_time.sec == 0 ||
+		    (reqp->timeout.sec < tmp_time.sec ||
+		     (reqp->timeout.sec == tmp_time.sec &&
+		      reqp->timeout.usec < tmp_time.usec))) {
+		    
+		     tmp_time = reqp->timeout;
+		}
+	    }
+	    if (tmp_time.sec == 0 && tmp_time.usec == 0)
+		continue;
+	    sfs_gettime(&curr_time);
+	    SUBTIME(tmp_time, curr_time);
+	    (void) biod_poll_wait(NFS_client,
+					tmp_time.sec * 1000000 + tmp_time.usec);
+	}
+    } /* while not done */
+
+    return(ret);
+
+} /* op_biod_read */
+
+#endif
+
+/*
+ * ----------------------  Async RPC Support Routines  ----------------------
+ */
+
+/*
+ * biod_clnt_call()
+ *
+ * Returns XID indicating success, 0 indicating failure.
+ */
+uint32_t
+biod_clnt_call(
+    CLIENT		*clnt_handlep,
+    uint32_t		proc,
+    xdrproc_t		xargs,
+    void		*argsp)
+{
+    struct timeval timeout;
+    uint32_t xid;
+
+    /*
+     * Set timeouts to be zero to force message passing semantics.
+     */
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+
+    if ((clnt_call(clnt_handlep, proc, xargs, argsp, NULL,
+					&xid, timeout)) != RPC_TIMEDOUT) {
+	clnt_perror(clnt_handlep, "biod_clnt_call failed");
+	return (0);
+    }
+
+    return (xid);
+} /* biod_clnt_call */
+
+
+/*
+ * biod_get_reply()
+ *
+ * Returns pointer to the biod_req struct entry that a reply was received
+ * for.  Returns NULL if an error was detected.
+ * NOTES:
+ * 1) This routine should only be called when it is known that there is
+ *    data waiting on the socket.
+ */
+static struct biod_req *
+biod_get_reply(
+    CLIENT		*clnt_handlep,
+    xdrproc_t		xresults,
+    void		*resultsp,
+    struct timeval	*tv)
+{
+    uint32_t		xid;
+    int			i;
+    int			cnt = 0;
+    bool_t		res;
+    uint32_t		xids[MAX_BIODS];
+
+    /*
+     * Load list of valid outstanding xids
+     */
+    for (i = 0; i < max_biod_reqs; i++) {
+        if (biod_reqp[i].in_use == TRUE)
+	    xids[cnt++] = biod_reqp[i].xid;
+    }
+
+    if (cnt == 0)
+	return (NULL);
+
+    if ((res = clnt_getreply(clnt_handlep, xresults,
+			resultsp, cnt, xids, &xid, tv)) != RPC_SUCCESS) {
+	if (DEBUG_CHILD_BIOD) {
+		if (res == RPC_CANTDECODERES) {
+			(void) fprintf(stderr, "No xid matched, found %x\n",
+				xid);
+		}
+	}
+	return (NULL);
+    }
+
+    /*
+     * Scan to find XID matched in the outstanding request queue.
+     */
+    for (i = 0; i < max_biod_reqs; i++) {
+        if (biod_reqp[i].in_use == TRUE && biod_reqp[i].xid == xid) {
+	    sfs_gettime(&(biod_reqp[i].stop));
+	    return (&biod_reqp[i]);
+        }
+    }
+
+    return ((struct biod_req *)0);
+} /* biod_get_reply */
+
+/*
+ * biod_poll_wait()
+ *
+ * Returns -1 on error, 0 for no data available, > 0 to indicate data available
+ */
+int
+biod_poll_wait(
+    CLIENT		*clnt_handlep,
+    uint32_t		usecs)
+{
+    return (clnt_poll(clnt_handlep, usecs));
+} /* biod_poll_wait */
+
diff --git a/TBBT/trace_play/sfs_c_bio.org b/TBBT/trace_play/sfs_c_bio.org
new file mode 100644
index 0000000..88c54f5
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_bio.org
@@ -0,0 +1,1012 @@
+#ifndef lint
+static char sfs_c_bioSid[] = "@(#)sfs_c_bio.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*
+ * ---------------------- sfs_c_bio.c ---------------------
+ *
+ *	Routines that attempt to simulate biod behavior
+ *
+ *	The routines contained here model biod behavior.  Simply call
+ *	biod_init() to replace regular calls to op_read() and op_write()
+ *	with calls to op_biod_read() and op_biod_write().  The variables
+ *	max_out_writes and max_out_reads control the maximum number of
+ *	outstanding writes and reads respectively.
+ *
+ *.Exported Routines
+ *	int	biod_init(int, int);
+ *	void	biod_turn_on(void);
+ *	void	op_biod_write(int, int, int);
+ *	void	op_biod_read(int);
+ *
+ *.Local Routines
+ *	uint32_t	biod_clnt_call(CLIENT *, uint32_t,
+ *						xdrproc_t, void *);
+ *	struct biod_req	*biod_get_reply(CLIENT *, xdrproc_t,
+ *						void *, struct timeval *);
+ *	int		biod_poll_wait(CLIENT *, uint32_t);
+ *
+ *.Revision_History
+ *	03-May-94	Robinson
+ *				History now kept in SCCS
+ *	03-Mar-92	0.1.0 Corbin
+ *					Added biod behavior
+ */
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+/*
+ * Information associated with outstanding read/write requests
+ */
+struct biod_req {
+    uint32_t		xid;		/* RPC transmission ID	*/
+    bool_t		in_use;		/* Indicates if the entry is in use */
+    unsigned int	count;		/* Count saved for Dump routines */
+    unsigned int	offset;		/* Offset saved for Dump routines */
+    struct ladtime	start;		/* Time RPC call was made */
+    struct ladtime	stop;		/* Time RPC reply was received */
+    struct ladtime	timeout;	/* Time RPC call will time out */
+};
+
+/*
+ * ----------------------  Static Declarations  ----------------------
+ */
+
+static int	max_out_writes;
+static int	max_out_reads;
+static int	max_biod_reqs = 0;
+static struct biod_req *biod_reqp;
+
+/* forward definitions for local functions */
+static uint32_t	biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
+static struct biod_req *biod_get_reply(CLIENT *, xdrproc_t,
+						void *, struct timeval *);
+static int	biod_poll_wait(CLIENT *, uint32_t);
+
+static int op_biod_write(int, int, int);
+static int op_biod_read(int);
+
+/*
+ * ----------------------  BIOD Support Routines  ----------------------
+ */
+
+/*
+ * biod_init()
+ *
+ * This function is called during the initialization phase. It performs
+ * the following tasks:
+ *	- Allocate memory to hold outstanding biod request information
+ *
+ * Returns 0 for OK, -1 for failure
+ */
+int
+biod_init(
+    int			out_writes,
+    int			out_reads)
+{
+    max_out_writes = MAXIMUM(1, out_writes);
+    max_out_reads = MAXIMUM(1, out_reads);
+    max_biod_reqs = MAXIMUM(out_writes, out_reads);
+
+    biod_reqp = (struct biod_req *) calloc(max_biod_reqs,
+					   sizeof (struct biod_req));
+    if (biod_reqp == (struct biod_req *)0) {
+	(void) fprintf(stderr, "%s: biod_init calloc failed.\n", sfs_Myname);
+	(void) fflush(stderr);
+	return (-1);
+    }
+
+    return (0);
+} /* biod_init */
+
+
+/*
+ *	- Change the operation functions for reads and writes to use the
+ *	  biod routines. This step should be done last to allow callers
+ *	  to still run with the old op functions if the biod initialization
+ *	  fails.
+ */
+void
+biod_turn_on(void)
+{
+    Ops[WRITE].funct = op_biod_write;
+    Ops[READ].funct = op_biod_read;
+}
+
+/*
+ * biod_term()
+ *
+ * This function is called during the termination phase to free any resources
+ * allocated by the biod_init() routine. It performs the following tasks:
+ *	- Frees memory associated with outstanding biod request information
+ *	- Frees the biod client handle
+ */
+void
+biod_term(void)
+{
+    if (max_biod_reqs) {
+	free(biod_reqp);
+    }
+} /* biod_term */
+
+/*
+ * Perform and RPC biod style write operation of length 'xfer_size'.
+ * If 'append_flag' is true, then write the data to the end of the file.
+ */
+static int
+op_biod_write(
+    int			xfer_size,
+    int			append_flag,
+    int			stab_flag)
+{
+    sfs_op_type		*op_ptr;	/* per operation info */
+    static char		*buf = NULL;	/* the data buffer */
+    unsigned int	size;		/* size of data write */
+    int			max_cnt;
+    attrstat		reply2;		/* the reply */
+    writeargs		args2;
+    WRITE3res		reply3;		/* the reply */
+    WRITE3args		args3;
+    struct ladtime	curr_time;
+    struct ladtime	tmp_time;
+    struct ladtime	call_timeout;
+    struct biod_req	*reqp;
+    int			ret;		/* ret val == call success */
+    int			num_out_reqs;	/* # of outstanding writes */
+    int			i;
+    int			error;
+    int32_t		offset;
+    static int		calls = 0;
+
+    calls++;
+
+    if (nfs_version != NFS_VERSION && nfs_version != NFS_V3)
+	return (0);
+
+    /*
+     * Initialize write buffer to known value
+     */  
+    if (buf == NULL) {
+        buf = init_write_buffer();
+    }
+
+
+    /*
+     * For now we treat DATA_SYNC to be the same as FILE_SYNC.
+     * If it is not a V3 op then it must always be stable
+     */  
+    if (stab_flag == DATA_SYNC || nfs_version != NFS_V3)
+        stab_flag = FILE_SYNC;
+
+    op_ptr = &Ops[WRITE];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args2.file, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+    (void) memmove((char *) &args3.file, (char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    args2.beginoffset = 0;	/* unused */
+
+    if (append_flag == 1) {
+	args2.offset = Cur_file_ptr->attributes2.size;
+	args3.offset = Cur_file_ptr->attributes3.size;
+    } else {
+	if (fh_size(Cur_file_ptr) > xfer_size) {
+	    offset = Bytes_per_block * (sfs_random() %
+			    (((fh_size(Cur_file_ptr) - xfer_size)
+			    / Bytes_per_block) + 1));
+	    args2.offset = offset;
+	    args3.offset._p._u = 0;
+	    args3.offset._p._l = offset;
+	} else {
+	    args2.offset = 0;
+	    args3.offset._p._u = args3.offset._p._l = 0;
+	}
+    }
+
+    size = Bytes_per_block;
+    args2.totalcount = size;	/* unused */
+    args2.data.data_len = size;
+    args2.data.data_val = buf;
+    args3.data.data_len = size;
+    args3.data.data_val = buf;
+    args3.count = size;
+    args3.stable = stab_flag;
+
+    /* Calculate the number of NFS writes required */
+    max_cnt = xfer_size / Bytes_per_block;
+    if ((xfer_size % Bytes_per_block) != 0) {
+	max_cnt++;
+    }
+
+    /* check our stats to see if this would overflow */
+    if (!Timed_run) {
+	if (op_ptr->target_calls > 0 &&
+	   (op_ptr->results.good_calls + max_cnt) > op_ptr->target_calls) {
+	    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+	}
+    }
+
+    if (DEBUG_CHILD_OPS) {
+	(void) fprintf(stderr, "write: %d buffers xfer_size %d\n",
+			  max_cnt, xfer_size);
+	(void) fflush(stderr);
+    }
+
+    /* Mark all request slots as not in use */
+    for (reqp = biod_reqp, i = 0; i < max_biod_reqs; i++, reqp++) {
+	reqp->in_use = FALSE;
+    }
+
+    if (Current_test_phase < Warmup_phase) {
+	call_timeout.sec = Nfs_timers[Init].tv_sec;
+	call_timeout.usec = Nfs_timers[Init].tv_usec;
+    } else {
+	call_timeout.sec = Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+    }
+
+    /* capture length for possible dump */
+    Dump_length = fh_size(Cur_file_ptr);
+ 
+    /* make the call(s) now */
+    num_out_reqs = 0;
+    while (xfer_size > 0 || num_out_reqs > 0) {
+	/*
+	 * Send out calls async until either the maximum number of outstanding
+	 * requests has been reached or there are no more requests to make.
+	 */
+	while (num_out_reqs < max_out_writes && xfer_size > 0) {
+
+	    /* find an empty write request slot */
+	    for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    break;
+		}
+	    }
+
+	    if (xfer_size < size) {
+		size = xfer_size;
+		args2.data.data_len = xfer_size;
+		args2.totalcount = xfer_size;		/* unused */
+		args3.data.data_len = xfer_size;
+		args3.count = xfer_size;
+	    }
+	    xfer_size -= size;
+
+	    sfs_gettime(&reqp->start);
+	    if (nfs_version == NFS_V3) {
+		    reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC3_WRITE,
+					xdr_WRITE3args, (char *) &args3);
+		    if (reqp->xid != 0) {
+			/* capture count and offset for possible dump */
+			reqp->count = args3.data.data_len;
+			reqp->offset = args3.offset._p._l;
+			reqp->timeout = reqp->start;
+			ADDTIME(reqp->timeout, call_timeout);
+			reqp->in_use = TRUE;
+			num_out_reqs++;
+	    	    }
+	    }
+	    if (nfs_version == NFS_VERSION) {
+		    reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC_WRITE,
+					xdr_write, (char *) &args2);
+		    if (reqp->xid != 0) {
+			/* capture count and offset for possible dump */
+			reqp->count = args2.data.data_len;
+			reqp->offset = args2.offset;
+			reqp->timeout = reqp->start;
+			ADDTIME(reqp->timeout, call_timeout);
+			reqp->in_use = TRUE;
+			num_out_reqs++;
+	    	    }
+	    }
+	    if (DEBUG_CHILD_BIOD) {
+		(void) fprintf (stderr,
+"[%d]:Biod write started xid %x start (%d.%06d) timeo (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec);
+	    }
+
+	    args2.offset += size;
+	    args3.offset._p._l += size;
+	    if (biod_poll_wait(NFS_client, 0) > 0) {
+		break;
+	    }
+	} /* while can make an async call */
+
+	/*
+	 * Process replies while there is data on the socket buffer.
+	 * Just do polls on the select, no sleeping occurs in this loop.
+	 */
+	do {
+	    error = biod_poll_wait(NFS_client, 0);
+	    switch (error) {
+		case -1:
+		    if (errno == EINTR) {
+			error = 1;
+			continue;
+		    }
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf(stderr, "%s:[%d]: biod_poll_wait error\n",
+					   sfs_Myname, calls);
+			(void) fflush(stderr);
+		    }
+		    break;
+
+		case 0:
+		    break;
+
+
+		default:
+		    if (nfs_version == NFS_VERSION)
+			    reqp = biod_get_reply(NFS_client, xdr_write,
+					  (char *) &reply2,
+					  &Nfs_timers[op_ptr->call_class]);
+		    if (nfs_version == NFS_V3)
+			    reqp = biod_get_reply(NFS_client, xdr_WRITE3res,
+					  (char *) &reply3,
+					  &Nfs_timers[op_ptr->call_class]);
+
+		    /*
+		     * If biod_get_reply returns NULL then we got an RPC
+		     * level error, probably a dropped fragment or the
+		     * remains of a previous partial request.
+		     */
+		    if (reqp == (struct biod_req *)NULL) {
+			error = 0;
+			break;
+		    }
+
+		    /*
+		     * We have a valid response, check if procedure completed
+		     * correctly.
+		     */
+		    if ((nfs_version == NFS_VERSION &&
+			 reply2.status == NFS_OK) ||
+			 (nfs_version == NFS_V3 && reply3.status == NFS3_OK)) {
+			Cur_file_ptr->state = Exists;
+			/*
+			 * In updating attributes we may get replies out
+			 * of order.  We blindly update the attributes
+			 * which may cause old attributes to be stored.
+			 * XXX We should check for old attributes.
+			 */
+		        if (nfs_version == NFS_VERSION)
+			    Cur_file_ptr->attributes2 =
+					reply2.attrstat_u.attributes;
+		        if (nfs_version == NFS_V3)
+			    Cur_file_ptr->attributes3 =
+					reply3.res_u.ok.file_wcc.after.attr;
+			if (DEBUG_CHILD_RPC) {
+			    (void) fprintf(stderr,
+					"%s: WRITE %s %d bytes offset %d \n",
+					sfs_Myname, Cur_filename,
+					reqp->count, reqp->offset);
+			    (void) fflush(stderr);
+			}
+
+			/* capture count and offset for possible dump */
+			Dump_count = reqp->count;
+			Dump_offset = reqp->offset;
+			sfs_elapsedtime(op_ptr, &reqp->start, &reqp->stop);
+			op_ptr->results.good_calls++;
+			Ops[TOTAL].results.good_calls++;
+			ret++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+		        if (DEBUG_CHILD_BIOD) {
+			    (void) fprintf (stderr,
+"[%d]:Biod write succeded xid %x start (%d.%06d) timeo (%d.%06d) stop (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec,
+				reqp->stop.sec, reqp->stop.usec);
+			}
+		    } else {
+			op_ptr->results.bad_calls++;
+			Ops[TOTAL].results.bad_calls++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+		        if (DEBUG_CHILD_BIOD) {
+			    (void) fprintf (stderr,
+"[%d]:Biod write failed xid %x start (%d.%06d) timeo (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec);
+
+			    (void) fprintf(stderr,
+				    "[%d]:BIOD WRITE FAILED: xid %x",
+				    calls, reqp->xid);
+
+			    if (nfs_version == NFS_VERSION)
+			        (void) fprintf(stderr, "  status %d",
+								reply2.status);
+			    if (nfs_version == NFS_V3)
+			        (void) fprintf(stderr, "  status %d",
+								reply3.status);
+			    (void) fprintf(stderr, "\n");
+			}
+		    }
+		    break;
+	    }
+	} while (error > 0 && num_out_reqs > 0);
+
+	/* Scan for replies that have timed out */
+	if (num_out_reqs > 0) {
+	    sfs_gettime(&curr_time);
+	    for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (reqp->timeout.sec < curr_time.sec ||
+		    (reqp->timeout.sec == curr_time.sec &&
+		    reqp->timeout.usec < curr_time.usec)) {
+
+		    op_ptr->results.bad_calls++;
+		    Ops[TOTAL].results.bad_calls++;
+		    reqp->in_use = FALSE;
+		    num_out_reqs--;
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf (stderr,
+"[%d]:Biod write timed out %x start (%d.%06d) timeo (%d.%06d) now (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->start.sec, reqp->start.usec,
+				reqp->timeout.sec, reqp->timeout.usec,
+				curr_time.sec, curr_time.usec);
+			if (biod_poll_wait(NFS_client, 0) > 0) {
+			   (void) fprintf(stderr,
+				"[%d]:BIOD WRITE TIMEOUT - data on input queue!\n", calls);
+			}
+		    }
+		}
+	    }
+	}
+
+	/*
+	 * We go to sleep waiting for a reply if all the requests have
+	 * been sent and there are outstanding requests, or we cannot
+	 * send any more requests.
+	 */
+	if ((xfer_size <= 0 && num_out_reqs > 0) ||
+	    num_out_reqs == max_out_writes) {
+	    /*
+	     * Find the next outstanding request that will timeout
+	     * and take a time differential to use for the poll timeout.
+	     * If the differential is less than zero, then we go to the
+	     * top of the loop. Note that we are not picky on errors
+	     * returned by select, after the sleep we return to the top
+	     * of the loop so extensive error/status checking is not
+	     * needed.
+	     */
+	    tmp_time.sec = 0;
+	    tmp_time.usec = 0;
+	    for (reqp = biod_reqp, i = 0; i < max_out_writes; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (tmp_time.sec == 0 ||
+		    (reqp->timeout.sec < tmp_time.sec ||
+		     (reqp->timeout.sec == tmp_time.sec &&
+		      reqp->timeout.usec < tmp_time.usec))) {
+		    
+		     tmp_time = reqp->timeout;
+		}
+	    }
+	    if (tmp_time.sec == 0 && tmp_time.usec == 0)
+		continue;
+	    sfs_gettime(&curr_time);
+	    SUBTIME(tmp_time, curr_time);
+	    (void) biod_poll_wait(NFS_client,
+					tmp_time.sec * 1000000 + tmp_time.usec);
+	}
+    } /* while not done */
+
+ 
+    /*
+     * If we have not gotten an error and we were asked for an async write
+     * send a commit operation.
+     */  
+    if (ret && stab_flag != FILE_SYNC)
+	ret += (*Ops[COMMIT].funct)();
+
+    return (ret);
+
+} /* op_biod_write */
+
+
+/*
+ * perform an RPC read operation of length 'xfer_size'
+ */
+static int
+op_biod_read(
+    int 			xfer_size)
+{
+    sfs_op_type			*op_ptr;	/* per operation info */
+    int				max_cnt;	/* packet ctrs */
+    char			buf[DEFAULT_MAX_BUFSIZE];/* data buffer */
+    readargs			args2;
+    readres			reply2;		/* the reply */
+    READ3args			args3;
+    READ3res			reply3;		/* the reply */
+    int				size;
+    struct ladtime		curr_time;
+    struct ladtime		call_timeout;
+    struct ladtime		tmp_time;
+    struct biod_req		*reqp;
+    int				ret;		/* ret val == call success */
+    int				num_out_reqs;	/* # of outstanding writes */
+    int				i;
+    int				error;
+    int32_t			offset;
+    static int		calls = 0;
+
+    calls++;
+
+    if (nfs_version != NFS_VERSION && nfs_version != NFS_V3)
+	return (0);
+
+    op_ptr = &Ops[READ];
+    ret = 0;
+
+    /* set up the arguments */
+    (void) memmove((char *) &args2.file, (char *) &Cur_file_ptr->fh2,
+			NFS_FHSIZE);
+    (void) memmove((char *) &args3.file, (char *) &Cur_file_ptr->fh3,
+			sizeof (nfs_fh3));
+
+    /*
+     * Don't allow a read of less than one block size
+     */
+    if (xfer_size < Bytes_per_block)
+        xfer_size = Bytes_per_block;
+ 
+
+    /* Calculate the number of NFS reads required */
+    max_cnt = xfer_size / Bytes_per_block;
+    if ((xfer_size % Bytes_per_block) != 0) {
+	    max_cnt++;
+    }
+
+    /* check our stats to see if this would overflow */
+    if (!Timed_run) {
+	if (op_ptr->target_calls > 0 &&
+	    (op_ptr->results.good_calls + max_cnt) > op_ptr->target_calls) {
+	    max_cnt = op_ptr->target_calls - op_ptr->results.good_calls;
+	}
+    }
+
+    args2.offset = 0;
+    args3.offset._p._l = args3.offset._p._u = 0;
+
+    /*
+     * randomly choose an offset that is a multiple of the block size
+     * and constrained by making the transfer fit within the file
+     */
+    if (fh_size(Cur_file_ptr) > xfer_size) {
+	offset = Bytes_per_block * (sfs_random() %
+			    (((fh_size(Cur_file_ptr) - xfer_size)
+			    / Bytes_per_block) + 1));
+	args2.offset = offset;
+	args3.offset._p._u = 0;
+	args3.offset._p._l = offset;
+    }
+
+    size = Bytes_per_block;
+    args2.count = size;
+    args3.count = size;
+    args2.totalcount = size;	/* unused */
+
+    /* Have lower layers fill in the data directly.  */
+    reply2.readres_u.reply.data.data_val = buf;
+    reply3.res_u.ok.data.data_val = buf;
+
+    if (DEBUG_CHILD_OPS) {
+	(void) fprintf(stderr, "read: %d buffers xfer_size %d\n",
+			  max_cnt, xfer_size);
+	(void) fflush(stderr);
+    }
+
+    /* Mark all request slots as not in use */
+    for (reqp = biod_reqp, i = 0; i < max_biod_reqs; i++, reqp++) {
+	reqp->in_use = FALSE;
+    }
+
+    if (Current_test_phase < Warmup_phase) {
+	call_timeout.sec = Nfs_timers[Init].tv_sec;
+	call_timeout.usec = Nfs_timers[Init].tv_usec;
+    } else {
+	call_timeout.sec = Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+    }
+
+    /* capture length for possible dump */
+    Dump_length = fh_size(Cur_file_ptr);
+
+    /* make the call(s) now */
+    num_out_reqs = 0;
+    while (xfer_size > 0 || num_out_reqs > 0) {
+	/*
+	 * Send out calls async until either the maximum number of outstanding
+	 * requests has been reached or there are no more requests to make.
+	 */
+	while (num_out_reqs < max_out_reads && xfer_size > 0) {
+
+	    /* find an empty read request slot */
+	    for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    break;
+		}
+	    }
+
+	    if (xfer_size < size) {
+		size = xfer_size;
+		args2.count = xfer_size;
+		args3.count = xfer_size;
+		args2.totalcount = xfer_size;		/* unused */
+	    }
+	    xfer_size -= size;
+
+	    sfs_gettime(&reqp->start);
+	    if (nfs_version == NFS_VERSION) {
+		reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC_READ,
+					xdr_read, (char *) &args2);
+		if (reqp->xid != 0) {
+		    /* capture count and offset for possible dump */
+		    reqp->count = args2.count;
+		    reqp->offset = args2.offset;
+		    reqp->timeout = reqp->start;
+		    ADDTIME(reqp->timeout, call_timeout);
+		    reqp->in_use = TRUE;
+		    num_out_reqs++;
+		}
+	    } else if (nfs_version == NFS_V3) {
+		reqp->xid = biod_clnt_call(NFS_client,
+					(uint32_t)NFSPROC3_READ,
+					xdr_READ3args, (char *) &args3);
+		if (reqp->xid != 0) {
+		    /* capture count and offset for possible dump */
+		    reqp->count = args3.count;
+		    reqp->offset = args3.offset._p._l;
+		    reqp->timeout = reqp->start;
+		    ADDTIME(reqp->timeout, call_timeout);
+		    reqp->in_use = TRUE;
+		    num_out_reqs++;
+		}
+	    }
+
+	    args2.offset += size;
+	    args3.offset._p._l += size;
+	    if (biod_poll_wait(NFS_client, 0) > 0) {
+		break;
+	    }
+	} /* while can make an async call */
+
+	/*
+	 * Process replies while there is data on the socket buffer.
+	 * Just do polls on the select, no sleeping occurs in this loop.
+	 */
+	do {
+	    error = biod_poll_wait(NFS_client, 0);
+	    switch (error) {
+		case -1:
+		    if (errno == EINTR) {
+			error = 1;
+			continue;
+		    }
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf(stderr,
+					"%s:[%d]: biod_poll_wait error\n",
+					sfs_Myname, calls);
+			(void) fflush(stderr);
+		    }
+		    break;
+
+		case 0:
+		    break;
+
+
+		default:
+		    if (nfs_version == NFS_VERSION)
+		        reqp = biod_get_reply(NFS_client, xdr_read,
+					  (char *) &reply2,
+					  &Nfs_timers[op_ptr->call_class]);
+		    if (nfs_version == NFS_V3)
+		        reqp = biod_get_reply(NFS_client, xdr_READ3res,
+					  (char *) &reply3,
+					  &Nfs_timers[op_ptr->call_class]);
+
+		    /*
+		     * If biod_get_reply returns NULL then we got an RPC
+		     * level error, probably a dropped fragment or the
+		     * remains of a previous partial request.
+		     */
+		    if (reqp == (struct biod_req *)NULL) {
+			error = 0;
+			break;
+		    }
+
+		    /*
+		     * We have a valid response, check if procedure completed
+		     * correctly.
+		     */
+		    if ((nfs_version == NFS_VERSION &&
+						reply2.status == NFS_OK) ||
+			 (nfs_version == NFS_V3 &&
+						reply3.status == NFS3_OK)) {
+			Cur_file_ptr->state = Exists;
+			if (DEBUG_CHILD_RPC) {
+			    (void) fprintf(stderr, "%s: READ %s %d bytes offset %d\n",
+			    	   sfs_Myname, Cur_filename, reqp->count, reqp->offset);
+			    (void) fflush(stderr);
+			}
+			/*
+			 * In updating attributes we may get replies out
+			 * of order.  We blindly update the attributes
+			 * which may cause old attributes to be stored.
+			 * XXX We should check for old attributes.
+			 */
+			if (nfs_version == NFS_VERSION) {
+			    Cur_file_ptr->attributes2 =
+					reply2.readres_u.reply.attributes;
+			    /* capture count and offset for possible dump */
+			    Dump_count = reply2.readres_u.reply.data.data_len;
+			}
+			if (nfs_version == NFS_V3) {
+			    Cur_file_ptr->attributes3 =
+					reply3.res_u.ok.file_attributes.attr;
+			    /* capture count and offset for possible dump */
+			    Dump_count = reply3.res_u.ok.data.data_len;
+			}
+
+			Dump_offset = reqp->offset;
+			sfs_elapsedtime(op_ptr, &reqp->start, &reqp->stop);
+			op_ptr->results.good_calls++;
+			Ops[TOTAL].results.good_calls++;
+			ret++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+		    } else {
+			op_ptr->results.bad_calls++;
+			Ops[TOTAL].results.bad_calls++;
+			reqp->in_use = FALSE;
+			num_out_reqs--;
+
+			if (DEBUG_CHILD_BIOD) {
+			    (void) fprintf(stderr,
+				    "[%d]:BIOD READ FAILED: xid %x",
+				    calls, reqp->xid);
+
+			    if (nfs_version == NFS_VERSION)
+			        (void) fprintf(stderr, "  status %d",
+								reply2.status);
+			    if (nfs_version == NFS_V3)
+			        (void) fprintf(stderr, "  status %d",
+								reply3.status);
+			    (void) fprintf(stderr, "\n");
+			}
+		    }
+		    break;
+	    } /* switch */
+	} while (error > 0 && num_out_reqs > 0);
+
+	/* Scan for replies that have timed out */
+	if (num_out_reqs > 0) {
+	    sfs_gettime(&curr_time);
+	    for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (reqp->timeout.sec < curr_time.sec ||
+		    (reqp->timeout.sec == curr_time.sec &&
+		     reqp->timeout.usec < curr_time.usec)) {
+
+		    op_ptr->results.bad_calls++;
+		    Ops[TOTAL].results.bad_calls++;
+		    reqp->in_use = FALSE;
+		    num_out_reqs--;
+		    if (DEBUG_CHILD_BIOD) {
+			(void) fprintf (stderr,
+"[%d]:Biod read timed out %x (%d.%06d) now (%d.%06d)\n",
+				calls, reqp->xid,
+				reqp->timeout.sec, reqp->timeout.usec,
+				curr_time.sec, curr_time.usec);
+			if (biod_poll_wait(NFS_client, 0) > 0) {
+			   (void) fprintf(stderr,
+				"[%d]:BIOD READ TIMEOUT - data on input queue!\n", calls);
+			}
+		    }
+		}
+	    }
+	}
+
+	/*
+	 * We go to sleep waiting for a reply if all the requests have
+	 * been sent and there are outstanding requests, or we cannot
+	 * send any more requests.
+	 */
+	if ((xfer_size <= 0 && num_out_reqs > 0) ||
+	    num_out_reqs == max_out_reads) {
+	    /*
+	     * Find the next outstanding request that will timeout
+	     * and take a time differential to use for the poll timeout.
+	     * If the differential is less than zero, then we go to the
+	     * top of the loop. Note that we are not picky on errors
+	     * returned by select, after the sleep we return to the top
+	     * of the loop so extensive error/status checking is not
+	     * needed.
+	     */
+	    tmp_time.sec = 0;
+	    tmp_time.usec = 0;
+	    for (reqp = biod_reqp, i = 0; i < max_out_reads; i++, reqp++) {
+		if (reqp->in_use == FALSE) {
+		    continue;
+		}
+		if (tmp_time.sec == 0 ||
+		    (reqp->timeout.sec < tmp_time.sec ||
+		     (reqp->timeout.sec == tmp_time.sec &&
+		      reqp->timeout.usec < tmp_time.usec))) {
+		    
+		     tmp_time = reqp->timeout;
+		}
+	    }
+	    if (tmp_time.sec == 0 && tmp_time.usec == 0)
+		continue;
+	    sfs_gettime(&curr_time);
+	    SUBTIME(tmp_time, curr_time);
+	    (void) biod_poll_wait(NFS_client,
+					tmp_time.sec * 1000000 + tmp_time.usec);
+	}
+    } /* while not done */
+
+    return(ret);
+
+} /* op_biod_read */
+
+/*
+ * ----------------------  Async RPC Support Routines  ----------------------
+ */
+
+/*
+ * biod_clnt_call()
+ *
+ * Returns XID indicating success, 0 indicating failure.
+ */
+static uint32_t
+biod_clnt_call(
+    CLIENT		*clnt_handlep,
+    uint32_t		proc,
+    xdrproc_t		xargs,
+    void		*argsp)
+{
+    struct timeval timeout;
+    uint32_t xid;
+
+    /*
+     * Set timeouts to be zero to force message passing semantics.
+     */
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+
+    if ((clnt_call(clnt_handlep, proc, xargs, argsp, NULL,
+					&xid, timeout)) != RPC_TIMEDOUT) {
+	clnt_perror(clnt_handlep, "biod_clnt_call failed");
+	return (0);
+    }
+
+    return (xid);
+} /* biod_clnt_call */
+
+
+/*
+ * biod_get_reply()
+ *
+ * Returns pointer to the biod_req struct entry that a reply was received
+ * for.  Returns NULL if an error was detected.
+ * NOTES:
+ * 1) This routine should only be called when it is known that there is
+ *    data waiting on the socket.
+ */
+static struct biod_req *
+biod_get_reply(
+    CLIENT		*clnt_handlep,
+    xdrproc_t		xresults,
+    void		*resultsp,
+    struct timeval	*tv)
+{
+    uint32_t		xid;
+    int			i;
+    int			cnt = 0;
+    bool_t		res;
+    uint32_t		xids[MAX_BIODS];
+
+    /*
+     * Load list of valid outstanding xids
+     */
+    for (i = 0; i < max_biod_reqs; i++) {
+        if (biod_reqp[i].in_use == TRUE)
+	    xids[cnt++] = biod_reqp[i].xid;
+    }
+
+    if (cnt == 0)
+	return (NULL);
+
+    if ((res = clnt_getreply(clnt_handlep, xresults,
+			resultsp, cnt, xids, &xid, tv)) != RPC_SUCCESS) {
+	if (DEBUG_CHILD_BIOD) {
+		if (res == RPC_CANTDECODERES) {
+			(void) fprintf(stderr, "No xid matched, found %x\n",
+				xid);
+		}
+	}
+	return (NULL);
+    }
+
+    /*
+     * Scan to find XID matched in the outstanding request queue.
+     */
+    for (i = 0; i < max_biod_reqs; i++) {
+        if (biod_reqp[i].in_use == TRUE && biod_reqp[i].xid == xid) {
+	    sfs_gettime(&(biod_reqp[i].stop));
+	    return (&biod_reqp[i]);
+        }
+    }
+
+    return ((struct biod_req *)0);
+} /* biod_get_reply */
+
+
+/*
+ * biod_poll_wait()
+ *
+ * Returns -1 on error, 0 for no data available, > 0 to indicate data available
+ */
+static int
+biod_poll_wait(
+    CLIENT		*clnt_handlep,
+    uint32_t		usecs)
+{
+    return (clnt_poll(clnt_handlep, usecs));
+} /* biod_poll_wait */
diff --git a/TBBT/trace_play/sfs_c_chd.2thread.c b/TBBT/trace_play/sfs_c_chd.2thread.c
new file mode 100644
index 0000000..48ab54e
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_chd.2thread.c
@@ -0,0 +1,3509 @@
+#ifndef lint
+static char sfs_c_chdSid[] = "@(#)sfs_c_chd.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * -------------------------- sfs_c_chd.c -------------------------
+ *
+ *      The sfs child.  Routines to initialize child parameters,
+ *	initialize test directories, and generate load.
+ *
+ *.Exported_Routines
+ *	void child(int, float, int, char *);
+ *	void init_fileinfo(void);
+ *	void init_counters(void);
+ *	sfs_fh_type * randfh(int, int, uint_t, sfs_state_type,
+ *				sfs_file_type);
+ *	int check_access(struct *stat)
+ *	int check_fh_access();
+ *
+ *.Local_Routines
+ *	void check_call_rate(void);
+ *	void init_targets(void);
+ *	void init_dirlayout(void);
+ *	void init_rpc(void);
+ *	void init_testdir(void);
+ *	int do_op(void);
+ *	int op(int);
+ *
+ *.Revision_History
+ *	21-Aug-92	Wittle 		randfh() uses working set files array.
+ *					init_fileinfo() sets up working set.
+ *      02-Jul-92	Teelucksingh    Target file size now based on peak load
+ *					instead of BTDT.
+ *	04-Jan-92	Pawlowski	Added raw data dump hooks.
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+#include "rfs_c_def.h"
+#include "generic_hash.h"
+#include "nfsd_nfsfh_cust.h"
+
+extern struct hostent   *Server_hostent;
+
+#define PROB_SCALE 1000L
+#define _M_MODULUS 2147483647L /* (2**31)-1 */
+
+#define _GROUP_DIVISOR 500
+#define _FILES_PER_GROUP 4
+#define _MIN_GROUPS 12
+#define _WORKING_SET_AT_25_OPS_PER_SEC 975
+
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+extern uint32_t    biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
+extern enum clnt_stat proc_header(CLIENT *cl, xdrproc_t xdr_results, void *results_ptr);
+extern int  biod_poll_wait(CLIENT *, uint32_t);
+extern enum clnt_stat get_areply_udp (CLIENT * cl, uint32_t *xid, struct timeval *timeout);
+extern char * parse_name (char * t, char * buf);
+
+/* forward definitions for local functions */
+static int init_rpc(void);
+
+/* RFS: forward definitions for local functions */
+void init_ops(void);
+static void init_signal();
+extern void init_file_system (void);
+extern void init_dep_tab (void);
+static int read_trace(void);
+static void read_fh_map();
+static void init_play (char * mount_point);
+static void trace_play(void);
+void print_result(void);
+static int get_nextop(void);
+static int check_timeout(void);
+static struct biod_req * get_biod_req(int dep_tab_index);
+static int lookup_biod_req (int xid);
+static void init_time_offset(void);
+void adjust_play_window (int flag, int * poll_timeout);
+static int poll_and_get_reply (int usecs);
+static char * nfs3_strerror(int status);
+static void check_clock(void);
+static double time_so_far1(void);
+static double get_resolution(void);
+static void usage(void);
+void init_dep_tab_entry (int dep_index);
+extern inline fh_map_t * lookup_fh (char * trace_fh );
+static inline void finish_request (int biod_index, int dep_index, int status);
+static inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line);
+static inline char * find_lead_trace_fh(int proc, char * line);
+static inline char * find_reply_trace_fh (char * line);
+
+/*
+ * -------------  Per Child Load Generation Rate Variables  -----------
+ */
+static uint_t Calls_this_period; /* calls made during the current run period */
+static uint_t Calls_this_test;	/* calls made during the test so far */
+static uint_t Reqs_this_period;	/* reqs made during the current run period */
+static uint_t Reqs_this_test;	/* reqs made during the test so far */
+static uint_t Sleep_msec_this_test; /* msec slept during the test so far */
+static uint_t Sleep_msec_this_period;
+static uint_t Previous_chkpnt_msec; /* beginning time of current run period */
+static int Target_sleep_mspc;	/* targeted sleep time per call */
+
+static char io_buf[BUFSIZ];	/* io buffer for print out messages */
+
+char * sfs_Myname;
+int     Log_fd;                         /* log fd */
+char    Logname[NFS_MAXNAMLEN];         /* child processes sync logfile */
+int 	Validate = 0;					/* fake variable */
+int Child_num = 0;						/* fake: child index */
+int Tcp = 0;							/* We implement UDP first */
+int Client_num = 1;						/* fake: number of client */
+uid_t Real_uid;
+gid_t Cur_gid;
+uid_t Cur_uid;
+/*
+ * -------------------------  SFS Child  -------------------------
+ */
+
+static int nfs2proc_to_rfsproc[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
+									10, 11, 12, 13, 14, 15, 16, 17};
+static int nfs3proc_to_rfsproc[NFS3_PROCEDURE_COUNT] = {0, 1, 2, 4, 18, 5, 6, 8, 9, 14, 
+													13, 21, 10, 15, 11, 12, 16, 23, 17, 20, 
+													22, 19};
+void print_usage(int pos, int argc, char ** argv)
+{
+	int i;
+	printf("sfs3 hostname:mount_dir trace_file|stdin fh_map_file play_scale warmup_time(in seconds) \n");
+	printf("sfs3 -pair_trace trace_file\n");
+	printf("sfs3 -pair_write trace_file\n");
+	printf("sfs3 -help\n");
+	printf ("pos %d argc %d", pos, argc);
+	for (i=0; i<argc; i++) {
+		printf(" %s", argv[i]);
+	} 
+	printf ("\n");
+	exit;
+}
+
+void print_cyclic_buffers ()
+{
+	CYCLIC_PRINT(memory_trace_index);
+	CYCLIC_PRINT(dep_tab_index);
+	CYCLIC_PRINT(dep_window_index);
+}
+
+void add_to_dep_tab(int i)
+{
+	char * trace_fh;
+	fh_map_t * fh_map_entry;
+	dep_tab_t * ent;
+
+    trace_fh = strstr (memory_trace[i].line, "fh");
+    if (!trace_fh)
+	printf ("memory_trace[%d].line %s\n", i, memory_trace[i].line);
+    RFS_ASSERT (trace_fh);
+    trace_fh += 3;
+    fh_map_entry = lookup_fh (trace_fh);
+    if (fh_map_entry && (fh_map_entry->flag==FH_MAP_FLAG_DISCARD) )  {
+        req_num_with_discard_fh ++;
+		return;
+	}
+    if (fh_map_entry)
+        req_num_with_init_fh ++;
+    else
+        req_num_with_new_fh ++;
+                                                                                                                              
+	RFS_ASSERT (!CYCLIC_FULL(dep_tab_index));
+	ent = &(dep_tab[dep_tab_index.head]);
+
+    ent->disk_index = memory_trace[i].disk_index;
+	ent->memory_index = i;
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+    ent->trace_status = memory_trace[i].trace_status;
+    ent->reply_trace_fh = memory_trace[i].reply_trace_fh;
+#endif
+    ent->line = memory_trace[i].line;
+    init_dep_tab_entry(dep_tab_index.head);
+
+    if (rfs_debug && (i%100000)==0)
+    	printf ("dep_tab[%d].disk_index %d = memory_trace[%d].disk_index %d\n", dep_tab_index.head, ent->disk_index, i, memory_trace[i].disk_index);
+    CYCLIC_MOVE_HEAD(memory_trace_index);
+    CYCLIC_MOVE_HEAD(dep_tab_index);
+}
+
+void init_profile_variables ()
+{
+	init_profile ("total_profile", &total_profile);
+	init_profile ("execute_next_request_profile", &execute_next_request_profile);
+	init_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	init_profile ("invalid_get_nextop_profile",&invalid_get_nextop_profile);
+	init_profile ("prepare_argument_profile", &prepare_argument_profile);
+	init_profile ("biod_clnt_call_profile", &biod_clnt_call_profile);
+	init_profile ("receive_next_reply_profile", &receive_next_reply_profile);
+	init_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	init_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	init_profile ("decode_reply_profile", &decode_reply_profile);
+	init_profile ("check_reply_profile", &check_reply_profile);
+	init_profile ("add_create_object_profile", &add_create_object_profile);
+	init_profile ("check_timeout_profile", &check_timeout_profile);
+	init_profile ("adjust_play_window_profile",&adjust_play_window_profile);
+	init_profile ("fgets_profile",&fgets_profile);
+	init_profile ("read_line_profile",&read_line_profile);
+	init_profile ("read_trace_profile",&read_trace_profile);
+}
+
+static char trace_file[256]="anon-lair62-011130-1200.txt";
+int print_memory_usage()
+{
+	printf("size of fh_map_t %d size of fh_map %d\n", sizeof(fh_map_t), sizeof(fh_map));
+	printf("sizeof dep_tab_t %d sizeof dep_tab %d\n", sizeof(dep_tab_t), sizeof(dep_tab));
+	printf("size of memory_trace_ent_t %d sizeof memory_trace %d\n", sizeof(memory_trace_ent_t), sizeof(memory_trace));
+	printf("size of CREATE3args %d\n", sizeof( CREATE3args));
+	printf("size of MKDIR3args %d\n", sizeof( MKDIR3args));
+	printf("size of READ3args %d\n", sizeof( READ3args));
+	printf("size of WRITE3args %d\n", sizeof( WRITE3args));
+	printf("size of RENAME3args %d\n", sizeof( RENAME3args));
+	printf("size of GETATTR3args %d\n", sizeof( GETATTR3args));
+	printf("size of SETATTR3args %d\n", sizeof( SETATTR3args));
+	printf("size of LINK3args %d\n", sizeof( LINK3args));
+	printf("size of SYMLINK3args %d\n", sizeof( SYMLINK3args));
+	printf("size of MKNOD3args %d\n", sizeof( MKNOD3args));
+	printf("size of RMDIR3args %d\n", sizeof( RMDIR3args));
+	printf("size of REMOVE3args %d\n", sizeof( REMOVE3args));
+	printf("size of LOOKUP3args %d\n", sizeof( LOOKUP3args));
+	printf("size of READDIR3args %d\n", sizeof( READDIR3args));
+	printf("size of READDIRPLUS3args %d\n", sizeof( READDIRPLUS3args));
+	printf("size of FSSTAT3args %d\n", sizeof( FSSTAT3args));
+	printf("size of FSINFO3args %d\n", sizeof( FSINFO3args));
+	printf("size of COMMIT3args %d\n", sizeof( COMMIT3args));
+	printf("size of ACCESS3args %d\n", sizeof( ACCESS3args));
+	printf("size of READLINK3args %d\n", sizeof( READLINK3args));
+
+
+}
+
+int io_thread ()
+{
+/* number of seconds the I/O thread pauses after each time trying to read the requests */
+#define IO_THREAD_PAUSE_TIME 1
+
+	int i;
+	int j = 0;
+
+	disk_io_status = read_trace ();
+	while (disk_io_status == TRACE_BUF_FULL) {
+
+		usleep (10000);
+        if ((j++%200)==0) {
+                printf("&&&&&&&&&& io thread, sleep %d seconds\n", j/10);
+        }
+
+		disk_io_status = read_trace ();
+		//printf ("io_thread, after read_trace, disk_index %d\n", disk_index);
+
+#ifdef SEQUEN_READ
+		for (i=0; i<SEQUEN_READ_NUM; i++) {
+			add_to_dep_tab(CYCLIC_MINUS(memory_trace_index.head,1,memory_trace_index.size));
+		}
+#endif
+		//printf ("***************** IO THREAD SLEEP 1 s\n");
+		//print_cyclic_buffers();
+		//pthread_yield();
+	}
+	RFS_ASSERT (disk_io_status == TRACE_FILE_END);
+}
+
+int execute_thread()
+{
+	int i;
+	struct timeval playstart_time, playend_time;
+
+	sleep (10);		/* first let io_thread to run for a while */
+	init_time_offset();
+	printf ("trace_play\n");
+
+	gettimeofday(&playstart_time, NULL);
+
+	trace_play ();
+
+	gettimeofday(&playend_time, NULL);
+
+	{
+		int usec, sec;
+		sec = playend_time.tv_sec - playstart_time.tv_sec;
+		usec = sec * 1000000 + (playend_time.tv_usec - playstart_time.tv_usec);
+		sec = usec / 1000000;
+		usec = usec % 1000000;
+		printf("Total play time: %d sec %d usec\n", sec, usec);
+	}
+
+	print_result();
+}
+
+int init_thread ()
+{
+	pthread_attr_t	attr;
+	int arg;
+	int ret = 0;
+	pthread_t io_thread_var;
+	pthread_t execute_thread_var;
+
+	ret = pthread_attr_init (&attr);
+	if (ret!=0) {
+		perror("pthread_attr_init attr");
+		return ret;
+	}
+	ret = pthread_create (&(io_thread_var), &attr, &io_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("io_pthread_attr_init");
+		return ret;
+	}
+
+/*
+	ret = pthread_create (&(execute_thread_var), &attr, &execute_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("io_pthread_attr_init");
+		return ret;
+	}
+*/
+}
+
+void init_buffers()
+{
+	CYCLIC_INIT("memory_trace_index",memory_trace_index,MAX_MEMORY_TRACE_LINES);
+	CYCLIC_INIT("dep_tab_index     ",dep_tab_index,DEP_TAB_SIZE);
+	CYCLIC_INIT("dep_window_index  ",dep_window_index,DEP_TAB_SIZE);
+}
+
+int main(int argc, char ** argv)
+{
+	extern char * optarg;
+	int i;
+	struct timeval in={1000000, 100};
+	
+	init_profile_variables();
+	if ((argc==1) || (argc==2 && !strcmp(argv[1],"-help"))) {
+		print_usage(0, argc, argv);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-pair_write")) {
+		if (argc==3) 
+			strcpy(trace_file, argv[2]);
+		else
+			strcpy(trace_file, "stdin");
+		pair_write(trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-pair_trace")) {
+		if (argc==3) 
+			strcpy(trace_file, argv[2]);
+		else
+			strcpy(trace_file, "stdin");
+		pair_trace(trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-check_aging")) {
+		if (argc!=3) {
+			print_usage(3, argc, argv);
+			exit(0);
+		}
+		strcpy(trace_file, argv[2]);
+		check_aging (trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-check_statistics")) {
+		if (argc!=3) {
+			print_usage(1, argc, argv);
+			exit(0);
+		}
+		strcpy(trace_file, argv[2]);
+		memset(fh_htable, 0, sizeof (fh_htable));
+		check_statistics (trace_file);
+		exit(0);
+	}
+
+	if (argc!=6) {
+		print_usage(2, argc, argv);
+		exit(0);
+	}
+	PLAY_SCALE = atoi (argv[4]);
+	RFS_ASSERT (PLAY_SCALE >=1 && PLAY_SCALE <=10000);
+
+	WARMUP_TIME = atoi (argv[5]);
+	RFS_ASSERT (WARMUP_TIME >=0 && WARMUP_TIME <=1000);
+	
+	print_memory_usage();
+	check_clock();
+    getmyhostname(lad_hostname, HOSTNAME_LEN);
+
+    init_ops();
+	/*
+	 * Get the uid and gid information.
+	 */
+	Real_uid = getuid();
+	Cur_gid = getgid();
+	//Real_uid = 513;
+	//Cur_gid = 513;
+
+	Nfs_timers = Nfs_udp_timers;
+
+	init_file_system ();
+	init_signal();
+	init_play (argv[1]);
+	//init_play ("capella:/p5/RFSFS");
+	init_fh_map();
+	read_fh_map (argv[3]);
+	//read_fh_map ("fh-path-map-play");
+	strcpy(trace_file, argv[2]);
+
+/* If ordered by TIMESTAMP,
+ * memory_trace_index.tail <= dep_tab_index.tail < dep_window_max <=
+ * dep_tab_index.head <= memory_trace_index.head
+ */
+
+	init_buffers();
+	//init_thread();
+	pthread_yield();
+	execute_thread();
+}
+
+void init_ops (void)
+{
+	Ops = nfsv3_Ops;
+	nfs_version = NFS_V3;
+}
+
+/* Set up the signal handlers for all signals */
+void init_signal()
+{
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	struct sigaction sig_act, old_sig_act;
+
+	/* use XOPEN signal handling */
+
+	sig_act.sa_handler = generic_catcher;
+	(void)sigemptyset(&sig_act.sa_mask);
+	sig_act.sa_flags = 0;
+
+	/* signals handlers for signals used by sfs */
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGINT,&sig_act,&old_sig_act) == -1) {
+	    perror("sigaction failed: SIGINT");
+	    exit(135);
+	}
+
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGTERM,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGTERM");
+	    exit(137);
+	}
+#else
+    /* signals handlers for signals used by sfs */
+    (void) signal(SIGINT, sfs_cleanup);
+    // RFS (void) signal(SIGALRM, sfs_alarm);
+	(void) signal(SIGTERM, sfs_cleanup);
+#endif
+}
+
+void
+init_play (
+    char	* mount_point)		/* Mount point for remote FS */
+{
+    char	namebuf[NFS_MAXNAMLEN] = "trace_play";	/* unique name for this program */
+    CLIENT *	mount_client_ptr;	/* Mount client handle */
+
+	if (!rfs_debug);
+    	(void) setvbuf(stderr, io_buf, _IOLBF, BUFSIZ);
+
+    sfs_Myname = namebuf;
+
+    /*
+     * May require root priv to perform bindresvport operation
+     */
+    mount_client_ptr = lad_getmnt_hand(mount_point);
+    if (mount_client_ptr == NULL) {
+		exit(145);
+    }
+
+    /*
+     * should be all done doing priv port stuff
+     */
+
+    if (init_rpc() == -1) {
+		(void) fprintf(stderr, "%s: rpc initialization failed\n", sfs_Myname);
+		(void) generic_kill(0, SIGINT);
+		exit(146);
+    }
+
+
+    /*
+     * finish all priv bindresvport calls
+     * reset uid
+     */
+    if (setuid(Real_uid) != (uid_t)0) {
+	(void) fprintf(stderr,"%s: %s%s", sfs_Myname,
+	    "cannot perform setuid operation.\n",
+	    "Do `make install` as root.\n");
+    }
+
+    init_mount_point(0, mount_point, mount_client_ptr);
+
+
+    /*
+     * Cleanup client handle for mount point
+     */
+    clnt_destroy(mount_client_ptr);
+
+	init_counters();
+}
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+inline char * read_line (int disk_index)
+{
+	static FILE * fp=NULL;
+	static int start=0;
+	static int start_disk_index=0;
+	int i;
+	static int finish_flag = 0;
+
+#define READ_LINE_BUF_SIZE (MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR+2)
+#define SAFE_BYTES 1000
+#define READ_LINE_LENGTH (MAX_TRACE_LINE_LENGTH+SAFE_BYTES)
+
+	static char line_buf[READ_LINE_BUF_SIZE][READ_LINE_LENGTH];
+	start_profile (&read_line_profile);
+
+	if (fp==NULL) {
+		if (strcmp(trace_file, "stdin")) {
+			fp = fopen(trace_file, "r");
+			if (!fp) {
+				printf("can not open files %s\n", fp);
+				perror("open");
+			}
+		} else {
+			fp = stdin;
+		}
+		RFS_ASSERT (fp!=NULL);
+		for (i=0; i<READ_LINE_BUF_SIZE; i++) {
+			start_profile(&fgets_profile);
+			if (!fgets(line_buf[i], READ_LINE_LENGTH, fp)) {
+				RFS_ASSERT (0);
+			}
+			end_profile(&fgets_profile);
+			//printf ("read_line, line_buf[%d]:%s", i, line_buf[i]);
+		}
+	}
+	
+	RFS_ASSERT (disk_index <= start_disk_index+READ_LINE_BUF_SIZE)
+	if (disk_index==(start_disk_index+READ_LINE_BUF_SIZE)) {
+		if (finish_flag) {
+			return NULL;
+		}
+		start_profile(&fgets_profile);
+		if (!fgets(line_buf[start], READ_LINE_LENGTH, fp)) {
+			end_profile(&fgets_profile);
+			finish_flag = 1;
+			return NULL;
+		}
+		end_profile(&fgets_profile);
+		//printf ("read_line, line_buf[%d]:%s", start, line_buf[start]);
+		start = (start+1) % READ_LINE_BUF_SIZE;
+		start_disk_index ++;
+	}
+	RFS_ASSERT (disk_index < start_disk_index+READ_LINE_BUF_SIZE)
+	i = (start+disk_index-start_disk_index)%READ_LINE_BUF_SIZE;
+
+/*
+	if (!(strlen(line_buf[i])>80)) {
+		printf ("start %d start_disk_index %d disk_index %d strlen %d line_buf[%d] %s\n", start, start_disk_index, disk_index, strlen(line_buf[i]), i, line_buf[i]);
+		RFS_ASSERT (strlen(line_buf[i])>80);
+	}
+	if (!((strlen(line_buf[i])>80) && (strlen(line_buf[i])<MAX_TRACE_LINE_LENGTH)))
+		printf ("disk_index %d strlen %d line_buf[%d] %s\n", disk_index, strlen(line_buf[i]), i, line_buf[i]);
+	RFS_ASSERT ((strlen(line_buf[i])>80) && (strlen(line_buf[i])<MAX_TRACE_LINE_LENGTH));
+*/
+
+	end_profile (&read_line_profile);
+	return (line_buf[i]);
+}
+
+#define OPS_FLAG_INC 0
+#define OPS_FLAG_PRINT 1
+int read_write_fh_statistics (int flag, char * buf, int timestamp)
+{
+	static FILE * fp = NULL;
+	char * p;
+	char c;
+	if (!fp) {
+		fp = fopen ("read_write_fh.output", "w");
+		RFS_ASSERT (fp);
+	}
+	if (flag == OPS_FLAG_INC) {
+		p = strstr (buf, "fh");
+		RFS_ASSERT (p);
+		c = p[40+3];
+		p[40+3]=0;
+		fprintf(fp, "%s\n", p+3+24);
+		p[40+3]=c;
+	};
+	if (flag == OPS_FLAG_PRINT) { 
+		int disk_index = (int) buf;
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+int write_statistics(int flag, char * buf, char * reply_buf, int trace_status)
+{
+	static FILE * fp = NULL;
+	int pre_size, size, count;
+	char * p = reply_buf;
+	if (!fp) {
+		fp = fopen ("write.output", "w");
+		RFS_ASSERT (fp);
+	}
+	if (flag == OPS_FLAG_INC) {
+		p = strstr (p, "pre-size");
+		RFS_ASSERT (p);
+		sscanf (p, "pre-size %x", &pre_size); 
+		p += strlen("pre-size");
+		p = strstr (p, "size");
+		RFS_ASSERT (p);
+		sscanf (p, "size %x", &size); 
+		p = strstr (p, "count");
+		if (!p) 
+			fprintf (fp, "%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+		RFS_ASSERT (p);
+		sscanf (p, "count %x", &count); 
+		fprintf (fp, "%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+	}
+	if (flag == OPS_FLAG_PRINT) {
+		int disk_index = (int) buf;
+		int timestamp = (int) reply_buf;
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+void ops_statistics (int ops_flag, int proc, int timestamp)
+{
+	static FILE * fp = NULL;
+	static struct {
+		int count;
+		int count_K;
+		int update_flag;
+		char name[32];
+	} ops[NOPS]={{0, 0, 0, "NULL"},{0, 0, 0, "GETATTR"},{0, 0, 1, "SETATTR"},{0, 0, 0, "ROOT"},
+				  {0, 0, 0, "LOOKUP"},{0, 0, 0, "READLINK"},{0, 0, 0, "READ"},{0, 0, 1, "WRCACHE"},
+				  {0, 0, 1, "WRITE"}, {0, 0, 1, "CREATE"},{0, 0, 1, "REMOVE"},{0, 0, 1, "RENAME"},
+				  {0, 0, 1, "LINK"}, {0, 0, 1, "SYMLINK"},{0, 0, 1, "MKDIR"},{0, 0, 1, "RMDIR"},
+				  {0, 0, 0, "READDIR"},{0, 0, 0, "FSSTAT"},{0, 0, 0, "ACCESS"},{0, 0, 0, "COMMIT"},
+				  {0, 0, 0, "FSINFO"},{0, 0, 1, "MKNOD"}, {0, 0, 0, "PATHCONF"}, {0, 0, 0, "READDIRPLUS"}};
+
+	if (ops_flag == OPS_FLAG_INC) {
+		RFS_ASSERT (proc>=0 && proc<NOPS);
+		ops[proc].count ++;
+		if (ops[proc].count == 1000) {
+			ops[proc].count_K ++;
+			ops[proc].count = 0;
+		}
+	}
+	if (ops_flag == OPS_FLAG_PRINT) {
+		int i;
+		int update_K=0, update=0, total_K=0, total=0;
+		float f1, f2;
+		int disk_index = proc;
+
+		if (!fp) {
+			fp = fopen ("mix.output", "w");
+			RFS_ASSERT (fp);
+		}
+		for (i=0; i<NOPS; i++) {
+			total_K += ops[i].count_K;
+			total += ops[i].count;
+			if (ops[i].update_flag) {
+				update_K += ops[i].count_K;
+				update += ops[i].count;
+			}
+		}
+		update_K += update/1000;
+		update = update%1000;
+		total_K += total/1000;
+		total = total%1000;
+
+		f1 = total_K;
+		f1 = f1*1000+total;
+		for (i=0; i<NOPS; i++) {
+			f2 = ops[i].count_K;
+			f2 = f2*1000+ops[i].count;
+			fprintf (fp, "%12s %8d,%03d %3.2f\%\n", ops[i].name, ops[i].count_K, ops[i].count, f2*100/f1);	
+			fprintf (stderr, "%12s %8d,%03d %3.2f\%\n", ops[i].name, ops[i].count_K, ops[i].count, f2*100/f1);	
+		}
+		f2 = update_K;
+		f2 = f2*1000+update;
+		fprintf (fp, "       total %8d,%03d\n", total_K, total);
+		fprintf (stderr, "       total %8d,%03d\n", total_K, total);
+		fprintf (fp, "      update %8d,%03d %2.2f\%\n", update_K, update, f2*100/f1);	
+		fprintf (stderr, "      update %8d,%03d %2.2f\%\n", update_K, update, f2*100/f1);	
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+		fprintf(stderr, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+
+void truncate_statistics (int flag, int proc, char * buf, char * reply_buf) 
+{
+#define TRACE_FH_SIZE2 16
+#define BLOCK_SIZE 4096
+	static int no_size_num = 0;
+	static int have_size_num = 0;
+	static int equal_size_num = 0;
+	static int first_size_num = 0;
+	static int truncate_num = 0;
+	static int truncate_size = 0;
+	static int truncate_KB = 0;
+	static int truncate_block_num = 0;
+	static int padding_num = 0;
+	static int padding_KB = 0;
+	static int padding_size = 0;
+	static FILE * fp = NULL;
+	char * p;
+	char * trace_fh;
+	int pre_size, size, count;
+	struct generic_entry * ent;
+
+	if (flag == OPS_FLAG_PRINT) {
+		int disk_index = proc;
+		int timestamp = (int)buf;
+		if (!fp) {
+			fp = fopen ("truncate.output", "w");
+			RFS_ASSERT (fp);
+		}
+		truncate_KB += truncate_size/1000;
+		truncate_size %= 1000;
+		padding_KB += padding_size/1000;
+		padding_size %= 1000;
+		fprintf(fp, "###### disk_index %d timestamp %d no_size_req %d have_size_req %d equal_size_req %d trunc_req %d trunc_KB %d trunc_block_num %d padding_num %d padding_KB %d\n", disk_index, timestamp, no_size_num, have_size_num, equal_size_num, truncate_num, truncate_KB, truncate_block_num, padding_num, padding_KB);
+		fprintf(stderr, "###### disk_index %d timestamp %d no_size_req %d have_size_req %d equal_size_req %d trunc_req %d trunc_KB %d trunc_block_num %d padding_num %d padding_KB %d\n", disk_index, timestamp, no_size_num, have_size_num, equal_size_num, truncate_num, truncate_KB, truncate_block_num, padding_num, padding_KB);
+		return;
+	}
+
+	p = strstr (&buf[TRACE_MSGID_POS], "fh");
+	RFS_ASSERT (p);
+	p+=3; 
+	trace_fh = p;
+		
+	if (proc==SETATTR) {
+		p = strstr (buf, " size ");
+	} else {
+		RFS_ASSERT (proc==WRITE);
+		p = strstr (reply_buf, " ftype 1 ");
+		RFS_ASSERT (p);
+		p = strstr (p, " size ");
+		RFS_ASSERT (p);
+		if (strstr(p, " ftype 1 ")) {
+			fprintf (fp, "#### %s%s\n", buf, reply_buf);
+			fprintf (stderr, "#### %s%s\n", buf, reply_buf);
+		}
+		RFS_ASSERT (!strstr(p, " ftype 1 "));
+	}
+	if (!p) {
+		no_size_num ++;
+		return;
+	}
+	have_size_num ++;
+
+	sscanf (p, " size %x", &size); 
+	if (size <0 || size > 2000000000) {
+		fprintf (fp, "#### size too big %x %s %s\n", size, buf, reply_buf);
+		fprintf (stderr, "#### size too big %x %s %s\n", size, buf, reply_buf);
+	}
+							
+	RFS_ASSERT (size >=0 && size <2000000000);		
+   	ent = generic_lookup (trace_fh+24, TRACE_FH_SIZE2, 0, fh_htable, FH_HTABLE_SIZE);
+	if (ent) {
+		if (ent->key3 != size) {
+			if (proc==SETATTR) {
+				//printf ("%s\n", buf);
+				//printf ("size change fh %s pre-size %x size %x\n", trace_fh, ent->key3, size);
+				if (ent->key3 > size) {
+					truncate_num ++;
+					truncate_size += ent->key3 - size;
+					truncate_block_num += (ent->key3+BLOCK_SIZE-1)/BLOCK_SIZE;
+					if (size!=0) {
+						//fprintf (stderr, "truncate: pre_size %x size %x %s\n", ent->key3, size, buf);
+						//fprintf (fp, "truncate: pre_size %x size %x %s\n", ent->key3, size, buf);
+						truncate_block_num -= (size + BLOCK_SIZE-1)/BLOCK_SIZE;
+					}
+					if (truncate_size > 1000000000) {
+						truncate_KB += truncate_size/1000;
+						truncate_size %= 1000;
+					}
+				} else {
+					padding_num ++; 
+					//printf ("%s\n", buf);
+					//printf ("padding fh %s pre-size %x size %x\n", trace_fh, ent->key3, size);
+					padding_size += size - ent->key3;
+					if (padding_size > 1000000000) {
+						padding_KB += padding_size/1000;
+						padding_size %= 1000;
+					}
+				}
+			}
+			ent->key3 = size; 
+		}else 
+			equal_size_num++;
+	} else {
+   		generic_insert(trace_fh+24, TRACE_FH_SIZE2, size, fh_htable, FH_HTABLE_SIZE);
+		first_size_num ++;
+	}
+};
+
+int get_timestamp (char * buf)
+{
+	char str[128];
+	int ret;
+	strncpy(str, buf, 100);
+	RFS_ASSERT (str[10]=='.');
+	str[10]=0;
+	ret = atoi(str);
+	RFS_ASSERT (ret >1000000000 && ret <2000000000);
+	return ret;
+}
+
+int check_aging (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid, proc;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		
+		proc = nfs3proc_to_rfsproc[nfs3proc];
+		ops_statistics (OPS_FLAG_INC, proc, -1);
+		
+		switch (proc) {
+		int off, count, size;
+		char * t;
+		case CREATE: printf("%s\n", "create"); break;
+		case MKDIR: printf("%s\n", "mkdir"); break;
+		case REMOVE: printf("%s\n", "remove"); break;
+		case RMDIR: printf("%s\n", "rmdir"); break;
+		case WRITE: 
+			t = buf;
+			t = strstr (t, "off");
+	        RFS_ASSERT (t);
+   		    t+=4;
+			sscanf (t, "%x", &off);
+			RFS_ASSERT (off>=0 && off<0x7FFFFFFF)
+			t = strstr (t, "count");
+		    RFS_ASSERT (t);
+   			t+=6;
+			sscanf (t, "%x", &count);
+			RFS_ASSERT (count <= 32768);
+			printf("%s off %x count %x\n", "write", off, count); 
+			//printf("%s count %x\n", "write", count); 
+			break;
+		case SETATTR: 
+			t = strstr (buf, " size ");
+			if (t) {
+				sscanf (t, " size %x", &size);
+				printf ("%s size %x\n", "setattr", size);
+			}
+		}
+		if ((disk_index%10000)==0) {
+			fprintf(stderr, "%d disk trace passed\n", disk_index);
+		}
+	};
+
+	fprintf(stderr, "%d disk trace parsed\n", disk_index);
+	ops_statistics (OPS_FLAG_PRINT, disk_index, -1);
+}
+
+
+int check_statistics (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid, proc;
+	static int last_timestamp_sec = -1;
+	int timestamp_sec;
+	int memory_trace_size = 0;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		timestamp_sec = get_timestamp(buf);
+		
+		proc = nfs3proc_to_rfsproc[nfs3proc];
+		ops_statistics (OPS_FLAG_INC, proc, -1);
+		
+		if (proc!= WRITE && proc!=SETATTR && proc!=READ) {
+			continue;
+		}
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE; i++) {
+			reply_buf = read_line(i);
+			if (debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+	               	trace_status = find_reply_status(reply_buf);
+					if (trace_status == NFS3_OK) {
+						if (proc==READ || proc==WRITE) 
+							read_write_fh_statistics (OPS_FLAG_INC, buf, 0);
+						if (proc == WRITE)
+							write_statistics (OPS_FLAG_INC, buf, reply_buf, trace_status);
+						if (proc==WRITE || proc==SETATTR) 
+							truncate_statistics (OPS_FLAG_INC, proc, buf, reply_buf);
+					}
+				};
+   	    	}
+		}
+		//if (memory_trace[memory_trace_size].trace_status == NFS3ERR_RFS_MISS)
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			//printf ("%s no reply\n", buf);
+			missing_reply_num ++;
+		}
+
+#if	0	/* commented out by G. Jason Peng */
+		if *
+		if ((missing_reply_num > memory_trace_size/10) && (missing_reply_num > 100)) {
+			printf ("missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+#endif
+
+		memory_trace_size ++;
+
+		if (last_timestamp_sec == -1) {
+			last_timestamp_sec = timestamp_sec;
+		} else if (timestamp_sec - last_timestamp_sec >=3600) {
+			ops_statistics (OPS_FLAG_PRINT, disk_index, timestamp_sec);
+			truncate_statistics (OPS_FLAG_PRINT, disk_index, (char *)timestamp_sec, NULL);
+			read_write_fh_statistics(OPS_FLAG_PRINT, (char *)disk_index, timestamp_sec);
+			write_statistics(OPS_FLAG_PRINT, (char *)disk_index, (char *)timestamp_sec, -1);
+			last_timestamp_sec = timestamp_sec;
+		}
+/*
+		if ((memory_trace_size%10000)==0) {
+			fprintf(stderr, "%d disk trace parsed, missing_reply %d\n", disk_index, missing_reply_num);
+			ops_statistics (OPS_FLAG_PRINT, -1);
+			truncate_statistics (OPS_FLAG_PRINT, -1, NULL, NULL);
+		}
+*/
+	};
+
+	fprintf(stderr, "%d disk trace parsed, missing_reply %d\n", disk_index, missing_reply_num);
+	ops_statistics (OPS_FLAG_PRINT, disk_index, timestamp_sec);
+	truncate_statistics (OPS_FLAG_PRINT, disk_index, (char *)timestamp_sec, NULL);
+	read_write_fh_statistics(OPS_FLAG_PRINT, (char *)disk_index, timestamp_sec);
+	write_statistics(OPS_FLAG_PRINT, (char *)disk_index, (char *)timestamp_sec, -1);
+}
+
+
+/* This routine output all the requests, together with their replies */
+int pair_trace (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid;
+	int ops[NFS3_PROCEDURE_COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	int memory_trace_size = 0;
+	FILE * outputfp;
+
+	outputfp = fopen ("pair.output", "w");
+	RFS_ASSERT (outputfp);
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		ops[nfs3proc]++;
+
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+		fprintf (outputfp, "%s\n", buf);
+
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR; i++) {
+			reply_buf = read_line(i);
+			if (debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+					fprintf(outputfp, "%s", reply_buf);
+					trace_status = find_reply_status(reply_buf);
+					if (debug)
+						fprintf(stderr, "reply found trace_status %d\n", find_reply_status(reply_buf));
+				};
+   	    	}
+		}
+
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			fprintf (stderr, "%s no reply\n", buf);
+			fprintf(outputfp, "missing_reply\n");
+			missing_reply_num ++;
+		}
+
+		if (missing_reply_num > memory_trace_size/10 && missing_reply_num >100) {
+			fprintf (stderr, "missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+
+		memory_trace_size ++;
+
+		if ((memory_trace_size%10000)==0)
+			fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+    //fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+
+}
+/* This routine output all the write requests, together with their replies. It is used for
+ * analysis of write requests: appended bytes, overwrite bytes etc
+ */
+int pair_write (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int pair_write_debug = 0;
+	int nfs3proc, msgid;
+	int ops[NFS3_PROCEDURE_COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	int memory_trace_size = 0;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		ops[nfs3proc]++;
+
+		if (!strstr(buf, "write")) 
+			continue;
+
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (pair_write_debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+
+		/* store the request to memory */
+		//strcpy (memory_trace[memory_trace_size].line, buf);
+		//memory_trace[memory_trace_size].disk_index = disk_index;
+
+		/* find and store the reply status and reply fhandle to memory */
+		//memory_trace[memory_trace_size].trace_status = NFS3ERR_RFS_MISS;
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR; i++) {
+			reply_buf = read_line(i);
+			if (pair_write_debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+					int pre_size, size, count;
+               		//memory_trace[memory_trace_size].trace_status = find_reply_status(reply_buf);
+					if (pair_write_debug)
+						printf("reply found trace_status %d\n", find_reply_status(reply_buf));
+						//break;
+	               	trace_status = find_reply_status(reply_buf);
+					if (trace_status == NFS3_OK) {
+						p = strstr (p, "pre-size");
+						RFS_ASSERT (p);
+						sscanf (p, "pre-size %x", &pre_size); 
+						p += strlen("pre-size");
+						p = strstr (p, "size");
+						RFS_ASSERT (p);
+						sscanf (p, "size %x", &size); 
+						p = strstr (p, "count");
+						if (!p) 
+							printf ("%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+						RFS_ASSERT (p);
+						sscanf (p, "count %x", &count); 
+						printf ("%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+						break;
+					}
+				};
+   	    	}
+		}
+		//if (memory_trace[memory_trace_size].trace_status == NFS3ERR_RFS_MISS)
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			printf ("%s no reply\n", buf);
+			missing_reply_num ++;
+		}
+
+#if	0	/* commented out by G. Jason Peng */
+		if (missing_reply_num > memory_trace_size/10) {
+			printf ("missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+#endif
+
+		memory_trace_size ++;
+
+		/*
+		if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+			fprintf (stderr, "memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+			break;
+		}
+		*/
+		if ((memory_trace_size%10000)==0)
+			fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+    //fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+
+}
+
+int read_trace ()
+{
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int debug = 0;
+	memory_trace_ent_t * ent=NULL;
+
+	start_profile (&read_trace_profile);
+
+	while (!CYCLIC_FULL(memory_trace_index)) {
+		if (ent!=NULL && (ent->trace_status == NFS3ERR_RFS_MISS))
+			buf = reply_buf;
+		if ((buf=read_line(++disk_index))==NULL) {
+END:		fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, CYCLIC_NUM(memory_trace_index), missing_reply_num );
+    		fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+			end_profile (&read_trace_profile);
+			return TRACE_FILE_END;
+		}
+	
+#ifdef notdef
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+
+		if (disk_index==1) {
+			trace_timestamp1 = get_timestamp (buf);
+		} else
+			trace_timestamp2 = get_timestamp (buf);
+#endif
+		/* store the request to memory */
+		ent = &(memory_trace[memory_trace_index.head]);
+		strcpy (ent->line, buf);
+		ent->disk_index = disk_index;
+
+		if (MAX_COMMAND_REPLY_DISTANCE ==1) {
+			ent->trace_status == NFS3ERR_RFS_MISS;
+		} else {
+			reply_buf=read_line(++disk_index);
+			RFS_ASSERT (reply_buf);
+			if (!strcmp(reply_buf, "missing_reply\n")) {
+				ent->trace_status == NFS3ERR_RFS_MISS;
+			} else {
+				ent->trace_status = find_reply_status(reply_buf);
+			}
+		};
+
+		if (ent->trace_status == NFS3ERR_RFS_MISS)
+			missing_reply_num ++;
+
+		if (MAX_COMMAND_REPLY_DISTANCE > 1) {
+			if ((missing_reply_num > disk_index/5) && (missing_reply_num > 100)) {
+				printf ("missing_reply_num %d too high for disk_index %d\n", missing_reply_num, disk_index);
+				exit (0);
+			}
+		}
+
+		/* find and store the reply trace fhandle for create-class requests */
+		if (ent->trace_status==NFS3_OK) {
+			if (strstr(buf, "create") || strstr(buf, "mkdir") 
+				|| (strstr(buf, "symlink") && (buf[TRACE_VERSION_POS]!='2')) 
+				|| strstr(buf, "mknod") ) {
+				p = find_reply_trace_fh(reply_buf);
+				memcpy(ent->reply_trace_fh, p, TRACE_FH_SIZE);
+			} else
+				memset(ent->reply_trace_fh, 0, TRACE_FH_SIZE);
+		}
+
+		add_to_dep_tab(memory_trace_index.head);
+
+		if (((disk_index+1)%20000)==0) {
+			fprintf(stderr, "%d disk trace parsed \n", disk_index+1);
+		};
+	};
+
+	end_profile (&read_trace_profile);
+	return TRACE_BUF_FULL;
+}
+#else	/* not defined REDUCE_MEMORY_TRACE_SIZE */
+int read_trace ()
+{
+	FILE * fp;
+	char buf[1024];
+	// char * t=buf;	
+	int disk_index=0;
+
+	fp = fopen(trace_file, "r");
+	RFS_ASSERT (fp!=NULL);
+	while (fgets(buf, MAX_TRACE_LINE_LENGTH, fp)) {
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("strlen(buf) %d buf %s \n", strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+
+		/* store the request to memory */
+		strcpy (memory_trace[memory_trace_size].line, buf);
+		memory_trace[memory_trace_size].disk_index = disk_index;
+		memory_trace_size ++;
+
+		if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+			fprintf (stderr, "memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+			break;
+		}
+		if ((disk_index%100000)==0)
+			fprintf(stderr, "%d disk trace parsed, store %d trace lines to memory\n", disk_index, memory_trace_size);
+		disk_index ++;
+	}
+
+	fprintf(stderr, "total %d disk lines %d memory lines \n", disk_index, memory_trace_size );
+}
+#endif
+
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+inline int disk_index_to_memory_index (int disk_index)
+{
+	static int memory_index = 0;
+
+	RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));
+	RFS_ASSERT (memory_trace[memory_trace_index.tail].disk_index <= disk_index);
+	RFS_ASSERT (memory_trace[CYCLIC_MINUS(memory_trace_index.head,1,memory_trace_index.size)].disk_index >=disk_index);
+	if (disk_index > memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index < disk_index) {
+			memory_index = CYCLIC_ADD(memory_index,1,memory_trace_index.size);
+		}
+	};
+	if (disk_index < memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index > disk_index) {
+			memory_index = CYCLIC_MINUS(memory_index,1,memory_trace_index.size);
+		}
+	};
+
+	RFS_ASSERT (disk_index == memory_trace[memory_index].disk_index);
+	return memory_index;
+}
+#else
+#define disk_index_to_memory_index(disk_index)	disk_index
+#endif
+
+#define get_line_by_disk_index(disk_index) \
+	memory_trace[disk_index_to_memory_index(disk_index)].line
+
+inline char * find_reply_line (char * command_line, int cur_disk_index)
+{
+	int i;
+	char * line;
+	char * p;
+	int request_memory_index = disk_index_to_memory_index (cur_disk_index);
+	for (i=request_memory_index+1; i<request_memory_index+MAX_COMMAND_REPLY_DISTANCE && i<MAX_MEMORY_TRACE_LINES; i++) {
+		line = memory_trace[i].line;
+		if (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+	        p = strchr (&line[TRACE_MSGID_POS], ' ');
+    	    RFS_ASSERT (p);
+			if (!strncmp(&line[TRACE_MSGID_POS], &command_line[TRACE_MSGID_POS], p-&(line[TRACE_MSGID_POS]))) 
+				return line;
+		}
+	}
+	return NULL;
+}
+
+inline int find_reply_status (char * line)
+{
+	char * p;
+	int i=0;
+
+	//printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	p = line+TRACE_MSGID_POS+2;	/* at least one letter for msgid and one letter for space */
+	if (strstr(p, "OK"))
+		return NFS3_OK;
+	if (strstr(p, "lookup 2"))
+		return 0x2;
+	if (strstr(p, "create d"))
+		return 0xd;
+	if (strstr(p, "setattr 1"))
+		return 0x1;
+	if (strstr(p, "setattr 2712")) /* 10002 NFS3ERR_NOT_SYNC */
+		return 0x2712;
+	if (strstr(p, "lookup d"))
+		return 0xd;
+	if (strstr(p, "read d"))
+		return 0xd;
+	if (strstr(p, "write d"))
+		return 0xd;
+	if (strstr(p, "write 46"))
+		return 0x46;
+	if (strstr(p, "getattr 46"))
+		return 0x46;
+	if (strstr(p, "mkdir d"))
+		return 0xd;
+	printf ("line %s  flag %c return value weird\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	printf ("!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	fprintf (stderr, "line %s  flag %c return value weird\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	fprintf (stderr, "!!!!!!!!!!!!!!!!!!!!!!!!\n");
+}
+
+inline int find_reply_status_old (char * line)
+{
+	char * p;
+	int i=0;
+
+	//printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	if (!strstr(line, "OK")) {
+		p=strstr(line, " 6 read ");
+		if (p) {
+			p+=strlen(" 6 read ");
+		} else {
+			p = strstr (line, "status=XXX");
+			RFS_ASSERT (p);
+			p--;
+			RFS_ASSERT (*p==' ');
+			while (*p==' ')
+				p--;
+			while (*p!=' ') {
+				p--;
+			}
+			p++;
+		}
+		sscanf (p, "%x", &i);
+		if ((i<=0) || (i>10000))
+			printf("line %s\n", line);
+		RFS_ASSERT (i>0 && i<10009);
+	}
+	return i;
+}
+
+inline char * find_reply_trace_fh (char * line)
+{
+	char * p;	
+	p = strstr (line, "OK fh");
+	if (!p)
+		printf ("find_reply_trace_fh line %s\n", line);
+	RFS_ASSERT (p);
+	return p+6;
+}
+
+#ifndef NO_DEPENDENCY_TABLE
+inline int disk_index_to_dep_index(int cur_dep_index, int disk_index)
+{
+	int i;
+	for (i=cur_dep_index; i>min_dep_index; i--) {
+		if (dep_tab[i].disk_index == disk_index)
+			return i;
+	} 
+	RFS_ASSERT (0);
+}
+#endif
+
+inline int is_play_candidate (int dep_index)
+{
+	int proc = dep_tab[dep_index].proc;
+	int status = dep_tab[dep_index].status;
+	int trace_status = dep_tab[dep_index].trace_status;
+
+#ifndef TAKE_CARE_CREATE_MODE_BY_DAN
+	/* for a failed create in trace, trace_replay just ignore many time the trace create fail
+	 * due to access control, but trace_play will success because our access control
+	 * may be loose (all uid/gid is mapped to single one 513:513, so we just skip these requests 
+	 */
+	if ((proc==CREATE || proc==MKDIR) && (trace_status!=NFS3_OK) && (status!=NFS3ERR_RFS_MISS)) {
+		if (dependency_debug)
+			printf ("disk[%d] ignore failed create/mkdir in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		failed_create_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_OTHER_FAILED_COMMAND
+	if (((trace_status == NFS3ERR_ACCES) && (proc==READ || proc==WRITE || proc==LOOKUP)) || 
+	    ((trace_status == NFS3ERR_PERM) && (proc==SETATTR)) 									){
+		if (dependency_debug)
+			printf ("disk[%d] ignore other failed command in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		
+		failed_other_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+	if ((dep_tab[dep_index].proc==READLINK) ) { /* send request */
+		skipped_readlink_command_num ++;
+		return FALSE;
+	}
+#endif
+/* This is actually take care in get_nextop by checking fh_map error when dep_index==min_dep_index */
+#ifndef TAKE_CARE_CUSTOM_COMMAND
+	/* this line has a file handle which should belong to discard but it is not
+	 * the file handle directly appears as parent directory in a lookup request
+	 * the return value is NOENT, the parent directory should have been initialized
+	 * but the initialization code just ignored all lookup request which didn't success
+	 * including NOENT even though the parent directory is still valid.
+	 */
+/*
+	if ((    ((dep_tab[dep_index].disk_index==262213) || (dep_tab[dep_index].disk_index==214402))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1100.txt")) 
+		) || 
+		(	 ((dep_tab[dep_index].disk_index==238460) || (dep_tab[dep_index].disk_index ==238470))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1000.txt"))
+		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+*/
+	if ((    ((dep_tab[dep_index].disk_index==423727) || (0))
+		  && !(strncmp(trace_file, "anon-lair62-011130-1500.txt", strlen("anon-lair62-011130-1500.txt"))) 
+		) || 
+		(	 ((dep_tab[dep_index].disk_index==238460) || (dep_tab[dep_index].disk_index ==238470))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1000.txt"))
+		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+	/* this line is about the mkdir 116d9d originally in anon-lair62-011130-1400.txt */
+	if (!strncmp(dep_tab[dep_index].line, "1007147245.194201", strlen("1007147245.194201"))) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_FSSTAT_COMMAND
+	/* the file handle used in this command is not processed properly by pre-processing */
+	if (proc==FSSTAT) {
+		char * trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+		fh_map_t * fh = lookup_fh (trace_fh);
+		if (!fh) {
+			skipped_fsstat_command_num++;
+			return FALSE;
+		}
+	}
+#endif
+	return TRUE;
+}
+
+inline int is_dir_op (int proc)
+{
+	switch (proc) {
+	case MKDIR:
+	case CREATE:
+	case LINK:
+	case SYMLINK:
+	case MKNOD:
+	case REMOVE:
+	case RMDIR:
+	case RENAME:
+		return 1;
+	default:
+		return 0;
+	}
+}	
+
+inline int is_create_op (int proc)
+{
+	if (proc==CREATE || proc==MKDIR || proc==LINK || proc==SYMLINK || proc==MKNOD || proc==RENAME)
+		return 1;
+	return 0;
+}
+
+inline int is_delete_op (int proc)
+{
+	if (proc==REMOVE || proc==RMDIR || proc==RENAME)
+		return 1;
+	return 0;
+}	
+
+static inline char * find_lead_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh");
+	RFS_ASSERT (p);
+	p+=3; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+inline char * find_another_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh2");
+	RFS_ASSERT (p);
+	p+=4; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+/* return the index of next request in dep_tab.
+ * Return -1 if there is no suitable request to send
+ */
+inline int get_nextop(void)
+{
+	int i,j, k;
+	int * t;
+	static int dep_index = -2;
+	char * line;
+	char * p;
+#define INIT_MIN_WAIT_VALUE -999
+	static int min_wait_fhandle_dep_index = INIT_MIN_WAIT_VALUE;
+	int proc;
+	int flag;
+
+	if (min_wait_fhandle_dep_index == -999)
+		min_wait_fhandle_dep_index = dep_window_index.head;
+
+	for (i=0; i<CYCLIC_NUM(dep_window_index); i++) {
+		dep_index = (dep_window_index.tail+i) % dep_window_index.size;
+	
+		proc = dep_tab[dep_index].proc;
+		flag = dep_tab[dep_index].flag;
+
+		if (dependency_debug)
+			printf ("get_nextop check dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+#ifdef NO_DEPENDENCY_TABLE
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT) {
+			if (is_play_candidate(dep_index)==TRUE) {
+				/* the trace_fh is the file handle for the operation directory, trace_fh_2 is other file handle
+				 * used in the request */
+				if (proc==LINK || proc==RENAME) {
+					dep_tab[dep_index].trace_fh = find_another_trace_fh (proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].trace_fh_2 = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = 0;
+				} else {
+					dep_tab[dep_index].trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = (fh_map_t *)1;
+				};
+				dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+#ifdef TIME_PLAY
+				dep_tab[dep_index].skip_sec = skip_sec;
+#endif
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_CANDIDATE\n", dep_tab[dep_index].disk_index);
+			} else {
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+				dep_tab[dep_index].flag = DEP_FLAG_DONE;
+				continue;
+			}
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE) ) {
+
+			if (!dep_tab[dep_index].fh)
+				dep_tab[dep_index].fh = lookup_fh (dep_tab[dep_index].trace_fh);
+			if (!dep_tab[dep_index].fh_2)
+				dep_tab[dep_index].fh_2 = lookup_fh (dep_tab[dep_index].trace_fh_2);
+
+			/* need to wait for file handle */
+			if ((!dep_tab[dep_index].fh) || (!dep_tab[dep_index].fh_2)) {
+				if (dependency_debug)
+					printf("disk[%d] can not lookup file handle\n", dep_tab[dep_index].disk_index);
+				if (dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) {
+					if (dependency_debug)
+						printf ("disk[%d] state DEP_FLAG_CANDIDATE to DEP_FLAG_WAIT_FHANDLE\n", dep_tab[dep_index].disk_index);
+					dep_tab[dep_index].flag = DEP_FLAG_WAIT_FHANDLE;
+					sfs_gettime (&dep_tab[dep_index].start);
+					if (CYCLIC_LESS(dep_tab_index,dep_index,min_wait_fhandle_dep_index)) 
+						min_wait_fhandle_dep_index = dep_index;
+				} else {
+					struct ladtime tmp;
+					if (dep_index==dep_window_index.tail) {
+						if (!profile_debug) 
+							printf ("fh_path_map error disk[%d] state DEP_FLAG_WAIT_FHANDLE to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+						fh_path_map_err_num ++;
+						dep_tab[dep_index].flag = DEP_FLAG_DONE;
+						continue;
+					}
+					sfs_gettime (&tmp);
+					SUBTIME (tmp, dep_tab[dep_index].start);
+#define DEPENDENCY_TIMEOUT 5
+#ifdef TIME_PLAY
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT + (skip_sec - dep_tab[dep_index].skip_sec));	
+#else
+					if (tmp.sec >= DEPENDENCY_TIMEOUT) {
+						printf("dep_tab[%d].flag %d disk_index %d line %s\n", dep_index,
+							dep_tab[dep_index].flag, dep_tab[dep_index].disk_index,
+							dep_tab[dep_index].line);
+					}
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT );	
+#endif
+				}
+				continue;
+			}
+
+			/* file handle ready, adjust_min_wait_fhandle_dep_index */
+			if ((dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE)) {
+				if (dep_index == min_wait_fhandle_dep_index) {
+					min_wait_fhandle_dep_index = dep_window_index.head;
+					for (j=CYCLIC_ADD(dep_index,1,dep_window_index.size); CYCLIC_LESS(dep_window_index,j,dep_window_index.head); j++) {
+						if (dep_tab[j].flag ==DEP_FLAG_WAIT_FHANDLE) {
+							min_wait_fhandle_dep_index = j;
+							break;
+						}
+					}
+				}
+			}
+			if (dependency_debug)
+				printf("disk[%d] found file handle\n", dep_tab[dep_index].disk_index);
+			dep_tab[dep_index].flag = DEP_FLAG_FHANDLE_READY;
+
+			/* the normal file operation can be executed now */
+			if (!is_dir_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug)
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			if (dependency_debug)
+				printf("disk[%d] directory operation \n", dep_tab[dep_index].disk_index);
+			/* the directory operation need to lock the directory first */
+			if (dep_tab[dep_index].fh->lock) {
+				if (dependency_debug)
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DIRECTORY\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DIRECTORY;
+				continue;
+			}
+		}
+				
+		if ((dep_tab[dep_index].flag == DEP_FLAG_FHANDLE_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DIRECTORY)) {
+			int j = dep_tab[dep_index].fh - fh_map;
+			if (dependency_debug) {
+				printf ("dep_tab[%d].disk_index %d, fh_map[%d] lock=%d\n",dep_index, dep_tab[dep_index].disk_index, j, dep_tab[dep_index].fh->lock);
+				printf ("trace_fh %s path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+				printf ("trace_fh %s path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+			}
+			if ((dep_tab[dep_index].fh->lock) || ((proc==RENAME) && (dep_tab[dep_index].fh_2->lock)) ) {
+				if (dependency_debug) 
+					printf ("continue to wait for directory lock\n");
+				continue;
+			}
+			if (dependency_debug) 
+				printf ("dep_tab[%d] disk index %d LOCK fh_map[%d] \n", dep_index, dep_tab[dep_index].disk_index, j);
+			dep_tab[dep_index].fh->lock = 1;
+			if (proc==RENAME)
+				dep_tab[dep_index].fh_2->lock = 1;
+
+			/* the non-delete directory operation can proceed now */
+			if (!is_delete_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			/* the delete operation can proceed if nobody ahead is waiting for fhandle */
+			/* probably this condition is not strong enough */
+//			if ((min_wait_fhandle_dep_index<dep_index) ) {
+			if (dep_index!=dep_window_index.tail) {
+				if (dependency_debug) 
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DELETE\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DELETE;
+				continue;
+			} 
+			dep_tab[dep_index].flag = DEP_FLAG_DIRECTORY_READY;
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_DIRECTORY_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DELETE)) {
+//			if (min_wait_fhandle_dep_index > dep_index) {
+			if (dep_index==dep_window_index.tail) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+		}
+#else /*NO_DEPENDENCY_TABLE undefined */
+	/* this part of code will be invalid after CYCLIC buffer design */
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT){
+			for (j=0, t=&(dep_tab[dep_index].dep_ops[0]);
+				(j<dep_tab[dep_index].init_dep_num) && (dep_tab[dep_index].cur_dep_num>0); 
+				j++, t++) {
+				if (*t !=-1) {
+					if (dep_tab[disk_index_to_dep_index(dep_index, *t)].flag == DEP_FLAG_DONE) { 
+						/* The depended request has been finished */ 
+						*t = -1;
+						dep_tab[dep_index].cur_dep_num --;
+					}
+				} 
+			}
+
+			if (dep_tab[dep_index].cur_dep_num == 0) {
+				return dep_index;
+			}
+		}
+#endif
+	}
+
+	if (dependency_debug) 
+		printf ("get_nexop return -1\n");
+	return -1;
+}
+
+int check_timeout(void)
+{
+	static int biod_index = 0;
+	int i;
+	int dep_index;	/* index into dep_tab */
+	int proc;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime timeout;
+
+	sfs_gettime (&current);	
+
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (biod_reqp[biod_index].in_use==TRUE) {
+			timeout = biod_reqp[biod_index].timeout;
+			if ((current.sec>timeout.sec) ||
+				((current.sec==timeout.sec) && (current.usec>timeout.usec))) {
+
+				dep_index = biod_reqp[biod_index].dep_tab_index;
+				proc = dep_tab[dep_index].proc;
+				op_ptr = &Ops[proc];
+				op_ptr->results.timeout_calls++;
+				Ops[TOTAL].results.timeout_calls++;
+
+				finish_request (biod_index, dep_index, NFS3ERR_RFS_TIMEOUT);
+
+				if (is_create_op(proc)) {
+					dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+					printf ("resend dep_tab[%d], disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+				}
+				//RFS_ASSERT (!is_create_op(proc));
+
+				//printf ("timeout request: biod_reqp[%d].start %d:%d timeout %d:%d current %d:%d\n", biod_index, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, timeout.sec, timeout.usec, current.sec, current.usec);
+			}
+		}
+	}
+}
+
+/* Allocate a biod_req entry to send and receive request dep_tab[dep_index]
+ * build the cross reference between dep_tab entry and biod_req entry
+ */
+struct biod_req * get_biod_req(int dep_index) /* index into dep_tab */
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (!biod_reqp[biod_index].in_use) {
+			biod_reqp[biod_index].in_use = 1;
+			biod_reqp[biod_index].dep_tab_index = dep_index;
+			dep_tab[dep_index].biod_req_index = biod_index;
+    		num_out_reqs++;
+			return &(biod_reqp[biod_index]);
+		}
+	}
+	return NULL;
+}
+
+/* Return index into biod_reqp
+ * return -1 upon failure 
+ */
+int lookup_biod_req (int xid)
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		/* give a NULL as timeout pointer may cause indefinitely block */
+		if (biod_reqp[biod_index].xid == xid) {
+			return biod_index;
+		}
+	}
+	return -1;
+}
+
+extern struct ladtime test_start;
+void init_time_offset(void)
+{
+	struct ladtime tmp1;
+	struct ladtime tmp2;
+
+	test_start.sec = 0;
+	test_start.usec = 0;
+	sfs_gettime (&tmp1);		/* called at initial time: tmp1 = play_starttime */
+#ifdef SPEED_UP
+	DIVTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime / SCALE */
+#endif
+#ifdef SLOW_DOWN
+	MULTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime * SCALE */
+#endif
+
+	tmp2 = trace_starttime; /* tmp2 = trace_starttime */
+	SUBTIME (tmp2, tmp1);	/* tmp2 = trace_starttime - play_starttime *|/ SCALE */
+	time_offset = tmp2;		/* time_offset = trace_starttime - play_starttime *|/ SCALE */ 
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void init_dep_tab_entry (int dep_index)
+{
+	char * line;
+	int version;
+	int nfsproc;
+	int msgid;
+
+	//line = get_line_by_disk_index (dep_tab[dep_index].disk_index);
+	line = dep_tab[dep_index].line;
+	sscanf (line, "%d.%d", &(dep_tab[dep_index].timestamp.tv_sec), &(dep_tab[dep_index].timestamp.tv_usec));
+	sscanf (&line[39], "%x %x", &msgid, &nfsproc);
+	if (line[TRACE_VERSION_POS]=='2') {
+		dep_tab[dep_index].proc = nfs2proc_to_rfsproc[nfsproc];
+		RFS_ASSERT (nfsproc <18);
+	} else {
+		/* This is for debug purpose */
+		if (line[TRACE_VERSION_POS] !='3') {
+			fprintf(stderr, "line[TRACE_VERSION_POS] %c line %s\n", line[TRACE_VERSION_POS], line);
+			line = get_line_by_disk_index (dep_tab[dep_index].disk_index-1);
+			if (!line)
+				line = get_line_by_disk_index (dep_tab[dep_index].disk_index-2);
+			RFS_ASSERT (line);
+			fprintf(stderr, "previousline %s\n", line);
+		}
+		RFS_ASSERT (line[TRACE_VERSION_POS] =='3');
+		if (nfsproc >= NFS3_PROCEDURE_COUNT) {
+			fprintf(stderr, "proc %d line %s\n", nfsproc, line);
+			
+		}
+		RFS_ASSERT (nfsproc <NFS3_PROCEDURE_COUNT);
+		dep_tab[dep_index].proc = nfs3proc_to_rfsproc[nfsproc];
+	}
+	RFS_ASSERT (dep_tab[dep_index].proc >= 0 && dep_tab[dep_index].proc < NOPS);
+	dep_tab[dep_index].flag = DEP_FLAG_INIT;
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+	dep_tab[dep_index].reply_line = find_reply_line (line, dep_tab[dep_index].disk_index);
+	if (dep_tab[dep_index].reply_line == NULL) {
+		//printf ("disk[%d] can not find the reply line, assume trace_status OK\n", dep_tab[dep_index].disk_index);
+		dep_tab[dep_index].trace_status = NFS3ERR_RFS_MISS;
+		missing_reply_num ++;
+	} else 
+		dep_tab[dep_index].trace_status = find_reply_status (dep_tab[dep_index].reply_line);
+#endif
+}
+
+void adjust_play_window (int flag, int * poll_timeout)
+{
+	struct ladtime max_window_time;
+	static struct ladtime max_poll_time = {0, 2000, 0};
+	struct ladtime t;
+	int i;
+	char * line;
+	cyclic_index_t old_dep_window_index = dep_window_index;
+
+#ifdef notdef
+	printf ("^^^^^^^^^^^^^^^ adjust_play_window, begin\n");
+	CYCLIC_PRINT (dep_tab_index);
+	printf ("dep_tab[%d].memory_index %d\n", dep_tab_index.tail, dep_tab[dep_tab_index.tail].memory_index);
+	CYCLIC_PRINT (dep_window_index);
+	CYCLIC_PRINT (memory_trace_index);
+	printf ("                adjust_play_window, begin\n");
+#endif
+
+	while ((!CYCLIC_EMPTY(dep_window_index)) && (dep_tab[dep_window_index.tail].flag == DEP_FLAG_DONE)) {
+#ifdef notdef
+		//CYCLIC_PRINT (memory_trace_index);
+		//printf("MOVE_TAIL_TO memory_index %d\n", dep_tab[dep_tab_index.tail].memory_index);
+		RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));	
+		RFS_ASSERT (CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head));
+		printf("%d is done\n", dep_window_index.tail);
+#endif
+		CYCLIC_MOVE_TAIL(dep_tab_index);
+		CYCLIC_MOVE_TAIL(dep_window_index);
+
+#ifdef notdef
+		CYCLIC_PRINT (dep_tab_index);
+		CYCLIC_PRINT (dep_window_index);
+
+		if (! (dep_tab_index.tail == dep_window_index.tail)) {
+			CYCLIC_PRINT(dep_tab_index);
+			CYCLIC_PRINT(dep_window_index);
+		};
+		RFS_ASSERT ( dep_tab_index.tail == dep_window_index.tail);
+#endif
+
+		if (!CYCLIC_EMPTY(dep_tab_index)) {
+#ifdef notdef
+			RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));	
+			if (!(CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head))) {
+				CYCLIC_PRINT(memory_trace_index);
+				CYCLIC_PRINT(dep_tab_index);
+				printf("dep_tab[head-1].memory_index, %d [tail].memory_index %d\n", 
+					dep_tab[CYCLIC_MINUS(dep_tab_index.head,1,dep_tab_index.size)].memory_index,
+					dep_tab[dep_tab_index.tail].memory_index);
+			}
+			RFS_ASSERT (CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head));
+#endif
+			CYCLIC_SET_TAIL_TO(&memory_trace_index, dep_tab[dep_tab_index.tail].memory_index);
+			//printf ("set memory_trace_index to %d=%d, dep_tab_index.tail %d\n", memory_trace_index.tail, dep_tab[dep_tab_index.tail].memory_index, dep_tab_index.tail);
+		} else {
+		//	CYCLIC_MOVE_TAIL (memory_trace_index);
+		}
+	}
+
+	while (CYCLIC_EMPTY(dep_tab_index)) {
+		
+		if (disk_io_status == TRACE_FILE_END) 
+			return;
+		else {
+			//printf ("************** ADJUST_PLAY_WINDOW sleep 1 s\n"); 
+			//print_cyclic_buffers();
+			pthread_yield();
+			//usleep (1000);
+		}
+	}
+
+	/* max_trace_window_time = current *|/ SCALE + trace_starttime */
+	sfs_gettime (&current);
+
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+	MULTIME (current, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+	DIVTIME (current, PLAY_SCALE);
+#endif
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+
+	/* Right now it is not clear how to deal with the situation where MAX_PLAY_WINDOW is reached */
+	if (CYCLIC_NUM(dep_window_index) == MAX_PLAY_WINDOW) {
+		//printf ("can not catch up the speed, dep_tab_size %d dep_window_max %d reach min_dep_index %d+MAX_PLAY_WINDOW\n", dep_tab_size, dep_window_max, min_dep_index);
+		//printf (".");
+		can_not_catch_speed_num ++;
+	}
+	//RFS_ASSERT (dep_window_max < min_dep_index+MAX_PLAY_WINDOW);
+#else
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+	while ((CYCLIC_NUM(dep_window_index) < MAX_PLAY_WINDOW) &&
+		   (CYCLIC_NUM(dep_window_index) < CYCLIC_NUM(dep_tab_index)) ) {
+		CYCLIC_MOVE_HEAD(dep_window_index);
+	}
+#endif
+
+	if (flag == BUSY)
+		*poll_timeout = 0;
+   	else if (CYCLIC_NUM(dep_window_index)==CYCLIC_NUM(dep_tab_index)) {
+		*poll_timeout = 1000000;	/* poll_timeout set to 1 second for the last request */
+	} else {
+#ifdef TIME_PLAY
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[dep_window_index.head].timestamp.tv_sec;
+		tmp.usec = dep_tab[dep_window_index.head].timestamp.tv_usec;
+		if (adjust_play_window_debug>=2)
+			printf ("dep_tab[dep_window_index.head %d].timestamp %d:%d, max_window_time %d:%d\n",
+				dep_window_index.head, tmp.sec, tmp.usec, max_window_time.sec, max_window_time.usec);
+
+		SUBTIME (tmp, max_window_time);
+#ifdef SPEED_UP
+		DIVTIME (tmp, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+		MULTIME (tmp, PLAY_SCALE);
+#endif
+/*
+		tmp1 = tmp;
+
+		if (tmp.sec > max_poll_time.sec) {
+
+			if (rfs_debug) 
+				printf ("dep_tab[%d].timestamp %d:%d, max_window_time %d:%d\n",
+				dep_window_max, dep_tab[dep_window_max].timestamp.tv_sec, dep_tab[dep_window_max].timestamp.tv_usec, max_window_time.sec, max_window_time.usec);
+			printf ("skip %d seconds\n", tmp.sec-max_poll_time.sec);
+			SUBTIME (tmp, max_poll_time);
+			tmp.usec = 0;
+			skip_sec += tmp.sec;
+			SUBTIME (test_start, tmp);
+			tmp = max_poll_time;
+		}
+*/
+
+		//RFS_ASSERT ((tmp.sec < 1000));
+		if (tmp.sec > 1000)
+			tmp.sec = 1000;
+		if ((tmp.sec ==0) && (tmp.usec==0)) {
+			*poll_timeout = 0;
+		} else
+			*poll_timeout = tmp.sec*1000000+tmp.usec;
+#else 
+		/*
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[dep_window_max].timestamp.tv_sec;
+		tmp.usec = dep_tab[dep_window_max].timestamp.tv_usec;
+		tmp1.sec = dep_tab[dep_window_max-1].timestamp.tv_sec;
+		tmp1.usec = dep_tab[dep_window_max-1].timestamp.tv_usec;
+		SUBTIME (tmp, tmp1);
+		RFS_ASSERT ((tmp.sec < 1000));
+		RFS_ASSERT ((tmp.sec>0) || ((tmp.sec==0) && (tmp.usec>0)));
+		*poll_timeout = tmp.sec*1000000+tmp.usec;
+		*/
+
+		*poll_timeout = 100000;
+#endif
+	}	
+	if (rfs_debug)
+		printf ("adjust_play_window: flag %d min %d -> %d, max %d -> %d poll_timeout %d \n", 
+		flag, old_dep_window_index.tail, dep_window_index.tail, old_dep_window_index.head,
+		dep_window_index.head, *poll_timeout);
+
+#ifdef notdef
+	printf ("^^^^^^^^^^^^^^^ adjust_play_window, end\n");
+	CYCLIC_PRINT (dep_tab_index);
+	printf ("dep_tab[%d].memory_index %d\n", dep_tab_index.tail, dep_tab[dep_tab_index.tail].memory_index);
+	CYCLIC_PRINT (dep_window_index);
+	CYCLIC_PRINT (memory_trace_index);
+	printf ("	 adjust_play_window, end\n\n");
+#endif
+	//CYCLIC_ASSERT(4);
+}
+
+/* poll for usecs and receive, after receive one reply,
+ * return index in biod_reqp of the corresponding request
+ */
+int poll_and_get_reply (int usecs)
+{
+	int biod_index = -1;
+	int xid;
+	int error;
+	struct timeval zero_time = {0, 0}; /* Immediately return */
+
+	do {
+		error = biod_poll_wait (NFS_client, usecs);
+		switch (error) {
+		case -1:
+			if (errno == EINTR) {
+				error = 1;
+				continue;
+			}
+			if (rfs_debug) {
+				(void) fprintf(stderr, "biod_poll_wait error\n");
+				perror ("");
+			    (void) fflush(stderr);
+			}
+			break;
+		case 0:
+			break;
+		default:
+#ifdef UDP
+			error = get_areply_udp (NFS_client, &xid, &zero_time);
+			// RFS_ASSERT (error!= RPC_TIMEOUT);	/* we have polled and know there is data */
+			// RFS_ASSERT (error!= RPC_CANTRECV);
+			RFS_ASSERT (error == RPC_SUCCESS);
+
+			biod_index = lookup_biod_req (xid);
+			sfs_gettime (&(biod_reqp[biod_index].stop));
+#else
+			RFS_ASSERT (0);
+#endif
+		}
+	} while (0);
+	return biod_index;
+}
+
+void print_result(void)
+{
+	int i, j;
+	struct ladtime t;
+	int dep_index;
+	int avg_msecs;
+	unsigned long long tmp;
+	int avg_usecs;
+
+    if (DEBUG_CHILD_GENERAL) {
+		(void) fprintf(stdout, "trace play result:\n");
+		(void) fprintf(stdout, "\t    percentage good_cnt bad_cnt timeout_cnt\telapsed time\t\t\taverage time\n");
+		for (i=0; i<NOPS+1; i++) {
+			if (Ops[i].results.good_calls==0) {
+				avg_msecs = 0;
+				avg_usecs = 0;
+			} else {
+				tmp = Ops[i].results.time.sec*1000000 + Ops[i].results.time.usec;
+				avg_msecs = 0;
+				avg_usecs = tmp/Ops[i].results.good_calls;
+/*
+				avg_msecs = (Ops[i].results.time.sec*1000 + Ops[i].results.time.usec/1000)/Ops[i].results.good_calls;
+				avg_usecs = (Ops[i].results.time.usec%1000)/Ops[i].results.good_calls;
+*/
+			}
+			(void) fprintf(stdout,	"%11s\t%4.1f\t%4d\t%4d\t%4d\t\tsec %8d usec %8d \tusec %8d\n", 
+				Ops[i].name, 
+				(float)(100*Ops[i].results.good_calls)/(float)Ops[TOTAL].results.good_calls, 
+				Ops[i].results.good_calls, Ops[i].results.bad_calls, Ops[i].results.timeout_calls,
+				Ops[i].results.time.sec, Ops[i].results.time.usec, avg_msecs*1000+avg_usecs);
+		}
+		(void) fflush (stdout);
+    }
+
+#if	0	/* commented out by G. Jason Peng */
+	RFS_ASSERT (read_data_owe_GB==0);
+	printf("read_data_total %d GB and %d bytes, owe %d GB and %d bytes, %d percent, adjusted %d times \n",read_data_total_GB, read_data_total, read_data_owe_GB, read_data_owe, (read_data_owe)/(read_data_total/100), read_data_adjust_times);
+	printf("write_data_total %d GB and %d bytes, owe %d GB and %d bytes, %d percent, adjusted %d times \n",write_data_total_GB, write_data_total, write_data_owe_GB, write_data_owe, (write_data_owe)/(write_data_total/100), write_data_adjust_times);
+	printf("poll_timeout_0_num %d poll_timeout_pos_num %d\n", poll_timeout_0_num, poll_timeout_pos_num);
+	printf("failed_create_command_num_in_original_trace %d\nfailed_other_command_num_in_original_trace %d\nskipped_readlink_command_num %d\nskipped_custom_command_num %d\nfh_path_map_err_num %d\nskipped_fsstat_command_num %d\nmissing_reply_num %d\nrename_rmdir_noent_reply_num %d\nrmdir_not_empty_reply_num %d\nloose_access_control_reply_num %d\nlookup_err_due_to_rename %d\nlookup_err_due_to_parallel_remove %d\nlookup_eaccess_enoent_mismatch %d\nread_io_err_num %d\nstale_fhandle_err_num %d abnormal_EEXIST_num %d abnormal_ENOENT_num %d proper_reply_num %d run_stage_proper_reply_num %d\n", 
+			failed_create_command_num,
+			failed_other_command_num,
+			skipped_readlink_command_num, 
+			skipped_custom_command_num,
+			fh_path_map_err_num, 
+			skipped_fsstat_command_num, 
+			missing_reply_num, 
+			rename_rmdir_noent_reply_num, 
+			rmdir_not_empty_reply_num, 
+			loose_access_control_reply_num, 
+			lookup_err_due_to_rename_num, 
+			lookup_err_due_to_parallel_remove_num,
+			lookup_eaccess_enoent_mismatch_num, 
+			read_io_err_num, 
+			stale_fhandle_err_num,
+			abnormal_EEXIST_num,
+			abnormal_ENOENT_num,
+			proper_reply_num, run_stage_proper_reply_num);
+#endif
+
+    clnt_destroy(NFS_client);
+    biod_term();
+
+//  print_dump(Client_num, Child_num);
+} 
+
+/*
+ * allocate and initialize client handles
+ */
+static int
+init_rpc(void)
+{
+	int dummy = 0;
+
+    /*
+     * Set up the client handles.  We get them all before trying one
+     * out to insure that the client handle for LOOKUP class is allocated
+     * before calling op_getattr().
+     */
+    if (DEBUG_CHILD_GENERAL) {
+    	(void) fprintf(stderr, "%s: set up client handle\n", sfs_Myname);
+    }
+
+    NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+					(uint32_t) NFS_PROGRAM,
+					(uint32_t) nfs_version,
+					RPC_ANYSOCK, &Nfs_timers[0]);
+		
+    if (NFS_client  == ((CLIENT *) NULL)) {
+        return(-1);
+    }
+
+    /*
+     * create credentials using the REAL uid
+     */
+    NFS_client->cl_auth = authunix_create(lad_hostname, (int)Real_uid,
+				      (int)Cur_gid, 0, NULL);
+
+
+	if (biod_init(dummy, dummy) == -1) {
+		    return(-1);
+	}
+
+    return(0);
+} /* init_rpc */
+
+void
+init_counters(void)
+{
+    uint_t i;
+    uint_t start_msec;
+
+    /* Ready to go - initialize operation counters */
+    for (i = 0; i < NOPS + 1; i++) {
+	Ops[i].req_cnt = 0;
+	Ops[i].results.good_calls = 0;
+	Ops[i].results.bad_calls = 0;
+	Ops[i].results.timeout_calls = 0;	// RFS
+	Ops[i].results.fast_calls = 0;
+	Ops[i].results.time.sec = 0;
+	Ops[i].results.time.usec = 0;
+	Ops[i].results.msec2 = 0;
+    }
+
+    /* initialize timers and period variables */
+    sfs_gettime(&Starttime);
+    Cur_time = Starttime;
+    start_msec = (Starttime.sec * 1000) + (Starttime.usec / 1000);
+    Previous_chkpnt_msec = start_msec;
+    Calls_this_period = 0;
+    Reqs_this_period = 0;
+    Sleep_msec_this_period = 0;
+    Calls_this_test = 0;
+    Reqs_this_test = 0;
+    Sleep_msec_this_test = 0;
+}
+
+static char *
+nfs3_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS3_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFS3ERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFS3ERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFS3ERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFS3ERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFS3ERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFS3ERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFS3ERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFS3ERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFS3ERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFS3ERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFS3ERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFS3ERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFS3ERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFS3ERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFS3ERR_MLINK:
+	    (void) strcpy(str, "Too many links");
+	    break;
+	case NFS3ERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFS3ERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFS3ERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFS3ERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFS3ERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFS3ERR_BADHANDLE:
+	    (void) strcpy(str, "Bad file handle");
+	    break;
+	case NFS3ERR_NOT_SYNC:
+	    (void) strcpy(str, "Not sync write");
+	    break;
+	case NFS3ERR_BAD_COOKIE:
+	    (void) strcpy(str, "Bad cookie");
+	    break;
+	case NFS3ERR_NOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFS3ERR_TOOSMALL:
+	    (void) strcpy(str, "Value too small");
+	    break;
+	case NFS3ERR_SERVERFAULT:
+	    (void) strcpy(str, "Server fault");
+	    break;
+	case NFS3ERR_BADTYPE:
+	    (void) strcpy(str, "Bad type");
+	    break;
+	case NFS3ERR_JUKEBOX:
+	    (void) strcpy(str, "Jukebox");
+	    break;
+	case NFS3ERR_RFS_TIMEOUT:
+		(void) strcpy(str, "Timeout");
+		break;
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+
+/*
+ * Check the gettimeofday() resolution. If the resolution
+ * is in chunks bigger than SFS_MIN_RES then the client
+ * does not have a usable resolution for running the 
+ * benchmark.
+ */
+static void
+check_clock(void)
+{
+	double time_res;
+	char tmp_hostname[HOSTNAME_LEN];
+
+	time_res = get_resolution();
+    	getmyhostname(tmp_hostname, HOSTNAME_LEN);
+	if( time_res > (double)SFS_MIN_RES )
+	{
+		(void) fprintf(stderr,
+		"\n%s: Clock resolution too poor to obtain valid results.\n",
+			tmp_hostname);
+		(void) fprintf(stderr,
+		"%s: Clock resolution %f Micro seconds.\n", tmp_hostname,
+			time_res);
+		exit(175);
+	}
+	else
+	{
+		(void) fprintf(stderr,
+		"\n%s: Good clock resolution [ %f ] Micro seconds.\n", 
+			tmp_hostname, time_res);
+	}
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns the resolution of the gettimeofday() function 
+ * in microseconds.
+ */
+static double
+get_resolution(void)
+{
+        double starttime, finishtime, besttime;
+        long  j,delay;
+	int k;
+
+        finishtime=time_so_far1(); /* Warm up the instruction cache */
+        starttime=time_so_far1();  /* Warm up the instruction cache */
+        delay=j=0;                 /* Warm up the data cache */
+	for(k=0;k<10;k++)
+	{
+	        while(1)
+       	 	{
+       	         	starttime=time_so_far1();
+       	         	for(j=0;j< delay;j++)
+       	                ;
+       	         	finishtime=time_so_far1();
+       	         	if(starttime==finishtime)
+       	                 	delay++;
+       	         	else
+			{
+				if(k==0)
+					besttime=(finishtime-starttime);
+				if((finishtime-starttime) < besttime)
+					besttime=(finishtime-starttime);
+                       	 	break;
+			}
+		}
+        }
+         return(besttime);
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns current result of gettimeofday() in microseconds.
+ */
+/************************************************************************/
+/* Time measurement routines.                                           */
+/* Return time in microseconds                                          */
+/************************************************************************/
+
+static double
+time_so_far1(void)
+{
+        /* For Windows the time_of_day() is useless. It increments in 55 */
+	/* milli second increments. By using the Win32api one can get */
+	/* access to the high performance measurement interfaces. */
+	/* With this one can get back into the 8 to 9 microsecond */
+	/* resolution.  */
+#ifdef Windows
+        LARGE_INTEGER freq,counter;
+        double wintime;
+        double bigcounter;
+
+        QueryPerformanceFrequency(&freq);
+        QueryPerformanceCounter(&counter);
+        bigcounter=(double)counter.HighPart *(double)0xffffffff +
+                (double)counter.LowPart;
+        wintime = (double)(bigcounter/(double)freq.LowPart);
+        return((double)wintime*1000000.0);
+#else
+#if defined (OSFV4) || defined(OSFV3) || defined(OSFV5)
+  struct timespec gp;
+
+  if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1)
+    perror("getclock");
+  return (( (double) (gp.tv_sec)*1000000.0) +
+    ( ((float)(gp.tv_nsec)) * 0.001 ));
+#else
+  struct timeval tp;
+
+  if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
+    perror("gettimeofday");
+  return ((double) (tp.tv_sec)*1000000.0) +
+    (((double) tp.tv_usec) );
+#endif
+#endif
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "trace play usage");
+}
+extern void init_file_system (void)
+{
+	return;
+}
+
+void show_fhandle (nfs_fh3 * fhp)
+{
+	struct knfs_fh * kfhp = (struct knfs_fh *)fhp;
+
+	int dev;
+
+	if (quiet_flag)
+		return;
+		
+	RFS_ASSERT (kfhp->fh_version == 1);
+	RFS_ASSERT (kfhp->fh_fsid_type == 0);
+	RFS_ASSERT (kfhp->fh_auth_type == 0);
+
+	dev = ntohs(kfhp->fh_dev_major);
+	dev = dev<<8;
+	dev = dev + ntohs(kfhp->fh_dev_minor);
+
+	/* kfhp->fh_dev_ino hold the inode number of export point of the mounted
+	 * file system. For example, if /tmp/t1 is exported, /tmp/t1/t2 is mounted,
+	 * then fh_dev_ino hold the inode number of t1, not t2
+	 */
+
+	switch (kfhp->fh_fileid_type) {
+		case 0:
+			printf("fh:type 0 root dev 0x%x dev_ino %d\n", dev, kfhp->fh_dev_ino); 
+			break;
+		case 1:
+			printf("fh:type 1 %d %x dev %x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, dev, kfhp->fh_dev_ino);
+			break;
+		case 2:
+			printf("fh:type2 %d %x dirino %d dev 0x%x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, kfhp->fh_dirino, dev, kfhp->fh_dev_ino);
+			break;
+		default:
+			RFS_ASSERT (0);
+	}
+}
+
+nfs_fh3 zero_fhandle;
+int init_fh_map ()
+{
+	memset (fh_map, 0, sizeof (fh_map));
+	memset(fh_htable, 0, sizeof (fh_htable));
+	memset (&zero_fhandle, 0, sizeof(nfs_fh3));
+	printf ("SIZE of fh map %d KB\n", sizeof (fh_map)/1000);
+	fh_i = 0;
+}
+
+int add_fh (int map_flag, char * trace_fh, char * path, nfs_fh3 * play_fh)
+{
+	char * old_trace_fh;
+
+	/* first lookup if the entry for fh is already in the table */
+    struct generic_entry * p;
+
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (p) {
+		RFS_ASSERT (fh_map[p->key3].flag = FH_MAP_FLAG_PARTIAL);
+		RFS_ASSERT (map_flag ==FH_MAP_FLAG_COMPLETE);
+		fh_map[p->key3].flag = map_flag;
+		//RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+		if (memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE)) {
+			int i;
+			printf ("fh_map[%d].trace_fh %s trace_fh %s", p->key3, fh_map[p->key3].trace_fh, trace_fh);
+			for (i=0; i<fh_i; i++) {
+				int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+				int * p = (int *)fh_map[i].trace_fh;
+				printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+				printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, fh_map[i].trace_fh, fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+			}
+#endif
+			RFS_ASSERT (0);
+		}
+		RFS_ASSERT (!strcmp(fh_map[p->key3].path, path));
+		/* It's possible that in fh-path-map, many trace_fh are corresponding to one path
+		 * some of it may be the result of lookup after symlink, which is not handled
+		 * properly as new created objects 
+		 */
+#ifdef TAKE_CARE_SYMBOLIC_LINK
+		RFS_ASSERT (!memcmp(&fh_map[p->key3].play_fh, &zero_fhandle, sizeof(nfs_fh3)));
+#endif
+		memcpy (&fh_map[p->key3].play_fh, play_fh, sizeof (nfs_fh3));
+		if ((fh_map_debug==1)) // || (stage ==TRACE_PLAY_STAGE)) 
+			printf ("update the play_fh for trace_fh %s path %s \n", trace_fh, path);
+		return 0;
+	}
+
+	fh_map[fh_i].flag = map_flag;
+	fh_map[fh_i].lock = 0;
+	strncpy(fh_map[fh_i].trace_fh, trace_fh, TRACE_FH_SIZE);
+
+	RFS_ASSERT (strlen(path) < MAX_PLAY_PATH_SIZE);
+	strcpy (fh_map [fh_i].path, path);
+	if (map_flag==FH_MAP_FLAG_COMPLETE)
+		memcpy (&fh_map[fh_i].play_fh, play_fh, sizeof(nfs_fh3));
+	else 
+		memset (&fh_map[fh_i].play_fh, 0, sizeof(nfs_fh3));
+
+	if ((fh_map_debug==1)) { // || (stage ==TRACE_PLAY_STAGE)) {
+		printf ("insert trace_fh %s path %s play_fh:\n", trace_fh, path);
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			//show_fhandle(play_fh);
+		} else 
+			printf("null\n");
+	}
+
+/*
+	if (map_flag == FH_MAP_FLAG_DISCARD)
+		printf ("insert flag %d trace_fh %s path %s play_fh:\n", map_flag, trace_fh, path);
+*/
+
+    generic_insert(trace_fh, TRACE_FH_SIZE, fh_i, fh_htable, FH_HTABLE_SIZE);
+	
+	fh_i = (fh_i+1);
+	RFS_ASSERT (fh_i < FH_MAP_SIZE);
+
+    return 0;
+};
+
+inline fh_map_t * lookup_fh (char * trace_fh )
+{
+    struct generic_entry * p;
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (fh_map_debug==1)
+		printf ("lookup trace_fh %s\n", trace_fh);
+
+    if (p) {
+		if (fh_map_debug==1) {
+			printf ("found: fh_i[%d] trace_fh %s path %s play_fh:\n", p->key3, fh_map[p->key3].trace_fh, fh_map[p->key3].path);
+			//show_fhandle(&fh_map[p->key3].play_fh);
+		}
+		RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+        return (&(fh_map[p->key3]));
+    } else {
+		//printf ("lookup_fh %s not found\n", trace_fh);
+		if (stage != READ_DEP_TAB_STAGE && (fh_map_debug==1)) {
+			printf ("lookup not found trace_fh %s\n", trace_fh);
+		}
+        return NULL;
+	}
+	RFS_ASSERT (0);
+}
+
+int delete_fh (char * trace_fh, int fh_map_index)
+{
+    generic_delete (trace_fh, TRACE_FH_SIZE, fh_map_index, fh_htable, FH_HTABLE_SIZE);
+    return 0;
+};
+
+int lookup_init_filesystem (nfs_fh3 * parent, char * name, nfs_fh3 * result)
+{
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+	static int i=0;
+
+    /* set up the arguments */
+    (void) memcpy((char *) &args.what.dir, (char *) parent,
+							sizeof (nfs_fh3));
+    args.what.name = name;
+    (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			Nfs_timers[Init]);
+    sfs_gettime(&stop);
+
+	if (rpc_stat !=RPC_SUCCESS) {
+		printf("rpc_stat %d\n", rpc_stat);
+		perror("");
+	}
+    RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+	(void) memcpy((char *) result, (char *) &reply.resok.object, sizeof (nfs_fh3));
+	return (reply.status);
+}
+
+void read_fh_map(char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	char trace_fh[TRACE_FH_SIZE];
+	char intbuf[9];
+	char * trace_path;
+	char * p;
+	int map_flag;
+#define MAX_PATH_DEPTH 20
+	nfs_fh3 parents[MAX_PATH_DEPTH];
+	char * lookup_path_ptr[MAX_PATH_DEPTH];
+	char lookup_path [MAX_PLAY_PATH_SIZE];
+	int depth;
+	int new_dir_flag = 0;
+	int lineno = 0;
+
+	depth = 0;
+	memset(lookup_path_ptr, 0, sizeof(lookup_path_ptr));
+	memcpy(&parents[depth], &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+	strcpy(lookup_path, "/");
+	lookup_path_ptr[depth]=&lookup_path[0];
+
+	fp = fopen(fh_map_file, "r");
+	if (!fp) {
+		printf ("can not opern %s\n", fh_map_file);
+		perror("open");
+		exit (0);
+	}
+	RFS_ASSERT (fp!=NULL);
+	
+	intbuf[8]=0;
+
+	memset(buf, 0, sizeof(buf));
+	while (fgets(buf, 1024, fp)) {
+		lineno ++;
+		if (fh_i % 10000==0)
+			printf("%d fh_map entry read\n", fh_i);
+
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf[strlen(buf)-1]=0;
+		if (fh_map_debug) {
+			printf("%d fgets return %s\n", fh_i, buf);
+			printf("depth %d lookup_path %s\n", depth, lookup_path);
+		}
+		//for (i=0; i<=depth; i++) 
+			//printf("lookup_path_ptr[%d] %s ", i, lookup_path_ptr[i]);
+		//printf("\n");
+#ifdef COMPRESS_TRACE_FH 
+		for (i=0; i<TRACE_FH_SIZE/8; i++) {
+			strncpy(intbuf, buf+i*8, 8);
+			sscanf(intbuf, "%x", trace_fh+i*8); // maybe it should be 4, anyway we don't compress for now 
+		}
+		trace_path = buf+TRACE_FH_SIZE*2+1;		/* +1 the trace contains only initial file handle */
+#else
+		memcpy(trace_fh, buf, TRACE_FH_SIZE);
+		trace_path = buf + TRACE_FH_SIZE +1;
+#endif
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		trace_path = +=2;	/* +3 if the trace contains both initial and later created file handle */
+#endif
+
+#ifdef NO_DEPENDENCY_TABLE
+		if (!strncmp (trace_path, "DISCARD", 7) ||
+			!strncmp (trace_path, "LN", 2)			) {
+			map_flag = FH_MAP_FLAG_DISCARD;
+			add_fh (map_flag, buf, trace_path, 0);
+			continue;
+		}
+#endif
+		
+		p = trace_path+strlen(trace_path)-2;
+		while (*p!='/')
+			p--;
+		p++;
+		//RFS_ASSERT (p-trace_path<=strlen(lookup_path)+1);
+		//RFS_ASSERT (p>trace_path);
+
+		if (strncmp(lookup_path, trace_path, p-trace_path)) {
+			printf("strncmp lookup_path %s trace_path %s for length %d\n", lookup_path, trace_path, p-trace_path);
+		}
+		RFS_ASSERT (!strncmp(lookup_path, trace_path, p-trace_path));
+		//while (strncmp(lookup_path, trace_path, p-trace_path)) {	/* one step deeper */
+		while (strlen(lookup_path)>p-trace_path && depth>0) {
+			//printf("depth--\n");
+			if (depth<=0) 
+				printf ("lookup_path %s trace_path %s p-trace_path %d depth %d\n", lookup_path, trace_path, p-trace_path, depth);
+			RFS_ASSERT (depth>0);
+			*lookup_path_ptr[depth]=0;
+			lookup_path_ptr[depth]=0;
+			depth--;
+		}
+		RFS_ASSERT (strlen(lookup_path)==(p-trace_path) || (depth==0));
+
+
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		if (buf[TRACE_FH_SIZE*2+1]=='Y') {
+			map_flag = FH_MAP_FLAG_COMPLETE;
+		} else {
+			map_flag = FH_MAP_FLAG_PARTIAL;
+			RFS_ASSERT (buf[TRACE_FH_SIZE*2+1]=='N');
+		}
+#else
+		map_flag = FH_MAP_FLAG_COMPLETE;
+#endif
+		if ((*(p+strlen(p)-1))=='/') {
+			*(p+strlen(p)-1)=0;
+			new_dir_flag = 1;
+		} else 
+			new_dir_flag = 0;
+
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			int ret = lookup_init_filesystem (&parents[depth], p, &parents[depth+1]);		
+			if (ret!=NFS3_OK) {
+				printf ("lineno %d %s\n", lineno, buf);
+			}
+ 			RFS_ASSERT (ret == NFS3_OK);
+			add_fh (map_flag, buf, trace_path, &parents[depth+1]);	
+		} else 
+			add_fh (map_flag, buf, trace_path, 0);
+
+		if (new_dir_flag) {
+			/* the new fhandle is of a directory */
+			lookup_path_ptr[depth+1] = lookup_path+strlen(lookup_path);
+			strcat (lookup_path, p);
+			strcat (lookup_path, "/");
+
+			//printf("depth++\n");
+			depth++;
+		}
+
+		memset(buf, 0, sizeof(buf));
+	}
+			
+	if (fh_map_debug) {
+		for (i=0; i<fh_i; i++) {
+			int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+			int * p = (int *)fh_map[i].trace_fh;
+			printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+			printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, fh_map[i].trace_fh, fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+		}
+#endif
+
+		fprintf(stderr, "total %d requests \n", i);
+	}
+}
+
+int f()
+{
+	return 1;
+}
+
+inline free_biod_req (int biod_index)
+{
+	RFS_ASSERT (biod_reqp[biod_index].in_use == TRUE);
+	biod_reqp[biod_index].in_use = FALSE;
+	num_out_reqs --;
+}
+
+inline void finish_request (int biod_index, int dep_index, int status)
+{
+	/* the ending operation, same as when a request time out */
+
+	dep_tab[dep_index].stop = biod_reqp[biod_index].stop;	/* RFS: to dump data */
+	free_biod_req (biod_index);
+
+	dep_tab[dep_index].status = status;
+	if (event_order_index < EVENT_ORDER_SIZE)
+		event_order[event_order_index++] = -dep_tab[dep_index].disk_index;
+
+	dep_tab[dep_index].flag = DEP_FLAG_DONE;
+	if (is_dir_op(dep_tab[dep_index].proc)) {
+		int j;
+		RFS_ASSERT (dep_tab[dep_index].fh->lock = 1);
+		dep_tab[dep_index].fh->lock = 0;
+		if (dep_tab[dep_index].proc==RENAME)
+			dep_tab[dep_index].fh_2->lock = 0;
+		j = dep_tab[dep_index].fh-fh_map;
+		if (dependency_debug) {
+			printf ("fh_map[%d] is UNlocked\n",j);
+			printf ("trace_fh %d path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+			printf ("trace_fh %d path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+		}
+	}
+}
+
+/* the request argument may have pointers pointing to buffers, e.g. the name in lookup, 
+ * the target of symlink, the write data */
+char arg_res[MAX_ARG_RES_SIZE];
+int poll_timeout = 0;		/* timeout in usecs */
+char buf1 [MAX_BUF1_SIZE]; 
+char buf2 [MAX_BUF2_SIZE];
+
+int execute_next_request ()
+{
+	int dep_index;
+	int proc;
+	char * line;
+	struct biod_req * reqp;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime call_timeout;
+	static int last_print_time = -1;
+
+	if (num_out_reqs == max_biod_reqs) {
+		return -1;
+	}
+
+	start_profile (&valid_get_nextop_profile);
+	start_profile (&invalid_get_nextop_profile);
+	dep_index = get_nextop();
+	if (dep_index == -1) {
+		end_profile (&invalid_get_nextop_profile);
+		return dep_index;
+	};
+	end_profile (&valid_get_nextop_profile);
+
+	start_profile (&prepare_argument_profile);
+	line = dep_tab[dep_index].line;
+
+	end_profile(&total_profile);
+	if ((total_profile.in.tv_sec - last_print_time >= 10)) {
+		last_print_time = total_profile.in.tv_sec;
+		//fprintf (stderr, "time %d processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+		fprintf (stdout, "time %d processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+/*
+		CYCLIC_PRINT (dep_tab_index);
+		{
+			int tmp = CYCLIC_MINUS(dep_tab_index.head,1,dep_tab_index.size);
+			printf("dep_tab_index.head-1 %d disk_index %d tail %d disk_index %d\n", tmp, dep_tab[tmp].disk_index,
+			dep_tab_index.tail, dep_tab[dep_tab_index.tail].disk_index);
+		}
+*/
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+/*
+		if (can_not_catch_speed_num < 2000) {
+			PLAY_SCALE ++;
+			printf ("set PLAY_SCALE to %d\n", PLAY_SCALE);
+		};
+		if (can_not_catch_speed_num > 50000) {
+			PLAY_SCALE /= 2;
+		} else {
+			if (can_not_catch_speed_num > 5000) {
+				PLAY_SCALE -= 2;
+				if (PLAY_SCALE < 1)
+					PLAY_SCALE = 1;
+			}
+		}
+*/
+#endif
+		if ((total_profile.in.tv_sec > 100)) {
+			can_not_catch_speed_num_total += can_not_catch_speed_num;
+		}
+		can_not_catch_speed_num = 0;
+#endif
+	}
+	if (rfs_debug)
+		printf ("processing dep_tab[%d] disk_index %d %s\n", dep_index, dep_tab[dep_index].disk_index, line);
+
+	proc = dep_tab[dep_index].proc;
+	rfs_Ops[proc].setarg (dep_index, line, arg_res, buf1, buf2);
+
+	op_ptr = &Ops[proc];
+	reqp = get_biod_req (dep_index);
+	RFS_ASSERT (reqp);
+
+#ifdef	notdef	/* place to set request timeout. G. Jason Peng */
+	call_timeout.sec = 2; //Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+#else
+	call_timeout.sec = 0;
+	call_timeout.usec = 500000;
+	//call_timeout.usec = 14000;
+	//call_timeout.usec = 13000;
+	//call_timeout.usec = 6000;
+	//call_timeout.usec = 8000;
+	//call_timeout.usec = 10000;
+#endif
+
+    /* make the call */
+    sfs_gettime(&(reqp->start));
+	end_profile (&prepare_argument_profile);
+	start_profile (&biod_clnt_call_profile);
+#define REAL_PLAY
+#ifdef REAL_PLAY
+    reqp->xid = biod_clnt_call(NFS_client, rfs_Ops[proc].nfsv3_proc, 
+					rfs_Ops[proc].xdr_arg, arg_res);
+#else
+
+	reqp->xid = dep_index+1;	/* just fake a message id and let it expire */
+#endif
+    RFS_ASSERT (reqp->xid != 0);
+    reqp->timeout = reqp->start;
+    ADDTIME (reqp->timeout, call_timeout);
+    dep_tab[dep_index].flag = DEP_FLAG_SENT;
+	if (event_order_index < EVENT_ORDER_SIZE)
+		event_order[event_order_index++] = dep_tab[dep_index].disk_index;
+
+	dep_tab[dep_index].start = reqp->start;	/* RFS: to dump data */
+	end_profile (&biod_clnt_call_profile);
+}
+
+void check_reply (int proc, int biod_index, int dep_index, int status, char * errmsg, int trace_status)
+{
+	if (((status!=trace_status)) && (status!=NFS3_OK) && (trace_status!=NFS3ERR_RFS_MISS)) {
+		if (!profile_debug)
+			printf ("receive problem reply, xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d command disk index %d\n", biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec, dep_tab[dep_index].disk_index); 
+#ifndef TAKE_CARE_UNLOOKED_UP_NON_NEW_FILES
+		/* these files is not looked up and is not create/mkdir/symlink/link/mknod ed before they
+		 * are refered by name through rename, remove
+		 */
+		if ((proc==RENAME || proc==REMOVE) && (status==NFS3ERR_NOENT) && (trace_status ==0)) {
+			/* current initialization doesnot take care of rename source, if there is no
+			 * create or lookup before that source, the source object will not exist when
+			 * rename occurs
+			 */
+			rename_rmdir_noent_reply_num++;
+		} else 
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+		if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_status==NFS3ERR_NOENT)) {
+			/* in the original trace, first lookup return NOENT, then symlink is executed, then lookup return OK
+			 * the initialization considers only the lookup return OK and created the file in the initialization
+			 * so in trace play the first lookup return OK
+			 */
+			RFS_ASSERT (1);
+		} else // if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) && (trace_status == 0)) {
+				/* trace_status could be EAGAIN */
+			if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) ) {
+			/* due to similar reason as above, the initialization code initializes the symbolic link as a normal
+			 * file already
+			 */
+			RFS_ASSERT (1);
+		} else
+#endif
+#ifndef TAKE_CARE_NOEMPTY_RMDIR
+		/* the remove packet seems got lost in the trace capture, so replay can not finish */
+		if ((proc==RMDIR) && (status==NFS3ERR_NOTEMPTY)) {
+   			RENAME3args		args;
+   			RENAME3res		reply;		/* the reply */
+			RMDIR3args * rmdir_argp;
+			enum clnt_stat rpc_stat;	/* result from RPC call */
+
+			rfs_Ops[proc].setarg (dep_index, dep_tab[dep_index].line, arg_res, buf1, buf2);
+			rmdir_argp = (RMDIR3args *)arg_res;
+
+			memcpy(&args.from, &(rmdir_argp->object), sizeof (diropargs3));
+			memcpy(&args.to.dir, &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+			args.from.name = buf1;	/* the buf1 is already filled when parsing rmdir */
+			args.to.name = buf2;
+			sprintf(buf2, "rmdir_%d_%s", dep_tab[dep_index].disk_index, rmdir_argp->object.name);
+
+  			rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
+			xdr_RENAME3args, (char *) &args,
+			xdr_RENAME3res, (char *) &reply,
+				Nfs_timers[Init]);
+			RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+			if (reply.status!=NFS3_OK)
+				printf ("change rmdir into rename, reply.status %d\n", reply.status);
+			RFS_ASSERT (reply.status==NFS3_OK);
+			rmdir_not_empty_reply_num ++;
+#endif
+#ifndef TAKE_CARE_ACCESS_ERROR
+		} else if ((status==0) && (trace_status==NFS3ERR_ACCES)) {
+			loose_access_control_reply_num ++;
+#endif
+#ifdef NO_DEPENDENCY_TABLE 
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3_OK)) {
+			lookup_err_due_to_rename_num ++;
+		} else if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_status == NFS3ERR_NOENT)) {
+			/* if there is a remove in front of the lookup, but it is
+ 			 * actually executed later than the lookup
+			 */
+			lookup_err_due_to_parallel_remove_num ++;
+#endif
+#ifndef TAKE_CARE_LOOKUP_EACCESS_ENOENT_MISMATCH
+		/* if the looked return EACCESS in the trace, means the object still exists
+		 * should have initialized, right not don't initialize it, hence play status 
+		 * could be ENOENT
+		 */
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3ERR_ACCES)) {
+			lookup_eaccess_enoent_mismatch_num ++;
+#endif
+#ifdef TOLERANT_READ_IO_ERR
+		} else if ((proc==READ) && (status==NFS3ERR_IO) && (trace_status==NFS3_OK)) {
+			read_io_err_num ++;
+#endif
+#ifdef TOLERANT_STALE_FHANDLE_ERR
+		} else if ((status==NFS3ERR_STALE) && (trace_status==NFS3_OK)) {
+			printf ("!!!!!!! STALE FILE HANDLE \n");
+			//sleep(1);
+			stale_fhandle_err_num ++;
+#endif
+		} else {
+			int i;
+			for (i=dep_window_index.tail; CYCLIC_LESS(dep_window_index,i,dep_window_index.head); i++) 
+				printf ("dep_tab[%d].disk_index %d, flag %d line %s\n", i, dep_tab[i].disk_index, dep_tab[i].flag, dep_tab[i].line);
+			if (status==EEXIST) {
+				abnormal_EEXIST_num ++;
+			} else if (status == ENOENT) {
+				abnormal_ENOENT_num ++;
+			} else
+				RFS_ASSERT (0);
+		}
+	} else {
+		proper_reply_num ++;
+		if (total_profile.in.tv_sec >= WARMUP_TIME) 
+			run_stage_proper_reply_num ++;
+	}
+
+}
+
+/* return -1 if there is no reply being received 
+ * return the dep_index if the corresponding reply has been received
+ */
+inline int receive_next_reply (int busy_flag)
+{
+	int dep_index;
+	int biod_index;
+	int proc;
+	char * line;
+	char * reply_line;
+	sfs_op_type *op_ptr;		/* per operation info */
+	int ret;
+	int status;
+	int trace_status;
+	char * errmsg;
+
+	/* wait for reply */
+	start_profile (&valid_poll_and_get_reply_profile);
+	start_profile (&invalid_poll_and_get_reply_profile);
+
+	if (busy_flag == BUSY) {
+		poll_timeout = 0;
+		poll_timeout_0_num ++;
+	} else {
+		poll_timeout = 2000;	/* 10000 or 2000 is a better number in non-debugging state */
+		//poll_timeout = 0;	/* 10000 or 2000 is a better number in non-debugging state */
+		poll_timeout_pos_num ++;
+	}
+
+	biod_index = poll_and_get_reply (poll_timeout);
+	if (biod_index==-1) {
+		end_profile (&invalid_poll_and_get_reply_profile);
+		return -1;
+	};
+	end_profile (&valid_poll_and_get_reply_profile);
+
+	start_profile (&decode_reply_profile);
+	/* check the corresponding request */
+	dep_index = biod_reqp[biod_index].dep_tab_index;
+	if (biod_reqp[biod_index].in_use==1) {
+		RFS_ASSERT (dep_tab[dep_index].biod_req_index == biod_index);
+	} else {
+		printf ("biod_index %d reply received but the request has been time out\n", biod_index);
+		return -1;
+	}
+
+	proc = dep_tab[dep_index].proc;
+	op_ptr = &Ops[proc];
+
+	if (dep_tab[dep_index].flag != DEP_FLAG_SENT) {
+		printf("dep_tab[%d].flag %d proc %d status %d start %d:%d stop %d:%d\n",
+			dep_index, dep_tab[dep_index].flag, proc, dep_tab[dep_index].status, 
+			dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec,
+			dep_tab[dep_index].stop.sec, dep_tab[dep_index].stop.usec );
+		printf ("received reply for timeout requests dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+		return dep_index;
+	}
+	RFS_ASSERT (dep_tab[dep_index].flag == DEP_FLAG_SENT);
+
+	/* decode the reply */
+	rfs_Ops[proc].setres (arg_res, buf1);
+	ret = proc_header (NFS_client, rfs_Ops[proc].xdr_res, arg_res);
+	RFS_ASSERT (ret == RPC_SUCCESS);
+	status = *((int *)arg_res);
+	errmsg = nfs3_strerror (status);
+	end_profile (&decode_reply_profile);
+
+	start_profile (&check_reply_profile);
+	/* compare with the reply in the trace */
+	line = dep_tab[dep_index].line;
+	reply_line = dep_tab[dep_index].reply_line;
+	trace_status = dep_tab[dep_index].trace_status;
+
+	/* print the result, trace play progress indicator 
+	if (rfs_debug || (	!profile_debug && ((dep_index %10000)==0)	) )
+		fprintf (stdout, "dep_tab[%d], disk_index %d, receive reply, rpc_ret %d xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d \n", dep_index, dep_tab[dep_index].disk_index, ret, biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec);
+	*/
+
+	/* error checking */
+	check_reply (proc, biod_index, dep_index, status, errmsg, trace_status);
+
+	/* free resources */
+	finish_request (biod_index, dep_index, status);
+	
+	/* we set 100 seconds warm up time */
+	if ((total_profile.in.tv_sec >= WARMUP_TIME)) {
+	/* get statistics */
+	if (status == trace_status || (status==NFS3_OK && trace_status==NFS3ERR_RFS_MISS) ) {
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+	} else {
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	}
+	sfs_elapsedtime (op_ptr, &(biod_reqp[biod_index].start), &(biod_reqp[biod_index].stop));
+	end_profile (&check_reply_profile);
+	}
+	
+	//start_profile (&add_create_object_profile);
+
+	if (trace_status == NFS3_OK && (proc==CREATE || proc==MKDIR || proc==SYMLINK || proc==MKNOD)) {
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+		RFS_ASSERT (reply_line);
+#endif
+		if (status!=NFS3_OK) {
+			/* commented out for 1022 */
+			printf ("!!!!!! Should have been an ASSERTION FAILURE \n");
+			RFS_ASSERT (proc==SYMLINK);
+			RFS_ASSERT (0);
+		} else {
+			if (proc!=SYMLINK || line[TRACE_VERSION_POS]!='2')
+				add_new_file_system_object(proc, dep_index, line, reply_line);
+		}
+	}
+	//end_profile (&add_create_object_profile);
+}
+
+inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line)
+{
+	char * child_trace_fh;
+	fh_map_t * parent_entryp;
+	char component_name[MAX_PLAY_PATH_SIZE];
+	char * parent_trace_fh;
+	char child_path[MAX_PLAY_PATH_SIZE];
+	post_op_fh3 * post_op_fh3_child;
+	char * reply_trace_fh;
+	nfs_fh3 * child_fh3;
+
+	parent_trace_fh = strstr (line, "fh");
+	RFS_ASSERT (parent_trace_fh);
+	parent_trace_fh +=3;
+	parent_entryp = lookup_fh (parent_trace_fh);
+	RFS_ASSERT (parent_entryp);
+	parse_name (parent_trace_fh+65, component_name);
+	strcpy (child_path, parent_entryp->path);
+	strcat (child_path, "/");
+	strcat (child_path, component_name);
+				
+	/* find the corresponding create request */
+	//printf ("before find reply trace_fh reply_line %s\n", reply_line);
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+	reply_trace_fh = dep_tab[dep_index].reply_trace_fh;
+#else
+	reply_trace_fh = find_reply_trace_fh (reply_line);
+#endif
+	RFS_ASSERT (reply_trace_fh != NULL);
+	switch (proc) {
+	case CREATE:
+		RFS_ASSERT (((CREATE3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((CREATE3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKDIR:
+		RFS_ASSERT (((MKDIR3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKDIR3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case SYMLINK:
+		RFS_ASSERT (((SYMLINK3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((SYMLINK3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKNOD:
+		RFS_ASSERT (((MKNOD3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKNOD3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case LOOKUP:
+		RFS_ASSERT (proc==LOOKUP);
+		child_fh3 = &((LOOKUP3res *)arg_res)->res_u.ok.object;
+		break;
+	default:
+		RFS_ASSERT (0);
+	}
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+	RFS_ASSERT (reply_trace_fh[TRACE_FH_SIZE]==' ');
+#endif
+	reply_trace_fh[TRACE_FH_SIZE] = 0;
+	add_fh (FH_MAP_FLAG_COMPLETE, reply_trace_fh, child_path, child_fh3); 	/* exist flag is not used now, set to 1 */
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+	/* just to preserve the original reply line not changed */
+	reply_trace_fh[TRACE_FH_SIZE] = ' ';
+#endif
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void trace_play(void)
+{
+	
+	/* The flag to indicate whether trace_player is BUSY. Trace_player is BUSY
+	 * when either there is request to send or there is reply being
+	 * received. Otherwise it is IDLE. The timeout for polling replies 
+	 * is set to 0 when BUSY, it is set to the waiting time to the first
+	 * request outside of current <min_dep_index, dep_window_max> window when IDLE.
+	 */
+   	int busy_flag = BUSY;		
+	//int dep_index;		/* index into dependency table: dep_tab */
+	//int biod_index; 	/* index into outstanding requests: biod_reqp */
+
+	disk_io_status = read_trace();
+	RFS_ASSERT (!CYCLIC_EMPTY(dep_tab_index));
+	CYCLIC_MOVE_HEAD(dep_window_index);
+
+	adjust_play_window(busy_flag, &poll_timeout);
+
+	start_profile (&total_profile);
+	while (!CYCLIC_EMPTY(dep_tab_index)) {
+		if ((total_profile.in.tv_sec > 600)) {
+			printf ("the process has run for more than 600 seconds, exit\n");
+			goto END;
+		}
+
+		if (busy_flag == IDLE) {
+			//start_profile (&check_timeout_profile);
+			check_timeout();
+			//end_profile (&check_timeout_profile);
+			if (disk_io_status!=TRACE_FILE_END) {
+				disk_io_status = read_trace();
+			};
+		}
+
+		//start_profile (&adjust_play_window_profile);
+	 	adjust_play_window (busy_flag, &poll_timeout);
+		if (rfs_debug)
+			printf("num_out_reqs %d\n", num_out_reqs);
+		busy_flag = IDLE;
+		//end_profile (&adjust_play_window_profile);
+
+		start_profile (&execute_next_request_profile);
+		while (execute_next_request()!=-1) {
+			busy_flag = BUSY;
+		}
+		end_profile (&execute_next_request_profile);
+
+
+		start_profile (&receive_next_reply_profile);
+		/* actually the performance of two policy seems to be same */
+//#define SEND_HIGHER_PRIORITY_POLICY
+#define SEND_RECEIVE_EQUAL_PRIORITY_POLICY	
+
+#ifdef SEND_HIGHER_PRIORITY_POLICY
+		receive_next_reply(IDLE);
+#endif
+#ifdef SEND_RECEIVE_EQUAL_PRIORITY_POLICY
+		busy_flag = IDLE;
+		while (receive_next_reply(busy_flag)!=-1)
+			busy_flag = BUSY;
+#endif
+		end_profile (&receive_next_reply_profile);
+
+		CYCLIC_ASSERT (0);
+	}
+	end_profile (&total_profile);
+
+	RFS_ASSERT (disk_io_status == TRACE_FILE_END);
+	if (num_out_reqs !=0 ) {
+		printf ("num_out_reqs %d\n", num_out_reqs);
+		CYCLIC_PRINT(dep_tab_index);
+	}
+	RFS_ASSERT(num_out_reqs==0);
+
+END:
+	printf ("trace starttime %d, trace_end_time %d trace_duration %d\n", trace_timestamp1, trace_timestamp2,
+		trace_timestamp2 - trace_timestamp1);
+	printf ("can_not_catch_speed_num_total %d can_not_catch_speed_num_last_10_seconds %d", 
+		can_not_catch_speed_num_total, can_not_catch_speed_num);
+	printf ("total_profile.about: %s\n", total_profile.about);
+	print_profile ("total_profile", &total_profile);
+	printf("\n");
+	//print_profile ("check_timeout", &check_timeout_profile);
+	//printf("\n");
+	//print_profile ("adjust_play_window", &adjust_play_window_profile);
+	//printf("\n");
+	print_profile ("execute_next_request_profile", &execute_next_request_profile);
+	print_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	print_profile ("invalid_get_nextop_profile", &invalid_get_nextop_profile);
+	print_profile ("prepare_argument_profile", &prepare_argument_profile);
+	print_profile ("biod_clnt_call_profile", &biod_clnt_call_profile);
+	printf("\n");
+	print_profile ("receive_next_reply_profile", &receive_next_reply_profile);
+	print_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	print_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	print_profile ("decode_reply_profile", &decode_reply_profile);
+	print_profile ("check_reply_profile", &check_reply_profile);
+	print_profile ("fgets_profile", &fgets_profile);
+	print_profile ("read_line_profile", &read_line_profile);
+	print_profile ("read_trace_profile", &read_trace_profile);
+	//print_profile ("add_create_object", &add_create_object_profile);
+	printf("\n");
+	
+	printf ("dep_tab_index.tail %d dep_tab_index.head %d num_out_reqs %d\n", dep_tab_index.tail, dep_tab_index.head, num_out_reqs);
+}
+
+int CYCLIC_SET_TAIL_TO(cyclic_index_t * index, int dest) 
+{ 
+	cyclic_index_t indextmp, indextmp2;
+	int oldnum, num;
+	indextmp = *index;
+	indextmp2 = indextmp;
+	oldnum = CYCLIC_NUM(indextmp); 
+
+	if (! ((dest>=0) && (dest<indextmp.size))) {
+		CYCLIC_PRINT(indextmp);
+		printf("dest %d\n", dest);
+	}
+	RFS_ASSERT ((dest>=0) && (dest<indextmp.size));
+	index->tail = dest; 
+	indextmp2.tail = dest;
+	num = CYCLIC_NUM(indextmp2); 
+
+	if (num > oldnum) { 
+		CYCLIC_PRINT(indextmp);
+		CYCLIC_PRINT(indextmp2);
+		printf("dest %d old_num %d num %d\n", dest, oldnum, num);
+	}
+	RFS_ASSERT (num <= oldnum);
+}
+
+int flush_junk()
+{
+	int i;
+	for (i=0; i<500; i++) {
+		printf ("*************************************************************\n");
+	}
+	fflush(stdout);
+}
+
+int CYCLIC_ASSERT (int i)
+{
+	int j;
+	if (!(dep_tab_index.tail == dep_window_index.tail)) {
+		printf("%s head %d tail %d, size %d\n", dep_tab_index.name, dep_tab_index.head, dep_tab_index.tail, dep_tab_index.size);
+		printf("%s head %d tail %d, size %d\n", dep_window_index.name, dep_window_index.head, dep_window_index.tail, dep_window_index.size);
+		printf("pos %d\n", i); 
+		flush_junk();
+		sleep (10);
+		RFS_ASSERT (0);
+	};
+ 
+	if (!((dep_window_index.head == dep_tab_index.head) || 
+		   CYCLIC_LESS(dep_tab_index, dep_window_index.head, dep_tab_index.head ) )) {
+		printf("%s head %d tail %d, size %d\n", dep_tab_index.name, dep_tab_index.head, dep_tab_index.tail, dep_tab_index.size);
+		printf("%s head %d tail %d, size %d\n", dep_window_index.name, dep_window_index.head, dep_window_index.tail, dep_window_index.size);
+		printf("pos %d\n", i); 
+		flush_junk();
+		sleep (10);
+		RFS_ASSERT (0);
+	};
+	for (i=0, j=0; i<max_biod_reqs; i++) {
+		if (biod_reqp[i].in_use == 1)
+			j++;
+	}
+	RFS_ASSERT (num_out_reqs==j);
+/*
+		RFS_ASSERT ((dep_window_index.head == dep_tab_index.head) || 
+			   CYCLIC_LESS(dep_tab_index, dep_window_index.head, dep_tab_index.head ));
+*/
+}
+
+/* sfs_c_chd.c */
diff --git a/TBBT/trace_play/sfs_c_chd.3thread.c b/TBBT/trace_play/sfs_c_chd.3thread.c
new file mode 100644
index 0000000..195beb0
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_chd.3thread.c
@@ -0,0 +1,3815 @@
+/* Try to change thread scheduling and uses three threads */
+#ifndef lint
+static char sfs_c_chdSid[] = "@(#)sfs_c_chd.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * -------------------------- sfs_c_chd.c -------------------------
+ *
+ *      The sfs child.  Routines to initialize child parameters,
+ *	initialize test directories, and generate load.
+ *
+ *.Exported_Routines
+ *	void child(int, float, int, char *);
+ *	void init_fileinfo(void);
+ *	void init_counters(void);
+ *	sfs_fh_type * randfh(int, int, uint_t, sfs_state_type,
+ *				sfs_file_type);
+ *	int check_access(struct *stat)
+ *	int check_fh_access();
+ *
+ *.Local_Routines
+ *	void check_call_rate(void);
+ *	void init_targets(void);
+ *	void init_dirlayout(void);
+ *	void init_rpc(void);
+ *	void init_testdir(void);
+ *	int do_op(void);
+ *	int op(int);
+ *
+ *.Revision_History
+ *	21-Aug-92	Wittle 		randfh() uses working set files array.
+ *					init_fileinfo() sets up working set.
+ *      02-Jul-92	Teelucksingh    Target file size now based on peak load
+ *					instead of BTDT.
+ *	04-Jan-92	Pawlowski	Added raw data dump hooks.
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+#include "rfs_c_def.h"
+#include "generic_hash.h"
+#include "nfsd_nfsfh_cust.h"
+
+extern struct hostent   *Server_hostent;
+
+#define PROB_SCALE 1000L
+#define _M_MODULUS 2147483647L /* (2**31)-1 */
+
+#define _GROUP_DIVISOR 500
+#define _FILES_PER_GROUP 4
+#define _MIN_GROUPS 12
+#define _WORKING_SET_AT_25_OPS_PER_SEC 975
+
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+extern uint32_t    biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
+extern enum clnt_stat proc_header(CLIENT *cl, xdrproc_t xdr_results, void *results_ptr);
+extern int  biod_poll_wait(CLIENT *, uint32_t);
+extern enum clnt_stat get_areply_udp (CLIENT * cl, uint32_t *xid, struct timeval *timeout);
+extern char * parse_name (char * t, char * buf);
+
+/* forward definitions for local functions */
+static int init_rpc(void);
+
+/* RFS: forward definitions for local functions */
+void init_ops(void);
+static void init_signal();
+extern void init_file_system (void);
+extern void init_dep_tab (void);
+static int read_trace(void);
+static void read_fh_map();
+static void init_play (char * mount_point);
+static void trace_play(void);
+void print_result(void);
+static int get_nextop(void);
+static int check_timeout(void);
+static struct biod_req * get_biod_req(int dep_tab_index);
+static int lookup_biod_req (int xid);
+static void init_time_offset(void);
+void adjust_play_window (int flag, int * poll_timeout_arg);
+static int poll_and_get_reply (int usecs);
+static char * nfs3_strerror(int status);
+static void check_clock(void);
+static double time_so_far1(void);
+static double get_resolution(void);
+static void usage(void);
+void init_dep_tab_entry (int dep_index);
+extern inline fh_map_t * lookup_fh (char * trace_fh );
+static void finish_request (int biod_index, int dep_index, int status, int dep_flag);
+static inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line);
+static inline char * find_lead_trace_fh(int proc, char * line);
+static inline char * find_reply_trace_fh (char * line);
+
+/*
+ * -------------  Per Child Load Generation Rate Variables  -----------
+ */
+static uint_t Calls_this_period; /* calls made during the current run period */
+static uint_t Calls_this_test;	/* calls made during the test so far */
+static uint_t Reqs_this_period;	/* reqs made during the current run period */
+static uint_t Reqs_this_test;	/* reqs made during the test so far */
+static uint_t Sleep_msec_this_test; /* msec slept during the test so far */
+static uint_t Sleep_msec_this_period;
+static uint_t Previous_chkpnt_msec; /* beginning time of current run period */
+static int Target_sleep_mspc;	/* targeted sleep time per call */
+
+static char io_buf[BUFSIZ];	/* io buffer for print out messages */
+
+char * sfs_Myname;
+int     Log_fd;                         /* log fd */
+char    Logname[NFS_MAXNAMLEN];         /* child processes sync logfile */
+int 	Validate = 0;					/* fake variable */
+int Child_num = 0;						/* fake: child index */
+int Tcp = 0;							/* We implement UDP first */
+int Client_num = 1;						/* fake: number of client */
+uid_t Real_uid;
+gid_t Cur_gid;
+uid_t Cur_uid;
+/* as long as the inital value is different, then it's OK */
+int recv_num = 0;
+int timeout_num = 0;
+int send_num = 0;
+int exit_flag = 0;
+int async_rpc_sem;
+int no_progress_flag = 0;
+int num_out_reqs_statistics[MAX_OUTSTANDING_REQ+1];
+int num_out_reqs_statistics_at_timeout[MAX_OUTSTANDING_REQ+1];
+
+/*
+ * -------------------------  SFS Child  -------------------------
+ */
+
+static int nfs2proc_to_rfsproc[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
+									10, 11, 12, 13, 14, 15, 16, 17};
+static int nfs3proc_to_rfsproc[NFS3_PROCEDURE_COUNT] = {0, 1, 2, 4, 18, 5, 6, 8, 9, 14, 
+													13, 21, 10, 15, 11, 12, 16, 23, 17, 20, 
+													22, 19};
+void print_usage(int pos, int argc, char ** argv)
+{
+	int i;
+	printf("sfs3 hostname:mount_dir trace_file|stdin fh_map_file play_scale warmup_time(in seconds) \n");
+	printf("sfs3 -pair_trace trace_file\n");
+	printf("sfs3 -pair_write trace_file\n");
+	printf("sfs3 -help\n");
+	printf ("pos %d argc %d", pos, argc);
+	for (i=0; i<argc; i++) {
+		printf(" %s", argv[i]);
+	} 
+	printf ("\n");
+	exit;
+}
+
+void print_cyclic_buffers ()
+{
+	CYCLIC_PRINT(memory_trace_index);
+	CYCLIC_PRINT(dep_tab_index);
+	CYCLIC_PRINT(dep_window_index);
+}
+
+void add_to_dep_tab(int i)
+{
+	char * trace_fh;
+	fh_map_t * fh_map_entry;
+	dep_tab_t * ent;
+
+    trace_fh = strstr (memory_trace[i].line, "fh");
+    if (!trace_fh)
+	printf ("memory_trace[%d].line %s\n", i, memory_trace[i].line);
+    RFS_ASSERT (trace_fh);
+    trace_fh += 3;
+    fh_map_entry = lookup_fh (trace_fh);
+    if (fh_map_entry && (fh_map_entry->flag==FH_MAP_FLAG_DISCARD) )  {
+        req_num_with_discard_fh ++;
+		return;
+	}
+    if (fh_map_entry)
+        req_num_with_init_fh ++;
+    else
+        req_num_with_new_fh ++;
+                                                                                                                              
+	RFS_ASSERT (!CYCLIC_FULL(dep_tab_index));
+	ent = &(dep_tab[dep_tab_index.head]);
+
+    ent->disk_index = memory_trace[i].disk_index;
+	ent->memory_index = i;
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+    ent->trace_status = memory_trace[i].trace_status;
+    ent->reply_trace_fh = memory_trace[i].reply_trace_fh;
+#endif
+    ent->line = memory_trace[i].line;
+    init_dep_tab_entry(dep_tab_index.head);
+
+    if (rfs_debug && (i%100000)==0)
+    	printf ("dep_tab[%d].disk_index %d = memory_trace[%d].disk_index %d\n", dep_tab_index.head, ent->disk_index, i, memory_trace[i].disk_index);
+    CYCLIC_MOVE_HEAD(memory_trace_index);
+    CYCLIC_MOVE_HEAD(dep_tab_index);
+}
+
+void init_profile_variables ()
+{
+	init_profile ("total_profile", &total_profile);
+	init_profile ("execute_next_request_profile", &execute_next_request_profile);
+	init_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	init_profile ("invalid_get_nextop_profile",&invalid_get_nextop_profile);
+	init_profile ("prepare_argument_profile", &prepare_argument_profile);
+	init_profile ("biod_clnt_call_profile", &biod_clnt_call_profile);
+	init_profile ("receive_next_reply_profile", &receive_next_reply_profile);
+	init_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	init_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	init_profile ("decode_reply_profile", &decode_reply_profile);
+	init_profile ("check_reply_profile", &check_reply_profile);
+	init_profile ("add_create_object_profile", &add_create_object_profile);
+	init_profile ("check_timeout_profile", &check_timeout_profile);
+	init_profile ("adjust_play_window_profile",&adjust_play_window_profile);
+	init_profile ("fgets_profile",&fgets_profile);
+	init_profile ("read_line_profile",&read_line_profile);
+	init_profile ("read_trace_profile",&read_trace_profile);
+}
+
+static char trace_file[256]="anon-lair62-011130-1200.txt";
+int print_memory_usage()
+{
+	printf("size of fh_map_t %d size of fh_map %d\n", sizeof(fh_map_t), sizeof(fh_map));
+	printf("sizeof dep_tab_t %d sizeof dep_tab %d\n", sizeof(dep_tab_t), sizeof(dep_tab));
+	printf("size of memory_trace_ent_t %d sizeof memory_trace %d\n", sizeof(memory_trace_ent_t), sizeof(memory_trace));
+	printf("size of CREATE3args %d\n", sizeof( CREATE3args));
+	printf("size of MKDIR3args %d\n", sizeof( MKDIR3args));
+	printf("size of READ3args %d\n", sizeof( READ3args));
+	printf("size of WRITE3args %d\n", sizeof( WRITE3args));
+	printf("size of RENAME3args %d\n", sizeof( RENAME3args));
+	printf("size of GETATTR3args %d\n", sizeof( GETATTR3args));
+	printf("size of SETATTR3args %d\n", sizeof( SETATTR3args));
+	printf("size of LINK3args %d\n", sizeof( LINK3args));
+	printf("size of SYMLINK3args %d\n", sizeof( SYMLINK3args));
+	printf("size of MKNOD3args %d\n", sizeof( MKNOD3args));
+	printf("size of RMDIR3args %d\n", sizeof( RMDIR3args));
+	printf("size of REMOVE3args %d\n", sizeof( REMOVE3args));
+	printf("size of LOOKUP3args %d\n", sizeof( LOOKUP3args));
+	printf("size of READDIR3args %d\n", sizeof( READDIR3args));
+	printf("size of READDIRPLUS3args %d\n", sizeof( READDIRPLUS3args));
+	printf("size of FSSTAT3args %d\n", sizeof( FSSTAT3args));
+	printf("size of FSINFO3args %d\n", sizeof( FSINFO3args));
+	printf("size of COMMIT3args %d\n", sizeof( COMMIT3args));
+	printf("size of ACCESS3args %d\n", sizeof( ACCESS3args));
+	printf("size of READLINK3args %d\n", sizeof( READLINK3args));
+
+
+}
+
+void recv_thread()
+{
+	int last_print_time = -1;
+	int busy_flag;
+
+	while (send_num ==0) {
+		usleep(1000);
+	}
+
+	//while (!CYCLIC_EMPTY(dep_tab_index)) {
+	while (!exit_flag) {
+		if ((total_profile.in.tv_sec - last_print_time >= 10)) {
+			static int recv_num_before_10_seconds = 0;
+			last_print_time = total_profile.in.tv_sec;
+			fprintf (stdout, "<<<<< recv_thread recv_num %d time %d num_out_reqs %d \n", recv_num, total_profile.in.tv_sec, num_out_reqs);
+			if (recv_num == recv_num_before_10_seconds) {
+				no_progress_flag = 1;
+				RFS_ASSERT (0);
+			} else 
+				recv_num_before_10_seconds = recv_num;
+		}
+		//start_profile (&check_timeout_profile);
+		check_timeout();
+		//end_profile (&check_timeout_profile);
+
+		pthread_yield();
+		//usleep(1000);
+		start_profile (&receive_next_reply_profile);
+		/* actually the performance of two policy seems to be same */
+//#define SEND_HIGHER_PRIORITY_POLICY
+#define SEND_RECEIVE_EQUAL_PRIORITY_POLICY	
+#ifdef SEND_HIGHER_PRIORITY_POLICY
+		receive_next_reply(IDLE);
+#endif
+#ifdef SEND_RECEIVE_EQUAL_PRIORITY_POLICY
+		busy_flag = IDLE;
+		while (receive_next_reply(busy_flag)!=-1) {
+			busy_flag = BUSY;
+		}
+#endif
+		end_profile (&receive_next_reply_profile);
+	}
+	printf ("<<<< recv thread EXIT\n");
+	exit_flag = 2;
+}
+
+int io_thread ()
+{
+/* number of seconds the I/O thread pauses after each time trying to read the requests */
+#define IO_THREAD_PAUSE_TIME 1
+
+	int i;
+	int j = 0;
+
+	disk_io_status = read_trace ();
+	while (disk_io_status == TRACE_BUF_FULL) {
+
+		usleep (10000);
+        if ((j++%1000)==0) {
+                printf("&&&&&&&&&& io thread, sleep %d seconds\n", j/100);
+        }
+
+		disk_io_status = read_trace ();
+		//printf ("io_thread, after read_trace, disk_index %d\n", disk_index);
+
+#ifdef SEQUEN_READ
+		for (i=0; i<SEQUEN_READ_NUM; i++) {
+			add_to_dep_tab(CYCLIC_MINUS(memory_trace_index.head,1,memory_trace_index.size));
+		}
+#endif
+		//printf ("***************** IO THREAD SLEEP 1 s\n");
+		//print_cyclic_buffers();
+		//pthread_yield();
+	}
+	RFS_ASSERT (disk_io_status == TRACE_FILE_END);
+	printf("io_thread EXIT\n");
+}
+
+int execute_thread()
+{
+	int i;
+	struct timeval playstart_time, playend_time;
+
+	sleep (10);		/* first let io_thread to run for a while */
+	printf ("trace_play\n");
+
+	gettimeofday(&playstart_time, NULL);
+
+	init_time_offset();
+	trace_play ();
+
+	gettimeofday(&playend_time, NULL);
+
+	{
+		int usec, sec;
+		sec = playend_time.tv_sec - playstart_time.tv_sec;
+		usec = sec * 1000000 + (playend_time.tv_usec - playstart_time.tv_usec);
+		sec = usec / 1000000;
+		usec = usec % 1000000;
+		printf("Total play time: %d sec %d usec\n", sec, usec);
+		if (sec > WARMUP_TIME)
+			print_result();
+		else
+			printf ("the trace play time %d is less than WARMUP_TIME %d, no statistical results\n");
+	}
+#ifdef RECV_THREAD
+	exit_flag = 1;
+	while (exit_flag == 1) {
+		usleep (1000);
+	}
+#endif
+
+    clnt_destroy(NFS_client);
+    biod_term();
+}
+
+int init_thread ()
+{
+	pthread_attr_t	attr;
+	int arg;
+	int ret = 0;
+	pthread_t io_thread_var;
+#ifdef RECV_THREAD
+	pthread_t recv_thread_var;
+#endif
+	pthread_t execute_thread_var;
+
+	ret = pthread_attr_init (&attr);
+	if (ret!=0) {
+		perror("pthread_attr_init attr");
+		return ret;
+	}
+#ifdef IO_THREAD
+	ret = pthread_create (&(io_thread_var), &attr, &io_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("io_pthread_attr_init");
+		return ret;
+	}
+#endif
+
+#ifdef RECV_THREAD
+	ret = pthread_create (&(recv_thread_var), &attr, &recv_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("recv_pthread_attr_init");
+		return ret;
+	}
+#endif
+
+/*
+	ret = pthread_create (&(execute_thread_var), &attr, &execute_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("io_pthread_attr_init");
+		return ret;
+	}
+*/
+}
+
+void init_buffers()
+{
+	CYCLIC_INIT("memory_trace_index",memory_trace_index,MAX_MEMORY_TRACE_LINES);
+	CYCLIC_INIT("dep_tab_index     ",dep_tab_index,DEP_TAB_SIZE);
+	CYCLIC_INIT("dep_window_index  ",dep_window_index,DEP_TAB_SIZE);
+}
+
+int main(int argc, char ** argv)
+{
+	extern char * optarg;
+	int i;
+	struct timeval in={1000000, 100};
+	
+	init_profile_variables();
+	if ((argc==1) || (argc==2 && !strcmp(argv[1],"-help"))) {
+		print_usage(0, argc, argv);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-pair_write")) {
+		if (argc==3) 
+			strcpy(trace_file, argv[2]);
+		else
+			strcpy(trace_file, "stdin");
+		pair_write(trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-pair_trace")) {
+		if (argc==3) 
+			strcpy(trace_file, argv[2]);
+		else
+			strcpy(trace_file, "stdin");
+		pair_trace(trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-check_aging")) {
+		if (argc!=3) {
+			print_usage(3, argc, argv);
+			exit(0);
+		}
+		strcpy(trace_file, argv[2]);
+		check_aging (trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-check_statistics")) {
+		if (argc!=3) {
+			print_usage(1, argc, argv);
+			exit(0);
+		}
+		strcpy(trace_file, argv[2]);
+		memset(fh_htable, 0, sizeof (fh_htable));
+		check_statistics (trace_file);
+		exit(0);
+	}
+
+	if (argc!=6) {
+		print_usage(2, argc, argv);
+		exit(0);
+	}
+
+	PLAY_SCALE = atoi (argv[4]);
+	RFS_ASSERT (PLAY_SCALE >=1 && PLAY_SCALE <=10000);
+
+	WARMUP_TIME = atoi (argv[5]);
+	RFS_ASSERT (WARMUP_TIME >=0 && WARMUP_TIME <=1000);
+	
+	print_memory_usage();
+	check_clock();
+    getmyhostname(lad_hostname, HOSTNAME_LEN);
+
+    init_ops();
+	/*
+	 * Get the uid and gid information.
+	 */
+	Real_uid = getuid();
+	Cur_gid = getgid();
+	//Real_uid = 513;
+	//Cur_gid = 513;
+
+	Nfs_timers = Nfs_udp_timers;
+
+	init_semaphores();
+	init_file_system ();
+	init_signal();
+	init_play (argv[1]);
+	//init_play ("capella:/p5/RFSFS");
+	init_fh_map();
+	read_fh_map (argv[3]);
+	//read_fh_map ("fh-path-map-play");
+	strcpy(trace_file, argv[2]);
+
+/* If ordered by TIMESTAMP,
+ * memory_trace_index.tail <= dep_tab_index.tail < dep_window_max <=
+ * dep_tab_index.head <= memory_trace_index.head
+ */
+
+	init_global_variables();
+	init_buffers();
+	init_thread();
+	pthread_yield();
+	execute_thread();
+}
+
+int init_global_variables()
+{
+	memset (num_out_reqs_statistics, 0, sizeof(num_out_reqs_statistics));
+	memset (num_out_reqs_statistics_at_timeout, 0, sizeof(num_out_reqs_statistics_at_timeout));
+}
+
+int init_semaphores()
+{
+	async_rpc_sem = dest_and_init_sem (ASYNC_RPC_SEM_KEY, 1, "async_rpc_sem");
+}
+
+void init_ops (void)
+{
+	Ops = nfsv3_Ops;
+	nfs_version = NFS_V3;
+}
+
+/* Set up the signal handlers for all signals */
+void init_signal()
+{
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	struct sigaction sig_act, old_sig_act;
+
+	/* use XOPEN signal handling */
+
+	sig_act.sa_handler = generic_catcher;
+	(void)sigemptyset(&sig_act.sa_mask);
+	sig_act.sa_flags = 0;
+
+	/* signals handlers for signals used by sfs */
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGINT,&sig_act,&old_sig_act) == -1) {
+	    perror("sigaction failed: SIGINT");
+	    exit(135);
+	}
+
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGTERM,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGTERM");
+	    exit(137);
+	}
+#else
+    /* signals handlers for signals used by sfs */
+    (void) signal(SIGINT, sfs_cleanup);
+    // RFS (void) signal(SIGALRM, sfs_alarm);
+	(void) signal(SIGTERM, sfs_cleanup);
+#endif
+}
+
+void
+init_play (
+    char	* mount_point)		/* Mount point for remote FS */
+{
+    char	namebuf[NFS_MAXNAMLEN] = "trace_play";	/* unique name for this program */
+    CLIENT *	mount_client_ptr;	/* Mount client handle */
+
+	if (!rfs_debug);
+    	(void) setvbuf(stderr, io_buf, _IOLBF, BUFSIZ);
+
+    sfs_Myname = namebuf;
+
+    /*
+     * May require root priv to perform bindresvport operation
+     */
+    mount_client_ptr = lad_getmnt_hand(mount_point);
+    if (mount_client_ptr == NULL) {
+		exit(145);
+    }
+
+    /*
+     * should be all done doing priv port stuff
+     */
+
+    if (init_rpc() == -1) {
+		(void) fprintf(stderr, "%s: rpc initialization failed\n", sfs_Myname);
+		(void) generic_kill(0, SIGINT);
+		exit(146);
+    }
+
+
+    /*
+     * finish all priv bindresvport calls
+     * reset uid
+     */
+    if (setuid(Real_uid) != (uid_t)0) {
+	(void) fprintf(stderr,"%s: %s%s", sfs_Myname,
+	    "cannot perform setuid operation.\n",
+	    "Do `make install` as root.\n");
+    }
+
+    init_mount_point(0, mount_point, mount_client_ptr);
+
+
+    /*
+     * Cleanup client handle for mount point
+     */
+    clnt_destroy(mount_client_ptr);
+
+	init_counters();
+}
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+void inline format_line (char * line_before, char * line)
+{
+	char * pv = line_before;
+	char * pl = line;
+	char * p;
+	int i;
+	
+	//printf("format_line before %s\n", line_before);
+	p = strstr (pv, "fh");
+	while (p!=NULL) {
+		while (pv<=p)
+			*pl++ = *pv++;
+		*pl++ = *pv++;
+		if (*pv==2) {
+			*pl++ = *pv++;
+		}
+		*pl++ = *pv++;
+		i = 0;
+		while (*pv !=' ') {
+			RFS_ASSERT ((*pv >='0' && *pv <='9') || (*pv >='a' && *pv<='f'));
+			*pl++ = *pv++;
+			i++;
+		}
+		RFS_ASSERT ((i==48) || (i==40) || (i==24));
+		while (i<48) {
+			*pl++ = '0';
+			i++;
+		}
+		p = strstr (pv, "fh");
+	}
+	while ((*pv)!=NULL) {
+		*pl++ = *pv++;
+	}
+	//printf("format_line after %s\n", line);
+}
+
+char * read_line (int disk_index)
+{
+	static FILE * fp=NULL;
+	static int start=0;
+	static int start_disk_index=0;
+	int i;
+	static int finish_flag = 0;
+	static int varfh_flag = 0;
+#define READ_LINE_BUF_SIZE (MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR+2)
+#define SAFE_BYTES 1000
+#define READ_LINE_LENGTH (MAX_TRACE_LINE_LENGTH+SAFE_BYTES)
+
+	static char line_buf[READ_LINE_BUF_SIZE][READ_LINE_LENGTH];
+	char varfh_line_buf[READ_LINE_LENGTH];
+
+	start_profile (&read_line_profile);
+
+	if (fp==NULL) {
+		if (strcmp(trace_file, "stdin")) {
+			fp = fopen(trace_file, "r");
+
+			if (strstr(trace_file, ".varfh")) {
+				varfh_flag = 1;
+			};
+			if (strstr(trace_file, ".fmt1")) {
+				TRACE_COMMAND_REPLY_FLAG_POS += 12;
+				TRACE_VERSION_POS +=12;
+				TRACE_MSGID_POS +=12;
+				TRACE_FH_SIZE =48;
+			}
+			if (!fp) {
+				printf("can not open files %s\n", fp);
+				perror("open");
+			}
+		} else {
+			fp = stdin;
+		}
+		RFS_ASSERT (fp!=NULL);
+		for (i=0; i<READ_LINE_BUF_SIZE; i++) {
+			start_profile(&fgets_profile);
+			if (varfh_flag) {
+				if (!fgets(varfh_line_buf, READ_LINE_LENGTH, fp)) {
+					RFS_ASSERT (0);
+				}
+				format_line (varfh_line_buf, line_buf[i]);
+			} else {
+				if (!fgets(line_buf[i], READ_LINE_LENGTH, fp)) {
+					RFS_ASSERT (0);
+				}
+			}
+			end_profile(&fgets_profile);
+			//printf ("read_line, line_buf[%d]:%s", i, line_buf[i]);
+		}
+	}
+	
+	if (disk_index > start_disk_index+READ_LINE_BUF_SIZE) {
+		printf ("disk_index %d start_disk_index %d READ_LINE_BUF_SIZE %d\n", 
+			disk_index, start_disk_index, READ_LINE_BUF_SIZE);
+	}
+	RFS_ASSERT (disk_index <= start_disk_index+READ_LINE_BUF_SIZE)
+	if (disk_index==(start_disk_index+READ_LINE_BUF_SIZE)) {
+		if (finish_flag) {
+			return NULL;
+		}
+		start_profile(&fgets_profile);
+		if (!fgets(line_buf[start], READ_LINE_LENGTH, fp)) {
+			end_profile(&fgets_profile);
+			finish_flag = 1;
+			return NULL;
+		}
+		end_profile(&fgets_profile);
+		//printf ("read_line, line_buf[%d]:%s", start, line_buf[start]);
+		start = (start+1) % READ_LINE_BUF_SIZE;
+		start_disk_index ++;
+	}
+	RFS_ASSERT (disk_index < start_disk_index+READ_LINE_BUF_SIZE)
+	i = (start+disk_index-start_disk_index)%READ_LINE_BUF_SIZE;
+
+/*
+	if (!(strlen(line_buf[i])>80)) {
+		printf ("start %d start_disk_index %d disk_index %d strlen %d line_buf[%d] %s\n", start, start_disk_index, disk_index, strlen(line_buf[i]), i, line_buf[i]);
+		RFS_ASSERT (strlen(line_buf[i])>80);
+	}
+	if (!((strlen(line_buf[i])>80) && (strlen(line_buf[i])<MAX_TRACE_LINE_LENGTH)))
+		printf ("disk_index %d strlen %d line_buf[%d] %s\n", disk_index, strlen(line_buf[i]), i, line_buf[i]);
+	RFS_ASSERT ((strlen(line_buf[i])>80) && (strlen(line_buf[i])<MAX_TRACE_LINE_LENGTH));
+*/
+
+	end_profile (&read_line_profile);
+	return (line_buf[i]);
+}
+
+#define OPS_FLAG_INC 0
+#define OPS_FLAG_PRINT 1
+int read_write_fh_statistics (int flag, char * buf, int timestamp)
+{
+	static FILE * fp = NULL;
+	char * p;
+	char c;
+	if (!fp) {
+		fp = fopen ("read_write_fh.output", "w");
+		RFS_ASSERT (fp);
+	}
+	if (flag == OPS_FLAG_INC) {
+		p = strstr (buf, "fh");
+		RFS_ASSERT (p);
+		c = p[40+3];
+		p[40+3]=0;
+		fprintf(fp, "%s\n", p+3+24);
+		p[40+3]=c;
+	};
+	if (flag == OPS_FLAG_PRINT) { 
+		int disk_index = (int) buf;
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+int write_statistics(int flag, char * buf, char * reply_buf, int trace_status)
+{
+	static FILE * fp = NULL;
+	int pre_size, size, count;
+	char * p = reply_buf;
+	if (!fp) {
+		fp = fopen ("write.output", "w");
+		RFS_ASSERT (fp);
+	}
+	if (flag == OPS_FLAG_INC) {
+		p = strstr (p, "pre-size");
+		RFS_ASSERT (p);
+		sscanf (p, "pre-size %x", &pre_size); 
+		p += strlen("pre-size");
+		p = strstr (p, "size");
+		RFS_ASSERT (p);
+		sscanf (p, "size %x", &size); 
+		p = strstr (p, "count");
+		if (!p) 
+			fprintf (fp, "%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+		RFS_ASSERT (p);
+		sscanf (p, "count %x", &count); 
+		fprintf (fp, "%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+	}
+	if (flag == OPS_FLAG_PRINT) {
+		int disk_index = (int) buf;
+		int timestamp = (int) reply_buf;
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+void ops_statistics (int ops_flag, int proc, int timestamp)
+{
+	static FILE * fp = NULL;
+	static struct {
+		int count;
+		int count_K;
+		int update_flag;
+		char name[32];
+	} ops[NOPS]={{0, 0, 0, "NULL"},{0, 0, 0, "GETATTR"},{0, 0, 1, "SETATTR"},{0, 0, 0, "ROOT"},
+				  {0, 0, 0, "LOOKUP"},{0, 0, 0, "READLINK"},{0, 0, 0, "READ"},{0, 0, 1, "WRCACHE"},
+				  {0, 0, 1, "WRITE"}, {0, 0, 1, "CREATE"},{0, 0, 1, "REMOVE"},{0, 0, 1, "RENAME"},
+				  {0, 0, 1, "LINK"}, {0, 0, 1, "SYMLINK"},{0, 0, 1, "MKDIR"},{0, 0, 1, "RMDIR"},
+				  {0, 0, 0, "READDIR"},{0, 0, 0, "FSSTAT"},{0, 0, 0, "ACCESS"},{0, 0, 0, "COMMIT"},
+				  {0, 0, 0, "FSINFO"},{0, 0, 1, "MKNOD"}, {0, 0, 0, "PATHCONF"}, {0, 0, 0, "READDIRPLUS"}};
+
+	if (ops_flag == OPS_FLAG_INC) {
+		RFS_ASSERT (proc>=0 && proc<NOPS);
+		ops[proc].count ++;
+		if (ops[proc].count == 1000) {
+			ops[proc].count_K ++;
+			ops[proc].count = 0;
+		}
+	}
+	if (ops_flag == OPS_FLAG_PRINT) {
+		int i;
+		int update_K=0, update=0, total_K=0, total=0;
+		float f1, f2;
+		int disk_index = proc;
+
+		if (!fp) {
+			fp = fopen ("mix.output", "w");
+			RFS_ASSERT (fp);
+		}
+		for (i=0; i<NOPS; i++) {
+			total_K += ops[i].count_K;
+			total += ops[i].count;
+			if (ops[i].update_flag) {
+				update_K += ops[i].count_K;
+				update += ops[i].count;
+			}
+		}
+		update_K += update/1000;
+		update = update%1000;
+		total_K += total/1000;
+		total = total%1000;
+
+		f1 = total_K;
+		f1 = f1*1000+total;
+		for (i=0; i<NOPS; i++) {
+			f2 = ops[i].count_K;
+			f2 = f2*1000+ops[i].count;
+			fprintf (fp, "%12s %8d,%03d %3.2f\%\n", ops[i].name, ops[i].count_K, ops[i].count, f2*100/f1);	
+			fprintf (stderr, "%12s %8d,%03d %3.2f\%\n", ops[i].name, ops[i].count_K, ops[i].count, f2*100/f1);	
+		}
+		f2 = update_K;
+		f2 = f2*1000+update;
+		fprintf (fp, "       total %8d,%03d\n", total_K, total);
+		fprintf (stderr, "       total %8d,%03d\n", total_K, total);
+		fprintf (fp, "      update %8d,%03d %2.2f\%\n", update_K, update, f2*100/f1);	
+		fprintf (stderr, "      update %8d,%03d %2.2f\%\n", update_K, update, f2*100/f1);	
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+		fprintf(stderr, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+
+void truncate_statistics (int flag, int proc, char * buf, char * reply_buf) 
+{
+#define TRACE_FH_SIZE2 16
+#define BLOCK_SIZE 4096
+	static int no_size_num = 0;
+	static int have_size_num = 0;
+	static int equal_size_num = 0;
+	static int first_size_num = 0;
+	static int truncate_num = 0;
+	static int truncate_size = 0;
+	static int truncate_KB = 0;
+	static int truncate_block_num = 0;
+	static int padding_num = 0;
+	static int padding_KB = 0;
+	static int padding_size = 0;
+	static FILE * fp = NULL;
+	char * p;
+	char * trace_fh;
+	int pre_size, size, count;
+	struct generic_entry * ent;
+
+	if (flag == OPS_FLAG_PRINT) {
+		int disk_index = proc;
+		int timestamp = (int)buf;
+		if (!fp) {
+			fp = fopen ("truncate.output", "w");
+			RFS_ASSERT (fp);
+		}
+		truncate_KB += truncate_size/1000;
+		truncate_size %= 1000;
+		padding_KB += padding_size/1000;
+		padding_size %= 1000;
+		fprintf(fp, "###### disk_index %d timestamp %d no_size_req %d have_size_req %d equal_size_req %d trunc_req %d trunc_KB %d trunc_block_num %d padding_num %d padding_KB %d\n", disk_index, timestamp, no_size_num, have_size_num, equal_size_num, truncate_num, truncate_KB, truncate_block_num, padding_num, padding_KB);
+		fprintf(stderr, "###### disk_index %d timestamp %d no_size_req %d have_size_req %d equal_size_req %d trunc_req %d trunc_KB %d trunc_block_num %d padding_num %d padding_KB %d\n", disk_index, timestamp, no_size_num, have_size_num, equal_size_num, truncate_num, truncate_KB, truncate_block_num, padding_num, padding_KB);
+		return;
+	}
+
+	p = strstr (&buf[TRACE_MSGID_POS], "fh");
+	RFS_ASSERT (p);
+	p+=3; 
+	trace_fh = p;
+		
+	if (proc==SETATTR) {
+		p = strstr (buf, " size ");
+	} else {
+		RFS_ASSERT (proc==WRITE);
+		p = strstr (reply_buf, " ftype 1 ");
+		RFS_ASSERT (p);
+		p = strstr (p, " size ");
+		RFS_ASSERT (p);
+		if (strstr(p, " ftype 1 ")) {
+			fprintf (fp, "#### %s%s\n", buf, reply_buf);
+			fprintf (stderr, "#### %s%s\n", buf, reply_buf);
+		}
+		RFS_ASSERT (!strstr(p, " ftype 1 "));
+	}
+	if (!p) {
+		no_size_num ++;
+		return;
+	}
+	have_size_num ++;
+
+	sscanf (p, " size %x", &size); 
+	if (size <0 || size > 2000000000) {
+		fprintf (fp, "#### size too big %x %s %s\n", size, buf, reply_buf);
+		fprintf (stderr, "#### size too big %x %s %s\n", size, buf, reply_buf);
+	}
+							
+	RFS_ASSERT (size >=0 && size <2000000000);		
+   	ent = generic_lookup (trace_fh+24, TRACE_FH_SIZE2, 0, fh_htable, FH_HTABLE_SIZE);
+	if (ent) {
+		if (ent->key3 != size) {
+			if (proc==SETATTR) {
+				//printf ("%s\n", buf);
+				//printf ("size change fh %s pre-size %x size %x\n", trace_fh, ent->key3, size);
+				if (ent->key3 > size) {
+					truncate_num ++;
+					truncate_size += ent->key3 - size;
+					truncate_block_num += (ent->key3+BLOCK_SIZE-1)/BLOCK_SIZE;
+					if (size!=0) {
+						//fprintf (stderr, "truncate: pre_size %x size %x %s\n", ent->key3, size, buf);
+						//fprintf (fp, "truncate: pre_size %x size %x %s\n", ent->key3, size, buf);
+						truncate_block_num -= (size + BLOCK_SIZE-1)/BLOCK_SIZE;
+					}
+					if (truncate_size > 1000000000) {
+						truncate_KB += truncate_size/1000;
+						truncate_size %= 1000;
+					}
+				} else {
+					padding_num ++; 
+					//printf ("%s\n", buf);
+					//printf ("padding fh %s pre-size %x size %x\n", trace_fh, ent->key3, size);
+					padding_size += size - ent->key3;
+					if (padding_size > 1000000000) {
+						padding_KB += padding_size/1000;
+						padding_size %= 1000;
+					}
+				}
+			}
+			ent->key3 = size; 
+		}else 
+			equal_size_num++;
+	} else {
+   		generic_insert(trace_fh+24, TRACE_FH_SIZE2, size, fh_htable, FH_HTABLE_SIZE);
+		first_size_num ++;
+	}
+};
+
+int get_timestamp_usec (char * buf)
+{
+	char str[128];
+	int ret;
+	strncpy(str, buf, 100);
+	RFS_ASSERT (str[10]=='.');
+	RFS_ASSERT (str[17]==' ');
+	str[17]=0;
+	ret = atoi(&str[11]);
+	RFS_ASSERT (ret >=0 && ret <=999999);
+	return ret;
+}
+
+int get_timestamp_sec (char * buf)
+{
+	char str[128];
+	int ret;
+	strncpy(str, buf, 100);
+	RFS_ASSERT (str[10]=='.');
+	str[10]=0;
+	ret = atoi(str);
+	RFS_ASSERT (ret >1000000000 && ret <2000000000);
+	return ret;
+}
+
+int check_aging (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid, proc;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		
+		proc = nfs3proc_to_rfsproc[nfs3proc];
+		ops_statistics (OPS_FLAG_INC, proc, -1);
+		
+		switch (proc) {
+		int off, count, size;
+		char * t;
+		case CREATE: printf("%s\n", "create"); break;
+		case MKDIR: printf("%s\n", "mkdir"); break;
+		case REMOVE: printf("%s\n", "remove"); break;
+		case RMDIR: printf("%s\n", "rmdir"); break;
+		case WRITE: 
+			t = buf;
+			t = strstr (t, "off");
+	        RFS_ASSERT (t);
+   		    t+=4;
+			sscanf (t, "%x", &off);
+			RFS_ASSERT (off>=0 && off<0x7FFFFFFF)
+			t = strstr (t, "count");
+		    RFS_ASSERT (t);
+   			t+=6;
+			sscanf (t, "%x", &count);
+			RFS_ASSERT (count <= 32768);
+			printf("%s off %x count %x\n", "write", off, count); 
+			//printf("%s count %x\n", "write", count); 
+			break;
+		case SETATTR: 
+			t = strstr (buf, " size ");
+			if (t) {
+				sscanf (t, " size %x", &size);
+				printf ("%s size %x\n", "setattr", size);
+			}
+		}
+		if ((disk_index%10000)==0) {
+			fprintf(stderr, "%d disk trace passed\n", disk_index);
+		}
+	};
+
+	fprintf(stderr, "%d disk trace parsed\n", disk_index);
+	ops_statistics (OPS_FLAG_PRINT, disk_index, -1);
+}
+
+
+int check_statistics (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid, proc;
+	static int last_timestamp_sec = -1;
+	int timestamp_sec;
+	int memory_trace_size = 0;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		timestamp_sec = get_timestamp_sec(buf);
+		
+		proc = nfs3proc_to_rfsproc[nfs3proc];
+		ops_statistics (OPS_FLAG_INC, proc, -1);
+		
+		if (proc!= WRITE && proc!=SETATTR && proc!=READ) {
+			continue;
+		}
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE; i++) {
+			reply_buf = read_line(i);
+			if (debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+	               	trace_status = find_reply_status(reply_buf);
+					if (trace_status == NFS3_OK) {
+						if (proc==READ || proc==WRITE) 
+							read_write_fh_statistics (OPS_FLAG_INC, buf, 0);
+						if (proc == WRITE)
+							write_statistics (OPS_FLAG_INC, buf, reply_buf, trace_status);
+						if (proc==WRITE || proc==SETATTR) 
+							truncate_statistics (OPS_FLAG_INC, proc, buf, reply_buf);
+					}
+				};
+   	    	}
+		}
+		//if (memory_trace[memory_trace_size].trace_status == NFS3ERR_RFS_MISS)
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			//printf ("%s no reply\n", buf);
+			missing_reply_num ++;
+		}
+
+#if	0	/* commented out by G. Jason Peng */
+		if *
+		if ((missing_reply_num > memory_trace_size/10) && (missing_reply_num > 100)) {
+			printf ("missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+#endif
+
+		memory_trace_size ++;
+
+		if (last_timestamp_sec == -1) {
+			last_timestamp_sec = timestamp_sec;
+		} else if (timestamp_sec - last_timestamp_sec >=3600) {
+			ops_statistics (OPS_FLAG_PRINT, disk_index, timestamp_sec);
+			truncate_statistics (OPS_FLAG_PRINT, disk_index, (char *)timestamp_sec, NULL);
+			read_write_fh_statistics(OPS_FLAG_PRINT, (char *)disk_index, timestamp_sec);
+			write_statistics(OPS_FLAG_PRINT, (char *)disk_index, (char *)timestamp_sec, -1);
+			last_timestamp_sec = timestamp_sec;
+		}
+/*
+		if ((memory_trace_size%10000)==0) {
+			fprintf(stderr, "%d disk trace parsed, missing_reply %d\n", disk_index, missing_reply_num);
+			ops_statistics (OPS_FLAG_PRINT, -1);
+			truncate_statistics (OPS_FLAG_PRINT, -1, NULL, NULL);
+		}
+*/
+	};
+
+	fprintf(stderr, "%d disk trace parsed, missing_reply %d\n", disk_index, missing_reply_num);
+	ops_statistics (OPS_FLAG_PRINT, disk_index, timestamp_sec);
+	truncate_statistics (OPS_FLAG_PRINT, disk_index, (char *)timestamp_sec, NULL);
+	read_write_fh_statistics(OPS_FLAG_PRINT, (char *)disk_index, timestamp_sec);
+	write_statistics(OPS_FLAG_PRINT, (char *)disk_index, (char *)timestamp_sec, -1);
+}
+
+
+/* This routine output all the requests, together with their replies */
+int pair_trace (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid;
+	int ops[NFS3_PROCEDURE_COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	int memory_trace_size = 0;
+	FILE * outputfp;
+	char output_file[1024];
+
+	strcpy (output_file, tracefile);
+	strcat (output_file, ".pair");
+	outputfp = fopen (output_file, "w");
+	RFS_ASSERT (outputfp);
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (disk_index == 258)
+			f();
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		ops[nfs3proc]++;
+
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+		fprintf (outputfp, "%s\n", buf);
+
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR; i++) {
+			reply_buf = read_line(i);
+			if (debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+					fprintf(outputfp, "%s", reply_buf);
+					trace_status = find_reply_status(reply_buf);
+					if (debug)
+						fprintf(stderr, "reply found trace_status %d\n", find_reply_status(reply_buf));
+					break;
+				};
+   	    	}
+		}
+
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			fprintf (stderr, "%s no reply\n", buf);
+			fprintf(outputfp, "missing_reply\n");
+			missing_reply_num ++;
+		}
+
+		if (missing_reply_num > memory_trace_size/10 && missing_reply_num >100) {
+			fprintf (stderr, "missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+
+		memory_trace_size ++;
+
+		if ((memory_trace_size%10000)==0)
+			fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+    //fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+
+}
+/* This routine output all the write requests, together with their replies. It is used for
+ * analysis of write requests: appended bytes, overwrite bytes etc
+ */
+int pair_write (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int pair_write_debug = 0;
+	int nfs3proc, msgid;
+	int ops[NFS3_PROCEDURE_COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	int memory_trace_size = 0;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		ops[nfs3proc]++;
+
+		if (!strstr(buf, "write")) 
+			continue;
+
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (pair_write_debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+
+		/* store the request to memory */
+		//strcpy (memory_trace[memory_trace_size].line, buf);
+		//memory_trace[memory_trace_size].disk_index = disk_index;
+
+		/* find and store the reply status and reply fhandle to memory */
+		//memory_trace[memory_trace_size].trace_status = NFS3ERR_RFS_MISS;
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR; i++) {
+			reply_buf = read_line(i);
+			if (pair_write_debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+					int pre_size, size, count;
+               		//memory_trace[memory_trace_size].trace_status = find_reply_status(reply_buf);
+					if (pair_write_debug)
+						printf("reply found trace_status %d\n", find_reply_status(reply_buf));
+						//break;
+	               	trace_status = find_reply_status(reply_buf);
+					if (trace_status == NFS3_OK) {
+						p = strstr (p, "pre-size");
+						RFS_ASSERT (p);
+						sscanf (p, "pre-size %x", &pre_size); 
+						p += strlen("pre-size");
+						p = strstr (p, "size");
+						RFS_ASSERT (p);
+						sscanf (p, "size %x", &size); 
+						p = strstr (p, "count");
+						if (!p) 
+							printf ("%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+						RFS_ASSERT (p);
+						sscanf (p, "count %x", &count); 
+						printf ("%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+						break;
+					}
+				};
+   	    	}
+		}
+		//if (memory_trace[memory_trace_size].trace_status == NFS3ERR_RFS_MISS)
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			printf ("%s no reply\n", buf);
+			missing_reply_num ++;
+		}
+
+#if	0	/* commented out by G. Jason Peng */
+		if (missing_reply_num > memory_trace_size/10) {
+			printf ("missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+#endif
+
+		memory_trace_size ++;
+
+		/*
+		if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+			fprintf (stderr, "memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+			break;
+		}
+		*/
+		if ((memory_trace_size%10000)==0)
+			fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+    //fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+
+}
+
+#ifdef notdef
+/* This function is not finished writing */
+int calculate_performance()
+{
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int debug = 0;
+
+typedef struct {
+	struct timeval start;
+	struct timeval stop;
+	int trace_status;
+	int op;
+} trace_performance_ent_t;
+
+	struct timeval req_time;
+	struct timeval reply_time;
+
+	trace_performance_ent_t * ent = NULL;
+
+	while (!CYCLIC_FULL(memory_trace_index)) {
+
+		if (ent!=NULL && (ent->trace_status == NFS3ERR_RFS_MISS))
+			buf = reply_buf;
+		if ((buf=read_line(++disk_index))==NULL) {
+END:		fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, CYCLIC_NUM(memory_trace_index), missing_reply_num );
+    		fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+			end_profile (&read_trace_profile);
+			return TRACE_FILE_END;
+		}
+
+		get_timestamp (&ent->req_time, buf);
+		if (MAX_COMMAND_REPLY_DISTANCE ==1) {
+			ent->trace_status == NFS3ERR_RFS_MISS;
+		} else {
+			reply_buf=read_line(++disk_index);
+			RFS_ASSERT (reply_buf);
+			if (!strcmp(reply_buf, "missing_reply\n")) {
+				ent->trace_status == NFS3ERR_RFS_MISS;
+			} else {
+				get_timestamp (&ent->reply_time, buf);
+				ent->trace_status = find_reply_status(reply_buf);
+			}
+		}
+	}
+}
+#endif
+
+int read_trace ()
+{
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int debug = 0;
+	memory_trace_ent_t * ent=NULL;
+
+	start_profile (&read_trace_profile);
+
+	while (!CYCLIC_FULL(memory_trace_index)) {
+		if (ent!=NULL && (ent->trace_status == NFS3ERR_RFS_MISS))
+			buf = reply_buf;
+		if ((buf=read_line(++disk_index))==NULL) {
+END:		fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, CYCLIC_NUM(memory_trace_index), missing_reply_num );
+    		fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+			end_profile (&read_trace_profile);
+			return TRACE_FILE_END;
+		}
+	
+		if (rfs_debug)
+			printf ("disk_index %d %s\n", disk_index, buf);
+
+		if (disk_index==0) {
+			trace_timestamp1 = get_timestamp_sec (buf);
+			trace_starttime.sec = get_timestamp_sec (buf);
+			trace_starttime.usec = get_timestamp_usec (buf);
+			trace_starttime.esec = 0;
+			printf ("trace starttime %d %d %d\n", trace_starttime.sec, trace_starttime.usec, trace_starttime.esec);
+		} else
+			trace_timestamp2 = get_timestamp_sec (buf);
+
+		/* store the request to memory */
+		ent = &(memory_trace[memory_trace_index.head]);
+		strcpy (ent->line, buf);
+		ent->disk_index = disk_index;
+
+		if (MAX_COMMAND_REPLY_DISTANCE ==1) {
+			ent->trace_status == NFS3ERR_RFS_MISS;
+		} else {
+			reply_buf=read_line(++disk_index);
+			RFS_ASSERT (reply_buf);
+			if (!strcmp(reply_buf, "missing_reply\n")) {
+				ent->trace_status == NFS3ERR_RFS_MISS;
+			} else {
+				ent->trace_status = find_reply_status(reply_buf);
+			}
+		};
+
+		if (ent->trace_status == NFS3ERR_RFS_MISS)
+			missing_reply_num ++;
+
+		if (MAX_COMMAND_REPLY_DISTANCE > 1) {
+			if ((missing_reply_num > disk_index/5) && (missing_reply_num > 100)) {
+				printf ("missing_reply_num %d too high for disk_index %d\n", missing_reply_num, disk_index);
+				exit (0);
+			}
+		}
+
+		/* find and store the reply trace fhandle for create-class requests */
+		if (ent->trace_status==NFS3_OK) {
+			if (strstr(buf, "create") || strstr(buf, "mkdir") 
+				|| (strstr(buf, "symlink") && (buf[TRACE_VERSION_POS]!='2')) 
+				|| strstr(buf, "mknod") ) {
+				p = find_reply_trace_fh(reply_buf);
+				if (p==NULL) {
+					printf("skip line disk_index %d %s \n", disk_index, buf);
+					continue;
+				}
+				memcpy(ent->reply_trace_fh, p, TRACE_FH_SIZE);
+			} else
+				memset(ent->reply_trace_fh, 0, TRACE_FH_SIZE);
+		}
+
+		add_to_dep_tab(memory_trace_index.head);
+
+		if (((disk_index+1)%20000)==0) {
+			fprintf(stderr, "%d disk trace parsed \n", disk_index+1);
+		};
+	};
+
+	end_profile (&read_trace_profile);
+	return TRACE_BUF_FULL;
+}
+#else	/* not defined REDUCE_MEMORY_TRACE_SIZE */
+int read_trace ()
+{
+	FILE * fp;
+	char buf[1024];
+	// char * t=buf;	
+	int disk_index=0;
+
+	fp = fopen(trace_file, "r");
+	RFS_ASSERT (fp!=NULL);
+	while (fgets(buf, MAX_TRACE_LINE_LENGTH, fp)) {
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("strlen(buf) %d buf %s \n", strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+
+		/* store the request to memory */
+		strcpy (memory_trace[memory_trace_size].line, buf);
+		memory_trace[memory_trace_size].disk_index = disk_index;
+		memory_trace_size ++;
+
+		if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+			fprintf (stderr, "memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+			break;
+		}
+		if ((disk_index%100000)==0)
+			fprintf(stderr, "%d disk trace parsed, store %d trace lines to memory\n", disk_index, memory_trace_size);
+		disk_index ++;
+	}
+
+	fprintf(stderr, "total %d disk lines %d memory lines \n", disk_index, memory_trace_size );
+}
+#endif
+
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+inline int disk_index_to_memory_index (int disk_index)
+{
+	static int memory_index = 0;
+
+	RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));
+	RFS_ASSERT (memory_trace[memory_trace_index.tail].disk_index <= disk_index);
+	RFS_ASSERT (memory_trace[CYCLIC_MINUS(memory_trace_index.head,1,memory_trace_index.size)].disk_index >=disk_index);
+	if (disk_index > memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index < disk_index) {
+			memory_index = CYCLIC_ADD(memory_index,1,memory_trace_index.size);
+		}
+	};
+	if (disk_index < memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index > disk_index) {
+			memory_index = CYCLIC_MINUS(memory_index,1,memory_trace_index.size);
+		}
+	};
+
+	RFS_ASSERT (disk_index == memory_trace[memory_index].disk_index);
+	return memory_index;
+}
+#else
+#define disk_index_to_memory_index(disk_index)	disk_index
+#endif
+
+#define get_line_by_disk_index(disk_index) \
+	memory_trace[disk_index_to_memory_index(disk_index)].line
+
+inline char * find_reply_line (char * command_line, int cur_disk_index)
+{
+	int i;
+	char * line;
+	char * p;
+	int request_memory_index = disk_index_to_memory_index (cur_disk_index);
+	for (i=request_memory_index+1; i<request_memory_index+MAX_COMMAND_REPLY_DISTANCE && i<MAX_MEMORY_TRACE_LINES; i++) {
+		line = memory_trace[i].line;
+		if (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+	        p = strchr (&line[TRACE_MSGID_POS], ' ');
+    	    RFS_ASSERT (p);
+			if (!strncmp(&line[TRACE_MSGID_POS], &command_line[TRACE_MSGID_POS], p-&(line[TRACE_MSGID_POS]))) 
+				return line;
+		}
+	}
+	return NULL;
+}
+
+inline int find_reply_status (char * line)
+{
+	char * p;
+	int i=0;
+
+	if (rfs_debug)
+		printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	if (!(line[TRACE_COMMAND_REPLY_FLAG_POS]=='R')) {
+		printf ("disk_index %d %s\n", disk_index, line);
+	};
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	p = line+TRACE_MSGID_POS+2;	/* at least one letter for msgid and one letter for space */
+	if (strstr(p, "OK"))
+		return NFS3_OK;
+	if (strstr(p, "lookup 2") || strstr(p, "lookup   2"))
+		return 0x2;
+	if (strstr(p, "create d"))
+		return 0xd;
+	if (strstr(p, "setattr 1"))
+		return 0x1;
+	if (strstr(p, "setattr 2712")) /* 10002 NFS3ERR_NOT_SYNC */
+		return 0x2712;
+	if (strstr(p, "lookup d"))
+		return 0xd;
+	if (strstr(p, "read d"))
+		return 0xd;
+	if (strstr(p, "write d"))
+		return 0xd;
+	if (strstr(p, "write 46"))
+		return 0x46;
+	if (strstr(p, "getattr 46"))
+		return 0x46;
+	if (strstr(p, "mkdir d"))
+		return 0xd;
+	printf ("line %s  flag %c return value weird\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	printf ("!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	fprintf (stderr, "line %s  flag %c return value weird\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	fprintf (stderr, "!!!!!!!!!!!!!!!!!!!!!!!!\n");
+}
+
+inline int find_reply_status_old (char * line)
+{
+	char * p;
+	int i=0;
+
+	//printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	if (!strstr(line, "OK")) {
+		p=strstr(line, " 6 read ");
+		if (p) {
+			p+=strlen(" 6 read ");
+		} else {
+			p = strstr (line, "status=XXX");
+			RFS_ASSERT (p);
+			p--;
+			RFS_ASSERT (*p==' ');
+			while (*p==' ')
+				p--;
+			while (*p!=' ') {
+				p--;
+			}
+			p++;
+		}
+		sscanf (p, "%x", &i);
+		if ((i<=0) || (i>10000))
+			printf("line %s\n", line);
+		RFS_ASSERT (i>0 && i<10009);
+	}
+	return i;
+}
+
+inline char * find_reply_trace_fh (char * line)
+{
+	char * p;	
+	p = strstr (line, "OK fh");
+	if (!p) {
+		printf ("disk_index %d find_reply_trace_fh line %s\n", disk_index, line);
+		return NULL;
+	} else
+		return p+6;
+}
+
+#ifndef NO_DEPENDENCY_TABLE
+inline int disk_index_to_dep_index(int cur_dep_index, int disk_index)
+{
+	int i;
+	for (i=cur_dep_index; i>min_dep_index; i--) {
+		if (dep_tab[i].disk_index == disk_index)
+			return i;
+	} 
+	RFS_ASSERT (0);
+}
+#endif
+
+inline int is_play_candidate (int dep_index)
+{
+	int proc = dep_tab[dep_index].proc;
+	int status = dep_tab[dep_index].status;
+	int trace_status = dep_tab[dep_index].trace_status;
+
+#ifndef TAKE_CARE_CREATE_MODE_BY_DAN
+	/* for a failed create in trace, trace_replay just ignore many time the trace create fail
+	 * due to access control, but trace_play will success because our access control
+	 * may be loose (all uid/gid is mapped to single one 513:513, so we just skip these requests 
+	 */
+	if ((proc==CREATE || proc==MKDIR) && (trace_status!=NFS3_OK) && (status!=NFS3ERR_RFS_MISS)) {
+		if (dependency_debug)
+			printf ("disk[%d] ignore failed create/mkdir in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		failed_create_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_OTHER_FAILED_COMMAND
+	if (((trace_status == NFS3ERR_ACCES) && (proc==READ || proc==WRITE || proc==LOOKUP)) || 
+	    ((trace_status == NFS3ERR_PERM) && (proc==SETATTR)) 									){
+		if (dependency_debug)
+			printf ("disk[%d] ignore other failed command in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		
+		failed_other_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+	if ((dep_tab[dep_index].proc==READLINK) ) { /* send request */
+		skipped_readlink_command_num ++;
+		return FALSE;
+	}
+#endif
+/* This is actually take care in get_nextop by checking fh_map error when dep_index==min_dep_index */
+#ifndef TAKE_CARE_CUSTOM_COMMAND
+	/* this line has a file handle which should belong to discard but it is not
+	 * the file handle directly appears as parent directory in a lookup request
+	 * the return value is NOENT, the parent directory should have been initialized
+	 * but the initialization code just ignored all lookup request which didn't success
+	 * including NOENT even though the parent directory is still valid.
+	 */
+/*
+	if ((    ((dep_tab[dep_index].disk_index==262213) || (dep_tab[dep_index].disk_index==214402))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1100.txt")) 
+		) || 
+		(	 ((dep_tab[dep_index].disk_index==238460) || (dep_tab[dep_index].disk_index ==238470))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1000.txt"))
+		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+*/
+	if ((    ((dep_tab[dep_index].disk_index==423727) || (0))
+		  && !(strncmp(trace_file, "anon-lair62-011130-1500.txt", strlen("anon-lair62-011130-1500.txt"))) 
+		) || 
+		(	 ((dep_tab[dep_index].disk_index==238460) || (dep_tab[dep_index].disk_index ==238470))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1000.txt"))
+		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+	/* this line is about the mkdir 116d9d originally in anon-lair62-011130-1400.txt */
+	if (!strncmp(dep_tab[dep_index].line, "1007147245.194201", strlen("1007147245.194201"))) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_FSSTAT_COMMAND
+	/* the file handle used in this command is not processed properly by pre-processing */
+	if (proc==FSSTAT) {
+		char * trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+		fh_map_t * fh = lookup_fh (trace_fh);
+		if (!fh) {
+			skipped_fsstat_command_num++;
+			return FALSE;
+		}
+	}
+#endif
+	return TRUE;
+}
+
+inline int is_dir_op (int proc)
+{
+	switch (proc) {
+	case MKDIR:
+	case CREATE:
+	case LINK:
+	case SYMLINK:
+	case MKNOD:
+	case REMOVE:
+	case RMDIR:
+	case RENAME:
+		return 1;
+	default:
+		return 0;
+	}
+}	
+
+inline int is_create_op (int proc)
+{
+	if (proc==CREATE || proc==MKDIR || proc==LINK || proc==SYMLINK || proc==MKNOD || proc==RENAME)
+		return 1;
+	return 0;
+}
+
+inline int is_delete_op (int proc)
+{
+	if (proc==REMOVE || proc==RMDIR || proc==RENAME)
+		return 1;
+	return 0;
+}	
+
+static inline char * find_lead_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh");
+	RFS_ASSERT (p);
+	p+=3; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+inline char * find_another_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh2");
+	RFS_ASSERT (p);
+	p+=4; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+/* return the index of next request in dep_tab.
+ * Return -1 if there is no suitable request to send
+ */
+inline int get_nextop(void)
+{
+	int i,j, k;
+	int * t;
+	static int dep_index = -2;
+	char * line;
+	char * p;
+#define INIT_MIN_WAIT_VALUE -999
+	static int min_wait_fhandle_dep_index = INIT_MIN_WAIT_VALUE;
+	int proc;
+	int flag;
+
+	if (min_wait_fhandle_dep_index == -999)
+		min_wait_fhandle_dep_index = dep_window_index.head;
+
+	for (i=0; i<CYCLIC_NUM(dep_window_index); i++) {
+		dep_index = (dep_window_index.tail+i) % dep_window_index.size;
+	
+		proc = dep_tab[dep_index].proc;
+		flag = dep_tab[dep_index].flag;
+
+		if (dependency_debug)
+			printf ("get_nextop check dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+#ifdef NO_DEPENDENCY_TABLE
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT) {
+			if (is_play_candidate(dep_index)==TRUE) {
+				/* the trace_fh is the file handle for the operation directory, trace_fh_2 is other file handle
+				 * used in the request */
+				if (proc==LINK || proc==RENAME) {
+					dep_tab[dep_index].trace_fh = find_another_trace_fh (proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].trace_fh_2 = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = 0;
+				} else {
+					dep_tab[dep_index].trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = (fh_map_t *)1;
+				};
+				dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+#ifdef TIME_PLAY
+				dep_tab[dep_index].skip_sec = skip_sec;
+#endif
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_CANDIDATE\n", dep_tab[dep_index].disk_index);
+			} else {
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+				dep_tab[dep_index].flag = DEP_FLAG_DONE;
+				continue;
+			}
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE) ) {
+
+			if (!dep_tab[dep_index].fh)
+				dep_tab[dep_index].fh = lookup_fh (dep_tab[dep_index].trace_fh);
+			if (!dep_tab[dep_index].fh_2)
+				dep_tab[dep_index].fh_2 = lookup_fh (dep_tab[dep_index].trace_fh_2);
+
+			/* need to wait for file handle */
+			if ((!dep_tab[dep_index].fh) || (!dep_tab[dep_index].fh_2)) {
+				if (dependency_debug)
+					printf("disk[%d] can not lookup file handle\n", dep_tab[dep_index].disk_index);
+				if (dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) {
+					if (dependency_debug)
+						printf ("disk[%d] state DEP_FLAG_CANDIDATE to DEP_FLAG_WAIT_FHANDLE\n", dep_tab[dep_index].disk_index);
+					dep_tab[dep_index].flag = DEP_FLAG_WAIT_FHANDLE;
+					sfs_gettime (&dep_tab[dep_index].start);
+					if (CYCLIC_LESS(dep_tab_index,dep_index,min_wait_fhandle_dep_index)) 
+						min_wait_fhandle_dep_index = dep_index;
+				} else {
+					struct ladtime tmp;
+					if (dep_index==dep_window_index.tail) {
+						if (!profile_debug) 
+							printf ("fh_path_map error disk[%d] state DEP_FLAG_WAIT_FHANDLE to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+						fh_path_map_err_num ++;
+						dep_tab[dep_index].flag = DEP_FLAG_DONE;
+						continue;
+					}
+					sfs_gettime (&tmp);
+					SUBTIME (tmp, dep_tab[dep_index].start);
+#define DEPENDENCY_TIMEOUT 50
+#ifdef TIME_PLAY
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT + (skip_sec - dep_tab[dep_index].skip_sec));	
+#else
+					if (tmp.sec >= DEPENDENCY_TIMEOUT) {
+						printf("dep_tab[%d].flag %d disk_index %d line %s\n", dep_index,
+							dep_tab[dep_index].flag, dep_tab[dep_index].disk_index,
+							dep_tab[dep_index].line);
+					}
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT );	
+#endif
+				}
+				continue;
+			}
+
+			/* file handle ready, adjust_min_wait_fhandle_dep_index */
+			if ((dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE)) {
+				if (dep_index == min_wait_fhandle_dep_index) {
+					min_wait_fhandle_dep_index = dep_window_index.head;
+					for (j=CYCLIC_ADD(dep_index,1,dep_window_index.size); CYCLIC_LESS(dep_window_index,j,dep_window_index.head); j++) {
+						if (dep_tab[j].flag ==DEP_FLAG_WAIT_FHANDLE) {
+							min_wait_fhandle_dep_index = j;
+							break;
+						}
+					}
+				}
+			}
+			if (dependency_debug)
+				printf("disk[%d] found file handle\n", dep_tab[dep_index].disk_index);
+			dep_tab[dep_index].flag = DEP_FLAG_FHANDLE_READY;
+
+			/* the normal file operation can be executed now */
+			if (!is_dir_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug)
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			if (dependency_debug)
+				printf("disk[%d] directory operation \n", dep_tab[dep_index].disk_index);
+			/* the directory operation need to lock the directory first */
+			if (dep_tab[dep_index].fh->lock) {
+				if (dependency_debug)
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DIRECTORY\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DIRECTORY;
+				continue;
+			}
+		}
+				
+		if ((dep_tab[dep_index].flag == DEP_FLAG_FHANDLE_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DIRECTORY)) {
+			int j = dep_tab[dep_index].fh - fh_map;
+			if (dependency_debug) {
+				printf ("dep_tab[%d].disk_index %d, fh_map[%d] lock=%d\n",dep_index, dep_tab[dep_index].disk_index, j, dep_tab[dep_index].fh->lock);
+				printf ("trace_fh %s path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+				printf ("trace_fh %s path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+			}
+			if ((dep_tab[dep_index].fh->lock) || ((proc==RENAME) && (dep_tab[dep_index].fh_2->lock)) ) {
+				if (dependency_debug) 
+					printf ("continue to wait for directory lock\n");
+				continue;
+			}
+			if (dependency_debug) 
+				printf ("dep_tab[%d] disk index %d LOCK fh_map[%d] \n", dep_index, dep_tab[dep_index].disk_index, j);
+			dep_tab[dep_index].fh->lock = 1;
+			if (proc==RENAME)
+				dep_tab[dep_index].fh_2->lock = 1;
+
+			/* the non-delete directory operation can proceed now */
+			if (!is_delete_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			/* the delete operation can proceed if nobody ahead is waiting for fhandle */
+			/* probably this condition is not strong enough */
+//			if ((min_wait_fhandle_dep_index<dep_index) ) {
+			if (dep_index!=dep_window_index.tail) {
+				if (dependency_debug) 
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DELETE\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DELETE;
+				continue;
+			} 
+			dep_tab[dep_index].flag = DEP_FLAG_DIRECTORY_READY;
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_DIRECTORY_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DELETE)) {
+//			if (min_wait_fhandle_dep_index > dep_index) {
+			if (dep_index==dep_window_index.tail) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+		}
+#else /*NO_DEPENDENCY_TABLE undefined */
+	/* this part of code will be invalid after CYCLIC buffer design */
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT){
+			for (j=0, t=&(dep_tab[dep_index].dep_ops[0]);
+				(j<dep_tab[dep_index].init_dep_num) && (dep_tab[dep_index].cur_dep_num>0); 
+				j++, t++) {
+				if (*t !=-1) {
+					if (dep_tab[disk_index_to_dep_index(dep_index, *t)].flag == DEP_FLAG_DONE) { 
+						/* The depended request has been finished */ 
+						*t = -1;
+						dep_tab[dep_index].cur_dep_num --;
+					}
+				} 
+			}
+
+			if (dep_tab[dep_index].cur_dep_num == 0) {
+				return dep_index;
+			}
+		}
+#endif
+	}
+
+	if (dependency_debug) 
+		printf ("get_nexop return -1\n");
+	return -1;
+}
+
+int check_timeout(void)
+{
+	static int biod_index = 0;
+	int i;
+	int dep_index;	/* index into dep_tab */
+	int proc;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime timeout;
+	struct ladtime current_time;
+
+	sfs_gettime (&current_time);	
+
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (biod_reqp[biod_index].in_use==TRUE) {
+			timeout = biod_reqp[biod_index].timeout;
+			if ((current_time.sec>timeout.sec) ||
+				((current_time.sec==timeout.sec) && (current_time.usec>timeout.usec))) {
+
+				dep_index = biod_reqp[biod_index].dep_tab_index;
+				proc = dep_tab[dep_index].proc;
+				op_ptr = &Ops[proc];
+				op_ptr->results.timeout_calls++;
+				Ops[TOTAL].results.timeout_calls++;
+
+
+				if (is_create_op(proc)) {
+					dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+					printf ("resend dep_tab[%d], disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+					finish_request (biod_index, dep_index, NFS3ERR_RFS_TIMEOUT, DEP_FLAG_CANDIDATE);
+				} else {
+					finish_request (biod_index, dep_index, NFS3ERR_RFS_TIMEOUT, DEP_FLAG_DONE);
+				}
+				timeout_num ++;
+				num_out_reqs_statistics_at_timeout[num_out_reqs]++;
+
+				//RFS_ASSERT (!is_create_op(proc));
+
+				if (per_packet_debug)
+					printf ("timeout request: disk_index %d, dep_index %d biod_reqp[%d].start %d:%d timeout %d:%d current %d:%d\n", dep_tab[dep_index].disk_index, dep_index, biod_index, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, timeout.sec, timeout.usec, current.sec, current.usec);
+			}
+		}
+	}
+}
+
+/* Allocate a biod_req entry to send and receive request dep_tab[dep_index]
+ * build the cross reference between dep_tab entry and biod_req entry
+ */
+struct biod_req * get_biod_req(int dep_index) /* index into dep_tab */
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (!biod_reqp[biod_index].in_use) {
+			biod_reqp[biod_index].in_use = 1;
+			biod_reqp[biod_index].dep_tab_index = dep_index;
+			dep_tab[dep_index].biod_req_index = biod_index;
+    		num_out_reqs++;
+			return &(biod_reqp[biod_index]);
+		}
+	}
+	return NULL;
+}
+
+/* Return index into biod_reqp
+ * return -1 upon failure 
+ */
+int lookup_biod_req (int xid)
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		/* give a NULL as timeout pointer may cause indefinitely block */
+		if ((biod_reqp[biod_index].in_use == TRUE) &&( biod_reqp[biod_index].xid == xid)) {
+			return biod_index;
+		}
+	}
+	return -1;
+}
+
+extern struct ladtime test_start;
+void init_time_offset(void)
+{
+	struct ladtime tmp1;
+	struct ladtime tmp2;
+
+	test_start.sec = 0;
+	test_start.usec = 0;
+	sfs_gettime (&tmp1);		/* called at initial time: tmp1 = play_starttime */
+#ifdef SPEED_UP
+	DIVTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime / SCALE */
+#endif
+#ifdef SLOW_DOWN
+	MULTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime * SCALE */
+#endif
+
+	tmp2 = trace_starttime; /* tmp2 = trace_starttime */
+	SUBTIME (tmp2, tmp1);	/* tmp2 = trace_starttime - play_starttime *|/ SCALE */
+	time_offset = tmp2;		/* time_offset = trace_starttime - play_starttime *|/ SCALE */ 
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void init_dep_tab_entry (int dep_index)
+{
+	char * line;
+	int version;
+	int nfsproc;
+	int msgid;
+
+	//line = get_line_by_disk_index (dep_tab[dep_index].disk_index);
+	line = dep_tab[dep_index].line;
+	sscanf (line, "%d.%d", &(dep_tab[dep_index].timestamp.tv_sec), &(dep_tab[dep_index].timestamp.tv_usec));
+	sscanf (&line[TRACE_MSGID_POS], "%x %x", &msgid, &nfsproc);
+	//printf ("msgid %x nfsproc %x\n", msgid, nfsproc);
+	if (line[TRACE_VERSION_POS]=='2') {
+		dep_tab[dep_index].proc = nfs2proc_to_rfsproc[nfsproc];
+		RFS_ASSERT (nfsproc <18);
+	} else {
+		/* This is for debug purpose */
+		if (line[TRACE_VERSION_POS] !='3') {
+			fprintf(stderr, "line[TRACE_VERSION_POS] %c line %s\n", line[TRACE_VERSION_POS], line);
+			line = get_line_by_disk_index (dep_tab[dep_index].disk_index-1);
+			if (!line)
+				line = get_line_by_disk_index (dep_tab[dep_index].disk_index-2);
+			RFS_ASSERT (line);
+			fprintf(stderr, "previousline %s\n", line);
+		}
+		RFS_ASSERT (line[TRACE_VERSION_POS] =='3');
+		if (nfsproc >= NFS3_PROCEDURE_COUNT) {
+			fprintf(stderr, "proc %d line %s\n", nfsproc, line);
+			
+		}
+		RFS_ASSERT (nfsproc <NFS3_PROCEDURE_COUNT);
+		dep_tab[dep_index].proc = nfs3proc_to_rfsproc[nfsproc];
+	}
+	RFS_ASSERT (dep_tab[dep_index].proc >= 0 && dep_tab[dep_index].proc < NOPS);
+	dep_tab[dep_index].flag = DEP_FLAG_INIT;
+}
+
+void adjust_play_window (int flag, int * poll_timeout_arg)
+{
+	struct ladtime max_window_time;
+	static struct ladtime max_poll_time = {0, 2000, 0};
+	struct ladtime t;
+	int i;
+	char * line;
+	cyclic_index_t old_dep_window_index = dep_window_index;
+
+#ifdef notdef
+	printf ("^^^^^^^^^^^^^^^ adjust_play_window, begin\n");
+	CYCLIC_PRINT (dep_tab_index);
+	printf ("dep_tab[%d].memory_index %d\n", dep_tab_index.tail, dep_tab[dep_tab_index.tail].memory_index);
+	CYCLIC_PRINT (dep_window_index);
+	CYCLIC_PRINT (memory_trace_index);
+	printf ("                adjust_play_window, begin\n");
+#endif
+
+	while ((!CYCLIC_EMPTY(dep_window_index)) && (dep_tab[dep_window_index.tail].flag == DEP_FLAG_DONE)) {
+#ifdef notdef
+		//CYCLIC_PRINT (memory_trace_index);
+		//printf("MOVE_TAIL_TO memory_index %d\n", dep_tab[dep_tab_index.tail].memory_index);
+		RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));	
+		RFS_ASSERT (CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head));
+		printf("%d is done\n", dep_window_index.tail);
+#endif
+		CYCLIC_MOVE_TAIL(dep_tab_index);
+		CYCLIC_MOVE_TAIL(dep_window_index);
+
+#ifdef notdef
+		CYCLIC_PRINT (dep_tab_index);
+		CYCLIC_PRINT (dep_window_index);
+
+		if (! (dep_tab_index.tail == dep_window_index.tail)) {
+			CYCLIC_PRINT(dep_tab_index);
+			CYCLIC_PRINT(dep_window_index);
+		};
+		RFS_ASSERT ( dep_tab_index.tail == dep_window_index.tail);
+#endif
+
+		if (!CYCLIC_EMPTY(dep_tab_index)) {
+#ifdef notdef
+			RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));	
+			if (!(CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head))) {
+				CYCLIC_PRINT(memory_trace_index);
+				CYCLIC_PRINT(dep_tab_index);
+				printf("dep_tab[head-1].memory_index, %d [tail].memory_index %d\n", 
+					dep_tab[CYCLIC_MINUS(dep_tab_index.head,1,dep_tab_index.size)].memory_index,
+					dep_tab[dep_tab_index.tail].memory_index);
+			}
+			RFS_ASSERT (CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head));
+#endif
+			CYCLIC_SET_TAIL_TO(&memory_trace_index, dep_tab[dep_tab_index.tail].memory_index);
+			//printf ("set memory_trace_index to %d=%d, dep_tab_index.tail %d\n", memory_trace_index.tail, dep_tab[dep_tab_index.tail].memory_index, dep_tab_index.tail);
+		} else {
+		//	CYCLIC_MOVE_TAIL (memory_trace_index);
+		}
+	}
+
+	while (CYCLIC_EMPTY(dep_tab_index)) {
+		
+		if (disk_io_status == TRACE_FILE_END) 
+			return;
+		else {
+			//printf ("************** ADJUST_PLAY_WINDOW sleep 1 s\n"); 
+			//print_cyclic_buffers();
+			//pthread_yield();
+			//usleep (1000);
+		}
+	}
+
+	/* max_trace_window_time = current *|/ SCALE + trace_starttime */
+	sfs_gettime (&current);
+
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+	MULTIME (current, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+	DIVTIME (current, PLAY_SCALE);
+#endif
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+
+	/* Right now it is not clear how to deal with the situation where MAX_PLAY_WINDOW is reached */
+	if (CYCLIC_NUM(dep_window_index) == MAX_PLAY_WINDOW) {
+		//printf ("can not catch up the speed, dep_tab_size %d dep_window_max %d reach min_dep_index %d+MAX_PLAY_WINDOW\n", dep_tab_size, dep_window_max, min_dep_index);
+		//printf (".");
+		can_not_catch_speed_num ++;
+	}
+	while ((CYCLIC_NUM(dep_window_index) < MAX_PLAY_WINDOW) &&
+		   (CYCLIC_NUM(dep_window_index) < CYCLIC_NUM(dep_tab_index)) ) {
+		struct ladtime t;
+		int dep_index = (dep_window_index.tail+i) % dep_window_index.size;
+        t.sec = dep_tab[dep_index].timestamp.tv_sec;
+        t.usec = dep_tab[dep_index].timestamp.tv_usec;
+		if ((t.sec>max_window_time.sec)||(t.sec==max_window_time.sec && t.usec>max_window_time.usec))
+            break;
+		CYCLIC_MOVE_HEAD(dep_window_index);
+	}
+#else
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+	while ((CYCLIC_NUM(dep_window_index) < MAX_PLAY_WINDOW) &&
+		   (CYCLIC_NUM(dep_window_index) < CYCLIC_NUM(dep_tab_index)) ) {
+		CYCLIC_MOVE_HEAD(dep_window_index);
+	}
+#endif
+
+	if (flag == BUSY)
+		*poll_timeout_arg = 0;
+   	else if (CYCLIC_NUM(dep_window_index)==CYCLIC_NUM(dep_tab_index)) {
+		*poll_timeout_arg = 1000;	/* poll_timeout set to 1 second for the last request */
+	} else {
+#ifdef TIME_PLAY
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[dep_window_index.head].timestamp.tv_sec;
+		tmp.usec = dep_tab[dep_window_index.head].timestamp.tv_usec;
+		if (adjust_play_window_debug>=2)
+			printf ("dep_tab[dep_window_index.head %d].timestamp %d:%d, max_window_time %d:%d\n",
+				dep_window_index.head, tmp.sec, tmp.usec, max_window_time.sec, max_window_time.usec);
+
+		SUBTIME (tmp, max_window_time);
+#ifdef SPEED_UP
+		DIVTIME (tmp, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+		MULTIME (tmp, PLAY_SCALE);
+#endif
+/*
+		tmp1 = tmp;
+
+		if (tmp.sec > max_poll_time.sec) {
+
+			if (rfs_debug) 
+				printf ("dep_tab[%d].timestamp %d:%d, max_window_time %d:%d\n",
+				dep_window_max, dep_tab[dep_window_max].timestamp.tv_sec, dep_tab[dep_window_max].timestamp.tv_usec, max_window_time.sec, max_window_time.usec);
+			printf ("skip %d seconds\n", tmp.sec-max_poll_time.sec);
+			SUBTIME (tmp, max_poll_time);
+			tmp.usec = 0;
+			skip_sec += tmp.sec;
+			SUBTIME (test_start, tmp);
+			tmp = max_poll_time;
+		}
+*/
+
+		//RFS_ASSERT ((tmp.sec < 1000));
+		if (tmp.sec > 1000)
+			tmp.sec = 1000;
+		if ((tmp.sec ==0) && (tmp.usec==0)) {
+			*poll_timeout_arg = 0;
+		} else
+			*poll_timeout_arg = tmp.sec*1000000+tmp.usec;
+#else 
+		/*
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[dep_window_max].timestamp.tv_sec;
+		tmp.usec = dep_tab[dep_window_max].timestamp.tv_usec;
+		tmp1.sec = dep_tab[dep_window_max-1].timestamp.tv_sec;
+		tmp1.usec = dep_tab[dep_window_max-1].timestamp.tv_usec;
+		SUBTIME (tmp, tmp1);
+		RFS_ASSERT ((tmp.sec < 1000));
+		RFS_ASSERT ((tmp.sec>0) || ((tmp.sec==0) && (tmp.usec>0)));
+		*poll_timeout = tmp.sec*1000000+tmp.usec;
+		*/
+
+		*poll_timeout_arg = 100000;
+#endif
+	}	
+	if (rfs_debug)
+		printf ("adjust_play_window: flag %d min %d -> %d, max %d -> %d poll_timeout_arg %d \n", 
+		flag, old_dep_window_index.tail, dep_window_index.tail, old_dep_window_index.head,
+		dep_window_index.head, *poll_timeout_arg);
+
+#ifdef notdef
+	printf ("^^^^^^^^^^^^^^^ adjust_play_window, end\n");
+	CYCLIC_PRINT (dep_tab_index);
+	printf ("dep_tab[%d].memory_index %d\n", dep_tab_index.tail, dep_tab[dep_tab_index.tail].memory_index);
+	CYCLIC_PRINT (dep_window_index);
+	CYCLIC_PRINT (memory_trace_index);
+	printf ("	 adjust_play_window, end\n\n");
+#endif
+	//CYCLIC_ASSERT(4);
+}
+
+/* poll for usecs and receive, after receive one reply,
+ * return index in biod_reqp of the corresponding request
+ */
+int poll_and_get_reply (int usecs)
+{
+	int biod_index = -1;
+	int xid;
+	int error;
+	struct timeval zero_time = {0, 0}; /* Immediately return */
+
+#ifdef RECV_THREAD
+	//printf("recv thread waitsem 1\n");
+	waitsem (async_rpc_sem);
+	//printf("recv thread got sem 1\n");
+#endif
+	do {
+		error = biod_poll_wait (NFS_client, usecs);
+		switch (error) {
+		case -1:
+			if (errno == EINTR) {
+				error = 1;
+				continue;
+			}
+			if (rfs_debug) {
+				(void) fprintf(stderr, "biod_poll_wait error\n");
+				perror ("");
+			    (void) fflush(stderr);
+			}
+			break;
+		case 0:
+			break;
+		default:
+#ifdef UDP
+			//printf("recv thread waitsem 2\n");
+			//waitsem (async_rpc_sem);
+			//printf("recv thread got sem 2\n");
+			error = get_areply_udp (NFS_client, &xid, &zero_time);
+			//postsem (async_rpc_sem);
+			//printf("recv thread postsem 2\n");
+			// RFS_ASSERT (error!= RPC_TIMEOUT);	/* we have polled and know there is data */
+			// RFS_ASSERT (error!= RPC_CANTRECV);
+			RFS_ASSERT (error == RPC_SUCCESS);
+
+			biod_index = lookup_biod_req (xid);
+			sfs_gettime (&(biod_reqp[biod_index].stop));
+#else
+			RFS_ASSERT (0);
+#endif
+		}
+	} while (0);
+#ifdef RECV_THREAD
+	postsem (async_rpc_sem);
+	//printf("recv thread postsem 1\n");
+#endif
+	return biod_index;
+}
+
+void print_result(void)
+{
+	int i, j;
+	struct ladtime t;
+	int dep_index;
+	int avg_msecs;
+	unsigned long long tmp;
+	int avg_usecs;
+
+    if (DEBUG_CHILD_GENERAL) {
+		(void) fprintf(stdout, "trace play result:\n");
+		(void) fprintf(stdout, "\t    percentage good_cnt bad_cnt timeout_cnt\telapsed time\t\t\taverage time\n");
+		for (i=0; i<NOPS+1; i++) {
+			if (Ops[i].results.good_calls==0) {
+				avg_msecs = 0;
+				avg_usecs = 0;
+			} else {
+				tmp = Ops[i].results.time.sec*1000000 + Ops[i].results.time.usec;
+				avg_msecs = 0;
+				avg_usecs = tmp/Ops[i].results.good_calls;
+/*
+				avg_msecs = (Ops[i].results.time.sec*1000 + Ops[i].results.time.usec/1000)/Ops[i].results.good_calls;
+				avg_usecs = (Ops[i].results.time.usec%1000)/Ops[i].results.good_calls;
+*/
+			}
+			(void) fprintf(stdout,	"%11s\t%4.1f\t%4d\t%4d\t%4d\t\tsec %8d usec %8d \tusec %8d\n", 
+				Ops[i].name, 
+				(float)(100*Ops[i].results.good_calls)/(float)Ops[TOTAL].results.good_calls, 
+				Ops[i].results.good_calls, Ops[i].results.bad_calls, Ops[i].results.timeout_calls,
+				Ops[i].results.time.sec, Ops[i].results.time.usec, avg_msecs*1000+avg_usecs);
+		}
+		(void) fflush (stdout);
+    }
+
+#if	0	/* commented out by G. Jason Peng */
+	RFS_ASSERT (read_data_owe_GB==0);
+	printf("read_data_total %d GB and %d bytes, owe %d GB and %d bytes, %d percent, adjusted %d times \n",read_data_total_GB, read_data_total, read_data_owe_GB, read_data_owe, (read_data_owe)/(read_data_total/100), read_data_adjust_times);
+	printf("write_data_total %d GB and %d bytes, owe %d GB and %d bytes, %d percent, adjusted %d times \n",write_data_total_GB, write_data_total, write_data_owe_GB, write_data_owe, (write_data_owe)/(write_data_total/100), write_data_adjust_times);
+	printf("poll_timeout_0_num %d poll_timeout_pos_num %d\n", poll_timeout_0_num, poll_timeout_pos_num);
+	printf("failed_create_command_num_in_original_trace %d\nfailed_other_command_num_in_original_trace %d\nskipped_readlink_command_num %d\nskipped_custom_command_num %d\nfh_path_map_err_num %d\nskipped_fsstat_command_num %d\nmissing_reply_num %d\nrename_rmdir_noent_reply_num %d\nrmdir_not_empty_reply_num %d\nloose_access_control_reply_num %d\nlookup_err_due_to_rename %d\nlookup_err_due_to_parallel_remove %d\nlookup_eaccess_enoent_mismatch %d\nread_io_err_num %d\nstale_fhandle_err_num %d abnormal_EEXIST_num %d abnormal_ENOENT_num %d proper_reply_num %d run_stage_proper_reply_num %d\n", 
+			failed_create_command_num,
+			failed_other_command_num,
+			skipped_readlink_command_num, 
+			skipped_custom_command_num,
+			fh_path_map_err_num, 
+			skipped_fsstat_command_num, 
+			missing_reply_num, 
+			rename_rmdir_noent_reply_num, 
+			rmdir_not_empty_reply_num, 
+			loose_access_control_reply_num, 
+			lookup_err_due_to_rename_num, 
+			lookup_err_due_to_parallel_remove_num,
+			lookup_eaccess_enoent_mismatch_num, 
+			read_io_err_num, 
+			stale_fhandle_err_num,
+			abnormal_EEXIST_num,
+			abnormal_ENOENT_num,
+			proper_reply_num, run_stage_proper_reply_num);
+#endif
+
+//  print_dump(Client_num, Child_num);
+} 
+
+/*
+ * allocate and initialize client handles
+ */
+static int
+init_rpc(void)
+{
+	int dummy = 0;
+
+    /*
+     * Set up the client handles.  We get them all before trying one
+     * out to insure that the client handle for LOOKUP class is allocated
+     * before calling op_getattr().
+     */
+    if (DEBUG_CHILD_GENERAL) {
+    	(void) fprintf(stderr, "%s: set up client handle\n", sfs_Myname);
+    }
+
+    NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+					(uint32_t) NFS_PROGRAM,
+					(uint32_t) nfs_version,
+					RPC_ANYSOCK, &Nfs_timers[0]);
+		
+    if (NFS_client  == ((CLIENT *) NULL)) {
+        return(-1);
+    }
+
+    /*
+     * create credentials using the REAL uid
+     */
+    NFS_client->cl_auth = authunix_create(lad_hostname, (int)Real_uid,
+				      (int)Cur_gid, 0, NULL);
+
+	if (biod_init(dummy, dummy) == -1) {
+		    return(-1);
+	}
+
+    return(0);
+} /* init_rpc */
+
+void
+init_counters(void)
+{
+    uint_t i;
+    uint_t start_msec;
+
+    /* Ready to go - initialize operation counters */
+    for (i = 0; i < NOPS + 1; i++) {
+	Ops[i].req_cnt = 0;
+	Ops[i].results.good_calls = 0;
+	Ops[i].results.bad_calls = 0;
+	Ops[i].results.timeout_calls = 0;	// RFS
+	Ops[i].results.fast_calls = 0;
+	Ops[i].results.time.sec = 0;
+	Ops[i].results.time.usec = 0;
+	Ops[i].results.msec2 = 0;
+    }
+
+    /* initialize timers and period variables */
+    sfs_gettime(&Starttime);
+    Cur_time = Starttime;
+    start_msec = (Starttime.sec * 1000) + (Starttime.usec / 1000);
+    Previous_chkpnt_msec = start_msec;
+    Calls_this_period = 0;
+    Reqs_this_period = 0;
+    Sleep_msec_this_period = 0;
+    Calls_this_test = 0;
+    Reqs_this_test = 0;
+    Sleep_msec_this_test = 0;
+}
+
+static char *
+nfs3_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS3_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFS3ERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFS3ERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFS3ERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFS3ERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFS3ERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFS3ERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFS3ERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFS3ERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFS3ERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFS3ERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFS3ERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFS3ERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFS3ERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFS3ERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFS3ERR_MLINK:
+	    (void) strcpy(str, "Too many links");
+	    break;
+	case NFS3ERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFS3ERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFS3ERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFS3ERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFS3ERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFS3ERR_BADHANDLE:
+	    (void) strcpy(str, "Bad file handle");
+	    break;
+	case NFS3ERR_NOT_SYNC:
+	    (void) strcpy(str, "Not sync write");
+	    break;
+	case NFS3ERR_BAD_COOKIE:
+	    (void) strcpy(str, "Bad cookie");
+	    break;
+	case NFS3ERR_NOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFS3ERR_TOOSMALL:
+	    (void) strcpy(str, "Value too small");
+	    break;
+	case NFS3ERR_SERVERFAULT:
+	    (void) strcpy(str, "Server fault");
+	    break;
+	case NFS3ERR_BADTYPE:
+	    (void) strcpy(str, "Bad type");
+	    break;
+	case NFS3ERR_JUKEBOX:
+	    (void) strcpy(str, "Jukebox");
+	    break;
+	case NFS3ERR_RFS_TIMEOUT:
+		(void) strcpy(str, "Timeout");
+		break;
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+
+/*
+ * Check the gettimeofday() resolution. If the resolution
+ * is in chunks bigger than SFS_MIN_RES then the client
+ * does not have a usable resolution for running the 
+ * benchmark.
+ */
+static void
+check_clock(void)
+{
+	double time_res;
+	char tmp_hostname[HOSTNAME_LEN];
+
+	time_res = get_resolution();
+    	getmyhostname(tmp_hostname, HOSTNAME_LEN);
+	if( time_res > (double)SFS_MIN_RES )
+	{
+		(void) fprintf(stderr,
+		"\n%s: Clock resolution too poor to obtain valid results.\n",
+			tmp_hostname);
+		(void) fprintf(stderr,
+		"%s: Clock resolution %f Micro seconds.\n", tmp_hostname,
+			time_res);
+		exit(175);
+	}
+	else
+	{
+		(void) fprintf(stderr,
+		"\n%s: Good clock resolution [ %f ] Micro seconds.\n", 
+			tmp_hostname, time_res);
+	}
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns the resolution of the gettimeofday() function 
+ * in microseconds.
+ */
+static double
+get_resolution(void)
+{
+        double starttime, finishtime, besttime;
+        long  j,delay;
+	int k;
+
+        finishtime=time_so_far1(); /* Warm up the instruction cache */
+        starttime=time_so_far1();  /* Warm up the instruction cache */
+        delay=j=0;                 /* Warm up the data cache */
+	for(k=0;k<10;k++)
+	{
+	        while(1)
+       	 	{
+       	         	starttime=time_so_far1();
+       	         	for(j=0;j< delay;j++)
+       	                ;
+       	         	finishtime=time_so_far1();
+       	         	if(starttime==finishtime)
+       	                 	delay++;
+       	         	else
+			{
+				if(k==0)
+					besttime=(finishtime-starttime);
+				if((finishtime-starttime) < besttime)
+					besttime=(finishtime-starttime);
+                       	 	break;
+			}
+		}
+        }
+         return(besttime);
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns current result of gettimeofday() in microseconds.
+ */
+/************************************************************************/
+/* Time measurement routines.                                           */
+/* Return time in microseconds                                          */
+/************************************************************************/
+
+static double
+time_so_far1(void)
+{
+        /* For Windows the time_of_day() is useless. It increments in 55 */
+	/* milli second increments. By using the Win32api one can get */
+	/* access to the high performance measurement interfaces. */
+	/* With this one can get back into the 8 to 9 microsecond */
+	/* resolution.  */
+#ifdef Windows
+        LARGE_INTEGER freq,counter;
+        double wintime;
+        double bigcounter;
+
+        QueryPerformanceFrequency(&freq);
+        QueryPerformanceCounter(&counter);
+        bigcounter=(double)counter.HighPart *(double)0xffffffff +
+                (double)counter.LowPart;
+        wintime = (double)(bigcounter/(double)freq.LowPart);
+        return((double)wintime*1000000.0);
+#else
+#if defined (OSFV4) || defined(OSFV3) || defined(OSFV5)
+  struct timespec gp;
+
+  if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1)
+    perror("getclock");
+  return (( (double) (gp.tv_sec)*1000000.0) +
+    ( ((float)(gp.tv_nsec)) * 0.001 ));
+#else
+  struct timeval tp;
+
+  if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
+    perror("gettimeofday");
+  return ((double) (tp.tv_sec)*1000000.0) +
+    (((double) tp.tv_usec) );
+#endif
+#endif
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "trace play usage");
+}
+extern void init_file_system (void)
+{
+	return;
+}
+
+void show_fhandle (nfs_fh3 * fhp)
+{
+	struct knfs_fh * kfhp = (struct knfs_fh *)fhp;
+
+	int dev;
+
+	if (quiet_flag)
+		return;
+		
+	RFS_ASSERT (kfhp->fh_version == 1);
+	RFS_ASSERT (kfhp->fh_fsid_type == 0);
+	RFS_ASSERT (kfhp->fh_auth_type == 0);
+
+	dev = ntohs(kfhp->fh_dev_major);
+	dev = dev<<8;
+	dev = dev + ntohs(kfhp->fh_dev_minor);
+
+	/* kfhp->fh_dev_ino hold the inode number of export point of the mounted
+	 * file system. For example, if /tmp/t1 is exported, /tmp/t1/t2 is mounted,
+	 * then fh_dev_ino hold the inode number of t1, not t2
+	 */
+
+	switch (kfhp->fh_fileid_type) {
+		case 0:
+			printf("fh:type 0 root dev 0x%x dev_ino %d\n", dev, kfhp->fh_dev_ino); 
+			break;
+		case 1:
+			printf("fh:type 1 %d %x dev %x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, dev, kfhp->fh_dev_ino);
+			break;
+		case 2:
+			printf("fh:type2 %d %x dirino %d dev 0x%x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, kfhp->fh_dirino, dev, kfhp->fh_dev_ino);
+			break;
+		default:
+			RFS_ASSERT (0);
+	}
+}
+
+nfs_fh3 zero_fhandle;
+int init_fh_map ()
+{
+	memset (fh_map, 0, sizeof (fh_map));
+	memset(fh_htable, 0, sizeof (fh_htable));
+	memset (&zero_fhandle, 0, sizeof(nfs_fh3));
+	printf ("SIZE of fh map %d KB\n", sizeof (fh_map)/1000);
+	fh_i = 0;
+}
+
+int add_fh (int map_flag, char * trace_fh, char * path, nfs_fh3 * play_fh)
+{
+	char * old_trace_fh;
+
+	/* first lookup if the entry for fh is already in the table */
+    struct generic_entry * p;
+
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (p) {
+		RFS_ASSERT (fh_map[p->key3].flag = FH_MAP_FLAG_PARTIAL);
+		RFS_ASSERT (map_flag ==FH_MAP_FLAG_COMPLETE);
+		fh_map[p->key3].flag = map_flag;
+		//RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+		if (memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE)) {
+			int i;
+			printf ("fh_map[%d].trace_fh %s trace_fh %s", p->key3, fh_map[p->key3].trace_fh, trace_fh);
+			for (i=0; i<fh_i; i++) {
+				int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+				int * p = (int *)fh_map[i].trace_fh;
+				printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+				printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, fh_map[i].trace_fh, fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+			}
+#endif
+			RFS_ASSERT (0);
+		}
+		RFS_ASSERT (!strcmp(fh_map[p->key3].path, path));
+		/* It's possible that in fh-path-map, many trace_fh are corresponding to one path
+		 * some of it may be the result of lookup after symlink, which is not handled
+		 * properly as new created objects 
+		 */
+#ifdef TAKE_CARE_SYMBOLIC_LINK
+		RFS_ASSERT (!memcmp(&fh_map[p->key3].play_fh, &zero_fhandle, sizeof(nfs_fh3)));
+#endif
+		memcpy (&fh_map[p->key3].play_fh, play_fh, sizeof (nfs_fh3));
+		if ((fh_map_debug==1)) // || (stage ==TRACE_PLAY_STAGE)) 
+			printf ("update the play_fh for trace_fh %s path %s \n", trace_fh, path);
+		return 0;
+	}
+
+	fh_map[fh_i].flag = map_flag;
+	fh_map[fh_i].lock = 0;
+	strncpy(fh_map[fh_i].trace_fh, trace_fh, TRACE_FH_SIZE);
+
+	RFS_ASSERT (strlen(path) < MAX_PLAY_PATH_SIZE);
+	strcpy (fh_map [fh_i].path, path);
+	if (map_flag==FH_MAP_FLAG_COMPLETE)
+		memcpy (&fh_map[fh_i].play_fh, play_fh, sizeof(nfs_fh3));
+	else 
+		memset (&fh_map[fh_i].play_fh, 0, sizeof(nfs_fh3));
+
+	if ((fh_map_debug==1)) { // || (stage ==TRACE_PLAY_STAGE)) {
+		printf ("insert trace_fh %s path %s play_fh:\n", trace_fh, path);
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			//show_fhandle(play_fh);
+		} else 
+			printf("null\n");
+	}
+
+/*
+	if (map_flag == FH_MAP_FLAG_DISCARD)
+		printf ("insert flag %d trace_fh %s path %s play_fh:\n", map_flag, trace_fh, path);
+*/
+
+    generic_insert(trace_fh, TRACE_FH_SIZE, fh_i, fh_htable, FH_HTABLE_SIZE);
+	
+	fh_i = (fh_i+1);
+	RFS_ASSERT (fh_i < FH_MAP_SIZE);
+
+    return 0;
+};
+
+inline fh_map_t * lookup_fh (char * trace_fh )
+{
+    struct generic_entry * p;
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (fh_map_debug==1)
+		printf ("lookup trace_fh %s\n", trace_fh);
+
+    if (p) {
+		if (fh_map_debug==1) {
+			printf ("found: fh_i[%d] trace_fh %s path %s play_fh:\n", p->key3, fh_map[p->key3].trace_fh, fh_map[p->key3].path);
+			//show_fhandle(&fh_map[p->key3].play_fh);
+		}
+		RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+        return (&(fh_map[p->key3]));
+    } else {
+		//printf ("lookup_fh %s not found\n", trace_fh);
+		if (stage != READ_DEP_TAB_STAGE && (fh_map_debug==1)) {
+			printf ("lookup not found trace_fh %s\n", trace_fh);
+		}
+        return NULL;
+	}
+	RFS_ASSERT (0);
+}
+
+int delete_fh (char * trace_fh, int fh_map_index)
+{
+    generic_delete (trace_fh, TRACE_FH_SIZE, fh_map_index, fh_htable, FH_HTABLE_SIZE);
+    return 0;
+};
+
+int lookup_init_filesystem (nfs_fh3 * parent, char * name, nfs_fh3 * result)
+{
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+	static int i=0;
+
+    /* set up the arguments */
+    (void) memcpy((char *) &args.what.dir, (char *) parent,
+							sizeof (nfs_fh3));
+    args.what.name = name;
+    (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			Nfs_timers[Init]);
+    sfs_gettime(&stop);
+
+	if (rpc_stat !=RPC_SUCCESS) {
+		printf("rpc_stat %d\n", rpc_stat);
+		perror("");
+	}
+    RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+	(void) memcpy((char *) result, (char *) &reply.resok.object, sizeof (nfs_fh3));
+	return (reply.status);
+}
+
+void read_fh_map(char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	char trace_fh[MAX_TRACE_FH_SIZE];
+	char intbuf[9];
+	char * trace_path;
+	char * p;
+	int map_flag;
+#define MAX_PATH_DEPTH 20
+	nfs_fh3 parents[MAX_PATH_DEPTH];
+	char * lookup_path_ptr[MAX_PATH_DEPTH];
+	char lookup_path [MAX_PLAY_PATH_SIZE];
+	int depth;
+	int new_dir_flag = 0;
+	int lineno = 0;
+
+	depth = 0;
+	memset(lookup_path_ptr, 0, sizeof(lookup_path_ptr));
+	memcpy(&parents[depth], &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+	strcpy(lookup_path, "/");
+	lookup_path_ptr[depth]=&lookup_path[0];
+
+	fp = fopen(fh_map_file, "r");
+	if (!fp) {
+		printf ("can not opern %s\n", fh_map_file);
+		perror("open");
+		exit (0);
+	}
+	RFS_ASSERT (fp!=NULL);
+	if (strstr(fh_map_file, "fmt1")) {
+		TRACE_FH_SIZE = 48;
+	}
+	
+	intbuf[8]=0;
+
+	memset(buf, 0, sizeof(buf));
+	while (fgets(buf, 1024, fp)) {
+		lineno ++;
+		if (fh_i % 10000==0)
+			printf("%d fh_map entry read\n", fh_i);
+
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf[strlen(buf)-1]=0;
+		if (fh_map_debug) {
+			printf("%d fgets return %s\n", fh_i, buf);
+			printf("depth %d lookup_path %s\n", depth, lookup_path);
+		}
+		//for (i=0; i<=depth; i++) 
+			//printf("lookup_path_ptr[%d] %s ", i, lookup_path_ptr[i]);
+		//printf("\n");
+#ifdef COMPRESS_TRACE_FH 
+		for (i=0; i<TRACE_FH_SIZE/8; i++) {
+			strncpy(intbuf, buf+i*8, 8);
+			sscanf(intbuf, "%x", trace_fh+i*8); // maybe it should be 4, anyway we don't compress for now 
+		}
+		trace_path = buf+TRACE_FH_SIZE*2+1;		/* +1 the trace contains only initial file handle */
+#else
+		memcpy(trace_fh, buf, TRACE_FH_SIZE);
+		trace_path = buf + TRACE_FH_SIZE +1;
+#endif
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		trace_path = +=2;	/* +3 if the trace contains both initial and later created file handle */
+#endif
+
+#ifdef NO_DEPENDENCY_TABLE
+		if (!strncmp (trace_path, "DISCARD", 7) ||
+			!strncmp (trace_path, "LN", 2)			) {
+			map_flag = FH_MAP_FLAG_DISCARD;
+			add_fh (map_flag, buf, trace_path, 0);
+			continue;
+		}
+#endif
+		
+		p = trace_path+strlen(trace_path)-2;
+		while (*p!='/')
+			p--;
+		p++;
+		//RFS_ASSERT (p-trace_path<=strlen(lookup_path)+1);
+		//RFS_ASSERT (p>trace_path);
+
+		if (strncmp(lookup_path, trace_path, p-trace_path)) {
+			printf("strncmp lookup_path %s trace_path %s for length %d\n", lookup_path, trace_path, p-trace_path);
+		}
+		RFS_ASSERT (!strncmp(lookup_path, trace_path, p-trace_path));
+		//while (strncmp(lookup_path, trace_path, p-trace_path)) {	/* one step deeper */
+		while (strlen(lookup_path)>p-trace_path && depth>0) {
+			//printf("depth--\n");
+			if (depth<=0) 
+				printf ("lookup_path %s trace_path %s p-trace_path %d depth %d\n", lookup_path, trace_path, p-trace_path, depth);
+			RFS_ASSERT (depth>0);
+			*lookup_path_ptr[depth]=0;
+			lookup_path_ptr[depth]=0;
+			depth--;
+		}
+		RFS_ASSERT (strlen(lookup_path)==(p-trace_path) || (depth==0));
+
+
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		if (buf[TRACE_FH_SIZE*2+1]=='Y') {
+			map_flag = FH_MAP_FLAG_COMPLETE;
+		} else {
+			map_flag = FH_MAP_FLAG_PARTIAL;
+			RFS_ASSERT (buf[TRACE_FH_SIZE*2+1]=='N');
+		}
+#else
+		map_flag = FH_MAP_FLAG_COMPLETE;
+#endif
+		if ((*(p+strlen(p)-1))=='/') {
+			*(p+strlen(p)-1)=0;
+			new_dir_flag = 1;
+		} else 
+			new_dir_flag = 0;
+
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			int ret = lookup_init_filesystem (&parents[depth], p, &parents[depth+1]);		
+			if (ret!=NFS3_OK) {
+				printf ("lineno %d %s\n", lineno, buf);
+			}
+ 			RFS_ASSERT (ret == NFS3_OK);
+			add_fh (map_flag, buf, trace_path, &parents[depth+1]);	
+		} else 
+			add_fh (map_flag, buf, trace_path, 0);
+
+		if (new_dir_flag) {
+			/* the new fhandle is of a directory */
+			lookup_path_ptr[depth+1] = lookup_path+strlen(lookup_path);
+			strcat (lookup_path, p);
+			strcat (lookup_path, "/");
+
+			//printf("depth++\n");
+			depth++;
+		}
+
+		memset(buf, 0, sizeof(buf));
+	}
+			
+	if (fh_map_debug) {
+		for (i=0; i<fh_i; i++) {
+			int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+			int * p = (int *)fh_map[i].trace_fh;
+			printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+			printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, fh_map[i].trace_fh, fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+		}
+#endif
+
+		fprintf(stderr, "total %d requests \n", i);
+	}
+}
+
+int f()
+{
+	return 1;
+}
+
+inline free_biod_req (int biod_index)
+{
+	RFS_ASSERT (biod_reqp[biod_index].in_use == TRUE);
+	biod_reqp[biod_index].in_use = FALSE;
+	num_out_reqs --;
+}
+
+void finish_request (int biod_index, int dep_index, int status, int dep_flag)
+{
+	static int i = 0;
+	/* the ending operation, same as when a request time out */
+
+	dep_tab[dep_index].stop = biod_reqp[biod_index].stop;	/* RFS: to dump data */
+	free_biod_req (biod_index);
+
+	dep_tab[dep_index].status = status;
+
+	if (event_order_index < EVENT_ORDER_SIZE)
+		event_order[event_order_index++] = -dep_tab[dep_index].disk_index;
+
+	dep_tab[dep_index].flag = dep_flag;
+	if (is_dir_op(dep_tab[dep_index].proc)) {
+		int j;
+		RFS_ASSERT (dep_tab[dep_index].fh->lock = 1);
+		dep_tab[dep_index].fh->lock = 0;
+		if (dep_tab[dep_index].proc==RENAME)
+			dep_tab[dep_index].fh_2->lock = 0;
+		j = dep_tab[dep_index].fh-fh_map;
+		if (dependency_debug) {
+			printf ("fh_map[%d] is UNlocked\n",j);
+			printf ("trace_fh %d path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+			printf ("trace_fh %d path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+		}
+	}
+}
+
+/* the request argument may have pointers pointing to buffers, e.g. the name in lookup, 
+ * the target of symlink, the write data */
+char arg_res[MAX_ARG_RES_SIZE];
+char buf1 [MAX_BUF1_SIZE]; 
+char buf2 [MAX_BUF2_SIZE];
+
+int execute_next_request ()
+{
+	int dep_index;
+	int proc;
+	char * line;
+	struct biod_req * reqp;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime call_timeout;
+	static int last_print_time = -1;
+
+	if (num_out_reqs == max_biod_reqs) {
+		return -1;
+	}
+
+	start_profile (&valid_get_nextop_profile);
+	start_profile (&invalid_get_nextop_profile);
+	dep_index = get_nextop();
+	if (dep_index == -1) {
+		end_profile (&invalid_get_nextop_profile);
+		return dep_index;
+	};
+	end_profile (&valid_get_nextop_profile);
+
+	start_profile (&prepare_argument_profile);
+	line = dep_tab[dep_index].line;
+
+	if (per_packet_debug)
+		fprintf (stdout, "time %d processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+
+	end_profile(&total_profile);
+	if ((total_profile.in.tv_sec - last_print_time >= 10)) {
+		last_print_time = total_profile.in.tv_sec;
+		//fprintf (stdout, "time %d processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+/*
+		CYCLIC_PRINT (dep_tab_index);
+		{
+			int tmp = CYCLIC_MINUS(dep_tab_index.head,1,dep_tab_index.size);
+			printf("dep_tab_index.head-1 %d disk_index %d tail %d disk_index %d\n", tmp, dep_tab[tmp].disk_index,
+			dep_tab_index.tail, dep_tab[dep_tab_index.tail].disk_index);
+		}
+*/
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+/*
+		if (can_not_catch_speed_num < 2000) {
+			PLAY_SCALE ++;
+			printf ("set PLAY_SCALE to %d\n", PLAY_SCALE);
+		};
+		if (can_not_catch_speed_num > 50000) {
+			PLAY_SCALE /= 2;
+		} else {
+			if (can_not_catch_speed_num > 5000) {
+				PLAY_SCALE -= 2;
+				if (PLAY_SCALE < 1)
+					PLAY_SCALE = 1;
+			}
+		}
+*/
+#endif
+		if ((total_profile.in.tv_sec > 100)) {
+			can_not_catch_speed_num_total += can_not_catch_speed_num;
+		}
+		can_not_catch_speed_num = 0;
+#endif
+	}
+	if (rfs_debug)
+		printf ("processing dep_tab[%d] disk_index %d %s\n", dep_index, dep_tab[dep_index].disk_index, line);
+
+	proc = dep_tab[dep_index].proc;
+	rfs_Ops[proc].setarg (dep_index, line, arg_res, buf1, buf2);
+
+	op_ptr = &Ops[proc];
+	reqp = get_biod_req (dep_index);
+	RFS_ASSERT (reqp);
+
+#ifdef	notdef	/* place to set request timeout. G. Jason Peng */
+	call_timeout.sec = 2; //Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+#else
+	call_timeout.sec = 0;
+	call_timeout.usec = 300000;
+	//call_timeout.usec = 14000;
+	//call_timeout.usec = 13000;
+	//call_timeout.usec = 6000;
+	//call_timeout.usec = 8000;
+	//call_timeout.usec = 10000;
+#endif
+
+    /* make the call */
+    sfs_gettime(&(reqp->start));
+	end_profile (&prepare_argument_profile);
+	start_profile (&biod_clnt_call_profile);
+#define REAL_PLAY
+#ifdef REAL_PLAY
+
+#ifdef RECV_THREAD
+	//printf ("send thread waitsem\n");
+	waitsem(async_rpc_sem);
+	//printf ("send thread got sem\n");
+#endif
+    reqp->xid = biod_clnt_call(NFS_client, rfs_Ops[proc].nfsv3_proc, 
+					rfs_Ops[proc].xdr_arg, arg_res);
+#ifdef RECV_THREAD
+	postsem(async_rpc_sem);
+	//printf ("send thread postsem\n");
+#endif
+
+#else	// REAL_PLAY
+	reqp->xid = dep_index+1;	/* just fake a message id and let it expire */
+#endif
+    RFS_ASSERT (reqp->xid != 0);
+    reqp->timeout = reqp->start;
+    ADDTIME (reqp->timeout, call_timeout);
+    dep_tab[dep_index].flag = DEP_FLAG_SENT;
+	if (event_order_index < EVENT_ORDER_SIZE)
+		event_order[event_order_index++] = dep_tab[dep_index].disk_index;
+
+	dep_tab[dep_index].start = reqp->start;	/* RFS: to dump data */
+	end_profile (&biod_clnt_call_profile);
+
+	send_num ++;
+}
+
+void check_reply (int proc, int biod_index, int dep_index, int status, char * errmsg, int trace_status)
+{
+	if (((status!=trace_status)) && (status!=NFS3_OK) && (trace_status!=NFS3ERR_RFS_MISS)) {
+		if (!profile_debug)
+			printf ("receive problem reply, xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d command disk index %d\n", biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec, dep_tab[dep_index].disk_index); 
+#ifndef TAKE_CARE_UNLOOKED_UP_NON_NEW_FILES
+		/* these files is not looked up and is not create/mkdir/symlink/link/mknod ed before they
+		 * are refered by name through rename, remove
+		 */
+		if ((proc==RENAME || proc==REMOVE) && (status==NFS3ERR_NOENT) && (trace_status ==0)) {
+			/* current initialization doesnot take care of rename source, if there is no
+			 * create or lookup before that source, the source object will not exist when
+			 * rename occurs
+			 */
+			rename_rmdir_noent_reply_num++;
+		} else 
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+		if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_status==NFS3ERR_NOENT)) {
+			/* in the original trace, first lookup return NOENT, then symlink is executed, then lookup return OK
+			 * the initialization considers only the lookup return OK and created the file in the initialization
+			 * so in trace play the first lookup return OK
+			 */
+			RFS_ASSERT (1);
+		} else // if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) && (trace_status == 0)) {
+				/* trace_status could be EAGAIN */
+			if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) ) {
+			/* due to similar reason as above, the initialization code initializes the symbolic link as a normal
+			 * file already
+			 */
+			RFS_ASSERT (1);
+		} else
+#endif
+#ifndef TAKE_CARE_NOEMPTY_RMDIR
+		/* the remove packet seems got lost in the trace capture, so replay can not finish */
+		if ((proc==RMDIR) && (status==NFS3ERR_NOTEMPTY)) {
+   			RENAME3args		args;
+   			RENAME3res		reply;		/* the reply */
+			RMDIR3args * rmdir_argp;
+			enum clnt_stat rpc_stat;	/* result from RPC call */
+
+			rfs_Ops[proc].setarg (dep_index, dep_tab[dep_index].line, arg_res, buf1, buf2);
+			rmdir_argp = (RMDIR3args *)arg_res;
+
+			memcpy(&args.from, &(rmdir_argp->object), sizeof (diropargs3));
+			memcpy(&args.to.dir, &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+			args.from.name = buf1;	/* the buf1 is already filled when parsing rmdir */
+			args.to.name = buf2;
+			sprintf(buf2, "rmdir_%d_%s", dep_tab[dep_index].disk_index, rmdir_argp->object.name);
+
+  			rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
+			xdr_RENAME3args, (char *) &args,
+			xdr_RENAME3res, (char *) &reply,
+				Nfs_timers[Init]);
+			RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+			if (reply.status!=NFS3_OK)
+				printf ("change rmdir into rename, reply.status %d\n", reply.status);
+			RFS_ASSERT (reply.status==NFS3_OK);
+			rmdir_not_empty_reply_num ++;
+#endif
+#ifndef TAKE_CARE_ACCESS_ERROR
+		} else if ((status==0) && (trace_status==NFS3ERR_ACCES)) {
+			loose_access_control_reply_num ++;
+#endif
+#ifdef NO_DEPENDENCY_TABLE 
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3_OK)) {
+			lookup_err_due_to_rename_num ++;
+		} else if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_status == NFS3ERR_NOENT)) {
+			/* if there is a remove in front of the lookup, but it is
+ 			 * actually executed later than the lookup
+			 */
+			lookup_err_due_to_parallel_remove_num ++;
+#endif
+#ifndef TAKE_CARE_LOOKUP_EACCESS_ENOENT_MISMATCH
+		/* if the looked return EACCESS in the trace, means the object still exists
+		 * should have initialized, right not don't initialize it, hence play status 
+		 * could be ENOENT
+		 */
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3ERR_ACCES)) {
+			lookup_eaccess_enoent_mismatch_num ++;
+#endif
+#ifdef TOLERANT_READ_IO_ERR
+		} else if ((proc==READ) && (status==NFS3ERR_IO) && (trace_status==NFS3_OK)) {
+			read_io_err_num ++;
+#endif
+#ifdef TOLERANT_STALE_FHANDLE_ERR
+		} else if ((status==NFS3ERR_STALE) && (trace_status==NFS3_OK)) {
+			printf ("!!!!!!! STALE FILE HANDLE \n");
+			//sleep(1);
+			stale_fhandle_err_num ++;
+#endif
+		} else {
+			int i;
+			for (i=dep_window_index.tail; CYCLIC_LESS(dep_window_index,i,dep_window_index.head); i++) {
+				if (dep_tab[i].flag!=1)
+					printf ("dep_tab[%d].disk_index %d, flag %d line %s\n", i, dep_tab[i].disk_index, dep_tab[i].flag, dep_tab[i].line);
+			}
+
+			if (status==EEXIST) {
+				abnormal_EEXIST_num ++;
+			} else if (status == ENOENT) {
+				abnormal_ENOENT_num ++;
+			} else {
+				printf ("!!!!!!!!!!!!!1 should fail\n");
+				//RFS_ASSERT (0);
+			}
+		}
+	} else {
+		proper_reply_num ++;
+		if (total_profile.in.tv_sec >= WARMUP_TIME) 
+			run_stage_proper_reply_num ++;
+	}
+
+}
+
+/* return -1 if there is no reply being received 
+ * return the dep_index if the corresponding reply has been received
+ */
+int receive_next_reply (int busy_flag)
+{
+	int dep_index;
+	int biod_index;
+	int proc;
+	char * line;
+	char * reply_line;
+	sfs_op_type *op_ptr;		/* per operation info */
+	int ret;
+	int status;
+	int trace_status;
+	char * errmsg;
+	int poll_timeout = 0;		/* timeout in usecs */
+
+	/* wait for reply */
+	start_profile (&valid_poll_and_get_reply_profile);
+	start_profile (&invalid_poll_and_get_reply_profile);
+
+	if (busy_flag == BUSY) {
+		poll_timeout = 0;
+		poll_timeout_0_num ++;
+	} else {
+		poll_timeout = 2000;	/* 10000 or 2000 is a better number in non-debugging state */
+		//poll_timeout = 0;	/* 10000 or 2000 is a better number in non-debugging state */
+		poll_timeout_pos_num ++;
+	}
+
+	biod_index = poll_and_get_reply (poll_timeout);
+	if (biod_index==-1) {
+		end_profile (&invalid_poll_and_get_reply_profile);
+		return -1;
+	};
+	end_profile (&valid_poll_and_get_reply_profile);
+
+	start_profile (&decode_reply_profile);
+	/* check the corresponding request */
+	dep_index = biod_reqp[biod_index].dep_tab_index;
+	if (biod_reqp[biod_index].in_use==1) {
+		RFS_ASSERT (dep_tab[dep_index].biod_req_index == biod_index);
+	} else {
+		printf ("biod_index %d reply received but the request has been time out\n", biod_index);
+		return -1;
+	}
+
+	proc = dep_tab[dep_index].proc;
+	op_ptr = &Ops[proc];
+
+	if (dep_tab[dep_index].flag != DEP_FLAG_SENT) {
+		printf("dep_tab[%d].flag %d proc %d status %d start %d:%d stop %d:%d\n",
+			dep_index, dep_tab[dep_index].flag, proc, dep_tab[dep_index].status, 
+			dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec,
+			dep_tab[dep_index].stop.sec, dep_tab[dep_index].stop.usec );
+		printf ("received reply for timeout requests dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+		return dep_index;
+	}
+	RFS_ASSERT (dep_tab[dep_index].flag == DEP_FLAG_SENT);
+
+	/* decode the reply */
+	rfs_Ops[proc].setres (arg_res, buf1);
+	ret = proc_header (NFS_client, rfs_Ops[proc].xdr_res, arg_res);
+	RFS_ASSERT (ret == RPC_SUCCESS);
+	status = *((int *)arg_res);
+	errmsg = nfs3_strerror (status);
+	end_profile (&decode_reply_profile);
+
+	start_profile (&check_reply_profile);
+	/* compare with the reply in the trace */
+	line = dep_tab[dep_index].line;
+	reply_line = dep_tab[dep_index].reply_line;
+	trace_status = dep_tab[dep_index].trace_status;
+
+	if (per_packet_debug || rfs_debug )
+		fprintf (stdout, "dep_tab[%d], disk_index %d, receive reply, rpc_ret %d xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d \n", dep_index, dep_tab[dep_index].disk_index, ret, biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec);
+
+	/* error checking */
+	check_reply (proc, biod_index, dep_index, status, errmsg, trace_status);
+
+	/* free resources */
+	finish_request (biod_index, dep_index, status, DEP_FLAG_DONE);
+	recv_num ++;
+	
+	/* we set 100 seconds warm up time */
+	if ((total_profile.in.tv_sec >= WARMUP_TIME)) {
+	/* get statistics */
+	if (status == trace_status || (status==NFS3_OK && trace_status==NFS3ERR_RFS_MISS) ) {
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+	} else {
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	}
+	sfs_elapsedtime (op_ptr, &(biod_reqp[biod_index].start), &(biod_reqp[biod_index].stop));
+	end_profile (&check_reply_profile);
+	}
+	
+	//start_profile (&add_create_object_profile);
+
+	if (trace_status == NFS3_OK && (proc==CREATE || proc==MKDIR || proc==SYMLINK || proc==MKNOD)) {
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+		RFS_ASSERT (reply_line);
+#endif
+		if (status!=NFS3_OK) {
+			/* commented out for 1022 */
+			printf ("!!!!!! Should have been an ASSERTION FAILURE \n");
+			RFS_ASSERT (proc==SYMLINK);
+			RFS_ASSERT (0);
+		} else {
+			if (proc!=SYMLINK || line[TRACE_VERSION_POS]!='2')
+				add_new_file_system_object(proc, dep_index, line, reply_line);
+		}
+	}
+	//end_profile (&add_create_object_profile);
+}
+
+inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line)
+{
+	char * child_trace_fh;
+	fh_map_t * parent_entryp;
+	char component_name[MAX_PLAY_PATH_SIZE];
+	char * parent_trace_fh;
+	char child_path[MAX_PLAY_PATH_SIZE];
+	post_op_fh3 * post_op_fh3_child;
+	char * reply_trace_fh;
+	nfs_fh3 * child_fh3;
+
+	parent_trace_fh = strstr (line, "fh");
+	RFS_ASSERT (parent_trace_fh);
+	parent_trace_fh +=3;
+	parent_entryp = lookup_fh (parent_trace_fh);
+	RFS_ASSERT (parent_entryp);
+	parse_name (parent_trace_fh+65, component_name);
+	strcpy (child_path, parent_entryp->path);
+	strcat (child_path, "/");
+	strcat (child_path, component_name);
+				
+	/* find the corresponding create request */
+	//printf ("before find reply trace_fh reply_line %s\n", reply_line);
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+	reply_trace_fh = dep_tab[dep_index].reply_trace_fh;
+#else
+	reply_trace_fh = find_reply_trace_fh (reply_line);
+#endif
+	RFS_ASSERT (reply_trace_fh != NULL);
+	switch (proc) {
+	case CREATE:
+		RFS_ASSERT (((CREATE3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((CREATE3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKDIR:
+		RFS_ASSERT (((MKDIR3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKDIR3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case SYMLINK:
+		RFS_ASSERT (((SYMLINK3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((SYMLINK3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKNOD:
+		RFS_ASSERT (((MKNOD3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKNOD3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case LOOKUP:
+		RFS_ASSERT (proc==LOOKUP);
+		child_fh3 = &((LOOKUP3res *)arg_res)->res_u.ok.object;
+		break;
+	default:
+		RFS_ASSERT (0);
+	}
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+	RFS_ASSERT (reply_trace_fh[TRACE_FH_SIZE]==' ');
+#endif
+	reply_trace_fh[TRACE_FH_SIZE] = 0;
+	add_fh (FH_MAP_FLAG_COMPLETE, reply_trace_fh, child_path, child_fh3); 	/* exist flag is not used now, set to 1 */
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+	/* just to preserve the original reply line not changed */
+	reply_trace_fh[TRACE_FH_SIZE] = ' ';
+#endif
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void trace_play(void)
+{
+	
+	/* The flag to indicate whether trace_player is BUSY. Trace_player is BUSY
+	 * when either there is request to send or there is reply being
+	 * received. Otherwise it is IDLE. The timeout for polling replies 
+	 * is set to 0 when BUSY, it is set to the waiting time to the first
+	 * request outside of current <min_dep_index, dep_window_max> window when IDLE.
+	 */
+   	int busy_flag = BUSY;		
+	//int dep_index;		/* index into dependency table: dep_tab */
+	//int biod_index; 	/* index into outstanding requests: biod_reqp */
+	static int last_print_time = -1;
+	int poll_timeout = 0;
+
+#ifndef IO_THREAD
+	disk_io_status = read_trace();
+#endif
+
+	RFS_ASSERT (!CYCLIC_EMPTY(dep_tab_index));
+	CYCLIC_MOVE_HEAD(dep_window_index);
+
+	adjust_play_window(busy_flag, &poll_timeout);
+
+	start_profile (&total_profile);
+	while (!CYCLIC_EMPTY(dep_tab_index)) {
+		end_profile(&total_profile);
+		if ((total_profile.in.tv_sec - last_print_time >= 10)) {
+			int i;
+
+			last_print_time = total_profile.in.tv_sec;
+			fprintf (stdout, ">>>> sendng thread: time %d send_num %d recv_num %d timeout_num %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, send_num, recv_num, timeout_num, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+			for (i=0; i<=MAX_OUTSTANDING_REQ; i++) {
+				if (num_out_reqs_statistics[i]!=0) {
+					printf("num_out_req[%d]=%d,", i, num_out_reqs_statistics[i]);
+					num_out_reqs_statistics[i]=0;
+				}
+			}
+			printf("\n");
+			for (i=0; i<=MAX_OUTSTANDING_REQ; i++) {
+				if (num_out_reqs_statistics_at_timeout[i]!=0) {
+					printf("num_out_req_at_timeout[%d]=%d,", i, num_out_reqs_statistics_at_timeout[i]);
+					num_out_reqs_statistics_at_timeout[i]=0;
+				}
+			}
+			printf("\n");
+			//	CYCLIC_PRINT(dep_tab_index);
+		}
+
+		if ((total_profile.in.tv_sec > 6000)) {
+			printf ("the process has run for more than 600 seconds, exit\n");
+			goto END;
+		}
+
+		if (busy_flag == IDLE) {
+#ifndef RECV_THREAD
+			//start_profile (&check_timeout_profile);
+			check_timeout();
+			//end_profile (&check_timeout_profile);
+#endif
+#ifndef IO_THREAD
+			if (disk_io_status!=TRACE_FILE_END) {
+				disk_io_status = read_trace();
+			};
+#endif
+		}
+
+		//start_profile (&adjust_play_window_profile);
+	 	adjust_play_window (busy_flag, &poll_timeout);
+		if (rfs_debug)
+			printf("num_out_reqs %d\n", num_out_reqs);
+		num_out_reqs_statistics[num_out_reqs]++;
+		busy_flag = IDLE;
+		//end_profile (&adjust_play_window_profile);
+
+		start_profile (&execute_next_request_profile);
+		while (execute_next_request()!=-1) {
+			busy_flag = BUSY;
+		}
+		end_profile (&execute_next_request_profile);
+
+#ifndef RECV_THREAD
+		start_profile (&receive_next_reply_profile);
+		/* actually the performance of two policy seems to be same */
+//#define SEND_HIGHER_PRIORITY_POLICY
+#define SEND_RECEIVE_EQUAL_PRIORITY_POLICY	
+
+#ifdef SEND_HIGHER_PRIORITY_POLICY
+		receive_next_reply(IDLE);
+#endif
+#ifdef SEND_RECEIVE_EQUAL_PRIORITY_POLICY
+		busy_flag = IDLE;
+		while (receive_next_reply(busy_flag)!=-1)
+			busy_flag = BUSY;
+#endif
+		end_profile (&receive_next_reply_profile);
+#endif
+		CYCLIC_ASSERT (0);
+	}
+	end_profile (&total_profile);
+
+	RFS_ASSERT (disk_io_status == TRACE_FILE_END);
+	if (num_out_reqs !=0 ) {
+		printf ("num_out_reqs %d\n", num_out_reqs);
+		CYCLIC_PRINT(dep_tab_index);
+	}
+	RFS_ASSERT(num_out_reqs==0);
+
+END:
+	printf ("trace starttime %d, trace_end_time %d trace_duration %d\n", trace_timestamp1, trace_timestamp2,
+		trace_timestamp2 - trace_timestamp1);
+	printf ("can_not_catch_speed_num_total %d can_not_catch_speed_num_last_10_seconds %d", 
+		can_not_catch_speed_num_total, can_not_catch_speed_num);
+	printf ("total_profile.about: %s\n", total_profile.about);
+	print_profile ("total_profile", &total_profile);
+	printf("\n");
+	//print_profile ("check_timeout", &check_timeout_profile);
+	//printf("\n");
+	//print_profile ("adjust_play_window", &adjust_play_window_profile);
+	//printf("\n");
+	print_profile ("execute_next_request_profile", &execute_next_request_profile);
+	print_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	print_profile ("invalid_get_nextop_profile", &invalid_get_nextop_profile);
+	print_profile ("prepare_argument_profile", &prepare_argument_profile);
+	print_profile ("biod_clnt_call_profile", &biod_clnt_call_profile);
+	printf("\n");
+	print_profile ("receive_next_reply_profile", &receive_next_reply_profile);
+	print_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	print_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	print_profile ("decode_reply_profile", &decode_reply_profile);
+	print_profile ("check_reply_profile", &check_reply_profile);
+	print_profile ("fgets_profile", &fgets_profile);
+	print_profile ("read_line_profile", &read_line_profile);
+	print_profile ("read_trace_profile", &read_trace_profile);
+	//print_profile ("add_create_object", &add_create_object_profile);
+	printf("\n");
+	
+	printf ("dep_tab_index.tail %d dep_tab_index.head %d num_out_reqs %d\n", dep_tab_index.tail, dep_tab_index.head, num_out_reqs);
+}
+
+
+int CYCLIC_SET_TAIL_TO(cyclic_index_t * index, int dest) 
+{ 
+	cyclic_index_t indextmp, indextmp2;
+	int oldnum, num;
+	indextmp = *index;
+	indextmp2 = indextmp;
+	oldnum = CYCLIC_NUM(indextmp); 
+
+	if (! ((dest>=0) && (dest<indextmp.size))) {
+		CYCLIC_PRINT(indextmp);
+		printf("dest %d\n", dest);
+	}
+	RFS_ASSERT ((dest>=0) && (dest<indextmp.size));
+	index->tail = dest; 
+	indextmp2.tail = dest;
+	num = CYCLIC_NUM(indextmp2); 
+
+	if (num > oldnum) { 
+		CYCLIC_PRINT(indextmp);
+		CYCLIC_PRINT(indextmp2);
+		printf("dest %d old_num %d num %d\n", dest, oldnum, num);
+	}
+	RFS_ASSERT (num <= oldnum);
+}
+
+int flush_junk()
+{
+	int i;
+	for (i=0; i<500; i++) {
+		printf ("*************************************************************\n");
+	}
+	fflush(stdout);
+}
+
+int CYCLIC_ASSERT (int i)
+{
+	int j;
+	if (!(dep_tab_index.tail == dep_window_index.tail)) {
+		printf("%s head %d tail %d, size %d\n", dep_tab_index.name, dep_tab_index.head, dep_tab_index.tail, dep_tab_index.size);
+		printf("%s head %d tail %d, size %d\n", dep_window_index.name, dep_window_index.head, dep_window_index.tail, dep_window_index.size);
+		printf("pos %d\n", i); 
+		flush_junk();
+		sleep (10);
+		RFS_ASSERT (0);
+	};
+ 
+	if (!((dep_window_index.head == dep_tab_index.head) || 
+		   CYCLIC_LESS(dep_tab_index, dep_window_index.head, dep_tab_index.head ) )) {
+		printf("%s head %d tail %d, size %d\n", dep_tab_index.name, dep_tab_index.head, dep_tab_index.tail, dep_tab_index.size);
+		printf("%s head %d tail %d, size %d\n", dep_window_index.name, dep_window_index.head, dep_window_index.tail, dep_window_index.size);
+		printf("pos %d\n", i); 
+		flush_junk();
+		sleep (10);
+		RFS_ASSERT (0);
+	};
+	for (i=0, j=0; i<max_biod_reqs; i++) {
+		if (biod_reqp[i].in_use == 1)
+			j++;
+	}
+#ifndef RECV_THREAD
+	RFS_ASSERT (num_out_reqs==j);
+#endif
+/*
+		RFS_ASSERT ((dep_window_index.head == dep_tab_index.head) || 
+			   CYCLIC_LESS(dep_tab_index, dep_window_index.head, dep_tab_index.head ));
+*/
+}
+
+/* sfs_c_chd.c */
diff --git a/TBBT/trace_play/sfs_c_chd.c b/TBBT/trace_play/sfs_c_chd.c
new file mode 120000
index 0000000..0c356df
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_chd.c
@@ -0,0 +1 @@
+sfs_c_chd.3thread.c
\ No newline at end of file
diff --git a/TBBT/trace_play/sfs_c_chd.c.old b/TBBT/trace_play/sfs_c_chd.c.old
new file mode 100644
index 0000000..1d2f423
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_chd.c.old
@@ -0,0 +1,2457 @@
+#ifndef lint
+static char sfs_c_chdSid[] = "@(#)sfs_c_chd.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * -------------------------- sfs_c_chd.c -------------------------
+ *
+ *      The sfs child.  Routines to initialize child parameters,
+ *	initialize test directories, and generate load.
+ *
+ *.Exported_Routines
+ *	void child(int, float, int, char *);
+ *	void init_fileinfo(void);
+ *	void init_counters(void);
+ *	sfs_fh_type * randfh(int, int, uint_t, sfs_state_type,
+ *				sfs_file_type);
+ *	int check_access(struct *stat)
+ *	int check_fh_access();
+ *
+ *.Local_Routines
+ *	void check_call_rate(void);
+ *	void init_targets(void);
+ *	void init_dirlayout(void);
+ *	void init_rpc(void);
+ *	void init_testdir(void);
+ *	int do_op(void);
+ *	int op(int);
+ *
+ *.Revision_History
+ *	21-Aug-92	Wittle 		randfh() uses working set files array.
+ *					init_fileinfo() sets up working set.
+ *      02-Jul-92	Teelucksingh    Target file size now based on peak load
+ *					instead of BTDT.
+ *	04-Jan-92	Pawlowski	Added raw data dump hooks.
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+#include "rfs_c_def.h"
+#include "generic_hash.h"
+#include "nfsd_nfsfh_cust.h"
+
+extern struct hostent   *Server_hostent;
+
+#define PROB_SCALE 1000L
+#define _M_MODULUS 2147483647L /* (2**31)-1 */
+
+#define _GROUP_DIVISOR 500
+#define _FILES_PER_GROUP 4
+#define _MIN_GROUPS 12
+#define _WORKING_SET_AT_25_OPS_PER_SEC 975
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+extern uint32_t    biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
+extern enum clnt_stat proc_header(CLIENT *cl, xdrproc_t xdr_results, void *results_ptr);
+extern int  biod_poll_wait(CLIENT *, uint32_t);
+extern enum clnt_stat get_areply_udp (CLIENT * cl, uint32_t *xid, struct timeval *timeout);
+extern char * parse_name (char * t, char * buf);
+
+/* forward definitions for local functions */
+static int init_rpc(void);
+
+/* RFS: forward definitions for local functions */
+void init_ops(void);
+static void init_signal();
+extern void init_file_system (void);
+extern void init_dep_tab (void);
+static void read_trace(char * trace_file);
+static void read_fh_map();
+static void init_play (char * mount_point);
+static void trace_play(void);
+static void print_result(void);
+static int get_nextop(void);
+static int check_timeout(void);
+static struct biod_req * get_biod_req(int dep_tab_index);
+static int lookup_biod_req (int xid);
+static void init_time_offset(void);
+static void adjust_play_window (int flag, int * poll_timeout);
+static int poll_and_get_reply (int usecs);
+static char * nfs3_strerror(int status);
+static void check_clock(void);
+static double time_so_far1(void);
+static double get_resolution(void);
+static void usage(void);
+void init_dep_tab_entry (int dep_index);
+extern inline fh_map_t * lookup_fh (char * trace_fh );
+static inline void finish_request (int biod_index, int dep_index, int status);
+static inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line);
+static inline char * find_lead_trace_fh(int proc, char * line);
+
+/*
+ * -------------  Per Child Load Generation Rate Variables  -----------
+ */
+static uint_t Calls_this_period; /* calls made during the current run period */
+static uint_t Calls_this_test;	/* calls made during the test so far */
+static uint_t Reqs_this_period;	/* reqs made during the current run period */
+static uint_t Reqs_this_test;	/* reqs made during the test so far */
+static uint_t Sleep_msec_this_test; /* msec slept during the test so far */
+static uint_t Sleep_msec_this_period;
+static uint_t Previous_chkpnt_msec; /* beginning time of current run period */
+static int Target_sleep_mspc;	/* targeted sleep time per call */
+
+static char io_buf[BUFSIZ];	/* io buffer for print out messages */
+
+char * sfs_Myname;
+int     Log_fd;                         /* log fd */
+char    Logname[NFS_MAXNAMLEN];         /* child processes sync logfile */
+int 	Validate = 0;					/* fake variable */
+int Child_num = 0;						/* fake: child index */
+int Tcp = 0;							/* We implement UDP first */
+int Client_num = 1;						/* fake: number of client */
+uid_t Real_uid;
+gid_t Cur_gid;
+uid_t Cur_uid;
+/*
+ * -------------------------  SFS Child  -------------------------
+ */
+
+void print_usage()
+{
+	printf("sfs3 hostname:mount_dir trace_file fh_map_file\n");
+	exit;
+}
+
+void read_dep_tab()
+{
+#ifdef NO_DEPENDENCY_TABLE
+	int i;
+	char * line;
+	char * trace_fh;
+	fh_map_t * fh_map_entry;
+	int req_num_with_new_fh = 0;
+	int	req_num_with_discard_fh = 0;
+	int req_num_with_init_fh =0;
+
+	for (i=0; i<memory_trace_size; i++) {
+		line = memory_trace[i].line;
+		if (line[TRACE_COMMAND_REPLY_FLAG_POS]=='C') {
+			trace_fh = strstr (line, "fh");
+			RFS_ASSERT (trace_fh);
+			trace_fh += 3;
+			fh_map_entry = lookup_fh (trace_fh);
+			if (fh_map_entry && (fh_map_entry->flag==FH_MAP_FLAG_DISCARD) )  {
+				req_num_with_discard_fh ++;
+				continue;
+			}
+			if (fh_map_entry)
+				req_num_with_init_fh ++;
+			else
+				req_num_with_new_fh ++;
+
+			dep_tab[dep_tab_size].disk_index = memory_trace[i].disk_index;
+			dep_tab[dep_tab_size].line = memory_trace[i].line;
+			if ((dep_tab_size%100000)==0)
+				printf ("dep_tab[%d].disk_index %d = memory_trace[%d].disk_index %d\n", dep_tab_size, dep_tab[dep_tab_size].disk_index, i, memory_trace[i].disk_index);
+			dep_tab_size ++;
+		}
+	}
+#else
+	RFS_ASSERT (0);
+#endif
+	printf ("read_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+}
+
+void init_profile()
+{
+	memset (&total_profile, 0, sizeof(total_profile));
+
+	memset (&execute_next_request_profile, 0, sizeof(execute_next_request_profile));
+	memset (&valid_get_nextop_profile, 0, sizeof(valid_get_nextop_profile));
+	memset (&invalid_get_nextop_profile, 0, sizeof(invalid_get_nextop_profile));
+	memset (&prepare_argument_profile, 0, sizeof(prepare_argument_profile));
+	memset (&biod_clnt_call_profile, 0, sizeof(biod_clnt_call_profile));
+
+	memset (&receive_next_reply_profile, 0, sizeof(receive_next_reply_profile));
+	memset (&valid_poll_and_get_reply_profile, 0, sizeof(valid_poll_and_get_reply_profile));
+	memset (&invalid_poll_and_get_reply_profile, 0, sizeof(invalid_poll_and_get_reply_profile));
+	memset (&decode_reply_profile, 0, sizeof(decode_reply_profile));
+	memset (&check_reply_profile, 0, sizeof(check_reply_profile));
+	memset (&add_create_object_profile, 0, sizeof(add_create_object_profile));
+
+	memset (&check_timeout_profile, 0, sizeof(check_timeout_profile));
+	memset (&adjust_play_window_profile, 0, sizeof(adjust_play_window_profile));
+}
+
+static char trace_file[256]="anon-lair62-011130-1200.txt";
+int print_memory_usage()
+{
+	printf("size of fh_map_t %d size of fh_map %d\n", sizeof(fh_map_t), sizeof(fh_map));
+	printf("sizeof dep_tab_t %d sizeof dep_tab %d\n", sizeof(dep_tab_t), sizeof(dep_tab));
+	printf("size of memory_trace_entry_t %d sizeof memory_trace %d\n", sizeof(memory_trace_entry_t), sizeof(memory_trace));
+	printf("size of CREATE3args %d\n", sizeof( CREATE3args));
+	printf("size of MKDIR3args %d\n", sizeof( MKDIR3args));
+	printf("size of READ3args %d\n", sizeof( READ3args));
+	printf("size of WRITE3args %d\n", sizeof( WRITE3args));
+	printf("size of RENAME3args %d\n", sizeof( RENAME3args));
+	printf("size of GETATTR3args %d\n", sizeof( GETATTR3args));
+	printf("size of SETATTR3args %d\n", sizeof( SETATTR3args));
+	printf("size of LINK3args %d\n", sizeof( LINK3args));
+	printf("size of SYMLINK3args %d\n", sizeof( SYMLINK3args));
+	printf("size of MKNOD3args %d\n", sizeof( MKNOD3args));
+	printf("size of RMDIR3args %d\n", sizeof( RMDIR3args));
+	printf("size of REMOVE3args %d\n", sizeof( REMOVE3args));
+	printf("size of LOOKUP3args %d\n", sizeof( LOOKUP3args));
+	printf("size of READDIR3args %d\n", sizeof( READDIR3args));
+	printf("size of READDIRPLUS3args %d\n", sizeof( READDIRPLUS3args));
+	printf("size of FSSTAT3args %d\n", sizeof( FSSTAT3args));
+	printf("size of FSINFO3args %d\n", sizeof( FSINFO3args));
+	printf("size of COMMIT3args %d\n", sizeof( COMMIT3args));
+	printf("size of ACCESS3args %d\n", sizeof( ACCESS3args));
+	printf("size of READLINK3args %d\n", sizeof( READLINK3args));
+
+
+}
+int main(int argc, char ** argv)
+{
+	extern char * optarg;
+	int i;
+	int memory_trace_size;
+
+	if (argc==2 && !strcmp(argv[1],"-help")) {
+		print_usage();
+		exit(0);
+	}
+	print_memory_usage();
+	check_clock();
+    getmyhostname(lad_hostname, HOSTNAME_LEN);
+
+    init_ops();
+	/*
+	 * Get the uid and gid information.
+	 */
+	Real_uid = getuid();
+	Cur_gid = getgid();
+	//Real_uid = 513;
+	//Cur_gid = 513;
+
+	Nfs_timers = Nfs_udp_timers;
+
+	init_file_system ();
+
+	init_signal();
+	init_play (argv[1]);
+	//init_play ("capella:/p5/RFSFS");
+	init_profile();
+	init_fh_map();
+	//read_fh_map (argv[3]);
+	read_fh_map ("fh-path-map-play");
+	init_dep_tab();			/* and  dep_tab_size */
+	//read_trace (argv[2]);
+	//read_trace ("anon-lair62-011130-1000.txt");
+	strcpy(trace_file, argv[2]);
+	read_trace (trace_file);
+	stage = READ_DEP_TAB_STAGE;
+	read_dep_tab();
+
+	for (i=0; i<dep_tab_size; i++) {
+		RFS_ASSERT (dep_tab[i].flag == DEP_FLAG_FREE) 
+		init_dep_tab_entry (i);
+	}
+	stage = TRACE_PLAY_STAGE;
+	init_time_offset();
+	printf ("trace_play\n");
+	trace_play ();
+	print_result();
+	printf("ffff\n");
+}
+
+void init_ops (void)
+{
+	Ops = nfsv3_Ops;
+	nfs_version = NFS_V3;
+}
+
+/* Set up the signal handlers for all signals */
+void init_signal()
+{
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	struct sigaction sig_act, old_sig_act;
+
+	/* use XOPEN signal handling */
+
+	sig_act.sa_handler = generic_catcher;
+	(void)sigemptyset(&sig_act.sa_mask);
+	sig_act.sa_flags = 0;
+
+	/* signals handlers for signals used by sfs */
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGINT,&sig_act,&old_sig_act) == -1) {
+	    perror("sigaction failed: SIGINT");
+	    exit(135);
+	}
+
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGTERM,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGTERM");
+	    exit(137);
+	}
+#else
+    /* signals handlers for signals used by sfs */
+    (void) signal(SIGINT, sfs_cleanup);
+    // RFS (void) signal(SIGALRM, sfs_alarm);
+	(void) signal(SIGTERM, sfs_cleanup);
+#endif
+}
+
+void
+init_play (
+    char	* mount_point)		/* Mount point for remote FS */
+{
+    char	namebuf[NFS_MAXNAMLEN] = "trace_play";	/* unique name for this program */
+    CLIENT *	mount_client_ptr;	/* Mount client handle */
+
+	if (!rfs_debug);
+    	(void) setvbuf(stderr, io_buf, _IOLBF, BUFSIZ);
+
+    sfs_Myname = namebuf;
+
+    /*
+     * May require root priv to perform bindresvport operation
+     */
+    mount_client_ptr = lad_getmnt_hand(mount_point);
+    if (mount_client_ptr == NULL) {
+		exit(145);
+    }
+
+    /*
+     * should be all done doing priv port stuff
+     */
+
+    if (init_rpc() == -1) {
+		(void) fprintf(stderr, "%s: rpc initialization failed\n", sfs_Myname);
+		(void) generic_kill(0, SIGINT);
+		exit(146);
+    }
+
+
+    /*
+     * finish all priv bindresvport calls
+     * reset uid
+     */
+    if (setuid(Real_uid) != (uid_t)0) {
+	(void) fprintf(stderr,"%s: %s%s", sfs_Myname,
+	    "cannot perform setuid operation.\n",
+	    "Do `make install` as root.\n");
+    }
+
+    init_mount_point(0, mount_point, mount_client_ptr);
+
+
+    /*
+     * Cleanup client handle for mount point
+     */
+    clnt_destroy(mount_client_ptr);
+
+	init_counters();
+	
+
+}
+
+void read_trace (char * tracefile)
+{
+	FILE * fp;
+	char buf[1024];
+	// char * t=buf;	
+	int disk_index=0;
+
+	fp = fopen(tracefile, "r");
+	RFS_ASSERT (fp!=NULL);
+	while (fgets(buf, 1024, fp)) {
+		//printf ("buf: %s buf[36] %c\n", buf, buf[36]);
+		//if (buf[36]=='C' || strstr(buf, "create") || strstr(buf, "lookup")) {
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]=='C' || strstr(buf, "create") || 
+			strstr(buf, "mkdir") || strstr(buf, "symlink") || strstr(buf, "mknod") || strstr(buf, "lookup")) {
+#endif
+			if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+				printf("strlen(buf) %d buf %s \n", strlen(buf), buf);
+			RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+
+			/* store the request to memory */
+			strcpy (memory_trace[memory_trace_size].line, buf);
+			memory_trace[memory_trace_size].disk_index = disk_index;
+			memory_trace_size ++;
+
+			if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+				fprintf (stderr, "memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+				break;
+			}
+			if ((disk_index%100000)==0)
+				fprintf(stderr, "%d disk trace parsed, store %d trace lines to memory\n", disk_index, memory_trace_size);
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+		} else {
+			RFS_ASSERT (buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+		}
+#endif
+		disk_index ++;
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines \n", disk_index, memory_trace_size );
+
+}
+
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+inline int disk_index_to_memory_index (int disk_index)
+{
+	static int memory_index = 0;
+	if (disk_index > memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index < disk_index) {
+			memory_index++;
+			RFS_ASSERT (memory_index < MAX_MEMORY_TRACE_LINES);
+		}
+	};
+	if (disk_index < memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index > disk_index) {
+			memory_index--;
+			RFS_ASSERT (memory_index >=0);
+		}
+	};
+
+	RFS_ASSERT (disk_index == memory_trace[memory_index].disk_index);
+	return memory_index;
+}
+#else
+#define disk_index_to_memory_index(disk_index)	disk_index
+#endif
+
+#define get_line_by_disk_index(disk_index) \
+	memory_trace[disk_index_to_memory_index(disk_index)].line
+
+inline char * find_reply_line (char * command_line, int cur_disk_index)
+{
+	int i;
+	char * line;
+	char * p;
+	int request_memory_index = disk_index_to_memory_index (cur_disk_index);
+	for (i=request_memory_index+1; i<request_memory_index+MAX_COMMAND_REPLY_DISTANCE && i<MAX_MEMORY_TRACE_LINES; i++) {
+		line = memory_trace[i].line;
+		if (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+	        p = strchr (&line[TRACE_MSGID_POS], ' ');
+    	    RFS_ASSERT (p);
+			if (!strncmp(&line[TRACE_MSGID_POS], &command_line[TRACE_MSGID_POS], p-&(line[TRACE_MSGID_POS]))) 
+				return line;
+		}
+	}
+	return NULL;
+}
+
+inline int find_reply_status (char * line)
+{
+	char * p;
+	int i=0;
+
+	//printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	p = line+TRACE_MSGID_POS+2;	/* at least one letter for msgid and one letter for space */
+	if (strstr(p, "OK"))
+		return NFS3_OK;
+	if (strstr(p, "lookup 2"))
+		return 0x2;
+	if (strstr(p, "create d"))
+		return 0xd;
+	if (strstr(p, "setattr 1"))
+		return 0x1;
+	if (strstr(p, "lookup d"))
+		return 0xd;
+	if (strstr(p, "read d"))
+		return 0xd;
+	if (strstr(p, "write d"))
+		return 0xd;
+	if (strstr(p, "mkdir d"))
+		return 0xd;
+	printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (0);
+}
+
+inline int find_reply_status_old (char * line)
+{
+	char * p;
+	int i=0;
+
+	//printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	if (!strstr(line, "OK")) {
+		p=strstr(line, " 6 read ");
+		if (p) {
+			p+=strlen(" 6 read ");
+		} else {
+			p = strstr (line, "status=XXX");
+			RFS_ASSERT (p);
+			p--;
+			RFS_ASSERT (*p==' ');
+			while (*p==' ')
+				p--;
+			while (*p!=' ') {
+				p--;
+			}
+			p++;
+		}
+		sscanf (p, "%x", &i);
+		if ((i<=0) || (i>10000))
+			printf("line %s\n", line);
+		RFS_ASSERT (i>0 && i<10009);
+	}
+	return i;
+}
+
+inline char * find_reply_trace_fh (char * line)
+{
+	char * p;	
+	p = strstr (line, "OK fh");
+	if (!p)
+		printf ("find_reply_trace_fh line %s\n", line);
+	RFS_ASSERT (p);
+	return p+6;
+}
+
+inline int disk_index_to_dep_index(int cur_dep_index, int disk_index)
+{
+	int i;
+	for (i=cur_dep_index; i>min_dep_index; i--) {
+		if (dep_tab[i].disk_index == disk_index)
+			return i;
+	} 
+	RFS_ASSERT (0);
+}
+
+inline int is_play_candidate (int dep_index)
+{
+	int proc = dep_tab[dep_index].proc;
+	int status = dep_tab[dep_index].status;
+	int trace_status = dep_tab[dep_index].trace_status;
+
+#ifndef TAKE_CARE_CREATE_MODE_BY_DAN
+	/* for a failed create in trace, trace_replay just ignore many time the trace create fail
+	 * due to access control, but trace_play will success because our access control
+	 * may be loose (all uid/gid is mapped to single one 513:513, so we just skip these requests 
+	 */
+	if ((proc==CREATE || proc==MKDIR) && (trace_status!=NFS3_OK) && (status!=NFS3ERR_RFS_MISS)) {
+		if (dependency_debug)
+			printf ("disk[%d] ignore failed create/mkdir in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		failed_create_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_OTHER_FAILED_COMMAND
+	if (((trace_status == NFS3ERR_ACCES) && (proc==READ || proc==WRITE || proc==LOOKUP)) || 
+	    ((trace_status == NFS3ERR_PERM) && (proc==SETATTR)) 									){
+		if (dependency_debug)
+			printf ("disk[%d] ignore other failed command in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		
+		failed_other_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+	if ((dep_tab[dep_index].proc==READLINK) ) { /* send request */
+		skipped_readlink_command_num ++;
+		return FALSE;
+	}
+#endif
+#define TAKE_CARE_CUSTOM_COMMAND
+/* This is actually take care in get_nextop by checking fh_map error when dep_index==min_dep_index */
+#ifndef TAKE_CARE_CUSTOM_COMMAND
+	/* this line has a file handle which should belong to discard but it is not
+	 * the file handle directly appears as parent directory in a lookup request
+	 * the return value is NOENT, the parent directory should have been initialized
+	 * but the initialization code just ignored all lookup request which didn't success
+	 * including NOENT even though the parent directory is still valid.
+	 */
+	if ((    ((dep_tab[dep_index].disk_index==262213) || (dep_tab[dep_index].disk_index==214402))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1100.txt")) 
+		) || 
+		(	 ((dep_tab[dep_index].disk_index==238460) || (dep_tab[dep_index].disk_index ==238470))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1000.txt"))
+		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_FSSTAT_COMMAND
+	/* the file handle used in this command is not processed properly by pre-processing */
+	if (proc==FSSTAT) {
+		char * trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+		fh_map_t * fh = lookup_fh (trace_fh);
+		if (!fh) {
+			skipped_fsstat_command_num++;
+			return FALSE;
+		}
+	}
+#endif
+	return TRUE;
+}
+
+inline int is_dir_op (int proc)
+{
+	switch (proc) {
+	case MKDIR:
+	case CREATE:
+	case LINK:
+	case SYMLINK:
+	case MKNOD:
+	case REMOVE:
+	case RMDIR:
+	case RENAME:
+		return 1;
+	default:
+		return 0;
+	}
+}	
+
+inline int is_create_op (int proc)
+{
+	if (proc==CREATE || proc==MKDIR || proc==LINK || proc==SYMLINK || proc==MKNOD || proc==RENAME)
+		return 1;
+	return 0;
+}
+
+inline int is_delete_op (int proc)
+{
+	if (proc==REMOVE || proc==RMDIR || proc==RENAME)
+		return 1;
+	return 0;
+}	
+
+static inline char * find_lead_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh");
+	RFS_ASSERT (p);
+	p+=3; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+inline char * find_another_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh2");
+	RFS_ASSERT (p);
+	p+=4; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+/* return the index of next request in dep_tab.
+ * Return -1 if there is no suitable request to send
+ */
+inline int get_nextop(void)
+{
+	int i,j, k;
+	int * t;
+	static int dep_index = -2;
+	char * line;
+	char * p;
+	static int min_wait_fhandle_dep_index = DEP_TAB_SIZE;
+	int proc;
+	int flag;
+
+	//if (dep_index < min_dep_index-1)
+	//	dep_index = min_dep_index-1;
+
+	dep_index = min_dep_index-1;
+	for (i=0; i<max_dep_index-min_dep_index; i++) {
+		dep_index ++;
+		if (dep_index == max_dep_index) {
+			dep_index = min_dep_index;
+		}
+	
+		proc = dep_tab[dep_index].proc;
+		flag = dep_tab[dep_index].flag;
+
+		if (dependency_debug)
+			printf ("get_nextop check dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+#ifdef NO_DEPENDENCY_TABLE
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT) {
+			if (is_play_candidate(dep_index)==TRUE) {
+				/* the trace_fh is the file handle for the operation directory, trace_fh_2 is other file handle
+				 * used in the request */
+				if (proc==LINK || proc==RENAME) {
+					dep_tab[dep_index].trace_fh = find_another_trace_fh (proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].trace_fh_2 = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = 0;
+				} else {
+					dep_tab[dep_index].trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = (fh_map_t *)1;
+				};
+				dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+#ifdef TIME_PLAY
+				dep_tab[dep_index].skip_sec = skip_sec;
+#endif
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_CANDIDATE\n", dep_tab[dep_index].disk_index);
+			} else {
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+				dep_tab[dep_index].flag = DEP_FLAG_DONE;
+				continue;
+			}
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE) ) {
+
+			if (!dep_tab[dep_index].fh)
+				dep_tab[dep_index].fh = lookup_fh (dep_tab[dep_index].trace_fh);
+			if (!dep_tab[dep_index].fh_2)
+				dep_tab[dep_index].fh_2 = lookup_fh (dep_tab[dep_index].trace_fh_2);
+
+			/* need to wait for file handle */
+			if ((!dep_tab[dep_index].fh) || (!dep_tab[dep_index].fh_2)) {
+				if (dependency_debug)
+					printf("disk[%d] can not lookup file handle\n", dep_tab[dep_index].disk_index);
+				if (dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) {
+					if (dependency_debug)
+						printf ("disk[%d] state DEP_FLAG_CANDIDATE to DEP_FLAG_WAIT_FHANDLE\n", dep_tab[dep_index].disk_index);
+					dep_tab[dep_index].flag = DEP_FLAG_WAIT_FHANDLE;
+					sfs_gettime (&dep_tab[dep_index].start);
+					if (dep_index < min_wait_fhandle_dep_index)
+						min_wait_fhandle_dep_index = dep_index;
+				} else {
+					struct ladtime tmp;
+					if (dep_index==min_dep_index) {
+						if (!profile_debug) 
+							printf ("fh_path_map error disk[%d] state DEP_FLAG_WAIT_FHANDLE to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+						fh_path_map_err_num ++;
+						dep_tab[dep_index].flag = DEP_FLAG_DONE;
+						continue;
+					}
+					sfs_gettime (&tmp);
+					SUBTIME (tmp, dep_tab[dep_index].start);
+#define DEPENDENCY_TIMEOUT 5
+#ifdef TIME_PLAY
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT + (skip_sec - dep_tab[dep_index].skip_sec));	
+#else
+					if (tmp.sec >= DEPENDENCY_TIMEOUT) {
+						printf("dep_tab[%d].flag %d disk_index %d line %s\n", dep_index,
+							dep_tab[dep_index].flag, dep_tab[dep_index].disk_index,
+							dep_tab[dep_index].line);
+					}
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT );	
+#endif
+				}
+				continue;
+			}
+
+			/* file handle ready, adjust_min_wait_fhandle_dep_index */
+			if ((dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE)) {
+				if (dep_index == min_wait_fhandle_dep_index) {
+					min_wait_fhandle_dep_index = dep_tab_size;
+					for (j=dep_index+1; j<max_dep_index; j++) {
+						if (dep_tab[j].flag ==DEP_FLAG_WAIT_FHANDLE) {
+							min_wait_fhandle_dep_index = j;
+							break;
+						}
+					}
+				}
+			}
+			if (dependency_debug)
+				printf("disk[%d] found file handle\n", dep_tab[dep_index].disk_index);
+			dep_tab[dep_index].flag = DEP_FLAG_FHANDLE_READY;
+
+			/* the normal file operation can be executed now */
+			if (!is_dir_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug)
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			if (dependency_debug)
+				printf("disk[%d] directory operation \n", dep_tab[dep_index].disk_index);
+			/* the directory operation need to lock the directory first */
+			if (dep_tab[dep_index].fh->lock) {
+				if (dependency_debug)
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DIRECTORY\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DIRECTORY;
+				continue;
+			}
+		}
+				
+		if ((dep_tab[dep_index].flag == DEP_FLAG_FHANDLE_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DIRECTORY)) {
+			int j = dep_tab[dep_index].fh - fh_map;
+			if (dependency_debug) {
+				printf ("dep_tab[%d].disk_index %d, fh_map[%d] lock=%d\n",dep_index, dep_tab[dep_index].disk_index, j, dep_tab[dep_index].fh->lock);
+				printf ("trace_fh %s path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+				printf ("trace_fh %s path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+			}
+			if ((dep_tab[dep_index].fh->lock) || ((proc==RENAME) && (dep_tab[dep_index].fh_2->lock)) ) {
+				if (dependency_debug) 
+					printf ("continue to wait for directory lock\n");
+				continue;
+			}
+			if (dependency_debug) 
+				printf ("dep_tab[%d] disk index %d LOCK fh_map[%d] \n", dep_index, dep_tab[dep_index].disk_index, j);
+			dep_tab[dep_index].fh->lock = 1;
+			if (proc==RENAME)
+				dep_tab[dep_index].fh_2->lock = 1;
+
+			/* the non-delete directory operation can proceed now */
+			if (!is_delete_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			/* the delete operation can proceed if nobody ahead is waiting for fhandle */
+			/* probably this condition is not strong enough */
+//			if ((min_wait_fhandle_dep_index<dep_index) ) {
+			if (dep_index!=min_dep_index) {
+				if (dependency_debug) 
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DELETE\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DELETE;
+				continue;
+			} 
+			dep_tab[dep_index].flag = DEP_FLAG_DIRECTORY_READY;
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_DIRECTORY_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DELETE)) {
+//			if (min_wait_fhandle_dep_index > dep_index) {
+			if (dep_index==min_dep_index) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+		}
+#else
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT){
+			for (j=0, t=&(dep_tab[dep_index].dep_ops[0]);
+				(j<dep_tab[dep_index].init_dep_num) && (dep_tab[dep_index].cur_dep_num>0); 
+				j++, t++) {
+				if (*t !=-1) {
+					if (dep_tab[disk_index_to_dep_index(dep_index, *t)].flag == DEP_FLAG_DONE) { 
+						/* The depended request has been finished */ 
+						*t = -1;
+						dep_tab[dep_index].cur_dep_num --;
+					}
+				} 
+			}
+
+			if (dep_tab[dep_index].cur_dep_num == 0) {
+				return dep_index;
+			}
+		}
+#endif
+	}
+
+	if (dependency_debug) 
+		printf ("get_nexop return -1\n");
+	return -1;
+}
+
+int check_timeout(void)
+{
+	static int biod_index = 0;
+	int i;
+	int dep_index;	/* index into dep_tab */
+	int proc;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime timeout;
+
+	sfs_gettime (&current);	
+
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (biod_reqp[biod_index].in_use==TRUE) {
+			timeout = biod_reqp[biod_index].timeout;
+			if ((current.sec>timeout.sec) ||
+				((current.sec==timeout.sec) && (current.usec>timeout.usec))) {
+
+				dep_index = biod_reqp[biod_index].dep_tab_index;
+				proc = dep_tab[dep_index].proc;
+				op_ptr = &Ops[proc];
+				op_ptr->results.timeout_calls++;
+				Ops[TOTAL].results.timeout_calls++;
+
+				finish_request (biod_index, dep_index, NFS3ERR_RFS_TIMEOUT);
+
+				if (is_create_op(proc)) {
+					dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+					printf ("resend dep_tab[%d], disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+				}
+				//RFS_ASSERT (!is_create_op(proc));
+
+				//printf ("timeout request: biod_reqp[%d].start %d:%d timeout %d:%d current %d:%d\n", biod_index, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, timeout.sec, timeout.usec, current.sec, current.usec);
+			}
+		}
+	}
+}
+
+/* Allocate a biod_req entry to send and receive request dep_tab[dep_index]
+ * build the cross reference between dep_tab entry and biod_req entry
+ */
+struct biod_req * get_biod_req(int dep_index) /* index into dep_tab */
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (!biod_reqp[biod_index].in_use) {
+			biod_reqp[biod_index].in_use = 1;
+			biod_reqp[biod_index].dep_tab_index = dep_index;
+			dep_tab[dep_index].biod_req_index = biod_index;
+			return &(biod_reqp[biod_index]);
+		}
+	}
+	return NULL;
+}
+
+/* Return index into biod_reqp
+ * return -1 upon failure 
+ */
+int lookup_biod_req (int xid)
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		/* give a NULL as timeout pointer may cause indefinitely block */
+		if (biod_reqp[biod_index].xid == xid) {
+			return biod_index;
+		}
+	}
+	return -1;
+}
+
+extern struct ladtime test_start;
+void init_time_offset(void)
+{
+	struct ladtime tmp1;
+	struct ladtime tmp2;
+
+	test_start.sec = 0;
+	test_start.usec = 0;
+	sfs_gettime (&tmp1);		/* called at initial time: tmp1 = play_starttime */
+#ifdef SPEED_UP
+	DIVTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime / SCALE */
+#endif
+#ifdef SLOW_DOWN
+	MULTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime * SCALE */
+#endif
+
+	tmp2 = trace_starttime; /* tmp2 = trace_starttime */
+	SUBTIME (tmp2, tmp1);	/* tmp2 = trace_starttime - play_starttime *|/ SCALE */
+	time_offset = tmp2;		/* time_offset = trace_starttime - play_starttime *|/ SCALE */ 
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void init_dep_tab_entry (int dep_index)
+{
+	static int nfs2proc_to_rfsproc[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
+															10, 11, 12, 13, 14, 15, 16, 17};
+	static int nfs3proc_to_rfsproc[NFS3_PROCEDURE_COUNT] = {0, 1, 2, 4, 18, 5, 6, 8, 9, 14, 
+															13, 21, 10, 15, 11, 12, 16, 23, 17, 20, 
+															22, 19};
+	char * line;
+	int version;
+	int nfsproc;
+	int msgid;
+
+	//line = get_line_by_disk_index (dep_tab[dep_index].disk_index);
+	line = dep_tab[dep_index].line;
+	sscanf (line, "%d.%d", &(dep_tab[dep_index].timestamp.tv_sec), &(dep_tab[dep_index].timestamp.tv_usec));
+	sscanf (&line[39], "%x %x", &msgid, &nfsproc);
+	if (line[TRACE_VERSION_POS]=='2') {
+		dep_tab[dep_index].proc = nfs2proc_to_rfsproc[nfsproc];
+		RFS_ASSERT (nfsproc <18);
+	} else {
+		/* This is for debug purpose */
+		if (line[TRACE_VERSION_POS] !='3') {
+			fprintf(stderr, "line[TRACE_VERSION_POS] %c line %s\n", line[TRACE_VERSION_POS], line);
+			line = get_line_by_disk_index (dep_tab[dep_index].disk_index-1);
+			if (!line)
+				line = get_line_by_disk_index (dep_tab[dep_index].disk_index-2);
+			RFS_ASSERT (line);
+			fprintf(stderr, "previousline %s\n", line);
+		}
+		RFS_ASSERT (line[TRACE_VERSION_POS] =='3');
+		if (nfsproc >= NFS3_PROCEDURE_COUNT) {
+			fprintf(stderr, "proc %d line %s\n", nfsproc, line);
+			
+		}
+		RFS_ASSERT (nfsproc <NFS3_PROCEDURE_COUNT);
+		dep_tab[dep_index].proc = nfs3proc_to_rfsproc[nfsproc];
+	}
+	RFS_ASSERT (dep_tab[dep_index].proc >= 0 && dep_tab[dep_index].proc < NOPS);
+	dep_tab[dep_index].flag = DEP_FLAG_INIT;
+	dep_tab[dep_index].reply_line = find_reply_line (line, dep_tab[dep_index].disk_index);
+	if (dep_tab[dep_index].reply_line == NULL) {
+		//printf ("disk[%d] can not find the reply line, assume trace_status OK\n", dep_tab[dep_index].disk_index);
+		dep_tab[dep_index].trace_status = NFS3ERR_RFS_MISS;
+		missing_reply_num ++;
+	} else 
+		dep_tab[dep_index].trace_status = find_reply_status (dep_tab[dep_index].reply_line);
+}
+
+static void adjust_play_window (int flag, int * poll_timeout)
+{
+	struct ladtime max_window_time;
+	static struct ladtime max_poll_time = {0, 2000, 0};
+	struct ladtime t;
+	int old_min = min_dep_index;
+	int old_max = max_dep_index;
+	int i;
+	char * line;
+
+	for (; (dep_tab[min_dep_index].flag == DEP_FLAG_DONE) && (min_dep_index<dep_tab_size); min_dep_index++)
+		;
+	RFS_ASSERT (min_dep_index <= max_dep_index);
+
+	/* max_trace_window_time = current *|/ SCALE + trace_starttime */
+	sfs_gettime (&current);
+
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+	MULTIME (current, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+	DIVTIME (current, PLAY_SCALE);
+#endif
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+
+	while ((max_dep_index<min_dep_index+MAX_PLAY_WINDOW) && (max_dep_index<dep_tab_size))
+	{
+		t.sec = dep_tab[max_dep_index].timestamp.tv_sec;
+		t.usec = dep_tab[max_dep_index].timestamp.tv_usec;
+
+		if (adjust_play_window_debug)
+			printf ("max_window_time sec %d usec %d : max_dep_index %d, t.sec %d t.usec %d\n", max_window_time.sec, max_window_time.usec,  max_dep_index, t.sec, t.usec );
+
+		if ((t.sec>max_window_time.sec)||(t.sec==max_window_time.sec && t.usec>max_window_time.usec))
+			break;
+		
+		max_dep_index++;
+	}
+
+	/* Right now it is not clear how to deal with the situation where MAX_PLAY_WINDOW is reached */
+	if (max_dep_index == min_dep_index+MAX_PLAY_WINDOW) {
+		//printf ("can not catch up the speed, max_dep_index %d reach min_dep_index %d+MAX_PLAY_WINDOW\n", max_dep_index, min_dep_index);
+		//printf (".");
+		can_not_catch_speed_num ++;
+	}
+	//RFS_ASSERT (max_dep_index < min_dep_index+MAX_PLAY_WINDOW);
+#else
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+	max_dep_index = min_dep_index + MAX_PLAY_WINDOW;
+	if (max_dep_index >dep_tab_size)
+		max_dep_index = dep_tab_size;
+#endif
+
+	if (flag == BUSY)
+		*poll_timeout = 0;
+   	else if (max_dep_index == dep_tab_size) {
+		*poll_timeout = 1000000;	/* poll_timeout set to 1 second for the last request */
+	} else {
+#ifdef TIME_PLAY
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[max_dep_index].timestamp.tv_sec;
+		tmp.usec = dep_tab[max_dep_index].timestamp.tv_usec;
+		if (adjust_play_window_debug)
+			printf ("dep_tab[max_dep_index %d].timestamp %d:%d, max_window_time %d:%d\n",
+				max_dep_index, tmp.sec, tmp.usec, max_window_time.sec, max_window_time.usec);
+
+		SUBTIME (tmp, max_window_time);
+#ifdef SPEED_UP
+		DIVTIME (tmp, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+		MULTIME (tmp, PLAY_SCALE);
+#endif
+		tmp1 = tmp;
+
+		if (tmp.sec > max_poll_time.sec) {
+
+			if (rfs_debug) 
+				printf ("dep_tab[%d].timestamp %d:%d, max_window_time %d:%d\n",
+				max_dep_index, dep_tab[max_dep_index].timestamp.tv_sec, dep_tab[max_dep_index].timestamp.tv_usec, max_window_time.sec, max_window_time.usec);
+			printf ("skip %d seconds\n", tmp.sec-max_poll_time.sec);
+			SUBTIME (tmp, max_poll_time);
+			tmp.usec = 0;
+			skip_sec += tmp.sec;
+			SUBTIME (test_start, tmp);
+			tmp = max_poll_time;
+		}
+
+		RFS_ASSERT ((tmp.sec < 1000));
+		if ((tmp.sec ==0) && (tmp.usec==0)) {
+			*poll_timeout = 0;
+		} else
+			*poll_timeout = tmp.sec*1000000+tmp.usec;
+#else 
+		/*
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[max_dep_index].timestamp.tv_sec;
+		tmp.usec = dep_tab[max_dep_index].timestamp.tv_usec;
+		tmp1.sec = dep_tab[max_dep_index-1].timestamp.tv_sec;
+		tmp1.usec = dep_tab[max_dep_index-1].timestamp.tv_usec;
+		SUBTIME (tmp, tmp1);
+		RFS_ASSERT ((tmp.sec < 1000));
+		RFS_ASSERT ((tmp.sec>0) || ((tmp.sec==0) && (tmp.usec>0)));
+		*poll_timeout = tmp.sec*1000000+tmp.usec;
+		*/
+
+		*poll_timeout = 100000;
+#endif
+	}	
+	if (rfs_debug)
+		printf ("adjust_play_window: flag %d min %d -> %d, max %d -> %d poll_timeout %d \n", flag, old_min, min_dep_index, old_max, max_dep_index, *poll_timeout);
+}
+
+/* poll for usecs and receive, after receive one reply,
+ * return index in biod_reqp of the corresponding request
+ */
+int poll_and_get_reply (int usecs)
+{
+	int biod_index = -1;
+	int xid;
+	int error;
+	struct timeval zero_time = {0, 0}; /* Immediately return */
+
+	do {
+		error = biod_poll_wait (NFS_client, usecs);
+		switch (error) {
+		case -1:
+			if (errno == EINTR) {
+				error = 1;
+				continue;
+			}
+			if (rfs_debug) {
+				(void) fprintf(stderr, "biod_poll_wait error\n");
+				perror ("");
+			    (void) fflush(stderr);
+			}
+			break;
+		case 0:
+			break;
+		default:
+#ifdef UDP
+			error = get_areply_udp (NFS_client, &xid, &zero_time);
+			// RFS_ASSERT (error!= RPC_TIMEOUT);	/* we have polled and know there is data */
+			// RFS_ASSERT (error!= RPC_CANTRECV);
+			RFS_ASSERT (error == RPC_SUCCESS);
+
+			biod_index = lookup_biod_req (xid);
+			sfs_gettime (&(biod_reqp[biod_index].stop));
+#else
+			RFS_ASSERT (0);
+#endif
+		}
+	} while (0);
+	return biod_index;
+}
+
+void print_result(void)
+{
+	int i, j;
+	struct ladtime t;
+	int dep_index;
+	int avg_msecs;
+	unsigned long long tmp;
+	int avg_usecs;
+
+    if (DEBUG_CHILD_GENERAL) {
+		(void) fprintf(stdout, "trace play result:\n");
+		(void) fprintf(stdout, "\t    percentage good_cnt bad_cnt timeout_cnt\telapsed time\t\t\taverage time\n");
+		for (i=0; i<NOPS+1; i++) {
+			if (Ops[i].results.good_calls==0) {
+				avg_msecs = 0;
+				avg_usecs = 0;
+			} else {
+				tmp = Ops[i].results.time.sec*1000000 + Ops[i].results.time.usec;
+				avg_msecs = 0;
+				avg_usecs = tmp/Ops[i].results.good_calls;
+/*
+				avg_msecs = (Ops[i].results.time.sec*1000 + Ops[i].results.time.usec/1000)/Ops[i].results.good_calls;
+				avg_usecs = (Ops[i].results.time.usec%1000)/Ops[i].results.good_calls;
+*/
+			}
+			(void) fprintf(stdout,	"%11s\t%4.1f\t%4d\t%4d\t%4d\t\tsec %8d usec %8d \tusec %8d\n", 
+				Ops[i].name, 
+				(float)(100*Ops[i].results.good_calls)/(float)Ops[TOTAL].results.good_calls, 
+				Ops[i].results.good_calls, Ops[i].results.bad_calls, Ops[i].results.timeout_calls,
+				Ops[i].results.time.sec, Ops[i].results.time.usec, avg_msecs*1000+avg_usecs);
+		}
+		(void) fflush (stdout);
+    }
+
+	RFS_ASSERT (read_data_owe_GB==0);
+	printf("read_data_bytes %d owe %d GB and %d bytes, %d percent, adjusted %d times \n",read_data_total, read_data_owe_GB, read_data_owe, (read_data_owe_GB*1073741824+read_data_owe)/(read_data_total/100), read_data_adjust_times);
+	printf("write_data_bytes %d owe %d GB and %d bytes, %d percent, adjusted %d times \n",write_data_total, write_data_owe_GB, write_data_owe, (write_data_owe_GB*1073741824+write_data_owe)/(write_data_total/100), write_data_adjust_times);
+	printf("poll_timeout_0_num %d poll_timeout_pos_num %d\n", poll_timeout_0_num, poll_timeout_pos_num);
+	printf("failed_create_command_num %d\nfailed_other_command_num %d\nskipped_readlink_command_num %d\nskipped_custom_command_num %d\nfh_path_map_err_num %d\nskipped_fsstat_command_num %d\nmissing_reply_num %d\nrename_rmdir_noent_reply_num %d\nrmdir_not_empty_reply_num %d\nloose_access_control_reply_num %d\nlookup_err_due_to_rename %d\nlookup_eaccess_enoent_mismatch %d\nread_io_err_num %d\nproper_reply_num %d\n", 
+			failed_create_command_num,
+			failed_other_command_num,
+			skipped_readlink_command_num, 
+			skipped_custom_command_num,
+			fh_path_map_err_num, 
+			skipped_fsstat_command_num, 
+			missing_reply_num, 
+			rename_rmdir_noent_reply_num, 
+			rmdir_not_empty_reply_num, 
+			loose_access_control_reply_num, 
+			lookup_err_due_to_rename_num, 
+			lookup_eaccess_enoent_mismatch_num, 
+			read_io_err_num, 
+			proper_reply_num);
+
+    clnt_destroy(NFS_client);
+    biod_term();
+
+//   print_dump(Client_num, Child_num);
+	return;
+	dep_index = 0;
+	printf ("[%4d] %s \tstart %4d:%6d \n",
+		dep_index, Ops[dep_tab[dep_index].proc].name, dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec);
+	for (i=1; i<dep_tab_size*2; i++) {
+		dep_index = event_order[i];
+		if (dep_index >0) 
+			printf ("[%4d] %s \tstart %4d:%6d \n",
+				dep_index, Ops[dep_tab[dep_index].proc].name, dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec);
+		else {
+			dep_index = -dep_index;
+			t=dep_tab[dep_index].stop;
+			SUBTIME (t, dep_tab[dep_index].start);
+			printf ("\t\t\t\t\t[%4d] %s stop %4d:%6d\tinterval %4d:%6d %s\n",
+				dep_index, Ops[dep_tab[dep_index].proc].name, dep_tab[dep_index].stop.sec, dep_tab[dep_index].stop.usec, t.sec, t.usec, nfs3_strerror(dep_tab[dep_index].status));
+		}	
+	}
+/*
+	
+	for (i=0, j=0; i<dep_tab_size || j<dep_tab_size; ) {
+		if ((i==dep_tab_size) || 
+			(LARGERTIME(dep_tab[i].start, dep_tab[j].stop) && j<dep_tab_size)) {
+			t=dep_tab[j].stop;
+			SUBTIME (t, dep_tab[j].start);
+			printf ("dep_tab[%d].proc %s                  stop %d:%d interval %d:%d status %s\n",
+				j, Ops[dep_tab[j].proc].name, dep_tab[j].stop.sec, dep_tab[j].stop.usec, t.sec, t.usec, nfs3_strerror(dep_tab[j].status));
+			j++;
+		} else {
+			printf ("dep_tab[%d].proc %s start %d:%d \n",
+				i, Ops[dep_tab[i].proc].name, dep_tab[i].start.sec, dep_tab[i].start.usec);
+			i++;
+		}
+	}
+*/
+} 
+
+/*
+ * allocate and initialize client handles
+ */
+static int
+init_rpc(void)
+{
+	int dummy = 0;
+
+    /*
+     * Set up the client handles.  We get them all before trying one
+     * out to insure that the client handle for LOOKUP class is allocated
+     * before calling op_getattr().
+     */
+    if (DEBUG_CHILD_GENERAL) {
+    	(void) fprintf(stderr, "%s: set up client handle\n", sfs_Myname);
+    }
+
+    NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+					(uint32_t) NFS_PROGRAM,
+					(uint32_t) nfs_version,
+					RPC_ANYSOCK, &Nfs_timers[0]);
+		
+    if (NFS_client  == ((CLIENT *) NULL)) {
+        return(-1);
+    }
+
+    /*
+     * create credentials using the REAL uid
+     */
+    NFS_client->cl_auth = authunix_create(lad_hostname, (int)Real_uid,
+				      (int)Cur_gid, 0, NULL);
+
+
+	if (biod_init(dummy, dummy) == -1) {
+		    return(-1);
+	}
+
+    return(0);
+} /* init_rpc */
+
+void
+init_counters(void)
+{
+    uint_t i;
+    uint_t start_msec;
+
+    /* Ready to go - initialize operation counters */
+    for (i = 0; i < NOPS + 1; i++) {
+	Ops[i].req_cnt = 0;
+	Ops[i].results.good_calls = 0;
+	Ops[i].results.bad_calls = 0;
+	Ops[i].results.timeout_calls = 0;	// RFS
+	Ops[i].results.fast_calls = 0;
+	Ops[i].results.time.sec = 0;
+	Ops[i].results.time.usec = 0;
+	Ops[i].results.msec2 = 0;
+    }
+
+    /* initialize timers and period variables */
+    sfs_gettime(&Starttime);
+    Cur_time = Starttime;
+    start_msec = (Starttime.sec * 1000) + (Starttime.usec / 1000);
+    Previous_chkpnt_msec = start_msec;
+    Calls_this_period = 0;
+    Reqs_this_period = 0;
+    Sleep_msec_this_period = 0;
+    Calls_this_test = 0;
+    Reqs_this_test = 0;
+    Sleep_msec_this_test = 0;
+}
+
+static char *
+nfs3_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS3_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFS3ERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFS3ERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFS3ERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFS3ERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFS3ERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFS3ERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFS3ERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFS3ERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFS3ERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFS3ERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFS3ERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFS3ERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFS3ERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFS3ERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFS3ERR_MLINK:
+	    (void) strcpy(str, "Too many links");
+	    break;
+	case NFS3ERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFS3ERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFS3ERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFS3ERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFS3ERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFS3ERR_BADHANDLE:
+	    (void) strcpy(str, "Bad file handle");
+	    break;
+	case NFS3ERR_NOT_SYNC:
+	    (void) strcpy(str, "Not sync write");
+	    break;
+	case NFS3ERR_BAD_COOKIE:
+	    (void) strcpy(str, "Bad cookie");
+	    break;
+	case NFS3ERR_NOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFS3ERR_TOOSMALL:
+	    (void) strcpy(str, "Value too small");
+	    break;
+	case NFS3ERR_SERVERFAULT:
+	    (void) strcpy(str, "Server fault");
+	    break;
+	case NFS3ERR_BADTYPE:
+	    (void) strcpy(str, "Bad type");
+	    break;
+	case NFS3ERR_JUKEBOX:
+	    (void) strcpy(str, "Jukebox");
+	    break;
+	case NFS3ERR_RFS_TIMEOUT:
+		(void) strcpy(str, "Timeout");
+		break;
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+
+/*
+ * Check the gettimeofday() resolution. If the resolution
+ * is in chunks bigger than SFS_MIN_RES then the client
+ * does not have a usable resolution for running the 
+ * benchmark.
+ */
+static void
+check_clock(void)
+{
+	double time_res;
+	char tmp_hostname[HOSTNAME_LEN];
+
+	time_res = get_resolution();
+    	getmyhostname(tmp_hostname, HOSTNAME_LEN);
+	if( time_res > (double)SFS_MIN_RES )
+	{
+		(void) fprintf(stderr,
+		"\n%s: Clock resolution too poor to obtain valid results.\n",
+			tmp_hostname);
+		(void) fprintf(stderr,
+		"%s: Clock resolution %f Micro seconds.\n", tmp_hostname,
+			time_res);
+		exit(175);
+	}
+	else
+	{
+		(void) fprintf(stderr,
+		"\n%s: Good clock resolution [ %f ] Micro seconds.\n", 
+			tmp_hostname, time_res);
+	}
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns the resolution of the gettimeofday() function 
+ * in microseconds.
+ */
+static double
+get_resolution(void)
+{
+        double starttime, finishtime, besttime;
+        long  j,delay;
+	int k;
+
+        finishtime=time_so_far1(); /* Warm up the instruction cache */
+        starttime=time_so_far1();  /* Warm up the instruction cache */
+        delay=j=0;                 /* Warm up the data cache */
+	for(k=0;k<10;k++)
+	{
+	        while(1)
+       	 	{
+       	         	starttime=time_so_far1();
+       	         	for(j=0;j< delay;j++)
+       	                ;
+       	         	finishtime=time_so_far1();
+       	         	if(starttime==finishtime)
+       	                 	delay++;
+       	         	else
+			{
+				if(k==0)
+					besttime=(finishtime-starttime);
+				if((finishtime-starttime) < besttime)
+					besttime=(finishtime-starttime);
+                       	 	break;
+			}
+		}
+        }
+         return(besttime);
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns current result of gettimeofday() in microseconds.
+ */
+/************************************************************************/
+/* Time measurement routines.                                           */
+/* Return time in microseconds                                          */
+/************************************************************************/
+
+static double
+time_so_far1(void)
+{
+        /* For Windows the time_of_day() is useless. It increments in 55 */
+	/* milli second increments. By using the Win32api one can get */
+	/* access to the high performance measurement interfaces. */
+	/* With this one can get back into the 8 to 9 microsecond */
+	/* resolution.  */
+#ifdef Windows
+        LARGE_INTEGER freq,counter;
+        double wintime;
+        double bigcounter;
+
+        QueryPerformanceFrequency(&freq);
+        QueryPerformanceCounter(&counter);
+        bigcounter=(double)counter.HighPart *(double)0xffffffff +
+                (double)counter.LowPart;
+        wintime = (double)(bigcounter/(double)freq.LowPart);
+        return((double)wintime*1000000.0);
+#else
+#if defined (OSFV4) || defined(OSFV3) || defined(OSFV5)
+  struct timespec gp;
+
+  if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1)
+    perror("getclock");
+  return (( (double) (gp.tv_sec)*1000000.0) +
+    ( ((float)(gp.tv_nsec)) * 0.001 ));
+#else
+  struct timeval tp;
+
+  if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
+    perror("gettimeofday");
+  return ((double) (tp.tv_sec)*1000000.0) +
+    (((double) tp.tv_usec) );
+#endif
+#endif
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "trace play usage");
+}
+extern void init_file_system (void)
+{
+	return;
+}
+
+extern void init_dep_tab (void)
+{
+	int i;
+	memset (&dep_tab, 0, sizeof(dep_tab));
+#ifdef notdef
+	dep_tab[0].disk_index = 0;
+	dep_tab[1].disk_index = 2;
+	dep_tab[2].disk_index = 3;
+	dep_tab[3].disk_index = 5;
+	dep_tab[4].disk_index = 7;
+	dep_tab[5].disk_index = 9;
+	dep_tab[6].disk_index = 11;
+	dep_tab[7].disk_index = 12;
+	dep_tab[8].disk_index = 15;
+	dep_tab[9].disk_index = 17;
+	dep_tab[10].disk_index = 18;
+	dep_tab[11].disk_index = 20;
+	dep_tab_size = 12;
+	//dep_tab_size = 2;
+#endif
+}
+
+extern void init_dep_tab_old (void)
+{
+	int i;
+
+	Cur_file_ptr = &Export_dir;
+	Cur_uid = Real_uid;
+
+	for (i=0; i<5; i++) {
+		dep_tab[i].flag = DEP_FLAG_INIT;
+		dep_tab[i].proc = CREATE;
+		dep_tab[i].timestamp.tv_sec = trace_starttime.sec;
+	    dep_tab[i].timestamp.tv_usec = trace_starttime.usec+i*10;	
+		dep_tab[i].init_dep_num = 0;
+		dep_tab[i].cur_dep_num = 0;
+	}
+
+	for (i=5; i<10; i++) {
+		dep_tab[i].flag = DEP_FLAG_INIT;
+		dep_tab[i].proc = CREATE;
+		dep_tab[i].timestamp.tv_sec = trace_starttime.sec+i;
+	    dep_tab[i].timestamp.tv_usec = trace_starttime.usec;	
+		dep_tab[i].init_dep_num = 0;
+		dep_tab[i].cur_dep_num = 0;
+	}
+
+	dep_tab[2].init_dep_num = 2;
+	dep_tab[2].cur_dep_num = 2;
+	dep_tab[2].dep_ops[0] = 0;
+	dep_tab[2].dep_ops[1] = 1;
+
+	// printf ("trace_starttime (%d %d)\n", trace_starttime.sec, trace_starttime.usec);
+
+	/*
+	for (i=2; i<4; i++) {
+		dep_tab[i].flag = DEP_FLAG_INIT;
+		dep_tab[i].proc = CREATE;
+		dep_tab[i].timestamp.tv_sec = trace_starttime.sec+i*10;
+	    dep_tab[i].timestamp.tv_usec = trace_starttime.usec;	
+		dep_tab[i].init_dep_num = 0;
+		dep_tab[i].cur_dep_num = 0;
+	}
+	*/
+
+	dep_tab_size = 10;
+
+	for (i=0; i<dep_tab_size; i++)
+	{
+		printf("dep_tab[%d].timestamp (%d %d)\n", i, dep_tab[i].timestamp.tv_sec, dep_tab[i].timestamp.tv_usec);
+	}
+}
+
+void show_fhandle (nfs_fh3 * fhp)
+{
+	struct knfs_fh * kfhp = (struct knfs_fh *)fhp;
+
+	int dev;
+
+	if (quiet_flag)
+		return;
+		
+	RFS_ASSERT (kfhp->fh_version == 1);
+	RFS_ASSERT (kfhp->fh_fsid_type == 0);
+	RFS_ASSERT (kfhp->fh_auth_type == 0);
+
+	dev = ntohs(kfhp->fh_dev_major);
+	dev = dev<<8;
+	dev = dev + ntohs(kfhp->fh_dev_minor);
+
+	/* kfhp->fh_dev_ino hold the inode number of export point of the mounted
+	 * file system. For example, if /tmp/t1 is exported, /tmp/t1/t2 is mounted,
+	 * then fh_dev_ino hold the inode number of t1, not t2
+	 */
+
+	switch (kfhp->fh_fileid_type) {
+		case 0:
+			printf("fh:type 0 root dev 0x%x dev_ino %d\n", dev, kfhp->fh_dev_ino); 
+			break;
+		case 1:
+			printf("fh:type 1 %d %x dev %x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, dev, kfhp->fh_dev_ino);
+			break;
+		case 2:
+			printf("fh:type2 %d %x dirino %d dev 0x%x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, kfhp->fh_dirino, dev, kfhp->fh_dev_ino);
+			break;
+		default:
+			RFS_ASSERT (0);
+	}
+}
+
+nfs_fh3 zero_fhandle;
+int init_fh_map ()
+{
+	memset (fh_map, 0, sizeof (fh_map));
+	memset(fh_htable, 0, sizeof (fh_htable));
+	memset (&zero_fhandle, 0, sizeof(nfs_fh3));
+	printf ("SIZE of fh map %d KB\n", sizeof (fh_map)/1000);
+	fh_i = 0;
+}
+
+int add_fh (int map_flag, char * trace_fh, char * path, nfs_fh3 * play_fh)
+{
+	char * old_trace_fh;
+
+	/* first lookup if the entry for fh is already in the table */
+    struct generic_entry * p;
+
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (p) {
+		RFS_ASSERT (fh_map[p->key3].flag = FH_MAP_FLAG_PARTIAL);
+		RFS_ASSERT (map_flag ==FH_MAP_FLAG_COMPLETE);
+		fh_map[p->key3].flag = map_flag;
+		//RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+		if (memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE)) {
+			int i;
+			printf ("fh_map[%d].trace_fh %s trace_fh %s", p->key3, fh_map[p->key3].trace_fh, trace_fh);
+			for (i=0; i<fh_i; i++) {
+				int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+				int * p = (int *)fh_map[i].trace_fh;
+				printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+				printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, fh_map[i].trace_fh, fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+			}
+#endif
+			RFS_ASSERT (0);
+		}
+		RFS_ASSERT (!strcmp(fh_map[p->key3].path, path));
+		/* It's possible that in fh-path-map, many trace_fh are corresponding to one path
+		 * some of it may be the result of lookup after symlink, which is not handled
+		 * properly as new created objects 
+		 */
+#ifdef TAKE_CARE_SYMBOLIC_LINK
+		RFS_ASSERT (!memcmp(&fh_map[p->key3].play_fh, &zero_fhandle, sizeof(nfs_fh3)));
+#endif
+		memcpy (&fh_map[p->key3].play_fh, play_fh, sizeof (nfs_fh3));
+		if ((fh_map_debug==1)) // || (stage ==TRACE_PLAY_STAGE)) 
+			printf ("update the play_fh for trace_fh %s path %s \n", trace_fh, path);
+		return 0;
+	}
+
+	fh_map[fh_i].flag = map_flag;
+	fh_map[fh_i].lock = 0;
+	strncpy(fh_map[fh_i].trace_fh, trace_fh, TRACE_FH_SIZE);
+
+	RFS_ASSERT (strlen(path) < MAX_PLAY_PATH_SIZE);
+	strcpy (fh_map [fh_i].path, path);
+	if (map_flag==FH_MAP_FLAG_COMPLETE)
+		memcpy (&fh_map[fh_i].play_fh, play_fh, sizeof(nfs_fh3));
+	else 
+		memset (&fh_map[fh_i].play_fh, 0, sizeof(nfs_fh3));
+
+	if ((fh_map_debug==1)) { // || (stage ==TRACE_PLAY_STAGE)) {
+		printf ("insert trace_fh %s path %s play_fh:\n", trace_fh, path);
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			//show_fhandle(play_fh);
+		} else 
+			printf("null\n");
+	}
+
+/*
+	if (map_flag == FH_MAP_FLAG_DISCARD)
+		printf ("insert flag %d trace_fh %s path %s play_fh:\n", map_flag, trace_fh, path);
+*/
+
+    generic_insert(trace_fh, TRACE_FH_SIZE, fh_i, fh_htable, FH_HTABLE_SIZE);
+	
+	fh_i = (fh_i+1);
+	RFS_ASSERT (fh_i < FH_MAP_SIZE);
+
+    return 0;
+};
+
+inline fh_map_t * lookup_fh (char * trace_fh )
+{
+    struct generic_entry * p;
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (fh_map_debug==1)
+		printf ("lookup trace_fh %s\n", trace_fh);
+
+    if (p) {
+		if (fh_map_debug==1) {
+			printf ("found: fh_i[%d] trace_fh %s path %s play_fh:\n", p->key3, fh_map[p->key3].trace_fh, fh_map[p->key3].path);
+			//show_fhandle(&fh_map[p->key3].play_fh);
+		}
+		RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+        return (&(fh_map[p->key3]));
+    } else {
+		//printf ("lookup_fh %s not found\n", trace_fh);
+		if (stage != READ_DEP_TAB_STAGE && (fh_map_debug==1)) {
+			printf ("lookup not found trace_fh %s\n", trace_fh);
+		}
+        return NULL;
+	}
+	RFS_ASSERT (0);
+}
+
+int delete_fh (char * trace_fh, int fh_map_index)
+{
+    generic_delete (trace_fh, TRACE_FH_SIZE, fh_map_index, fh_htable, FH_HTABLE_SIZE);
+    return 0;
+};
+
+void lookup_init_filesystem (nfs_fh3 * parent, char * name, nfs_fh3 * result)
+{
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+	static int i=0;
+
+    /* set up the arguments */
+    (void) memcpy((char *) &args.what.dir, (char *) parent,
+							sizeof (nfs_fh3));
+    args.what.name = name;
+    (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			Nfs_timers[Init]);
+    sfs_gettime(&stop);
+
+	if (rpc_stat !=RPC_SUCCESS) {
+		printf("rpc_stat %d\n", rpc_stat);
+		perror("");
+	}
+    RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+	RFS_ASSERT (reply.status == NFS3_OK);
+	(void) memcpy((char *) result, (char *) &reply.resok.object, sizeof (nfs_fh3));
+}
+
+void read_fh_map(char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	char trace_fh[TRACE_FH_SIZE];
+	char intbuf[9];
+	char * trace_path;
+	char * p;
+	int map_flag;
+#define MAX_PATH_DEPTH 20
+	nfs_fh3 parents[MAX_PATH_DEPTH];
+	char * lookup_path_ptr[MAX_PATH_DEPTH];
+	char lookup_path [MAX_PLAY_PATH_SIZE];
+	int depth;
+	int new_dir_flag = 0;
+
+	depth = 0;
+	memset(lookup_path_ptr, 0, sizeof(lookup_path_ptr));
+	memcpy(&parents[depth], &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+	strcpy(lookup_path, "/");
+	lookup_path_ptr[depth]=&lookup_path[0];
+
+	fp = fopen(fh_map_file, "r");
+	RFS_ASSERT (fp!=NULL);
+	
+	intbuf[8]=0;
+
+	memset(buf, 0, sizeof(buf));
+	while (fgets(buf, 1024, fp)) {
+
+		if (fh_i % 10000==0)
+			printf("%d fh_map entry read\n", fh_i);
+
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf[strlen(buf)-1]=0;
+		if (fh_map_debug) {
+			printf("%d fgets return %s\n", fh_i, buf);
+			printf("depth %d lookup_path %s\n", depth, lookup_path);
+		}
+		//for (i=0; i<=depth; i++) 
+			//printf("lookup_path_ptr[%d] %s ", i, lookup_path_ptr[i]);
+		//printf("\n");
+#ifdef COMPRESS_TRACE_FH 
+		for (i=0; i<TRACE_FH_SIZE/8; i++) {
+			strncpy(intbuf, buf+i*8, 8);
+			sscanf(intbuf, "%x", trace_fh+i*8); // maybe it should be 4, anyway we don't compress for now 
+		}
+		trace_path = buf+TRACE_FH_SIZE*2+1;		/* +1 the trace contains only initial file handle */
+#else
+		memcpy(trace_fh, buf, TRACE_FH_SIZE);
+		trace_path = buf + TRACE_FH_SIZE +1;
+#endif
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		trace_path = +=2;	/* +3 if the trace contains both initial and later created file handle */
+#endif
+
+#ifdef NO_DEPENDENCY_TABLE
+		if (!strncmp (trace_path, "DISCARD", 7)) {
+			map_flag = FH_MAP_FLAG_DISCARD;
+			add_fh (map_flag, buf, trace_path, 0);
+			continue;
+		}
+#endif
+		
+		p = trace_path+strlen(trace_path)-2;
+		while (*p!='/')
+			p--;
+		p++;
+		//RFS_ASSERT (p-trace_path<=strlen(lookup_path)+1);
+		//RFS_ASSERT (p>trace_path);
+
+		if (strncmp(lookup_path, trace_path, p-trace_path)) {
+			printf("strncmp lookup_path %s trace_path %s for length %d\n", lookup_path, trace_path, p-trace_path);
+		}
+		RFS_ASSERT (!strncmp(lookup_path, trace_path, p-trace_path));
+		//while (strncmp(lookup_path, trace_path, p-trace_path)) {	/* one step deeper */
+		while (strlen(lookup_path)>p-trace_path && depth>0) {
+			//printf("depth--\n");
+			if (depth<=0) 
+				printf ("lookup_path %s trace_path %s p-trace_path %d depth %d\n", lookup_path, trace_path, p-trace_path, depth);
+			RFS_ASSERT (depth>0);
+			*lookup_path_ptr[depth]=0;
+			lookup_path_ptr[depth]=0;
+			depth--;
+		}
+		RFS_ASSERT (strlen(lookup_path)==(p-trace_path) || (depth==0));
+
+
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		if (buf[TRACE_FH_SIZE*2+1]=='Y') {
+			map_flag = FH_MAP_FLAG_COMPLETE;
+		} else {
+			map_flag = FH_MAP_FLAG_PARTIAL;
+			RFS_ASSERT (buf[TRACE_FH_SIZE*2+1]=='N');
+		}
+#else
+		map_flag = FH_MAP_FLAG_COMPLETE;
+#endif
+		if ((*(p+strlen(p)-1))=='/') {
+			*(p+strlen(p)-1)=0;
+			new_dir_flag = 1;
+		} else 
+			new_dir_flag = 0;
+
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			lookup_init_filesystem (&parents[depth], p, &parents[depth+1]);		
+			add_fh (map_flag, buf, trace_path, &parents[depth+1]);	
+		} else 
+			add_fh (map_flag, buf, trace_path, 0);
+
+		if (new_dir_flag) {
+			/* the new fhandle is of a directory */
+			lookup_path_ptr[depth+1] = lookup_path+strlen(lookup_path);
+			strcat (lookup_path, p);
+			strcat (lookup_path, "/");
+
+			//printf("depth++\n");
+			depth++;
+		}
+
+		memset(buf, 0, sizeof(buf));
+	}
+			
+	if (fh_map_debug) {
+		for (i=0; i<fh_i; i++) {
+			int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+			int * p = (int *)fh_map[i].trace_fh;
+			printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+			printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, fh_map[i].trace_fh, fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+		}
+#endif
+
+		fprintf(stderr, "total %d requests \n", i);
+	}
+}
+
+int f()
+{
+	return 1;
+}
+
+inline void finish_request (int biod_index, int dep_index, int status)
+{
+	/* the ending operation, same as when a request time out */
+	dep_tab[dep_index].stop = biod_reqp[biod_index].stop;	/* RFS: to dump data */
+	dep_tab[dep_index].status = status;
+	event_order[event_order_index++] = -dep_index;
+	biod_reqp[biod_index].in_use = FALSE;
+	dep_tab[dep_index].flag = DEP_FLAG_DONE;
+	if (is_dir_op(dep_tab[dep_index].proc)) {
+		int j;
+		RFS_ASSERT (dep_tab[dep_index].fh->lock = 1);
+		dep_tab[dep_index].fh->lock = 0;
+		if (dep_tab[dep_index].proc==RENAME)
+			dep_tab[dep_index].fh_2->lock = 0;
+		j = dep_tab[dep_index].fh-fh_map;
+		if (dependency_debug) {
+			printf ("fh_map[%d] is UNlocked\n",j);
+			printf ("trace_fh %d path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+			printf ("trace_fh %d path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+		}
+	}
+	num_out_reqs --;
+}
+
+/* the request argument may have pointers pointing to buffers, e.g. the name in lookup, 
+ * the target of symlink, the write data */
+char arg_res[MAX_ARG_RES_SIZE];
+int poll_timeout = 0;		/* timeout in usecs */
+char buf1 [MAX_BUF1_SIZE]; 
+char buf2 [MAX_BUF2_SIZE];
+
+int execute_next_request ()
+{
+	int dep_index;
+	int proc;
+	char * line;
+	struct biod_req * reqp;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime call_timeout;
+
+	start_profile (&valid_get_nextop_profile);
+	start_profile (&invalid_get_nextop_profile);
+	dep_index = get_nextop();
+	if (dep_index == -1) {
+		end_profile (&invalid_get_nextop_profile);
+		return dep_index;
+	};
+	end_profile (&valid_get_nextop_profile);
+
+	start_profile (&prepare_argument_profile);
+	line = dep_tab[dep_index].line;
+	if ((dep_index%(10000))==0) {
+#ifndef TIME_PLAY
+		fprintf (stderr, "processing dep_tab[%d] disk_index %d num_out_reqs %d \n", dep_index, dep_tab[dep_index].disk_index, num_out_reqs);
+#else
+		fprintf (stderr, "processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+#ifdef SPEED_UP
+		if (can_not_catch_speed_num < 2000) {
+			PLAY_SCALE ++;
+			printf ("set PLAY_SCALE to %d\n", PLAY_SCALE);
+		};
+		if (can_not_catch_speed_num > 50000) {
+			PLAY_SCALE /= 2;
+		} else {
+			if (can_not_catch_speed_num > 5000) {
+				PLAY_SCALE -= 2;
+				if (PLAY_SCALE < 1)
+					PLAY_SCALE = 1;
+			}
+		}
+#endif
+		can_not_catch_speed_num = 0;
+#endif
+	}
+	if (rfs_debug)
+		printf ("processing dep_tab[%d] disk_index %d %s\n", dep_index, dep_tab[dep_index].disk_index, line);
+
+	proc = dep_tab[dep_index].proc;
+	rfs_Ops[proc].setarg (dep_index, line, arg_res, buf1, buf2);
+
+	op_ptr = &Ops[proc];
+	reqp = get_biod_req (dep_index);
+	RFS_ASSERT (reqp);
+
+	call_timeout.sec = 2; //Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+
+    /* make the call */
+    sfs_gettime(&(reqp->start));
+	end_profile (&prepare_argument_profile);
+	start_profile (&biod_clnt_call_profile);
+#define REAL_PLAY
+#ifdef REAL_PLAY
+    reqp->xid = biod_clnt_call(NFS_client, rfs_Ops[proc].nfsv3_proc, 
+					rfs_Ops[proc].xdr_arg, arg_res);
+#else
+
+	reqp->xid = dep_index+1;	/* just fake a message id and let it expire */
+#endif
+    if (reqp->xid != 0) {
+        reqp->timeout = reqp->start;
+        ADDTIME (reqp->timeout, call_timeout);
+        num_out_reqs++;
+        dep_tab[dep_index].flag = DEP_FLAG_SENT;
+		event_order[event_order_index++] = dep_index;
+    } else
+		RFS_ASSERT (0);
+
+	dep_tab[dep_index].start = reqp->start;	/* RFS: to dump data */
+	end_profile (&biod_clnt_call_profile);
+}
+
+inline void check_reply (int proc, int biod_index, int dep_index, int status, char * errmsg, int trace_status)
+{
+	if (((status!=trace_status)) && (trace_status!=NFS3ERR_RFS_MISS)) {
+		if (!profile_debug)
+			printf ("receive problem reply, xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d command disk index %d\n", biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec, dep_tab[dep_index].disk_index); 
+#ifndef TAKE_CARE_UNLOOKED_UP_NON_NEW_FILES
+		/* these files is not looked up and is not create/mkdir/symlink/link/mknod ed before they
+		 * are refered by name through rename, remove
+		 */
+		if ((proc==RENAME || proc==REMOVE) && (status==NFS3ERR_NOENT) && (trace_status ==0)) {
+			/* current initialization doesnot take care of rename source, if there is no
+			 * create or lookup before that source, the source object will not exist when
+			 * rename occurs
+			 */
+			rename_rmdir_noent_reply_num++;
+		} else 
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+		if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_status==NFS3ERR_NOENT)) {
+			/* in the original trace, first lookup return NOENT, then symlink is executed, then lookup return OK
+			 * the initialization considers only the lookup return OK and created the file in the initialization
+			 * so in trace play the first lookup return OK
+			 */
+			RFS_ASSERT (1);
+		} else if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) && (trace_status == 0)) {
+			/* due to similar reason as above, the initialization code initializes the symbolic link as a normal
+			 * file already
+			 */
+			RFS_ASSERT (1);
+		} else
+#endif
+#ifndef TAKE_CARE_NOEMPTY_RMDIR
+		/* the remove packet seems got lost in the trace capture, so replay can not finish */
+		if ((proc==RMDIR) && (status==NFS3ERR_NOTEMPTY)) {
+   			RENAME3args		args;
+   			RENAME3res		reply;		/* the reply */
+			RMDIR3args * rmdir_argp;
+			enum clnt_stat rpc_stat;	/* result from RPC call */
+
+			rfs_Ops[proc].setarg (dep_index, dep_tab[dep_index].line, arg_res, buf1, buf2);
+			rmdir_argp = (RMDIR3args *)arg_res;
+
+			memcpy(&args.from, &(rmdir_argp->object), sizeof (diropargs3));
+			memcpy(&args.to.dir, &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+			args.from.name = buf1;	/* the buf1 is already filled when parsing rmdir */
+			args.to.name = buf2;
+			sprintf(buf2, "rmdir_%d_%s", dep_tab[dep_index].disk_index, rmdir_argp->object.name);
+
+  			rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
+			xdr_RENAME3args, (char *) &args,
+			xdr_RENAME3res, (char *) &reply,
+				Nfs_timers[Init]);
+			RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+			if (reply.status!=NFS3_OK)
+				printf ("change rmdir into rename, reply.status %d\n", reply.status);
+			RFS_ASSERT (reply.status==NFS3_OK);
+			rmdir_not_empty_reply_num ++;
+#endif
+#ifndef TAKE_CARE_ACCESS_ERROR
+		} else if ((status==0) && (trace_status==NFS3ERR_ACCES)) {
+			loose_access_control_reply_num ++;
+#endif
+#ifdef NO_DEPENDENCY_TABLE 
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3_OK)) {
+			lookup_err_due_to_rename_num ++;
+#endif
+#ifndef TAKE_CARE_LOOKUP_EACCESS_ENOENT_MISMATCH
+		/* if the looked return EACCESS in the trace, means the object still exists
+		 * should have initialized, right not don't initialize it, hence play status 
+		 * could be ENOENT
+		 */
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3ERR_ACCES)) {
+			lookup_eaccess_enoent_mismatch_num ++;
+#endif
+#ifdef TOLERANT_READ_IO_ERR
+		} else if ((proc==READ) && (status==NFS3ERR_IO) && (trace_status==NFS3_OK)) {
+			read_io_err_num ++;
+#endif
+		} else {
+			int i;
+			for (i=min_dep_index; i<max_dep_index; i++) 
+				printf ("dep_tab[%d].disk_index %d, flag %d line %s\n", i, dep_tab[i].disk_index, dep_tab[i].flag, dep_tab[i].line);
+			RFS_ASSERT (0);
+		}
+	} else 
+		proper_reply_num ++;
+
+}
+
+/* return -1 if there is no reply being received 
+ * return the dep_index if the corresponding reply has been received
+ */
+inline int receive_next_reply (int busy_flag)
+{
+	int dep_index;
+	int biod_index;
+	int proc;
+	char * line;
+	char * reply_line;
+	sfs_op_type *op_ptr;		/* per operation info */
+	int ret;
+	int status;
+	int trace_status;
+	char * errmsg;
+
+	/* wait for reply */
+	start_profile (&valid_poll_and_get_reply_profile);
+	start_profile (&invalid_poll_and_get_reply_profile);
+
+	if (busy_flag == BUSY) {
+		poll_timeout = 0;
+		poll_timeout_0_num ++;
+	} else {
+		poll_timeout = 10000;	/* 10000 or 2000 is a better number in non-debugging state */
+		poll_timeout_pos_num ++;
+	}
+
+	biod_index = poll_and_get_reply (poll_timeout);
+	if (biod_index==-1) {
+		end_profile (&invalid_poll_and_get_reply_profile);
+		return -1;
+	};
+	end_profile (&valid_poll_and_get_reply_profile);
+
+	start_profile (&decode_reply_profile);
+	/* check the corresponding request */
+	dep_index = biod_reqp[biod_index].dep_tab_index;
+	proc = dep_tab[dep_index].proc;
+	op_ptr = &Ops[proc];
+
+	if (dep_tab[dep_index].flag != DEP_FLAG_SENT) {
+		printf("dep_tab[%d].flag %d proc %d status %d start %d:%d stop %d:%d\n",
+			dep_index, dep_tab[dep_index].flag, proc, dep_tab[dep_index].status, 
+			dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec,
+			dep_tab[dep_index].stop.sec, dep_tab[dep_index].stop.usec );
+		printf ("received reply for timeout requests dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+		return dep_index;
+	}
+	RFS_ASSERT (dep_tab[dep_index].flag == DEP_FLAG_SENT);
+
+	/* decode the reply */
+	rfs_Ops[proc].setres (arg_res, buf1);
+	ret = proc_header (NFS_client, rfs_Ops[proc].xdr_res, arg_res);
+	RFS_ASSERT (ret == RPC_SUCCESS);
+	status = *((int *)arg_res);
+	errmsg = nfs3_strerror (status);
+	end_profile (&decode_reply_profile);
+
+	start_profile (&check_reply_profile);
+	/* compare with the reply in the trace */
+	line = dep_tab[dep_index].line;
+	reply_line = dep_tab[dep_index].reply_line;
+	trace_status = dep_tab[dep_index].trace_status;
+
+	/* print the result, trace play progress indicator */
+	if (rfs_debug || (	!profile_debug && ((dep_index %10000)==0)	) )
+		fprintf (stdout, "dep_tab[%d], disk_index %d, receive reply, rpc_ret %d xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d \n", dep_index, dep_tab[dep_index].disk_index, ret, biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec);
+
+	/* error checking */
+	check_reply (proc, biod_index, dep_index, status, errmsg, trace_status);
+
+	/* free resources */
+	finish_request (biod_index, dep_index, status);
+	
+	/* get statistics */
+	if (status == trace_status) {
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+	} else {
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	}
+	sfs_elapsedtime (op_ptr, &(biod_reqp[biod_index].start), &(biod_reqp[biod_index].stop));
+	end_profile (&check_reply_profile);
+	
+	//start_profile (&add_create_object_profile);
+/*
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+	if (trace_status == NFS3_OK && (proc==CREATE || proc==MKDIR || proc==MKNOD)) {
+#else
+#endif
+*/
+	if (trace_status == NFS3_OK && (proc==CREATE || proc==MKDIR || proc==SYMLINK || proc==MKNOD)) {
+		RFS_ASSERT (reply_line);
+		if (status!=NFS3_OK) {
+			RFS_ASSERT (proc==SYMLINK);
+		} else {
+			if (proc!=SYMLINK || line[TRACE_VERSION_POS]!='2')
+				add_new_file_system_object(proc, dep_index, line, reply_line);
+		}
+	}
+	//end_profile (&add_create_object_profile);
+}
+
+inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line)
+{
+	char * child_trace_fh;
+	fh_map_t * parent_entryp;
+	char component_name[MAX_PLAY_PATH_SIZE];
+	char * parent_trace_fh;
+	char child_path[MAX_PLAY_PATH_SIZE];
+	post_op_fh3 * post_op_fh3_child;
+	char * reply_trace_fh;
+	nfs_fh3 * child_fh3;
+
+	parent_trace_fh = strstr (line, "fh");
+	RFS_ASSERT (parent_trace_fh);
+	parent_trace_fh +=3;
+	parent_entryp = lookup_fh (parent_trace_fh);
+	RFS_ASSERT (parent_entryp);
+	parse_name (parent_trace_fh+65, component_name);
+	strcpy (child_path, parent_entryp->path);
+	strcat (child_path, "/");
+	strcat (child_path, component_name);
+				
+	/* find the corresponding create request */
+	//printf ("before find reply trace_fh reply_line %s\n", reply_line);
+	reply_trace_fh = find_reply_trace_fh (reply_line);
+	RFS_ASSERT (reply_trace_fh != NULL);
+	switch (proc) {
+	case CREATE:
+		RFS_ASSERT (((CREATE3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((CREATE3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKDIR:
+		RFS_ASSERT (((MKDIR3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKDIR3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case SYMLINK:
+		RFS_ASSERT (((SYMLINK3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((SYMLINK3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKNOD:
+		RFS_ASSERT (((MKNOD3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKNOD3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case LOOKUP:
+		RFS_ASSERT (proc==LOOKUP);
+		child_fh3 = &((LOOKUP3res *)arg_res)->res_u.ok.object;
+		break;
+	default:
+		RFS_ASSERT (0);
+	}
+	RFS_ASSERT (reply_trace_fh[TRACE_FH_SIZE]==' ');
+	reply_trace_fh[TRACE_FH_SIZE] = 0;
+	add_fh (FH_MAP_FLAG_COMPLETE, reply_trace_fh, child_path, child_fh3); 	/* exist flag is not used now, set to 1 */
+	reply_trace_fh[TRACE_FH_SIZE] = ' ';
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void trace_play(void)
+{
+	
+	/* The flag to indicate whether trace_player is BUSY. Trace_player is BUSY
+	 * when either there is request to send or there is reply being
+	 * received. Otherwise it is IDLE. The timeout for polling replies 
+	 * is set to 0 when BUSY, it is set to the waiting time to the first
+	 * request outside of current <min_dep_index, max_dep_index> window when IDLE.
+	 */
+   	int busy_flag = BUSY;		
+
+	//int dep_index;		/* index into dependency table: dep_tab */
+	//int biod_index; 	/* index into outstanding requests: biod_reqp */
+
+	int count = 0;
+	min_dep_index = 0;
+	max_dep_index = 0;
+	adjust_play_window(busy_flag, &poll_timeout);
+
+	start_profile (&total_profile);
+	while ((min_dep_index<dep_tab_size) || (num_out_reqs>0)) {
+
+		if (busy_flag == IDLE) {
+			//start_profile (&check_timeout_profile);
+			check_timeout();
+			//end_profile (&check_timeout_profile);
+		}
+
+		//start_profile (&adjust_play_window_profile);
+	 	//adjust_play_window (flag, &poll_timeout);
+	 	//adjust_play_window (flag+(max_dep_index-min_dep_index), &poll_timeout);
+	 	adjust_play_window (busy_flag, &poll_timeout);
+		if (rfs_debug)
+			printf("num_out_reqs %d\n", num_out_reqs);
+		busy_flag = IDLE;
+		//end_profile (&adjust_play_window_profile);
+
+		start_profile (&execute_next_request_profile);
+		while (execute_next_request()!=-1)
+			busy_flag = BUSY;
+		end_profile (&execute_next_request_profile);
+
+		start_profile (&receive_next_reply_profile);
+		/* actually the performance of two policy seems to be same */
+//#define SEND_HIGHER_PRIORITY_POLICY
+#define SEND_RECEIVE_EQUAL_PRIORITY_POLICY	
+
+#ifdef SEND_HIGHER_PRIORITY_POLICY
+		receive_next_reply(IDLE);
+#endif
+#ifdef SEND_RECEIVE_EQUAL_PRIORITY_POLICY
+		busy_flag = IDLE;
+		while (receive_next_reply(busy_flag)!=-1)
+			busy_flag = BUSY;
+#endif
+		end_profile (&receive_next_reply_profile);
+	}
+	end_profile (&total_profile);
+
+	print_profile ("total_profile", &total_profile);
+	printf("\n");
+	//print_profile ("check_timeout", &check_timeout_profile);
+	//printf("\n");
+	//print_profile ("adjust_play_window", &adjust_play_window_profile);
+	//printf("\n");
+	print_profile ("execute_next_request_profile", &execute_next_request_profile);
+	print_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	print_profile ("invalid_get_nextop_profile", &invalid_get_nextop_profile);
+	print_profile ("prepare_argument", &prepare_argument_profile);
+	print_profile ("biod_clnt_call", &biod_clnt_call_profile);
+	printf("\n");
+	print_profile ("receive_next_reply", &receive_next_reply_profile);
+	print_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	print_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	print_profile ("decode_reply", &decode_reply_profile);
+	print_profile ("check_reply", &check_reply_profile);
+	//print_profile ("add_create_object", &add_create_object_profile);
+	printf("\n");
+	
+	printf ("min_dep_index %d dep_tab_size %d num_out_reqs %d\n", min_dep_index, dep_tab_size, num_out_reqs);
+}
+/* sfs_c_chd.c */
diff --git a/TBBT/trace_play/sfs_c_chd.c.old.2 b/TBBT/trace_play/sfs_c_chd.c.old.2
new file mode 100644
index 0000000..a8c71f7
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_chd.c.old.2
@@ -0,0 +1,2294 @@
+#ifndef lint
+static char sfs_c_chdSid[] = "@(#)sfs_c_chd.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * -------------------------- sfs_c_chd.c -------------------------
+ *
+ *      The sfs child.  Routines to initialize child parameters,
+ *	initialize test directories, and generate load.
+ *
+ *.Exported_Routines
+ *	void child(int, float, int, char *);
+ *	void init_fileinfo(void);
+ *	void init_counters(void);
+ *	sfs_fh_type * randfh(int, int, uint_t, sfs_state_type,
+ *				sfs_file_type);
+ *	int check_access(struct *stat)
+ *	int check_fh_access();
+ *
+ *.Local_Routines
+ *	void check_call_rate(void);
+ *	void init_targets(void);
+ *	void init_dirlayout(void);
+ *	void init_rpc(void);
+ *	void init_testdir(void);
+ *	int do_op(void);
+ *	int op(int);
+ *
+ *.Revision_History
+ *	21-Aug-92	Wittle 		randfh() uses working set files array.
+ *					init_fileinfo() sets up working set.
+ *      02-Jul-92	Teelucksingh    Target file size now based on peak load
+ *					instead of BTDT.
+ *	04-Jan-92	Pawlowski	Added raw data dump hooks.
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+#include "rfs_c_def.h"
+#include "generic_hash.h"
+#include "nfsd_nfsfh_cust.h"
+
+extern struct hostent   *Server_hostent;
+
+#define PROB_SCALE 1000L
+#define _M_MODULUS 2147483647L /* (2**31)-1 */
+
+#define _GROUP_DIVISOR 500
+#define _FILES_PER_GROUP 4
+#define _MIN_GROUPS 12
+#define _WORKING_SET_AT_25_OPS_PER_SEC 975
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+extern uint32_t    biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
+extern enum clnt_stat proc_header(CLIENT *cl, xdrproc_t xdr_results, void *results_ptr);
+extern int  biod_poll_wait(CLIENT *, uint32_t);
+extern enum clnt_stat get_areply_udp (CLIENT * cl, uint32_t *xid, struct timeval *timeout);
+extern char * parse_name (char * t, char * buf);
+
+/* forward definitions for local functions */
+static int init_rpc(void);
+
+/* RFS: forward definitions for local functions */
+void init_ops(void);
+static void init_signal();
+extern void init_file_system (void);
+extern void init_dep_tab (void);
+static void read_trace(char * trace_file);
+static void read_fh_map();
+static void init_play (char * mount_point);
+static void trace_play(void);
+static void print_result(void);
+static int get_nextop(void);
+static int check_timeout(void);
+static struct biod_req * get_biod_req(int dep_tab_index);
+static int lookup_biod_req (int xid);
+static void init_time_offset(void);
+static void adjust_play_window (int flag, int * poll_timeout);
+static int poll_and_get_reply (int usecs);
+static char * nfs3_strerror(int status);
+static void check_clock(void);
+static double time_so_far1(void);
+static double get_resolution(void);
+static void usage(void);
+void init_dep_tab_entry (int dep_index);
+extern fh_map_t * lookup_fh (char * trace_fh );
+static inline void finish_request (int biod_index, int dep_index, int status);
+static void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line);
+
+/*
+ * -------------  Per Child Load Generation Rate Variables  -----------
+ */
+static uint_t Calls_this_period; /* calls made during the current run period */
+static uint_t Calls_this_test;	/* calls made during the test so far */
+static uint_t Reqs_this_period;	/* reqs made during the current run period */
+static uint_t Reqs_this_test;	/* reqs made during the test so far */
+static uint_t Sleep_msec_this_test; /* msec slept during the test so far */
+static uint_t Sleep_msec_this_period;
+static uint_t Previous_chkpnt_msec; /* beginning time of current run period */
+static int Target_sleep_mspc;	/* targeted sleep time per call */
+
+static char io_buf[BUFSIZ];	/* io buffer for print out messages */
+
+char * sfs_Myname;
+int     Log_fd;                         /* log fd */
+char    Logname[NFS_MAXNAMLEN];         /* child processes sync logfile */
+int 	Validate = 0;					/* fake variable */
+int Child_num = 0;						/* fake: child index */
+int Tcp = 0;							/* We implement UDP first */
+int Client_num = 1;						/* fake: number of client */
+uid_t Real_uid;
+gid_t Cur_gid;
+uid_t Cur_uid;
+/*
+ * -------------------------  SFS Child  -------------------------
+ */
+
+void print_usage()
+{
+	printf("sfs3 hostname:mount_dir trace_file fh_map_file\n");
+	exit;
+}
+
+void read_dep_tab()
+{
+#ifdef NO_DEPENDENCY_TABLE
+	int i;
+	char * line;
+	char * trace_fh;
+	fh_map_t * fh_map_entry;
+	int req_num_with_new_fh = 0;
+	int	req_num_with_discard_fh = 0;
+	int req_num_with_init_fh =0;
+
+	for (i=0; i<memory_trace_size; i++) {
+		line = memory_trace[i].line;
+		if (line[TRACE_COMMAND_REPLY_FLAG_POS]=='C') {
+			trace_fh = strstr (line, "fh");
+			RFS_ASSERT (trace_fh);
+			trace_fh += 3;
+			fh_map_entry = lookup_fh (trace_fh);
+			if (fh_map_entry && (fh_map_entry->flag==FH_MAP_FLAG_DISCARD) )  {
+				req_num_with_discard_fh ++;
+				continue;
+			}
+			if (fh_map_entry)
+				req_num_with_init_fh ++;
+			else
+				req_num_with_new_fh ++;
+
+			dep_tab[dep_tab_size].disk_index = memory_trace[i].disk_index;
+			dep_tab[dep_tab_size].line = memory_trace[i].line;
+			if ((dep_tab_size%100000)==0)
+				printf ("dep_tab[%d].disk_index %d = memory_trace[%d].disk_index %d\n", dep_tab_size, dep_tab[dep_tab_size].disk_index, i, memory_trace[i].disk_index);
+			dep_tab_size ++;
+		}
+	}
+#else
+	RFS_ASSERT (0);
+#endif
+	printf ("read_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+}
+
+void init_profile()
+{
+	memset (&total_profile, 0, sizeof(total_profile));
+
+	memset (&execute_next_request_profile, 0, sizeof(execute_next_request_profile));
+	memset (&valid_get_nextop_profile, 0, sizeof(valid_get_nextop_profile));
+	memset (&invalid_get_nextop_profile, 0, sizeof(invalid_get_nextop_profile));
+	memset (&prepare_argument_profile, 0, sizeof(prepare_argument_profile));
+	memset (&biod_clnt_call_profile, 0, sizeof(biod_clnt_call_profile));
+
+	memset (&receive_next_reply_profile, 0, sizeof(receive_next_reply_profile));
+	memset (&valid_poll_and_get_reply_profile, 0, sizeof(valid_poll_and_get_reply_profile));
+	memset (&invalid_poll_and_get_reply_profile, 0, sizeof(invalid_poll_and_get_reply_profile));
+	memset (&decode_reply_profile, 0, sizeof(decode_reply_profile));
+	memset (&check_reply_profile, 0, sizeof(check_reply_profile));
+	memset (&add_create_object_profile, 0, sizeof(add_create_object_profile));
+
+	memset (&check_timeout_profile, 0, sizeof(check_timeout_profile));
+	memset (&adjust_play_window_profile, 0, sizeof(adjust_play_window_profile));
+}
+
+int main(int argc, char ** argv)
+{
+	extern char * optarg;
+	char tracefile[256];
+	int i;
+	int memory_trace_size;
+
+	if (argc==2 && !strcmp(argv[1],"-help")) {
+		print_usage();
+		exit(0);
+	}
+
+	check_clock();
+    getmyhostname(lad_hostname, HOSTNAME_LEN);
+
+    init_ops();
+	/*
+	 * Get the uid and gid information.
+	 */
+	Real_uid = getuid();
+	Cur_gid = getgid();
+	//Real_uid = 513;
+	//Cur_gid = 513;
+
+	Nfs_timers = Nfs_udp_timers;
+
+	init_file_system ();
+
+	init_signal();
+	//init_play (argv[1]);
+	init_play ("capella:/p5/RFSFS");
+	init_profile();
+	init_fh_map();
+	//read_fh_map (argv[3]);
+	read_fh_map ("fh-path-map");
+	init_dep_tab();			/* and  dep_tab_size */
+	//read_trace (argv[2]);
+	read_trace ("anon-lair62-011130-1100.txt");
+	stage = READ_DEP_TAB_STAGE;
+	read_dep_tab();
+
+	for (i=0; i<dep_tab_size; i++) {
+		RFS_ASSERT (dep_tab[i].flag == DEP_FLAG_FREE) 
+		init_dep_tab_entry (i);
+	}
+	stage = TRACE_PLAY_STAGE;
+	init_time_offset();
+	trace_play ();
+	print_result();
+	printf("ffff\n");
+}
+
+void init_ops (void)
+{
+	Ops = nfsv3_Ops;
+	nfs_version = NFS_V3;
+}
+
+/* Set up the signal handlers for all signals */
+void init_signal()
+{
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	struct sigaction sig_act, old_sig_act;
+
+	/* use XOPEN signal handling */
+
+	sig_act.sa_handler = generic_catcher;
+	(void)sigemptyset(&sig_act.sa_mask);
+	sig_act.sa_flags = 0;
+
+	/* signals handlers for signals used by sfs */
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGINT,&sig_act,&old_sig_act) == -1) {
+	    perror("sigaction failed: SIGINT");
+	    exit(135);
+	}
+
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGTERM,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGTERM");
+	    exit(137);
+	}
+#else
+    /* signals handlers for signals used by sfs */
+    (void) signal(SIGINT, sfs_cleanup);
+    // RFS (void) signal(SIGALRM, sfs_alarm);
+	(void) signal(SIGTERM, sfs_cleanup);
+#endif
+}
+
+void
+init_play (
+    char	* mount_point)		/* Mount point for remote FS */
+{
+    char	namebuf[NFS_MAXNAMLEN] = "trace_play";	/* unique name for this program */
+    CLIENT *	mount_client_ptr;	/* Mount client handle */
+
+	if (!rfs_debug);
+    	(void) setvbuf(stderr, io_buf, _IOLBF, BUFSIZ);
+
+    sfs_Myname = namebuf;
+
+    /*
+     * May require root priv to perform bindresvport operation
+     */
+    mount_client_ptr = lad_getmnt_hand(mount_point);
+    if (mount_client_ptr == NULL) {
+		exit(145);
+    }
+
+    /*
+     * should be all done doing priv port stuff
+     */
+
+    if (init_rpc() == -1) {
+		(void) fprintf(stderr, "%s: rpc initialization failed\n", sfs_Myname);
+		(void) generic_kill(0, SIGINT);
+		exit(146);
+    }
+
+
+    /*
+     * finish all priv bindresvport calls
+     * reset uid
+     */
+    if (setuid(Real_uid) != (uid_t)0) {
+	(void) fprintf(stderr,"%s: %s%s", sfs_Myname,
+	    "cannot perform setuid operation.\n",
+	    "Do `make install` as root.\n");
+    }
+
+    init_mount_point(0, mount_point, mount_client_ptr);
+
+
+    /*
+     * Cleanup client handle for mount point
+     */
+    clnt_destroy(mount_client_ptr);
+
+	init_counters();
+	
+
+}
+
+void read_trace (char * tracefile)
+{
+	FILE * fp;
+	char buf[1024];
+	// char * t=buf;	
+	int disk_index=0;
+
+	fp = fopen(tracefile, "r");
+	RFS_ASSERT (fp!=NULL);
+	while (fgets(buf, 1024, fp)) {
+		//printf ("buf: %s buf[36] %c\n", buf, buf[36]);
+		//if (buf[36]=='C' || strstr(buf, "create") || strstr(buf, "lookup")) {
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]=='C' || strstr(buf, "create") || 
+			strstr(buf, "mkdir") || strstr(buf, "symlink") || strstr(buf, "mknod") || strstr(buf, "lookup")) {
+#endif
+			if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+				printf("strlen(buf) %d buf %s \n", strlen(buf), buf);
+			RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+
+			/* store the request to memory */
+			strcpy (memory_trace[memory_trace_size].line, buf);
+			memory_trace[memory_trace_size].disk_index = disk_index;
+			memory_trace_size ++;
+
+			if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+				printf ("memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+				break;
+			}
+			if ((disk_index%100000)==0)
+				fprintf(stderr, "%d disk trace parsed, store %d trace lines to memory\n", disk_index, memory_trace_size);
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+		} else {
+			RFS_ASSERT (buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+		}
+#endif
+		disk_index ++;
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines \n", disk_index, memory_trace_size );
+
+}
+
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+inline int disk_index_to_memory_index (int disk_index)
+{
+	static int memory_index = 0;
+	if (disk_index > memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index < disk_index) {
+			memory_index++;
+			RFS_ASSERT (memory_index < MAX_MEMORY_TRACE_LINES);
+		}
+	};
+	if (disk_index < memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index > disk_index) {
+			memory_index--;
+			RFS_ASSERT (memory_index >=0);
+		}
+	};
+
+	RFS_ASSERT (disk_index == memory_trace[memory_index].disk_index);
+	return memory_index;
+}
+#else
+#define disk_index_to_memory_index(disk_index)	disk_index
+#endif
+
+#define get_line_by_disk_index(disk_index) \
+	memory_trace[disk_index_to_memory_index(disk_index)].line
+
+inline char * find_reply_line (char * command_line, int cur_disk_index)
+{
+	int i;
+	char * line;
+	char * p;
+	int request_memory_index = disk_index_to_memory_index (cur_disk_index);
+	for (i=request_memory_index+1; i<request_memory_index+MAX_COMMAND_REPLY_DISTANCE && i<MAX_MEMORY_TRACE_LINES; i++) {
+		line = memory_trace[i].line;
+		if (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+	        p = strchr (&line[TRACE_MSGID_POS], ' ');
+    	    RFS_ASSERT (p);
+			if (!strncmp(&line[TRACE_MSGID_POS], &command_line[TRACE_MSGID_POS], p-&(line[TRACE_MSGID_POS]))) 
+				return line;
+		}
+	}
+	return NULL;
+}
+
+inline int find_reply_status (char * line)
+{
+	char * p;
+	int i=0;
+
+	//printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	if (!strstr(line, "OK")) {
+		p=strstr(line, " 6 read ");
+		if (p) {
+			p+=strlen(" 6 read ");
+		} else {
+			p = strstr (line, "status=XXX");
+			RFS_ASSERT (p);
+			p--;
+			RFS_ASSERT (*p==' ');
+			while (*p==' ')
+				p--;
+			while (*p!=' ') {
+				p--;
+			}
+			p++;
+		}
+		sscanf (p, "%x", &i);
+		if ((i<=0) || (i>10000))
+			printf("line %s\n", line);
+		RFS_ASSERT (i>0 && i<10009);
+	}
+	return i;
+}
+
+inline char * find_reply_trace_fh (char * line)
+{
+	char * p;	
+	p = strstr (line, "OK fh");
+	if (!p)
+		printf ("find_reply_trace_fh line %s\n", line);
+	RFS_ASSERT (p);
+	return p+6;
+}
+
+inline int disk_index_to_dep_index(int cur_dep_index, int disk_index)
+{
+	int i;
+	for (i=cur_dep_index; i>min_dep_index; i--) {
+		if (dep_tab[i].disk_index == disk_index)
+			return i;
+	} 
+	RFS_ASSERT (0);
+}
+
+inline int is_play_candidate (int dep_index)
+{
+#ifndef TAKE_CARE_CREATE_MODE_BY_DAN
+	int trace_reply_status;
+	char * reply_line;
+	if ((dep_tab[dep_index].proc==CREATE)) {
+		/* for a failed create in trace, trace_replay just ignore */
+		reply_line = find_reply_line (dep_tab[dep_index].line, dep_tab[dep_index].disk_index);
+		if (reply_line == NULL) {
+			if (dependency_debug)
+				printf ("disk[%d] can not find the reply line, assume trace_reply_status OK\n", dep_tab[dep_index].disk_index);
+			trace_reply_status = NFS3_OK;
+		} else 
+			trace_reply_status = find_reply_status (reply_line);
+		/* many time the trace create fail due to access control, but trace_play will success because our access control
+		 * may be loose (all uid/gid is mapped to single one 513:513, so we just skip these requests 
+		 */
+		if ((dep_tab[dep_index].proc == CREATE) && (trace_reply_status!=NFS3_OK)) {
+			if (dependency_debug)
+				printf ("disk[%d] ignore failed create in trace, trace_reply_status %d line %s", dep_tab[dep_index].disk_index, trace_reply_status, dep_tab[dep_index].line);
+			failed_create_command_num ++;
+			return FALSE;
+		}
+	}
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+	if ((dep_tab[dep_index].proc==READLINK)) { /* send request */
+		skipped_readlink_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_CUSTOM_COMMAND
+	/* this line has a file handle which should belong to discard but it is not
+	 * the file handle directly appears as parent directory in a lookup request
+	 * the return value is NOENT, the parent directory should have been initialized
+	 * but the initialization code just ignored all lookup request which didn't success
+	 * including NOENT even though the parent directory is still valid.
+	 */
+	if ((dep_tab[dep_index].disk_index==262213 ||
+		 dep_tab[dep_index].disk_index==214402		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+#endif
+	return TRUE;
+}
+
+inline int is_dir_op (int proc)
+{
+	switch (proc) {
+	case MKDIR:
+	case CREATE:
+	case LINK:
+	case SYMLINK:
+	case MKNOD:
+	case REMOVE:
+	case RMDIR:
+	case RENAME:
+		return 1;
+	default:
+		return 0;
+	}
+}	
+
+inline int is_create_op (int proc)
+{
+	if (proc==CREATE || proc==MKDIR || proc==LINK || proc==SYMLINK || proc==MKNOD || proc==RENAME)
+		return 1;
+	return 0;
+}
+
+inline int is_delete_op (int proc)
+{
+	if (proc==REMOVE || proc==RMDIR || proc==RENAME)
+		return 1;
+	return 0;
+}	
+
+inline char * find_lead_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh");
+	RFS_ASSERT (p);
+	p+=3; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+inline char * find_another_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh2");
+	RFS_ASSERT (p);
+	p+=4; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+/* return the index of next request in dep_tab.
+ * Return -1 if there is no suitable request to send
+ */
+inline int get_nextop(void)
+{
+	int i,j, k;
+	int * t;
+	static int dep_index = -2;
+	char * line;
+	char * p;
+	static int min_wait_fhandle_dep_index = DEP_TAB_SIZE;
+	int proc;
+	int flag;
+
+	//if (dep_index < min_dep_index-1)
+	//	dep_index = min_dep_index-1;
+
+	dep_index = min_dep_index-1;
+	for (i=0; i<max_dep_index-min_dep_index; i++) {
+		dep_index ++;
+		if (dep_index == max_dep_index) {
+			dep_index = min_dep_index;
+		}
+	
+		proc = dep_tab[dep_index].proc;
+		flag = dep_tab[dep_index].flag;
+
+		if (dependency_debug)
+			printf ("get_nextop check dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+#ifdef NO_DEPENDENCY_TABLE
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT) {
+			if (is_play_candidate(dep_index)==TRUE) {
+				/* the trace_fh is the file handle for the operation directory, trace_fh_2 is other file handle
+				 * used in the request */
+				if (proc==LINK || proc==RENAME) {
+					dep_tab[dep_index].trace_fh = find_another_trace_fh (proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].trace_fh_2 = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = 0;
+				} else {
+					dep_tab[dep_index].trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = (fh_map_t *)1;
+				};
+				dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+#ifdef TIME_PLAY
+				dep_tab[dep_index].skip_sec = skip_sec;
+#endif
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_CANDIDATE\n", dep_tab[dep_index].disk_index);
+			} else {
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+				dep_tab[dep_index].flag = DEP_FLAG_DONE;
+				continue;
+			}
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE) ) {
+
+			if (!dep_tab[dep_index].fh)
+				dep_tab[dep_index].fh = lookup_fh (dep_tab[dep_index].trace_fh);
+			if (!dep_tab[dep_index].fh_2)
+				dep_tab[dep_index].fh_2 = lookup_fh (dep_tab[dep_index].trace_fh_2);
+
+			/* need to wait for file handle */
+			if ((!dep_tab[dep_index].fh) || (!dep_tab[dep_index].fh_2)) {
+				if (dependency_debug)
+					printf("disk[%d] can not lookup file handle\n", dep_tab[dep_index].disk_index);
+				if (dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) {
+					if (dependency_debug)
+						printf ("disk[%d] state DEP_FLAG_CANDIDATE to DEP_FLAG_WAIT_FHANDLE\n", dep_tab[dep_index].disk_index);
+					dep_tab[dep_index].flag = DEP_FLAG_WAIT_FHANDLE;
+					sfs_gettime (&dep_tab[dep_index].start);
+					if (dep_index < min_wait_fhandle_dep_index)
+						min_wait_fhandle_dep_index = dep_index;
+				} else {
+					struct ladtime tmp;
+					sfs_gettime (&tmp);
+					SUBTIME (tmp, dep_tab[dep_index].start);
+#ifdef TIME_PLAY
+					RFS_ASSERT (tmp.sec < 20 + (skip_sec - dep_tab[dep_index].skip_sec));	
+#else
+					RFS_ASSERT (tmp.sec < 20 );	
+#endif
+				}
+				continue;
+			}
+
+			/* file handle ready, adjust_min_wait_fhandle_dep_index */
+			if ((dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE)) {
+				if (dep_index == min_wait_fhandle_dep_index) {
+					min_wait_fhandle_dep_index = dep_tab_size;
+					for (j=dep_index+1; j<max_dep_index; j++) {
+						if (dep_tab[j].flag ==DEP_FLAG_WAIT_FHANDLE) {
+							min_wait_fhandle_dep_index = j;
+							break;
+						}
+					}
+				}
+			}
+			if (dependency_debug)
+				printf("disk[%d] found file handle\n", dep_tab[dep_index].disk_index);
+			dep_tab[dep_index].flag = DEP_FLAG_FHANDLE_READY;
+
+			/* the normal file operation can be executed now */
+			if (!is_dir_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug)
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			if (dependency_debug)
+				printf("disk[%d] directory operation \n", dep_tab[dep_index].disk_index);
+			/* the directory operation need to lock the directory first */
+			if (dep_tab[dep_index].fh->lock) {
+				if (dependency_debug)
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DIRECTORY\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DIRECTORY;
+				continue;
+			}
+		}
+				
+		if ((dep_tab[dep_index].flag == DEP_FLAG_FHANDLE_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DIRECTORY)) {
+			int j = dep_tab[dep_index].fh - fh_map;
+			if (dependency_debug) {
+				printf ("dep_tab[%d].disk_index %d, fh_map[%d] lock=%d\n",dep_index, dep_tab[dep_index].disk_index, j, dep_tab[dep_index].fh->lock);
+				printf ("trace_fh %s path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+				printf ("trace_fh %s path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+			}
+			if ((dep_tab[dep_index].fh->lock) || ((proc==RENAME) && (dep_tab[dep_index].fh_2->lock)) ) {
+				if (dependency_debug) 
+					printf ("continue to wait for directory lock\n");
+				continue;
+			}
+			if (dependency_debug) 
+				printf ("dep_tab[%d] disk index %d LOCK fh_map[%d] \n", dep_index, dep_tab[dep_index].disk_index, j);
+			dep_tab[dep_index].fh->lock = 1;
+			if (proc==RENAME)
+				dep_tab[dep_index].fh_2->lock = 1;
+
+			/* the non-delete directory operation can proceed now */
+			if (!is_delete_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			/* the delete operation can proceed if nobody ahead is waiting for fhandle */
+			/* probably this condition is not strong enough */
+//			if ((min_wait_fhandle_dep_index<dep_index) ) {
+			if (dep_index!=min_dep_index) {
+				if (dependency_debug) 
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DELETE\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DELETE;
+				continue;
+			} 
+			dep_tab[dep_index].flag = DEP_FLAG_DIRECTORY_READY;
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_DIRECTORY_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DELETE)) {
+//			if (min_wait_fhandle_dep_index > dep_index) {
+			if (dep_index==min_dep_index) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+		}
+#else
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT){
+			for (j=0, t=&(dep_tab[dep_index].dep_ops[0]);
+				(j<dep_tab[dep_index].init_dep_num) && (dep_tab[dep_index].cur_dep_num>0); 
+				j++, t++) {
+				if (*t !=-1) {
+					if (dep_tab[disk_index_to_dep_index(dep_index, *t)].flag == DEP_FLAG_DONE) { /* The depended request has been finished */ 
+						*t = -1;
+						dep_tab[dep_index].cur_dep_num --;
+					}
+				} 
+			}
+
+			if (dep_tab[dep_index].cur_dep_num == 0) {
+				return dep_index;
+			}
+		}
+#endif
+	}
+
+	if (dependency_debug) 
+		printf ("get_nexop return -1\n");
+	return -1;
+}
+
+int check_timeout(void)
+{
+	static int biod_index = 0;
+	int i;
+	int dep_index;	/* index into dep_tab */
+	int proc;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime timeout;
+
+	sfs_gettime (&current);	
+
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (biod_reqp[biod_index].in_use==TRUE) {
+			timeout = biod_reqp[biod_index].timeout;
+			if ((current.sec>timeout.sec) ||
+				((current.sec==timeout.sec) && (current.usec>timeout.usec))) {
+
+				dep_index = biod_reqp[biod_index].dep_tab_index;
+				proc = dep_tab[dep_index].proc;
+				op_ptr = &Ops[proc];
+				op_ptr->results.timeout_calls++;
+				Ops[TOTAL].results.timeout_calls++;
+
+				finish_request (biod_index, dep_index, NFS3ERR_RFS_TIMEOUT);
+
+				if (is_create_op(proc)) {
+					dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+					printf ("resend dep_tab[%d], disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+				}
+				//RFS_ASSERT (!is_create_op(proc));
+
+				//printf ("timeout request: biod_reqp[%d].start %d:%d timeout %d:%d current %d:%d\n", biod_index, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, timeout.sec, timeout.usec, current.sec, current.usec);
+			}
+		}
+	}
+}
+
+/* Allocate a biod_req entry to send and receive request dep_tab[dep_index]
+ * build the cross reference between dep_tab entry and biod_req entry
+ */
+struct biod_req * get_biod_req(int dep_index) /* index into dep_tab */
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (!biod_reqp[biod_index].in_use) {
+			biod_reqp[biod_index].in_use = 1;
+			biod_reqp[biod_index].dep_tab_index = dep_index;
+			dep_tab[dep_index].biod_req_index = biod_index;
+			return &(biod_reqp[biod_index]);
+		}
+	}
+	return NULL;
+}
+
+/* Return index into biod_reqp
+ * return -1 upon failure 
+ */
+int lookup_biod_req (int xid)
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		/* give a NULL as timeout pointer may cause indefinitely block */
+		if (biod_reqp[biod_index].xid == xid) {
+			return biod_index;
+		}
+	}
+	return -1;
+}
+
+extern struct ladtime test_start;
+void init_time_offset(void)
+{
+	struct ladtime tmp1;
+	struct ladtime tmp2;
+
+	test_start.sec = 0;
+	test_start.usec = 0;
+	sfs_gettime (&tmp1);		/* called at initial time: tmp1 = play_starttime */
+#ifdef SPEED_UP
+	DIVTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime / SCALE */
+#endif
+#ifdef SLOW_DOWN
+	MULTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime * SCALE */
+#endif
+
+	tmp2 = trace_starttime; /* tmp2 = trace_starttime */
+	SUBTIME (tmp2, tmp1);	/* tmp2 = trace_starttime - play_starttime *|/ SCALE */
+	time_offset = tmp2;		/* time_offset = trace_starttime - play_starttime *|/ SCALE */ 
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void init_dep_tab_entry (int dep_index)
+{
+	static int nfs2proc_to_rfsproc[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
+															10, 11, 12, 13, 14, 15, 16, 17};
+	static int nfs3proc_to_rfsproc[NFS3_PROCEDURE_COUNT] = {0, 1, 2, 4, 18, 5, 6, 8, 9, 14, 
+															13, 21, 10, 15, 11, 12, 16, 23, 17, 20, 
+															22, 19};
+	char * line;
+	int version;
+	int nfsproc;
+	int msgid;
+
+	//line = get_line_by_disk_index (dep_tab[dep_index].disk_index);
+	line = dep_tab[dep_index].line;
+	sscanf (line, "%d.%d", &(dep_tab[dep_index].timestamp.tv_sec), &(dep_tab[dep_index].timestamp.tv_usec));
+	sscanf (&line[39], "%x %x", &msgid, &nfsproc);
+	if (line[TRACE_VERSION_POS]=='2') {
+		dep_tab[dep_index].proc = nfs2proc_to_rfsproc[nfsproc];
+		RFS_ASSERT (nfsproc <18);
+	} else {
+		/* This is for debug purpose */
+		if (line[TRACE_VERSION_POS] !='3') {
+			fprintf(stderr, "line[TRACE_VERSION_POS] %c line %s\n", line[TRACE_VERSION_POS], line);
+			line = get_line_by_disk_index (dep_tab[dep_index].disk_index-1);
+			if (!line)
+				line = get_line_by_disk_index (dep_tab[dep_index].disk_index-2);
+			RFS_ASSERT (line);
+			fprintf(stderr, "previousline %s\n", line);
+		}
+		RFS_ASSERT (line[TRACE_VERSION_POS] =='3');
+		if (nfsproc >= NFS3_PROCEDURE_COUNT) {
+			fprintf(stderr, "proc %d line %s\n", nfsproc, line);
+			
+		}
+		RFS_ASSERT (nfsproc <NFS3_PROCEDURE_COUNT);
+		dep_tab[dep_index].proc = nfs3proc_to_rfsproc[nfsproc];
+	}
+	RFS_ASSERT (dep_tab[dep_index].proc >= 0 && dep_tab[dep_index].proc < NOPS);
+	dep_tab[dep_index].flag = DEP_FLAG_INIT;
+}
+
+/* initialize status, reply status, reply lines in one shot is probably better ????????????????
+
+static void adjust_play_window (int flag, int * poll_timeout)
+{
+	struct ladtime max_window_time;
+	static struct ladtime max_poll_time = {0, 2000, 0};
+	struct ladtime t;
+	int old_min = min_dep_index;
+	int old_max = max_dep_index;
+	int i;
+	char * line;
+
+	for (; (dep_tab[min_dep_index].flag == DEP_FLAG_DONE) && (min_dep_index<dep_tab_size); min_dep_index++)
+		;
+	RFS_ASSERT (min_dep_index <= max_dep_index);
+
+	/* max_trace_window_time = current *|/ SCALE + trace_starttime */
+	sfs_gettime (&current);
+
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+	MULTIME (current, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+	DIVTIME (current, PLAY_SCALE);
+#endif
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+
+	while ((max_dep_index<min_dep_index+MAX_PLAY_WINDOW) && (max_dep_index<dep_tab_size))
+	{
+		t.sec = dep_tab[max_dep_index].timestamp.tv_sec;
+		t.usec = dep_tab[max_dep_index].timestamp.tv_usec;
+
+		if (adjust_play_window_debug)
+			printf ("max_window_time sec %d usec %d : max_dep_index %d, t.sec %d t.usec %d\n", max_window_time.sec, max_window_time.usec,  max_dep_index, t.sec, t.usec );
+
+		if ((t.sec>max_window_time.sec)||(t.sec==max_window_time.sec && t.usec>max_window_time.usec))
+			break;
+		
+		max_dep_index++;
+	}
+
+	/* Right now it is not clear how to deal with the situation where MAX_PLAY_WINDOW is reached */
+	if (max_dep_index == min_dep_index+MAX_PLAY_WINDOW) {
+		//printf ("can not catch up the speed, max_dep_index %d reach min_dep_index %d+MAX_PLAY_WINDOW\n", max_dep_index, min_dep_index);
+		//printf (".");
+		can_not_catch_speed_num ++;
+	}
+	//RFS_ASSERT (max_dep_index < min_dep_index+MAX_PLAY_WINDOW);
+#else
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+	max_dep_index = min_dep_index + MAX_PLAY_WINDOW;
+	if (max_dep_index >dep_tab_size)
+		max_dep_index = dep_tab_size;
+#endif
+
+	if (flag == BUSY)
+		*poll_timeout = 0;
+   	else if (max_dep_index == dep_tab_size) {
+		*poll_timeout = 1000000;	/* poll_timeout set to 1 second for the last request */
+	} else {
+#ifdef TIME_PLAY
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[max_dep_index].timestamp.tv_sec;
+		tmp.usec = dep_tab[max_dep_index].timestamp.tv_usec;
+		if (adjust_play_window_debug)
+			printf ("dep_tab[max_dep_index %d].timestamp %d:%d, max_window_time %d:%d\n",
+				max_dep_index, tmp.sec, tmp.usec, max_window_time.sec, max_window_time.usec);
+
+		SUBTIME (tmp, max_window_time);
+#ifdef SPEED_UP
+		DIVTIME (tmp, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+		MULTIME (tmp, PLAY_SCALE);
+#endif
+		tmp1 = tmp;
+
+		if (tmp.sec > max_poll_time.sec) {
+
+			if (rfs_debug) 
+				printf ("dep_tab[%d].timestamp %d:%d, max_window_time %d:%d\n",
+				max_dep_index, dep_tab[max_dep_index].timestamp.tv_sec, dep_tab[max_dep_index].timestamp.tv_usec, max_window_time.sec, max_window_time.usec);
+			printf ("skip %d seconds\n", tmp.sec-max_poll_time.sec);
+			SUBTIME (tmp, max_poll_time);
+			tmp.usec = 0;
+			skip_sec += tmp.sec;
+			SUBTIME (test_start, tmp);
+			tmp = max_poll_time;
+		}
+
+		RFS_ASSERT ((tmp.sec < 1000));
+		if ((tmp.sec ==0) && (tmp.usec==0)) {
+			*poll_timeout = 0;
+		} else
+			*poll_timeout = tmp.sec*1000000+tmp.usec;
+#else 
+		/*
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[max_dep_index].timestamp.tv_sec;
+		tmp.usec = dep_tab[max_dep_index].timestamp.tv_usec;
+		tmp1.sec = dep_tab[max_dep_index-1].timestamp.tv_sec;
+		tmp1.usec = dep_tab[max_dep_index-1].timestamp.tv_usec;
+		SUBTIME (tmp, tmp1);
+		RFS_ASSERT ((tmp.sec < 1000));
+		RFS_ASSERT ((tmp.sec>0) || ((tmp.sec==0) && (tmp.usec>0)));
+		*poll_timeout = tmp.sec*1000000+tmp.usec;
+		*/
+
+		*poll_timeout = 100000;
+#endif
+	}	
+	if (rfs_debug)
+		printf ("adjust_play_window: flag %d min %d -> %d, max %d -> %d poll_timeout %d \n", flag, old_min, min_dep_index, old_max, max_dep_index, *poll_timeout);
+}
+
+/* poll for usecs and receive, after receive one reply,
+ * return index in biod_reqp of the corresponding request
+ */
+int poll_and_get_reply (int usecs)
+{
+	int biod_index = -1;
+	int xid;
+	int error;
+	struct timeval zero_time = {0, 0}; /* Immediately return */
+
+	do {
+		error = biod_poll_wait (NFS_client, usecs);
+		switch (error) {
+		case -1:
+			if (errno == EINTR) {
+				error = 1;
+				continue;
+			}
+			if (rfs_debug) {
+				(void) fprintf(stderr, "biod_poll_wait error\n");
+				perror ("");
+			    (void) fflush(stderr);
+			}
+			break;
+		case 0:
+			break;
+		default:
+#ifdef UDP
+			error = get_areply_udp (NFS_client, &xid, &zero_time);
+			// RFS_ASSERT (error!= RPC_TIMEOUT);	/* we have polled and know there is data */
+			// RFS_ASSERT (error!= RPC_CANTRECV);
+			RFS_ASSERT (error == RPC_SUCCESS);
+
+			biod_index = lookup_biod_req (xid);
+			sfs_gettime (&(biod_reqp[biod_index].stop));
+#else
+			RFS_ASSERT (0);
+#endif
+		}
+	} while (0);
+	return biod_index;
+}
+
+void print_result(void)
+{
+	int i, j;
+	struct ladtime t;
+	int dep_index;
+	int avg_msecs;
+	unsigned long long tmp;
+	int avg_usecs;
+
+	printf("read_data_bytes %d owe %d GB and %d bytes, adjusted %d times \n",read_data_total, read_data_owe_GB, read_data_owe, read_data_adjust_times);
+	printf("write_data_bytes %d owe %d GB and %d bytes, adjusted %d times \n",write_data_total, write_data_owe_GB, write_data_owe, write_data_adjust_times);
+	printf("failed_create_command_num %d skipped_readlink_command_num %d skipped_custom_command_num %d\n missing_reply_num %d rename_rmdir_noent_reply_num %d rmdir_not_empty_reply_num %d\n loose_access_control_reply_num %d, proper_reply_num %d, lookup_err_due_to_rename %d\n", 
+			failed_create_command_num, skipped_readlink_command_num, skipped_custom_command_num,
+			missing_reply_num, rename_rmdir_noent_reply_num, rmdir_not_empty_reply_num, 
+			loose_access_control_reply_num, lookup_err_due_to_rename_num, proper_reply_num );
+
+    if (DEBUG_CHILD_GENERAL) {
+		(void) fprintf(stdout, "trace play result:\n");
+		(void) fprintf(stdout, "\t    percentage good_cnt bad_cnt timeout_cnt\telapsed time\t\t\taverage time\n");
+		for (i=0; i<NOPS+1; i++) {
+			if (Ops[i].results.good_calls==0) {
+				avg_msecs = 0;
+				avg_usecs = 0;
+			} else {
+				tmp = Ops[i].results.time.sec*1000000 + Ops[i].results.time.usec;
+				avg_msecs = 0;
+				avg_usecs = tmp/Ops[i].results.good_calls;
+/*
+				avg_msecs = (Ops[i].results.time.sec*1000 + Ops[i].results.time.usec/1000)/Ops[i].results.good_calls;
+				avg_usecs = (Ops[i].results.time.usec%1000)/Ops[i].results.good_calls;
+*/
+			}
+			(void) fprintf(stdout,	"%11s\t%4.1f\t%4d\t%4d\t%4d\t\tsec %8d usec %8d \tusec %8d\n", 
+				Ops[i].name, 
+				(float)(100*Ops[i].results.good_calls)/(float)Ops[TOTAL].results.good_calls, 
+				Ops[i].results.good_calls, Ops[i].results.bad_calls, Ops[i].results.timeout_calls,
+				Ops[i].results.time.sec, Ops[i].results.time.usec, avg_msecs*1000+avg_usecs);
+		}
+		(void) fflush (stdout);
+    }
+
+    clnt_destroy(NFS_client);
+    biod_term();
+
+//   print_dump(Client_num, Child_num);
+	return;
+	dep_index = 0;
+	printf ("[%4d] %s \tstart %4d:%6d \n",
+		dep_index, Ops[dep_tab[dep_index].proc].name, dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec);
+	for (i=1; i<dep_tab_size*2; i++) {
+		dep_index = event_order[i];
+		if (dep_index >0) 
+			printf ("[%4d] %s \tstart %4d:%6d \n",
+				dep_index, Ops[dep_tab[dep_index].proc].name, dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec);
+		else {
+			dep_index = -dep_index;
+			t=dep_tab[dep_index].stop;
+			SUBTIME (t, dep_tab[dep_index].start);
+			printf ("\t\t\t\t\t[%4d] %s stop %4d:%6d\tinterval %4d:%6d %s\n",
+				dep_index, Ops[dep_tab[dep_index].proc].name, dep_tab[dep_index].stop.sec, dep_tab[dep_index].stop.usec, t.sec, t.usec, nfs3_strerror(dep_tab[dep_index].status));
+		}	
+	}
+/*
+	
+	for (i=0, j=0; i<dep_tab_size || j<dep_tab_size; ) {
+		if ((i==dep_tab_size) || 
+			(LARGERTIME(dep_tab[i].start, dep_tab[j].stop) && j<dep_tab_size)) {
+			t=dep_tab[j].stop;
+			SUBTIME (t, dep_tab[j].start);
+			printf ("dep_tab[%d].proc %s                  stop %d:%d interval %d:%d status %s\n",
+				j, Ops[dep_tab[j].proc].name, dep_tab[j].stop.sec, dep_tab[j].stop.usec, t.sec, t.usec, nfs3_strerror(dep_tab[j].status));
+			j++;
+		} else {
+			printf ("dep_tab[%d].proc %s start %d:%d \n",
+				i, Ops[dep_tab[i].proc].name, dep_tab[i].start.sec, dep_tab[i].start.usec);
+			i++;
+		}
+	}
+*/
+} 
+
+/*
+ * allocate and initialize client handles
+ */
+static int
+init_rpc(void)
+{
+	int dummy = 0;
+
+    /*
+     * Set up the client handles.  We get them all before trying one
+     * out to insure that the client handle for LOOKUP class is allocated
+     * before calling op_getattr().
+     */
+    if (DEBUG_CHILD_GENERAL) {
+    	(void) fprintf(stderr, "%s: set up client handle\n", sfs_Myname);
+    }
+
+    NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+					(uint32_t) NFS_PROGRAM,
+					(uint32_t) nfs_version,
+					RPC_ANYSOCK, &Nfs_timers[0]);
+		
+    if (NFS_client  == ((CLIENT *) NULL)) {
+        return(-1);
+    }
+
+    /*
+     * create credentials using the REAL uid
+     */
+    NFS_client->cl_auth = authunix_create(lad_hostname, (int)Real_uid,
+				      (int)Cur_gid, 0, NULL);
+
+
+	if (biod_init(dummy, dummy) == -1) {
+		    return(-1);
+	}
+
+    return(0);
+} /* init_rpc */
+
+void
+init_counters(void)
+{
+    uint_t i;
+    uint_t start_msec;
+
+    /* Ready to go - initialize operation counters */
+    for (i = 0; i < NOPS + 1; i++) {
+	Ops[i].req_cnt = 0;
+	Ops[i].results.good_calls = 0;
+	Ops[i].results.bad_calls = 0;
+	Ops[i].results.timeout_calls = 0;	// RFS
+	Ops[i].results.fast_calls = 0;
+	Ops[i].results.time.sec = 0;
+	Ops[i].results.time.usec = 0;
+	Ops[i].results.msec2 = 0;
+    }
+
+    /* initialize timers and period variables */
+    sfs_gettime(&Starttime);
+    Cur_time = Starttime;
+    start_msec = (Starttime.sec * 1000) + (Starttime.usec / 1000);
+    Previous_chkpnt_msec = start_msec;
+    Calls_this_period = 0;
+    Reqs_this_period = 0;
+    Sleep_msec_this_period = 0;
+    Calls_this_test = 0;
+    Reqs_this_test = 0;
+    Sleep_msec_this_test = 0;
+}
+
+static char *
+nfs3_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS3_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFS3ERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFS3ERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFS3ERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFS3ERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFS3ERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFS3ERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFS3ERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFS3ERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFS3ERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFS3ERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFS3ERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFS3ERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFS3ERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFS3ERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFS3ERR_MLINK:
+	    (void) strcpy(str, "Too many links");
+	    break;
+	case NFS3ERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFS3ERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFS3ERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFS3ERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFS3ERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFS3ERR_BADHANDLE:
+	    (void) strcpy(str, "Bad file handle");
+	    break;
+	case NFS3ERR_NOT_SYNC:
+	    (void) strcpy(str, "Not sync write");
+	    break;
+	case NFS3ERR_BAD_COOKIE:
+	    (void) strcpy(str, "Bad cookie");
+	    break;
+	case NFS3ERR_NOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFS3ERR_TOOSMALL:
+	    (void) strcpy(str, "Value too small");
+	    break;
+	case NFS3ERR_SERVERFAULT:
+	    (void) strcpy(str, "Server fault");
+	    break;
+	case NFS3ERR_BADTYPE:
+	    (void) strcpy(str, "Bad type");
+	    break;
+	case NFS3ERR_JUKEBOX:
+	    (void) strcpy(str, "Jukebox");
+	    break;
+	case NFS3ERR_RFS_TIMEOUT:
+		(void) strcpy(str, "Timeout");
+		break;
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+
+/*
+ * Check the gettimeofday() resolution. If the resolution
+ * is in chunks bigger than SFS_MIN_RES then the client
+ * does not have a usable resolution for running the 
+ * benchmark.
+ */
+static void
+check_clock(void)
+{
+	double time_res;
+	char tmp_hostname[HOSTNAME_LEN];
+
+	time_res = get_resolution();
+    	getmyhostname(tmp_hostname, HOSTNAME_LEN);
+	if( time_res > (double)SFS_MIN_RES )
+	{
+		(void) fprintf(stderr,
+		"\n%s: Clock resolution too poor to obtain valid results.\n",
+			tmp_hostname);
+		(void) fprintf(stderr,
+		"%s: Clock resolution %f Micro seconds.\n", tmp_hostname,
+			time_res);
+		exit(175);
+	}
+	else
+	{
+		(void) fprintf(stderr,
+		"\n%s: Good clock resolution [ %f ] Micro seconds.\n", 
+			tmp_hostname, time_res);
+	}
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns the resolution of the gettimeofday() function 
+ * in microseconds.
+ */
+static double
+get_resolution(void)
+{
+        double starttime, finishtime, besttime;
+        long  j,delay;
+	int k;
+
+        finishtime=time_so_far1(); /* Warm up the instruction cache */
+        starttime=time_so_far1();  /* Warm up the instruction cache */
+        delay=j=0;                 /* Warm up the data cache */
+	for(k=0;k<10;k++)
+	{
+	        while(1)
+       	 	{
+       	         	starttime=time_so_far1();
+       	         	for(j=0;j< delay;j++)
+       	                ;
+       	         	finishtime=time_so_far1();
+       	         	if(starttime==finishtime)
+       	                 	delay++;
+       	         	else
+			{
+				if(k==0)
+					besttime=(finishtime-starttime);
+				if((finishtime-starttime) < besttime)
+					besttime=(finishtime-starttime);
+                       	 	break;
+			}
+		}
+        }
+         return(besttime);
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns current result of gettimeofday() in microseconds.
+ */
+/************************************************************************/
+/* Time measurement routines.                                           */
+/* Return time in microseconds                                          */
+/************************************************************************/
+
+static double
+time_so_far1(void)
+{
+        /* For Windows the time_of_day() is useless. It increments in 55 */
+	/* milli second increments. By using the Win32api one can get */
+	/* access to the high performance measurement interfaces. */
+	/* With this one can get back into the 8 to 9 microsecond */
+	/* resolution.  */
+#ifdef Windows
+        LARGE_INTEGER freq,counter;
+        double wintime;
+        double bigcounter;
+
+        QueryPerformanceFrequency(&freq);
+        QueryPerformanceCounter(&counter);
+        bigcounter=(double)counter.HighPart *(double)0xffffffff +
+                (double)counter.LowPart;
+        wintime = (double)(bigcounter/(double)freq.LowPart);
+        return((double)wintime*1000000.0);
+#else
+#if defined (OSFV4) || defined(OSFV3) || defined(OSFV5)
+  struct timespec gp;
+
+  if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1)
+    perror("getclock");
+  return (( (double) (gp.tv_sec)*1000000.0) +
+    ( ((float)(gp.tv_nsec)) * 0.001 ));
+#else
+  struct timeval tp;
+
+  if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
+    perror("gettimeofday");
+  return ((double) (tp.tv_sec)*1000000.0) +
+    (((double) tp.tv_usec) );
+#endif
+#endif
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "trace play usage");
+}
+extern void init_file_system (void)
+{
+	return;
+}
+
+extern void init_dep_tab (void)
+{
+	int i;
+	memset (&dep_tab, 0, sizeof(dep_tab));
+#ifdef notdef
+	dep_tab[0].disk_index = 0;
+	dep_tab[1].disk_index = 2;
+	dep_tab[2].disk_index = 3;
+	dep_tab[3].disk_index = 5;
+	dep_tab[4].disk_index = 7;
+	dep_tab[5].disk_index = 9;
+	dep_tab[6].disk_index = 11;
+	dep_tab[7].disk_index = 12;
+	dep_tab[8].disk_index = 15;
+	dep_tab[9].disk_index = 17;
+	dep_tab[10].disk_index = 18;
+	dep_tab[11].disk_index = 20;
+	dep_tab_size = 12;
+	//dep_tab_size = 2;
+#endif
+}
+
+extern void init_dep_tab_old (void)
+{
+	int i;
+
+	Cur_file_ptr = &Export_dir;
+	Cur_uid = Real_uid;
+
+	for (i=0; i<5; i++) {
+		dep_tab[i].flag = DEP_FLAG_INIT;
+		dep_tab[i].proc = CREATE;
+		dep_tab[i].timestamp.tv_sec = trace_starttime.sec;
+	    dep_tab[i].timestamp.tv_usec = trace_starttime.usec+i*10;	
+		dep_tab[i].init_dep_num = 0;
+		dep_tab[i].cur_dep_num = 0;
+	}
+
+	for (i=5; i<10; i++) {
+		dep_tab[i].flag = DEP_FLAG_INIT;
+		dep_tab[i].proc = CREATE;
+		dep_tab[i].timestamp.tv_sec = trace_starttime.sec+i;
+	    dep_tab[i].timestamp.tv_usec = trace_starttime.usec;	
+		dep_tab[i].init_dep_num = 0;
+		dep_tab[i].cur_dep_num = 0;
+	}
+
+	dep_tab[2].init_dep_num = 2;
+	dep_tab[2].cur_dep_num = 2;
+	dep_tab[2].dep_ops[0] = 0;
+	dep_tab[2].dep_ops[1] = 1;
+
+	// printf ("trace_starttime (%d %d)\n", trace_starttime.sec, trace_starttime.usec);
+
+	/*
+	for (i=2; i<4; i++) {
+		dep_tab[i].flag = DEP_FLAG_INIT;
+		dep_tab[i].proc = CREATE;
+		dep_tab[i].timestamp.tv_sec = trace_starttime.sec+i*10;
+	    dep_tab[i].timestamp.tv_usec = trace_starttime.usec;	
+		dep_tab[i].init_dep_num = 0;
+		dep_tab[i].cur_dep_num = 0;
+	}
+	*/
+
+	dep_tab_size = 10;
+
+	for (i=0; i<dep_tab_size; i++)
+	{
+		printf("dep_tab[%d].timestamp (%d %d)\n", i, dep_tab[i].timestamp.tv_sec, dep_tab[i].timestamp.tv_usec);
+	}
+}
+
+void show_fhandle (nfs_fh3 * fhp)
+{
+	struct knfs_fh * kfhp = (struct knfs_fh *)fhp;
+
+	int dev;
+
+	if (quiet_flag)
+		return;
+		
+	RFS_ASSERT (kfhp->fh_version == 1);
+	RFS_ASSERT (kfhp->fh_fsid_type == 0);
+	RFS_ASSERT (kfhp->fh_auth_type == 0);
+
+	dev = ntohs(kfhp->fh_dev_major);
+	dev = dev<<8;
+	dev = dev + ntohs(kfhp->fh_dev_minor);
+
+	/* kfhp->fh_dev_ino hold the inode number of export point of the mounted
+	 * file system. For example, if /tmp/t1 is exported, /tmp/t1/t2 is mounted,
+	 * then fh_dev_ino hold the inode number of t1, not t2
+	 */
+
+	switch (kfhp->fh_fileid_type) {
+		case 0:
+			printf("fh:type 0 root dev 0x%x dev_ino %d\n", dev, kfhp->fh_dev_ino); 
+			break;
+		case 1:
+			printf("fh:type 1 %d %x dev %x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, dev, kfhp->fh_dev_ino);
+			break;
+		case 2:
+			printf("fh:type2 %d %x dirino %d dev 0x%x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, kfhp->fh_dirino, dev, kfhp->fh_dev_ino);
+			break;
+		default:
+			RFS_ASSERT (0);
+	}
+}
+
+nfs_fh3 zero_fhandle;
+int init_fh_map ()
+{
+	memset (fh_map, 0, sizeof (fh_map));
+	memset(fh_htable, 0, sizeof (fh_htable));
+	memset (&zero_fhandle, 0, sizeof(nfs_fh3));
+	printf ("SIZE of fh map %d KB\n", sizeof (fh_map)/1000);
+	fh_i = 0;
+}
+
+int add_fh (int map_flag, char * trace_fh, char * path, nfs_fh3 * play_fh)
+{
+	char * old_trace_fh;
+
+	/* first lookup if the entry for fh is already in the table */
+    struct generic_entry * p;
+
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (p) {
+		RFS_ASSERT (fh_map[p->key3].flag = FH_MAP_FLAG_PARTIAL);
+		RFS_ASSERT (map_flag ==FH_MAP_FLAG_COMPLETE);
+		fh_map[p->key3].flag = map_flag;
+		RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+		RFS_ASSERT (!strcmp(fh_map[p->key3].path, path));
+		RFS_ASSERT (!memcmp(&fh_map[p->key3].play_fh, &zero_fhandle, sizeof(nfs_fh3)));
+		memcpy (&fh_map[p->key3].play_fh, play_fh, sizeof (nfs_fh3));
+		if ((fh_map_debug==1)) // || (stage ==TRACE_PLAY_STAGE)) 
+			printf ("update the play_fh for trace_fh %s path %s \n", trace_fh, path);
+		return 0;
+	}
+
+	fh_map[fh_i].flag = map_flag;
+	fh_map[fh_i].lock = 0;
+	memcpy(fh_map[fh_i].trace_fh, trace_fh, TRACE_FH_SIZE);
+
+	RFS_ASSERT (strlen(path) < MAX_PLAY_PATH_SIZE);
+	strcpy (fh_map [fh_i].path, path);
+	if (map_flag==FH_MAP_FLAG_COMPLETE)
+		memcpy (&fh_map[fh_i].play_fh, play_fh, sizeof(nfs_fh3));
+	else 
+		memset (&fh_map[fh_i].play_fh, 0, sizeof(nfs_fh3));
+
+	if ((fh_map_debug==1)) { // || (stage ==TRACE_PLAY_STAGE)) {
+		printf ("insert trace_fh %s path %s play_fh:\n", trace_fh, path);
+		if (map_flag == FH_MAP_FLAG_COMPLETE)
+			show_fhandle(play_fh);
+		else 
+			printf("null\n");
+	}
+
+/*
+	if (map_flag == FH_MAP_FLAG_DISCARD)
+		printf ("insert flag %d trace_fh %s path %s play_fh:\n", map_flag, trace_fh, path);
+*/
+
+    generic_insert(trace_fh, TRACE_FH_SIZE, fh_i, fh_htable, FH_HTABLE_SIZE);
+	
+	fh_i = (fh_i+1);
+	RFS_ASSERT (fh_i < FH_MAP_SIZE);
+
+    return 0;
+};
+
+fh_map_t * lookup_fh (char * trace_fh )
+{
+    struct generic_entry * p;
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (fh_map_debug==1)
+		printf ("lookup trace_fh %s\n", trace_fh);
+
+    if (p) {
+		if (fh_map_debug==1) {
+			printf ("found: fh_i %d path %s play_fh:", p->key3, fh_map[p->key3].path);
+			show_fhandle(&fh_map[p->key3].play_fh);
+		}
+        return (&(fh_map[p->key3]));
+    } else {
+		//printf ("lookup_fh %s not found\n", trace_fh);
+		if (stage != READ_DEP_TAB_STAGE && (fh_map_debug==1)) {
+			printf ("lookup not found trace_fh %s\n", trace_fh);
+		}
+        return NULL;
+	}
+	RFS_ASSERT (0);
+}
+
+int delete_fh (char * trace_fh, int fh_map_index)
+{
+    generic_delete (trace_fh, TRACE_FH_SIZE, fh_map_index, fh_htable, FH_HTABLE_SIZE);
+    return 0;
+};
+
+void lookup_init_filesystem (nfs_fh3 * parent, char * name, nfs_fh3 * result)
+{
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+	static int i=0;
+
+    /* set up the arguments */
+    (void) memcpy((char *) &args.what.dir, (char *) parent,
+							sizeof (nfs_fh3));
+    args.what.name = name;
+    (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			Nfs_timers[Init]);
+    sfs_gettime(&stop);
+
+	if (rpc_stat !=RPC_SUCCESS) {
+		printf("rpc_stat %d\n", rpc_stat);
+		perror("");
+	}
+    RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+	RFS_ASSERT (reply.status == NFS3_OK);
+	(void) memcpy((char *) result, (char *) &reply.resok.object, sizeof (nfs_fh3));
+}
+
+void read_fh_map(char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	char trace_fh[TRACE_FH_SIZE];
+	char intbuf[9];
+	char * trace_path;
+	char * p;
+	int map_flag;
+#define MAX_PATH_DEPTH 20
+	nfs_fh3 parents[MAX_PATH_DEPTH];
+	char * lookup_path_ptr[MAX_PATH_DEPTH];
+	char lookup_path [MAX_PLAY_PATH_SIZE];
+	int depth;
+	int new_dir_flag = 0;
+
+	depth = 0;
+	memset(lookup_path_ptr, 0, sizeof(lookup_path_ptr));
+	memcpy(&parents[depth], &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+	strcpy(lookup_path, "/");
+	lookup_path_ptr[depth]=&lookup_path[0];
+
+	fp = fopen(fh_map_file, "r");
+	RFS_ASSERT (fp!=NULL);
+	
+	intbuf[8]=0;
+
+	memset(buf, 0, sizeof(buf));
+	while (fgets(buf, 1024, fp)) {
+
+		if (fh_i % 10000==0)
+			printf("%d fh_map entry read\n", fh_i);
+
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf[strlen(buf)-1]=0;
+		if (fh_map_debug) {
+			printf("%d fgets return %s\n", fh_i, buf);
+			printf("depth %d lookup_path %s\n", depth, lookup_path);
+		}
+		//for (i=0; i<=depth; i++) 
+			//printf("lookup_path_ptr[%d] %s ", i, lookup_path_ptr[i]);
+		//printf("\n");
+#ifdef COMPRESS_TRACE_FH 
+		for (i=0; i<TRACE_FH_SIZE/8; i++) {
+			strncpy(intbuf, buf+i*8, 8);
+			sscanf(intbuf, "%x", trace_fh+i*8); // maybe it should be 4, anyway we don't compress for now 
+		}
+		trace_path = buf+TRACE_FH_SIZE*2+1;		/* +1 the trace contains only initial file handle */
+#else
+		memcpy(trace_fh, buf, TRACE_FH_SIZE);
+		trace_path = buf + TRACE_FH_SIZE +1;
+#endif
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		trace_path = +=2;	/* +3 if the trace contains both initial and later created file handle */
+#endif
+
+#ifdef NO_DEPENDENCY_TABLE
+		if (!strncmp (trace_path, "DISCARD", 7)) {
+			map_flag = FH_MAP_FLAG_DISCARD;
+			add_fh (map_flag, buf, trace_path, 0);
+			continue;
+		}
+#endif
+		
+		p = trace_path+strlen(trace_path)-2;
+		while (*p!='/')
+			p--;
+		p++;
+		//RFS_ASSERT (p-trace_path<=strlen(lookup_path)+1);
+		//RFS_ASSERT (p>trace_path);
+
+		if (strncmp(lookup_path, trace_path, p-trace_path)) {
+			printf("strncmp lookup_path %s trace_path %s for length %d\n", lookup_path, trace_path, p-trace_path);
+		}
+		RFS_ASSERT (!strncmp(lookup_path, trace_path, p-trace_path));
+		//while (strncmp(lookup_path, trace_path, p-trace_path)) {	/* one step deeper */
+		while (strlen(lookup_path)>p-trace_path && depth>0) {
+			//printf("depth--\n");
+			if (depth<=0) 
+				printf ("lookup_path %s trace_path %s p-trace_path %d depth %d\n", lookup_path, trace_path, p-trace_path, depth);
+			RFS_ASSERT (depth>0);
+			*lookup_path_ptr[depth]=0;
+			lookup_path_ptr[depth]=0;
+			depth--;
+		}
+		RFS_ASSERT (strlen(lookup_path)==(p-trace_path) || (depth==0));
+
+
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		if (buf[TRACE_FH_SIZE*2+1]=='Y') {
+			map_flag = FH_MAP_FLAG_COMPLETE;
+		} else {
+			map_flag = FH_MAP_FLAG_PARTIAL;
+			RFS_ASSERT (buf[TRACE_FH_SIZE*2+1]=='N');
+		}
+#else
+		map_flag = FH_MAP_FLAG_COMPLETE;
+#endif
+		if ((*(p+strlen(p)-1))=='/') {
+			*(p+strlen(p)-1)=0;
+			new_dir_flag = 1;
+		} else 
+			new_dir_flag = 0;
+
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			lookup_init_filesystem (&parents[depth], p, &parents[depth+1]);		
+			add_fh (map_flag, buf, trace_path, &parents[depth+1]);	
+		} else 
+			add_fh (map_flag, buf, trace_path, 0);
+
+		if (new_dir_flag) {
+			/* the new fhandle is of a directory */
+			lookup_path_ptr[depth+1] = lookup_path+strlen(lookup_path);
+			strcat (lookup_path, p);
+			strcat (lookup_path, "/");
+
+			//printf("depth++\n");
+			depth++;
+		}
+
+		memset(buf, 0, sizeof(buf));
+	}
+			
+	if (fh_map_debug) {
+		for (i=0; i<fh_i; i++) {
+			int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+			int * p = (int *)fh_map[i].trace_fh;
+			printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+			printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, fh_map[i].trace_fh, fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+		}
+#endif
+
+		fprintf(stderr, "total %d requests \n", i);
+	}
+}
+
+int f()
+{
+	return 1;
+}
+
+inline void finish_request (int biod_index, int dep_index, int status)
+{
+	/* the ending operation, same as when a request time out */
+	dep_tab[dep_index].stop = biod_reqp[biod_index].stop;	/* RFS: to dump data */
+	dep_tab[dep_index].status = status;
+	event_order[event_order_index++] = -dep_index;
+	biod_reqp[biod_index].in_use = FALSE;
+	dep_tab[dep_index].flag = DEP_FLAG_DONE;
+	if (is_dir_op(dep_tab[dep_index].proc)) {
+		int j;
+		RFS_ASSERT (dep_tab[dep_index].fh->lock = 1);
+		dep_tab[dep_index].fh->lock = 0;
+		if (dep_tab[dep_index].proc==RENAME)
+			dep_tab[dep_index].fh_2->lock = 0;
+		j = dep_tab[dep_index].fh-fh_map;
+		if (dependency_debug) {
+			printf ("fh_map[%d] is UNlocked\n",j);
+			printf ("trace_fh %d path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+			printf ("trace_fh %d path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+		}
+	}
+	num_out_reqs --;
+}
+
+/* the request argument may have pointers pointing to buffers, e.g. the name in lookup, 
+ * the target of symlink, the write data */
+char arg_res[MAX_ARG_RES_SIZE];
+int poll_timeout = 0;		/* timeout in usecs */
+char buf1 [MAX_BUF1_SIZE]; 
+char buf2 [MAX_BUF2_SIZE];
+#define NFS3_REPLY_MISS -1
+
+int execute_next_request ()
+{
+	int dep_index;
+	int proc;
+	char * line;
+	struct biod_req * reqp;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime call_timeout;
+
+	start_profile (&valid_get_nextop_profile);
+	start_profile (&invalid_get_nextop_profile);
+	dep_index = get_nextop();
+	if (dep_index == -1) {
+		end_profile (&invalid_get_nextop_profile);
+		return dep_index;
+	};
+	end_profile (&valid_get_nextop_profile);
+
+	start_profile (&prepare_argument_profile);
+	line = dep_tab[dep_index].line;
+	if ((dep_index%(10000))==0) {
+#ifndef TIME_PLAY
+		fprintf (stderr, "processing dep_tab[%d] disk_index %d num_out_reqs %d \n", dep_index, dep_tab[dep_index].disk_index, num_out_reqs);
+#else
+		fprintf (stderr, "processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+#ifdef SPEED_UP
+		if (can_not_catch_speed_num < 2000) {
+			PLAY_SCALE ++;
+			printf ("set PLAY_SCALE to %d\n", PLAY_SCALE);
+		};
+		if (can_not_catch_speed_num > 50000) {
+			PLAY_SCALE /= 2;
+		} else {
+			if (can_not_catch_speed_num > 5000) {
+				PLAY_SCALE -= 2;
+				if (PLAY_SCALE < 1)
+					PLAY_SCALE = 1;
+			}
+		}
+#endif
+		can_not_catch_speed_num = 0;
+#endif
+	}
+	if (rfs_debug)
+		printf ("processing dep_tab[%d] disk_index %d %s\n", dep_index, dep_tab[dep_index].disk_index, line);
+
+	proc = dep_tab[dep_index].proc;
+	rfs_Ops[proc].setarg (dep_index, line, arg_res, buf1, buf2);
+
+	op_ptr = &Ops[proc];
+	reqp = get_biod_req (dep_index);
+	RFS_ASSERT (reqp);
+
+	call_timeout.sec = 4; //Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+
+    /* make the call */
+    sfs_gettime(&(reqp->start));
+	end_profile (&prepare_argument_profile);
+	start_profile (&biod_clnt_call_profile);
+#define REAL_PLAY
+#ifdef REAL_PLAY
+    reqp->xid = biod_clnt_call(NFS_client, rfs_Ops[proc].nfsv3_proc, 
+					rfs_Ops[proc].xdr_arg, arg_res);
+#else
+
+	reqp->xid = dep_index+1;	/* just fake a message id and let it expire */
+#endif
+    if (reqp->xid != 0) {
+        reqp->timeout = reqp->start;
+        ADDTIME (reqp->timeout, call_timeout);
+        num_out_reqs++;
+        dep_tab[dep_index].flag = DEP_FLAG_SENT;
+		event_order[event_order_index++] = dep_index;
+    } else
+		RFS_ASSERT (0);
+
+	dep_tab[dep_index].start = reqp->start;	/* RFS: to dump data */
+	end_profile (&biod_clnt_call_profile);
+}
+
+void check_reply (int proc, int biod_index, int dep_index, int status, char * errmsg, int trace_reply_status)
+{
+	if (((status!=trace_reply_status)) && (trace_reply_status!=NFS3_REPLY_MISS)) {
+		if (rfs_debug)
+			printf ("receive problem reply, xid %x nfs_ret %d %s trace_reply_status %d start %d:%d stop %d:%d command disk index %d\n", biod_reqp[biod_index].xid, status, errmsg, trace_reply_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec, dep_tab[dep_index].disk_index); 
+#ifndef TAKE_CARE_UNLOOKED_UP_NON_NEW_FILES
+		/* these files is not looked up and is not create/mkdir/symlink/link/mknod ed before they
+		 * are refered by name through rename, remove
+		 */
+		if ((proc==RENAME || proc==REMOVE) && (status==NFS3ERR_NOENT) && (trace_reply_status ==0)) {
+			/* current initialization doesnot take care of rename source, if there is no
+			 * create or lookup before that source, the source object will not exist when
+			 * rename occurs
+			 */
+			RFS_ASSERT (1);
+			rename_rmdir_noent_reply_num++;
+		} else 
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+		if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_reply_status==NFS3ERR_NOENT)) {
+			/* in the original trace, first lookup return NOENT, then symlink is executed, then lookup return OK
+			 * the initialization considers only the lookup return OK and created the file in the initialization
+			 * so in trace play the first lookup return OK
+			 */
+			RFS_ASSERT (1);
+		} else if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) && (trace_reply_status == 0)) {
+			/* due to similar reason as above, the initialization code initializes the symbolic link as a normal
+			 * file already
+			 */
+			RFS_ASSERT (1);
+		} else
+#endif
+#ifndef TAKE_CARE_NOEMPTY_RMDIR
+		/* the remove packet seems got lost in the trace capture, so replay can not finish */
+		if ((proc==RMDIR) && (status==NFS3ERR_NOTEMPTY)) {
+   			RENAME3args		args;
+   			RENAME3res		reply;		/* the reply */
+			RMDIR3args * rmdir_argp;
+			enum clnt_stat rpc_stat;	/* result from RPC call */
+
+			rfs_Ops[proc].setarg (dep_index, dep_tab[dep_index].line, arg_res, buf1, buf2);
+			rmdir_argp = (RMDIR3args *)arg_res;
+
+			memcpy(&args.from, &(rmdir_argp->object), sizeof (diropargs3));
+			memcpy(&args.to.dir, &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+			args.from.name = buf1;	/* the buf1 is already filled when parsing rmdir */
+			args.to.name = buf2;
+			sprintf(buf2, "rmdir_%d_%s", dep_tab[dep_index].disk_index, rmdir_argp->object.name);
+
+  			rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
+			xdr_RENAME3args, (char *) &args,
+			xdr_RENAME3res, (char *) &reply,
+				Nfs_timers[Init]);
+			RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+			if (reply.status!=NFS3_OK)
+				printf ("change rmdir into rename, reply.status %d\n", reply.status);
+			RFS_ASSERT (reply.status==NFS3_OK);
+			rmdir_not_empty_reply_num ++;
+#endif
+#ifndef TAKE_CARE_ACCESS_ERROR
+		} else if ((status==0) && (trace_reply_status==NFS3ERR_ACCES)) {
+			loose_access_control_reply_num ++;
+#endif
+#ifdef NO_DEPENDENCY_TABLE 
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_reply_status==NFS3_OK)) {
+			lookup_err_due_to_rename_num ++;
+#endif
+		} else {
+			int i;
+			for (i=min_dep_index; i<max_dep_index; i++) 
+				printf ("dep_tab[%d].disk_index %d, flag %d line %s\n", i, dep_tab[i].disk_index, dep_tab[i].flag, dep_tab[i].line);
+			RFS_ASSERT (0);
+		}
+	} else 
+		proper_reply_num ++;
+
+}
+
+/* return -1 if there is no reply being received 
+ * return the dep_index if the corresponding reply has been received
+ */
+int receive_next_reply (int busy_flag)
+{
+	int dep_index;
+	int biod_index;
+	int proc;
+	char * line;
+	char * reply_line;
+	sfs_op_type *op_ptr;		/* per operation info */
+	int ret;
+	int status;
+	int trace_reply_status;
+	char * errmsg;
+
+	/* wait for reply */
+	start_profile (&valid_poll_and_get_reply_profile);
+	start_profile (&invalid_poll_and_get_reply_profile);
+/*
+	if (busy_flag == IDLE)
+		poll_timeout = 0;
+	else 
+		poll_timeout = 10000;
+*/
+	biod_index = poll_and_get_reply (poll_timeout);
+	if (biod_index==-1) {
+		end_profile (&invalid_poll_and_get_reply_profile);
+		return -1;
+	};
+	end_profile (&valid_poll_and_get_reply_profile);
+
+	start_profile (&decode_reply_profile);
+	/* check the corresponding request */
+	dep_index = biod_reqp[biod_index].dep_tab_index;
+	proc = dep_tab[dep_index].proc;
+	op_ptr = &Ops[proc];
+
+	if (dep_tab[dep_index].flag != DEP_FLAG_SENT) {
+		printf("dep_tab[%d].flag %d proc %d status %d start %d:%d stop %d:%d\n",
+			dep_index, dep_tab[dep_index].flag, proc, dep_tab[dep_index].status, 
+			dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec,
+			dep_tab[dep_index].stop.sec, dep_tab[dep_index].stop.usec );
+		printf ("received reply for timeout requests dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+		return dep_index;
+	}
+	RFS_ASSERT (dep_tab[dep_index].flag == DEP_FLAG_SENT);
+
+	/* decode the reply */
+	rfs_Ops[proc].setres (arg_res, buf1);
+	ret = proc_header (NFS_client, rfs_Ops[proc].xdr_res, arg_res);
+	RFS_ASSERT (ret == RPC_SUCCESS);
+	status = *((int *)arg_res);
+	errmsg = nfs3_strerror (status);
+	end_profile (&decode_reply_profile);
+
+	start_profile (&check_reply_profile);
+	/* compare with the reply in the trace */
+	line = dep_tab[dep_index].line;
+	reply_line = find_reply_line (line, dep_tab[dep_index].disk_index);
+	if (reply_line == NULL) {
+		//printf ("disk[%d] can not find the reply line, assume trace_reply_status OK\n", dep_tab[dep_index].disk_index);
+		trace_reply_status = NFS3_REPLY_MISS;
+		missing_reply_num ++;
+	} else 
+		trace_reply_status = find_reply_status (reply_line);
+
+	/* print the result, trace play progress indicator */
+	if ((dep_index %10000)==0 || rfs_debug)
+		fprintf (stdout, "dep_tab[%d], disk_index %d, receive reply, rpc_ret %d xid %x nfs_ret %d %s trace_reply_status %d start %d:%d stop %d:%d \n", dep_index, dep_tab[dep_index].disk_index, ret, biod_reqp[biod_index].xid, status, errmsg, trace_reply_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec);
+
+	/* error checking */
+	check_reply (proc, biod_index, dep_index, status, errmsg, trace_reply_status);
+
+	/* free resources */
+	finish_request (biod_index, dep_index, status);
+	
+	/* get statistics */
+	if (status == trace_reply_status) {
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+	} else {
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	}
+	sfs_elapsedtime (op_ptr, &(biod_reqp[biod_index].start), &(biod_reqp[biod_index].stop));
+	end_profile (&check_reply_profile);
+	
+	//start_profile (&add_create_object_profile);
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+	if (trace_reply_status == NFS3_OK && (proc==CREATE || proc==MKDIR || proc==MKNOD)) {
+#else
+	if (trace_reply_status == NFS3_OK && (proc==CREATE || proc==MKDIR || proc==SYMLINK || proc==MKNOD)) {
+#endif
+		RFS_ASSERT (status == NFS_OK);
+		RFS_ASSERT (reply_line);
+		add_new_file_system_object(proc, dep_index, line, reply_line);
+	}
+	//end_profile (&add_create_object_profile);
+}
+
+void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line)
+{
+	char * child_trace_fh;
+	fh_map_t * parent_entryp;
+	char component_name[MAX_PLAY_PATH_SIZE];
+	char * parent_trace_fh;
+	char child_path[MAX_PLAY_PATH_SIZE];
+	post_op_fh3 * post_op_fh3_child;
+	char * reply_trace_fh;
+	nfs_fh3 * child_fh3;
+
+	parent_trace_fh = strstr (line, "fh");
+	RFS_ASSERT (parent_trace_fh);
+	parent_trace_fh +=3;
+	parent_entryp = lookup_fh (parent_trace_fh);
+	RFS_ASSERT (parent_entryp);
+	parse_name (parent_trace_fh+65, component_name);
+	strcpy (child_path, parent_entryp->path);
+	strcat (child_path, "/");
+	strcat (child_path, component_name);
+				
+	/* find the corresponding create request */
+	//printf ("before find reply trace_fh reply_line %s\n", reply_line);
+	reply_trace_fh = find_reply_trace_fh (reply_line);
+	RFS_ASSERT (reply_trace_fh != NULL);
+	switch (proc) {
+	case CREATE:
+		RFS_ASSERT (((CREATE3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((CREATE3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKDIR:
+		RFS_ASSERT (((MKDIR3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKDIR3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case SYMLINK:
+		RFS_ASSERT (((SYMLINK3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((SYMLINK3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKNOD:
+		RFS_ASSERT (((MKNOD3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKNOD3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case LOOKUP:
+		RFS_ASSERT (proc==LOOKUP);
+		child_fh3 = &((LOOKUP3res *)arg_res)->res_u.ok.object;
+		break;
+	default:
+		RFS_ASSERT (0);
+	}
+	RFS_ASSERT (reply_trace_fh[TRACE_FH_SIZE]==' ');
+	reply_trace_fh[TRACE_FH_SIZE] = 0;
+	add_fh (FH_MAP_FLAG_COMPLETE, reply_trace_fh, child_path, child_fh3); 	/* exist flag is not used now, set to 1 */
+	reply_trace_fh[TRACE_FH_SIZE] = ' ';
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void trace_play(void)
+{
+	
+	/* The flag to indicate whether trace_player is BUSY. Trace_player is BUSY
+	 * when either there is request to send or there is reply being
+	 * received. Otherwise it is IDLE. The timeout for polling replies 
+	 * is set to 0 when BUSY, it is set to the waiting time to the first
+	 * request outside of current <min_dep_index, max_dep_index> window when IDLE.
+	 */
+   	int busy_flag = BUSY;		
+
+	//int dep_index;		/* index into dependency table: dep_tab */
+	//int biod_index; 	/* index into outstanding requests: biod_reqp */
+
+	int count = 0;
+	min_dep_index = 0;
+	max_dep_index = 0;
+	adjust_play_window(busy_flag, &poll_timeout);
+
+	start_profile (&total_profile);
+	while ((min_dep_index<dep_tab_size) || (num_out_reqs>0)) {
+
+		if (busy_flag == IDLE) {
+			//start_profile (&check_timeout_profile);
+			check_timeout();
+			//end_profile (&check_timeout_profile);
+		}
+
+		//start_profile (&adjust_play_window_profile);
+	 	//adjust_play_window (flag, &poll_timeout);
+	 	//adjust_play_window (flag+(max_dep_index-min_dep_index), &poll_timeout);
+	 	adjust_play_window (busy_flag, &poll_timeout);
+		if (rfs_debug)
+			printf("num_out_reqs %d\n", num_out_reqs);
+		busy_flag = IDLE;
+		//end_profile (&adjust_play_window_profile);
+
+		start_profile (&execute_next_request_profile);
+		while (execute_next_request()!=-1)
+			busy_flag = BUSY;
+		end_profile (&execute_next_request_profile);
+
+		start_profile (&receive_next_reply_profile);
+		while (receive_next_reply(busy_flag)!=-1)
+			busy_flag = BUSY;
+		end_profile (&receive_next_reply_profile);
+	}
+	end_profile (&total_profile);
+
+	print_profile ("total_profile", &total_profile);
+	printf("\n");
+	print_profile ("check_timeout", &check_timeout_profile);
+	printf("\n");
+	print_profile ("adjust_play_window", &adjust_play_window_profile);
+	printf("\n");
+	print_profile ("execute_next_request_profile", &execute_next_request_profile);
+	print_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	print_profile ("invalid_get_nextop_profile", &invalid_get_nextop_profile);
+	print_profile ("prepare_argument", &prepare_argument_profile);
+	print_profile ("biod_clnt_call", &biod_clnt_call_profile);
+	printf("\n");
+	print_profile ("receive_next_reply", &receive_next_reply_profile);
+	print_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	print_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	print_profile ("decode_reply", &decode_reply_profile);
+	print_profile ("check_reply", &check_reply_profile);
+	print_profile ("add_create_object", &add_create_object_profile);
+	printf("\n");
+	
+	printf ("min_dep_index %d dep_tab_size %d num_out_reqs %d\n", min_dep_index, dep_tab_size, num_out_reqs);
+}
+/* sfs_c_chd.c */
diff --git a/TBBT/trace_play/sfs_c_chd.c.org b/TBBT/trace_play/sfs_c_chd.c.org
new file mode 100644
index 0000000..27a122c
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_chd.c.org
@@ -0,0 +1,2866 @@
+#ifndef lint
+static char sfs_c_chdSid[] = "@(#)sfs_c_chd.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * -------------------------- sfs_c_chd.c -------------------------
+ *
+ *      The sfs child.  Routines to initialize child parameters,
+ *	initialize test directories, and generate load.
+ *
+ *.Exported_Routines
+ *	void child(int, float, int, char *);
+ *	void init_fileinfo(void);
+ *	void init_counters(void);
+ *	sfs_fh_type * randfh(int, int, uint_t, sfs_state_type,
+ *				sfs_file_type);
+ *	int check_access(struct *stat)
+ *	int check_fh_access();
+ *
+ *.Local_Routines
+ *	void check_call_rate(void);
+ *	void init_targets(void);
+ *	void init_dirlayout(void);
+ *	void init_rpc(void);
+ *	void init_testdir(void);
+ *	int do_op(void);
+ *	int op(int);
+ *
+ *.Revision_History
+ *	21-Aug-92	Wittle 		randfh() uses working set files array.
+ *					init_fileinfo() sets up working set.
+ *      02-Jul-92	Teelucksingh    Target file size now based on peak load
+ *					instead of BTDT.
+ *	04-Jan-92	Pawlowski	Added raw data dump hooks.
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+extern struct hostent   *Server_hostent;
+
+#define PROB_SCALE 1000L
+#define _M_MODULUS 2147483647L /* (2**31)-1 */
+
+#define _GROUP_DIVISOR 500
+#define _FILES_PER_GROUP 4
+#define _MIN_GROUPS 12
+#define _WORKING_SET_AT_25_OPS_PER_SEC 975
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+
+/* forward definitions for local functions */
+static void check_call_rate(void);
+static void init_targets(void);
+static int init_rpc(void);
+static void init_testdir(void);
+static int do_op(void);
+static int op(int);
+static void init_dirlayout(void);
+
+
+/*
+ * -------------------  File Set Size Control -------------------------
+ */
+static uint_t Setattr_borrowed = 0;	/* setattr op used for file truncate */
+static uint_t Create_borrowed = 0;		/* create op used for file truncate */
+
+/*
+ * -------------  Per Child Load Generation Rate Variables  -----------
+ */
+static float Child_call_load;	/* per child call/sec rate */
+static float Child_req_load;	/* per child req/sec rate */
+static uint_t Calls_this_period; /* calls made during the current run period */
+static uint_t Calls_this_test;	/* calls made during the test so far */
+static uint_t Reqs_this_period;	/* reqs made during the current run period */
+static uint_t Reqs_this_test;	/* reqs made during the test so far */
+static uint_t Sleep_msec_this_test; /* msec slept during the test so far */
+static uint_t Sleep_msec_this_period;
+static uint_t Previous_chkpnt_msec; /* beginning time of current run period */
+static int Target_sleep_mspc;	/* targeted sleep time per call */
+static int Measurement_in_progress = 0;
+
+static sfs_work_set_type Dir_working_set;
+static sfs_work_set_type Io_working_set;
+static sfs_work_set_type Non_io_working_set;
+static sfs_work_set_type Symlink_working_set;
+
+static uint_t Files_created = 0;         /* unique integer part of file names */
+static char io_buf[BUFSIZ];
+int generations = 
+	(_WORKING_SET_AT_25_OPS_PER_SEC/_GROUP_DIVISOR) * _MIN_GROUPS;
+/*
+ * -------------------------  SFS Child  -------------------------
+ */
+
+
+/*
+ * Child number 'child_num'.  Initialize internal data structure and
+ * the test directory,  then notify parent (through log file) that we
+ * are ready to start generating 'load' calls per second into the current
+ * working directory, or optionally, into the directories specified by
+ * 'argc' and 'argv'.  Wait for the start signal, and then generate load
+ * until we complete all our goal for calls or until the run time expires,
+ * depending on the 'Timed_run' flag.  The run time expires when the parent
+ * sends the stop signal.
+ */
+void
+child(
+    int		child_num,
+    int		children,
+    float	load,
+    int 	argc,
+    char	*argv[])
+{
+    char	namebuf[NFS_MAXNAMLEN];	/* unique name for this program */
+    char	*nameptr;
+    int		i;			/* general use */
+    int		op_count;		/* ops completed during each request */
+    uint_t	rand_sleep_msec;	/* random sleep msec between calls */
+    uint_t	current_msec;		/* current test time in msecs */
+    double	previous_pcnt;
+    CLIENT *	mount_client_ptr;	/* Mount client handle */
+    char *	mount_point;		/* Mount point for remote FS */
+    int		Saveerrno;
+    int		mnt_argc;
+
+    struct ladtime	elapsed_time;	/* Current_time - Start_time */
+    sfs_results_report_type	report; /* final results log */
+
+    (void) setvbuf(stderr, io_buf, _IOLBF, BUFSIZ);
+
+    /* Change my name for error logging */
+    if ((nameptr = strrchr(sfs_Myname, '/')) != NULL)
+	sfs_Myname = ++nameptr;
+    (void) sprintf(namebuf, "%s%d", sfs_Myname, child_num);
+    sfs_Myname = namebuf;
+    Child_call_load = load;
+    Current_test_phase = Mount_phase;
+
+    /* Seed the random number generator based on my child number */
+
+    /*
+     * Note: If random seeds are allocated by the prime client
+     * then this code must change.
+     */
+    sfs_srandom((int)(load + Child_num + 1));
+
+    /* Setup user and group information */
+    Cur_uid = Real_uid;
+
+    /*
+     * Initialize call and request targets.
+     * Calls are the Over-The-Wire (OTW) operations that occur due to
+     * each request.  A request may cause one or more calls.
+     * Initialize the child file info and mount the remote test directory.
+     * Set up the rpc and biod structures.
+     */
+    init_targets();
+    init_fileinfo();
+    init_dirlayout();
+
+    /*
+     * Mount points list:
+     *   If the mount point list is equal to the number of procs (P), the
+     *   mount point for child M is the M'th entry in the list.
+     *   If the mount point list is greater than the number of procs (P), the
+     *   mount point for client N child M is ((N - 1) * P) + M
+     */
+    if (argc == children)
+	mnt_argc = Child_num;
+    else
+	mnt_argc = (Client_num - 1) * children + Child_num;
+
+    if (mnt_argc >= argc) {
+	(void) fprintf(stderr,
+"%s: Invalid mount point list: required %d only specified %d mount points\n",
+			sfs_Myname, mnt_argc + 1, argc);
+	(void) generic_kill(0, SIGINT);
+	exit(181);
+    }
+
+    mount_point = argv[mnt_argc];
+
+    /*
+     * May require root priv to perform bindresvport operation
+     */
+    mount_client_ptr = lad_getmnt_hand(mount_point);
+    if (mount_client_ptr == NULL) {
+	exit(145);
+    }
+
+    /*
+     * should be all done doing priv port stuff
+     */
+
+    if (init_rpc() == -1) {
+	(void) fprintf(stderr, "%s: rpc initialization failed\n", sfs_Myname);
+	(void) generic_kill(0, SIGINT);
+	exit(146);
+    }
+
+    /*
+     * finish all priv bindresvport calls
+     * reset uid
+     */
+    if (setuid(Real_uid) != (uid_t)0) {
+	(void) fprintf(stderr,"%s: %s%s", sfs_Myname,
+	    "cannot perform setuid operation.\n",
+	    "Do `make install` as root.\n");
+    }
+
+    init_mount_point(Child_num, mount_point, mount_client_ptr);
+
+    /*
+     * Cleanup client handle for mount point
+     */
+    clnt_destroy(mount_client_ptr);
+
+    /*
+     * Tell parent I'm ready to initialize my test directory,
+     * wait for the go ahead signal.
+     */
+    if (write(Log_fd, "x", 1) != 1) {
+	(void) fprintf(stderr, "%s: can't write to synchronization file %s",
+			sfs_Myname, Logname);
+	(void) generic_kill(0, SIGINT);
+	exit(147);
+    }
+    (void) pause();
+
+    if (DEBUG_CHILD_GENERAL) {
+	if (Timed_run) {
+	    if (Prime_client) {
+		(void) fprintf(stderr,
+	"Child %d loading at %3.2f calls/sec (%3.2f reqs/sec) for %d seconds\n",
+		    Child_num, Child_call_load, Child_req_load,
+		    Runtime - MULTICLIENT_OFFSET);
+	    }
+	    else {
+	    (void) fprintf(stderr,
+	"Child %d loading at %3.2f calls/sec (%3.2f reqs/sec) for %d seconds\n",
+		    Child_num, Child_call_load, Child_req_load, Runtime);
+	    }
+	} else {
+	    (void) fprintf(stderr,
+	"Child %d loading at %3.2f calls/sec (%3.2f reqs/sec) for %d calls\n",
+		    Child_num, Child_call_load, Child_req_load,
+		    Ops[TOTAL].target_calls);
+	}
+	(void) fflush(stderr);
+    }
+
+    /* Initialize the test directory */
+    Current_test_phase = Populate_phase;
+    init_testdir();
+
+    /*
+     * activate the biod behaviour if desired
+     */
+    if (Biod_max_outstanding_reads > 0 || Biod_max_outstanding_writes > 0) {
+	biod_turn_on();
+    }
+
+    /*
+     * Tell parent I'm ready to start test, wait for the go ahead signal.
+     */
+    if (write(Log_fd, "x", 1) != 1) {
+	(void) fprintf(stderr, "%s: can't write to synchronization file %s\n",
+			sfs_Myname, Logname);
+	(void) generic_kill(0, SIGINT);
+	exit(148);
+    }
+    (void) pause();
+
+    if (DEBUG_CHILD_GENERAL) {
+	if (Timed_run) {
+	    if (Prime_client) {
+		(void) fprintf(stderr,
+	"Child %d loading at %3.2f calls/sec (%3.2f reqs/sec) for %d seconds\n",
+		    Child_num, Child_call_load, Child_req_load,
+		    Runtime - MULTICLIENT_OFFSET);
+	    }
+	    else {
+	    (void) fprintf(stderr,
+	"Child %d loading at %3.2f calls/sec (%3.2f reqs/sec) for %d seconds\n",
+		    Child_num, Child_call_load, Child_req_load, Runtime);
+	    }
+	} else {
+	    (void) fprintf(stderr,
+	"Child %d loading at %3.2f calls/sec (%3.2f reqs/sec) for %d calls\n",
+		    Child_num, Child_call_load, Child_req_load,
+		    Ops[TOTAL].target_calls);
+	}
+	(void) fflush(stderr);
+    }
+
+
+    /* Start the warmup phase; initialize operation counters */
+    Current_test_phase = Warmup_phase;
+    init_counters();
+    Measurement_in_progress = 0;
+
+    /*
+     * Compute the average sleep time per call.
+     * Start off with the assumption that we can sleep half the time.
+     * Note: using msec-per-call to adjust sleeping time
+     * limits benchmark load rates to less than 1000 calls-per-sec-per-child.
+     */
+    Target_sleep_mspc = (int) (((1000.0 / Child_call_load) / 2.0) + .5);
+
+    /*
+     * Occasionally, check to see if ops are being generating at the
+     * correct rate.  During the warmup phase, checks are made every 2 seconds.
+     * Hopefully, this will allow the test to reach steady state before the
+     * warmup phase ends.  During the timed test run, checks are made every
+     * 10 seconds.  The switch is made when we receive the start signal.
+     */
+    Msec_per_period = DEFAULT_WARM_RATE_CHECK * 1000;
+
+    /* Loop generating load */
+    while ((Timed_run && Runtime) ||
+	   (!Timed_run &&
+	    (Ops[TOTAL].results.good_calls < Ops[TOTAL].target_calls))) {
+
+	if (start_run_phase) {
+	    init_counters();
+	    Measurement_in_progress = 1;
+	    /*
+	     * Progress is checked every 10 seconds during the test run.
+	     */  
+	    Msec_per_period = DEFAULT_RUN_RATE_CHECK * 1000;
+
+	    start_run_phase = 0;
+	}
+
+	/* Do an NFS operation, unless we need to sleep for the whole period. */
+	if (Target_sleep_mspc < Msec_per_period)
+	    op_count = do_op();
+	else
+	    op_count = 0;
+
+	/* if the call was successful, add op_count to the period total. */
+	if (op_count > 0) {
+	    Calls_this_period += op_count;
+	    Reqs_this_period++;
+	}
+
+	/*
+	 * If the call was successful,
+	 * or we need to sleep for the whole period,
+	 * sleep for a while before doing the next op.
+	 */
+	if ((op_count > 0) || (Target_sleep_mspc >= Msec_per_period)) {
+	    /*
+	     * Sleep for the whole period or
+	     * for a random (positive) time period in the range
+	     * (Target_sleep_mspc +- 1/2(Target_sleep_mspc)).
+	     */
+	    if (Target_sleep_mspc >= Msec_per_period)
+		rand_sleep_msec =  Msec_per_period;
+	    else if (Target_sleep_mspc >= 1)
+		rand_sleep_msec = (Target_sleep_mspc >> 1)
+				  + (sfs_random() % Target_sleep_mspc);
+	    else
+		rand_sleep_msec = 0;
+
+	    if (rand_sleep_msec != 0) {
+		if (DEBUG_CHILD_TIMING) {
+		    (void) fprintf(stderr, "Child %d sleep for %d msec\n",
+					Child_num, rand_sleep_msec);
+		    (void) fflush(stderr);
+		}
+		Sleep_msec_this_period += msec_sleep(rand_sleep_msec);
+	    }
+	}
+
+	/*
+	 * See if it's time to check our progress.
+	 * If an operation was just performed, then Cur_time was updated
+	 * in the op routine; otherwise we need to get Cur_time.
+	 */
+	if (op_count <= 0) {
+	    sfs_gettime(&Cur_time);
+	}
+
+	current_msec = (Cur_time.sec * 1000) + (Cur_time.usec / 1000);
+	if (DEBUG_CHILD_XPOINT) {
+		(void) fprintf(stderr, "cur=%d prev=%d per=%d\n",
+			current_msec, Previous_chkpnt_msec, Msec_per_period);
+	}
+
+	if ((current_msec - Previous_chkpnt_msec) > Msec_per_period) {
+	    check_call_rate();
+	}
+
+    } /* end while more calls to make */
+
+    /*
+     * We are done generating our part of the load.
+     * Store total time in last slot of counts array.
+     *
+     * The last slot has the wall clock time of all the load generation.
+     * Individual slots have the wall clock time spent just for the op
+     * gen routine.
+     */
+    sfs_gettime(&Cur_time);
+    Measurement_in_progress = 0;
+    elapsed_time.sec = Cur_time.sec;
+    elapsed_time.usec = Cur_time.usec;
+    SUBTIME(elapsed_time, Starttime);
+
+    Ops[TOTAL].results.time.sec = elapsed_time.sec;
+    Ops[TOTAL].results.time.usec = elapsed_time.usec;
+
+    if (DEBUG_CHILD_FILES) {
+	(void) fprintf(stderr,
+		    "%s: max fss %d KB  min fss %d KB\n",
+			sfs_Myname, Most_fss_bytes, Least_fss_bytes);
+	(void) fflush(stderr);
+    }
+
+    if (DEBUG_CHILD_FILES) {
+	(void) fprintf(stderr, "Child %d Files:\n", Child_num);
+	for (i = 0; i < Num_io_files; i++)
+	    (void) fprintf(stderr, "Io[%d] use %d xfer %d\n",
+				i, Io_files[i].use_cnt, Io_files[i].xfer_cnt);
+	for (i = 0; i < Num_non_io_files; i++)
+	    (void) fprintf(stderr, "Non_io[%d] use %d xfer %d\n",
+				i, Non_io_files[i].use_cnt,
+				Non_io_files[i].xfer_cnt);
+	for (i = 0; i < Num_dir_files; i++)
+	    (void) fprintf(stderr, "Dir[%d] use %d xfer %d\n",
+				i, Dirs[i].use_cnt, Dirs[i].xfer_cnt);
+	for (i = 0; i < Num_symlink_files; i++)
+	    (void) fprintf(stderr, "Sym[%d] use %d xfer %d\n",
+				i, Symlinks[i].use_cnt, Symlinks[i].xfer_cnt);
+	(void) fflush(stderr);
+    }
+
+    if (DEBUG_CHILD_SETUP) {
+	int j, group_size, offset, index, tot;
+	for (i = 0; i < Io_working_set.access_group_cnt; i++) {
+	    group_size = Io_working_set.access_group_size;
+	    if (i < (Num_working_io_files -
+		     ((Num_working_io_files / Io_working_set.access_group_cnt)
+		      * Io_working_set.access_group_cnt)))
+		group_size += 1;
+	    tot = 0;
+	    for (j = 0; j < group_size; j++) {
+		offset = i + (j * Io_working_set.access_group_cnt);
+		index = Io_working_set.entries[offset].index;
+		tot += Io_files[index].use_cnt;
+		(void) fprintf(stderr, "Working[%d] use %d xfer %d\n",
+				offset, Io_files[index].use_cnt,
+				Io_files[index].xfer_cnt);
+	    }
+	    (void) fprintf(stderr, "Group %d total use %d\n", i, tot);
+	}
+	(void) fflush(stderr);
+    }
+
+    if (DEBUG_CHILD_GENERAL) {
+	(void) fprintf(stderr, "Child %d Ops:\n", Child_num);
+
+	previous_pcnt = 0.0;
+	(void) fprintf(stderr,
+    "             calls                             reqs\n");
+	(void) fprintf(stderr,
+    "             trgt actl  trgt actl  bad  no     trgt actl   trgt   actl\n");
+	(void) fprintf(stderr,
+    "     name    mix  mix   cnt   cnt  cnt  cnt     mix  mix    cnt    cnt\n");
+
+	for (i = 0; i < NOPS + 1; i++) {
+	    (void) fprintf(stderr,
+		    "%11s %4d %4.1f %5d %5d %4d %3d    %4.1f %4.1f %6d %6d\n",
+		    Ops[i].name, Ops[i].mix_pcnt,
+		    (float) (100 * Ops[i].results.good_calls)
+			/ (float) Ops[TOTAL].results.good_calls,
+		    Ops[i].target_calls, Ops[i].results.good_calls,
+		    Ops[i].results.bad_calls, Ops[i].no_calls,
+		    Ops[i].req_pcnt - previous_pcnt,
+		    (float) (100 * Ops[i].req_cnt) / (float) Ops[TOTAL].req_cnt,
+		    Ops[i].target_reqs, Ops[i].req_cnt);
+	    previous_pcnt = Ops[i].req_pcnt;
+	}
+	(void) fflush(stderr);
+    }
+
+    if (DEBUG_CHILD_GENERAL) {
+	(void) fprintf(stderr, "Child %d made %d of %d calls in %ld sec\n",
+			Child_num, Ops[TOTAL].results.good_calls,
+			Ops[TOTAL].target_calls,
+			Ops[TOTAL].results.time.sec);
+	(void) fflush(stderr);
+    }
+
+    clnt_destroy(NFS_client);
+    biod_term();
+
+    /* write stats to log file (append mode) */
+    report.version = nfs_version;
+    for (i = 0; i < NOPS + 1; i++) {
+	report.results_buf[i] = Ops[i].results;
+    }
+    report.total_fss_bytes = Total_fss_bytes;
+    report.least_fss_bytes = Least_fss_bytes;
+    report.most_fss_bytes = Most_fss_bytes;
+    report.base_fss_bytes = Base_fss_bytes;
+
+    if (write(Log_fd, (char *) &report, sizeof(report)) == -1) {
+	Saveerrno = errno;
+	(void) fprintf(stderr, "%s: can't write to synchronization file %s ",
+			sfs_Myname, Logname);
+	errno = Saveerrno;
+	perror(Logname);
+	(void) generic_kill(0, SIGINT);
+	exit(149);
+    }
+    (void) close(Log_fd);
+
+    print_dump(Client_num, Child_num);
+
+} /* child */
+
+
+/*
+ * --------------------  Call Target Initialization  --------------------
+ */
+
+/*
+ * Initialize call and request targets.
+ */
+static void
+init_targets(void)
+{
+    int		call_target;		/* total number of calls to make */
+    int		req_target;		/* total number of reqs to make */
+    int32_t	equal_mix;		/* equal mix of operations */
+    int32_t	slack;			/* calls leftover after % mix */
+    int		randnum;		/* a random number */
+    int32_t	i;			/* general use */
+    double	total_req_pcnt;
+    double	previous_pcnt;
+    int		nops_used = 0;
+
+
+    /*
+     * Compute number of target calls for each operation.
+     * These are used to estimate the number of filehandles
+     * that will be used for each type of operation.
+     */
+    call_target = Ops[TOTAL].target_calls;
+    Ops[TOTAL].target_calls = 0;
+
+    for (i = 0; i < NOPS; i++) {
+	Ops[i].target_calls = (Ops[i].mix_pcnt * call_target) / 100;
+	Ops[TOTAL].target_calls += Ops[i].target_calls;
+	if (Ops[i].mix_pcnt != 0)
+	    nops_used++;
+    }
+
+    /* Put left over calls into the heavier mix operations. */
+    slack = call_target - Ops[TOTAL].target_calls;
+    equal_mix =  (100 / nops_used) / 2;
+    while (slack > 0) {
+	randnum = sfs_random() % NOPS;
+	if (Ops[randnum].mix_pcnt != 0 && Ops[randnum].mix_pcnt >= equal_mix) {
+	    Ops[randnum].target_calls++;
+	    Ops[TOTAL].target_calls++;
+	    slack--;
+	}
+    }
+
+    /*
+     * compute request targets (based on suggestions from M. Molloy, HP)
+     */
+
+    /* compute total of target requests, based on weighted ops */
+    total_req_pcnt = 0.0;
+    for (i = 0; i < NOPS ; i++) {
+	switch (i) {
+	case READ:
+	    total_req_pcnt += ((double) Ops[i].mix_pcnt)
+			    / Io_dist_ptr->avg_ops_per_read_req;
+	    break;
+	case WRITE:
+	    total_req_pcnt += ((double) Ops[i].mix_pcnt)
+			    / Io_dist_ptr->avg_ops_per_write_req;
+	    break;
+	case COMMIT:	/* Commits never generate requests */
+	    break;
+	default:
+	    total_req_pcnt += (double) Ops[i].mix_pcnt;
+	    break;
+	}
+    }
+
+    /*
+     * compute cumulative frequency distribution percentile for each op.
+     * This code assumes that the NULLCALL does not generate multiple
+     * OTW operations per request.
+     */
+    previous_pcnt = 0.0;
+    for (i = 0; i < NOPS; i++) {
+	switch (i) {
+	case READ:
+	    Ops[i].req_pcnt = previous_pcnt +
+			      (((100.0 * (double) Ops[i].mix_pcnt)
+			      / Io_dist_ptr->avg_ops_per_read_req)
+			      / total_req_pcnt);
+	    break;
+	case WRITE:
+	    Ops[i].req_pcnt = previous_pcnt +
+			      (((100.0 * (double) Ops[i].mix_pcnt)
+			      / Io_dist_ptr->avg_ops_per_write_req)
+			      / total_req_pcnt);
+	    break;
+	case COMMIT:	/* Commits never generate requests */
+	    Ops[i].req_pcnt = previous_pcnt;
+	    break;
+	default:
+	    Ops[i].req_pcnt = previous_pcnt +
+			      ((100.0 * (double) Ops[i].mix_pcnt)
+			      / total_req_pcnt);
+	    break;
+	}
+	previous_pcnt = Ops[i].req_pcnt;
+    }
+    /* force last bucket to 100 */
+    Ops[NOPS-1].req_pcnt = 100;
+
+    /* compute the req load rate */
+    Child_req_load = (total_req_pcnt * Child_call_load) / 100.0;
+
+    /*
+     * Compute number of target reqs for each operation.
+     * These are used for debugging purposes.
+     */
+    req_target = (total_req_pcnt * Ops[TOTAL].target_calls) / 100;
+    Ops[TOTAL].target_reqs = 0;
+
+    previous_pcnt = 0.0;
+    for (i = 0; i < NOPS; i++) {
+	Ops[i].target_reqs = 0;
+	if (Ops[i].mix_pcnt != 0) {
+	    Ops[i].target_reqs = ((Ops[i].req_pcnt - previous_pcnt) *
+							req_target) / 100;
+	}
+	Ops[TOTAL].target_reqs += Ops[i].target_reqs;
+	previous_pcnt = Ops[i].req_pcnt;
+    }
+
+    /* Put left over reqs into the heavier mix operations. */
+    slack = req_target - Ops[TOTAL].target_reqs;
+    equal_mix =  (100 / nops_used) / 2;
+    while (slack > 0) {
+	randnum = sfs_random() % NOPS;
+	if (Ops[randnum].target_reqs != 0 &&
+					Ops[randnum].req_pcnt >= equal_mix) {
+	    Ops[randnum].target_reqs++;
+	    Ops[TOTAL].target_reqs++;
+	    slack--;
+	}
+    }
+    if (DEBUG_CHILD_GENERAL) {
+	(void) fprintf(stderr,
+			"      Op\t  Op mix\tCalls\t\t Req mix\t Reqs\t\n");
+	previous_pcnt = 0.0;
+	for (i = 0; i < NOPS; i++) {
+	    (void) fprintf(stderr, "%8s\t%8d\t%5d\t\t%8.2f\t%5d\n",
+				Ops[i].name,
+				Ops[i].mix_pcnt, Ops[i].target_calls,
+				Ops[i].req_pcnt - previous_pcnt,
+				Ops[i].target_reqs);
+	    previous_pcnt = Ops[i].req_pcnt;
+	}
+    }
+} /* init_targets */
+
+
+/*
+ * -----------------------  File Set Initialization  -----------------------
+ */
+
+static file_array_initialized = 0;
+static int file_size_array[100];
+
+/*
+ * For a value between 0-99, return a size based on distribution
+ */
+static int
+get_file_size(int i)
+{
+    if (i < 0 || i > 99)
+	return (0);
+
+    if (file_array_initialized == 0) {
+	int j, k;
+
+	for (j = 0, k = 0; j < 100; j++) {
+	    if (j >= Default_file_size_dist[k].pcnt &&
+			Default_file_size_dist[k + 1].size != 0)
+		k++;
+	    file_size_array[j] = Default_file_size_dist[k].size * 1024;
+	}
+	file_array_initialized++;
+    }
+    return (file_size_array[i]);
+}
+
+/*
+ * allocate and initialize the various file information structures.
+ */
+void
+init_fileinfo(void)
+{
+    int      i, index;
+    int      j;
+    int      group_size, group_cnt;
+    int      range, previous_range;
+    int      next_value;
+    double   lambda;
+    double   e_to_the_lambda;
+    double   cumulative_ratio;
+    int	     num_non_io_to_init;
+    int	     io_file_num = 0;
+    int	     files_per_generation;
+    sfs_fh_data 	*fh_datap;
+
+
+    /*
+     * Zero number of files created used to create unique names
+     */
+    Files_created = 0;
+
+    /*
+     * Dirs - Initialize the files info structure.
+     * Directories must come first, in initializing test dirs we
+     * need to make sure that any files deleted are no full directories
+     */
+    Num_dir_files =
+	     Num_dirs +				/* exist: readdir, rmdir */
+	     Ops[MKDIR].target_calls +		/* non-exist: mkdir */
+	     Ops[RMDIR].target_calls;		/* empty dir to be removed */
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "%s: allocate %d directories\n",
+			   sfs_Myname, Num_dir_files);
+	(void) fflush(stderr);
+    }
+    Dirs = (sfs_fh_type *) calloc(Num_dir_files, sizeof(sfs_fh_type));
+
+    if (Dirs == (sfs_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo dir calloc %d bytes failed",
+			sfs_Myname, Num_dir_files * sizeof(sfs_fh_type));
+	(void) generic_kill(0, SIGINT);
+	exit(150);
+    }
+    for (i = 0; i < Num_dir_files; i++) {
+	Dirs[i].working_set = 0;
+	Dirs[i].state = Nonexistent;
+	if (i <= (Num_dirs + Ops[RMDIR].target_calls)) {
+	    Dirs[i].initialize = 1;
+	    Dirs[i].fh_data = (sfs_fh_data *)0;
+	}
+	Dirs[i].unique_num = i;
+    }
+
+    /* Working Set Directory Files - Initialize the working files array. */
+    Num_working_dirs = Num_dir_files;
+    Dir_working_set.entries = (sfs_work_fh_type *)
+			      calloc(Num_working_dirs,
+				     sizeof(sfs_work_fh_type));
+    if (Dir_working_set.entries == (sfs_work_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo wdir calloc %d bytes failed",
+		sfs_Myname, Num_working_dirs * sizeof(sfs_work_fh_type));
+	(void) generic_kill(0, SIGINT);
+	exit(151);
+    }
+
+    /*
+     * Dirs are accessed uniformly.  See Non_io_files for a description.
+     */
+    if (init_rand_range(Num_dir_files)) {
+	(void) fprintf(stderr, "%s: init_fileinfo dir init_rand_range failed",
+		sfs_Myname);
+	(void) generic_kill(0, SIGINT);
+	exit(183);
+    }
+
+    for (i = 0; i < Num_working_dirs; i++) {
+	if (Num_working_dirs != Num_dir_files) {
+	    /* generate a random subset */
+	    index = rand_range(i);
+	} else {
+	    /* match the working set one-to-one with the files */
+	    index = i;
+	}
+
+	Dirs[index].working_set = 1;
+	Dir_working_set.entries[i].index = index;
+	Dir_working_set.entries[i].range = i + 1;
+    }
+    Dir_working_set.access_group_size = Num_working_dirs;
+    Dir_working_set.access_group_cnt = 1;
+
+    Dir_working_set.max_range = Num_working_dirs;
+
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "\nDir size=%d cnt=%d max=%d\n",
+			    Dir_working_set.access_group_size,
+			    Dir_working_set.access_group_cnt,
+			    Dir_working_set.max_range);
+	(void) fflush(stderr);
+    }
+
+
+    /*
+     * I/o Files - Initialize the files info structure to Num_io_files.
+     */
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "%s: allocate %d i/o files, %d working\n",
+			   sfs_Myname, Num_io_files, Num_working_io_files);
+	(void) fflush(stderr);
+    }
+
+    Io_files = (sfs_fh_type *) calloc(Num_io_files, sizeof(sfs_fh_type));
+    if (Io_files == (sfs_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo %d io files calloc %d bytes failed",
+			sfs_Myname, Num_io_files,
+			Num_io_files * sizeof(sfs_fh_type));
+	(void) generic_kill(0, SIGINT);
+	exit(152);
+    }
+    io_file_num = 0;
+    for (i = 0; i < Num_io_files; i++) {
+	Io_files[i].working_set = 0;
+	Io_files[i].state = Nonexistent;
+	Io_files[i].initialize = 1;
+	Io_files[i].size = get_file_size(io_file_num % 100);
+	Io_files[i].unique_num = Files_created++;
+	/* Memory allocation for the fh_data will be done later.  */
+	Io_files[i].fh_data = (sfs_fh_data *)0;
+	io_file_num++;
+    }
+
+    /*
+     * Working Set I/o Files - Initialize the working files array.
+     * Only Access_percent of the Io_files are put into the working set.
+     */
+    Io_working_set.entries = (sfs_work_fh_type *)
+			   calloc(Num_working_io_files,
+				  sizeof(sfs_work_fh_type));
+    if (Io_working_set.entries == (sfs_work_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo wio calloc %d bytes failed",
+		sfs_Myname, Num_working_io_files * sizeof(sfs_work_fh_type));
+	(void) generic_kill(0, SIGINT);
+	exit(153);
+    }
+
+
+    if (DEBUG_CHILD_FILES) {
+	(void) fprintf(stderr, "working_set: ");
+	(void) fflush(stderr);
+    }
+
+    /*
+     * For now, the access distribution is poisson.  See below.
+     */
+/* #define UNIFORM_ACCESS */
+#define POISSON_ACCESS
+
+#ifdef UNIFORM_ACCESS
+    /*
+     * With a uniform access distribution, there is no need for access
+     * groups.
+     * Hopefully SPEC-SFS will agree on a non-uniform access function.
+     * (see below for an example using a poisson distribution).
+     */
+    if (init_rand_range(Num_io_files)) {
+	(void) fprintf(stderr, "%s: init_fileinfo io init_rand_range failed",
+		sfs_Myname);
+	(void) generic_kill(0, SIGINT);
+	exit(184);
+    }
+
+    for (i = 0; i < Num_working_io_files; i++) {
+	if (Num_working_io_files != Num_io_files) {
+	    /* generate a random subset */
+	    index = rand_range(i);
+	} else {
+	    /* match the working set one-to-one with the files */
+	    index = i;
+	}
+	Io_files[index].working_set = 1;
+	Io_working_set.entries[i].index = index;
+	Io_working_set.entries[i].range = i + 1;
+
+	if (DEBUG_CHILD_FILES) {
+	    (void) fprintf(stderr, "%d,", index);
+	    (void) fflush(stderr);
+	}
+    }
+    Io_working_set.access_group_size = Num_working_io_files;
+    Io_working_set.access_group_cnt = 1;
+    Io_working_set.max_range = Num_working_io_files;
+
+    if (DEBUG_CHILD_FILES) {
+	(void) fprintf(stderr, "\nIo size=%d cnt=%d max=%d\n",
+			    Io_working_set.access_group_size,
+			    Io_working_set.access_group_cnt,
+			    Io_working_set.max_range);
+	(void) fflush(stderr);
+    }
+
+#endif /* ! UNIFORM_ACCESS */
+#ifdef POISSON_ACCESS
+
+    /*
+     * The working set is partitioned into access groups of Access_group_size
+     * files.  Each group is assigned a probability of being accessed.
+     * This is implemented as a cumulative distribution table, with
+     * variable probabilities for each group.  The distribution function
+     * is used to generate a sequence of values, one for each group.
+     * Each group is assigned a 'range' value that is the sum of all
+     * previous range values, plus the next value in the distribution
+     * sequence.  Thus, the probability of choosing any particular group
+     * is equal to the relative height of the distribution curve at the
+     * point represented by that group.
+     * The choice is made by generating a random number in the range
+     * 0 up to (the sum of all values in the distribution sequence - 1),
+     * and finding the group with the greatest range value less than
+     * the random number.
+     * Once a group is chosen, a random number in the range
+     * 1 - Access_group_size is used to pick an entry from within the group.
+     * The entry chosen points to a file in the Io_files array.
+     * If the file at Io_files[index] is eligible for the operation,
+     * then it is accessed, otherwise, the access group is searched
+     * sequentially (mod Access_group_size with wrap-around) until an
+     * eligible file is found.
+     * Access_group_size is derived so that there are enough files
+     * in each group to give a good chance of finding an eligible file
+     * for each operation, but so that there are enough groups (each
+     * representing a point on the distribution curve) to generate a
+     * fairly smooth access distribution curve.
+     */
+
+    /*
+     * group_cnt = 8 + ((Num_working_io_files/500) * 4);
+     *
+     * The function is chosen to guarentee that each group contains
+     * at least 1 file, and, beginning with a base of 8 groups, the
+     * number of groups increases by 4 for each 500 files in the working
+     * set.  It was arrived at heuristically.  The goal is to put enough
+     * files into each group to ensure that a file with the right
+     * attributes can be found once the group is selected (which can be
+     * difficult for small working sets), while at the same time creating
+     * enough groups to provide enough points on the distribution curve
+     * to yield an interesting access distribution.
+     *
+     * Since this function is being computed per child, the interesting range
+     * of working set sizes is computed based on a range of per child load
+     * values from 1 op/sec to 100 op/sec.  Note that this assumes an
+     * average server response time of at least 10 msec, which seems to be
+     * a good minimum value for a wide range of servers given the default
+     * mix of NFS operations.
+     * Based on these load values, the total file set, based on the default
+     * values of 10 MB/op and 38 files/MB, works out to 380 - 38000 files.
+     * The default working set of 10% of these files yields a working
+     * set size of 38 - 3800 files.
+     */
+
+     files_per_generation = (_GROUP_DIVISOR * generations) / _FILES_PER_GROUP;
+     Io_working_set.access_group_cnt = generations +
+	((Num_working_io_files/files_per_generation) * generations);
+    /*
+     * if the number of files in the working set is not a multiple of
+     * the group size, then some groups will contain (group_size+1) files.
+     * Thus, this is the base group size.
+     */
+    Io_working_set.access_group_size = Num_working_io_files /
+				      Io_working_set.access_group_cnt;
+
+    if (init_rand_range(Num_io_files)) {
+	(void) fprintf(stderr, "%s: init_fileinfo io init_rand_range failed",
+		sfs_Myname);
+	(void) generic_kill(0, SIGINT);
+	exit(185);
+    }
+
+    /* randomly set up working set of indices into Io_files */
+    for (i = 0; i < Num_working_io_files; i++) {
+	if (Num_working_io_files != Num_io_files) {
+	    /* generate a random subset */
+	    index = rand_range(i);
+	} else {
+	    /* match the working set one-to-one with the files */
+	    index = i;
+	}
+	Io_files[index].working_set = 1;
+	Io_working_set.entries[i].index = index;
+
+	if (DEBUG_CHILD_FILES) {
+	    (void) fprintf(stderr, "%d,", index);
+	    (void) fflush(stderr);
+	}
+    }
+
+    /* initialization for distribution function */
+    range = 0;
+    lambda = (double) (generations / 2);
+    if (lambda <= 0) lambda = 1;
+    e_to_the_lambda = exp(lambda);
+    cumulative_ratio = 1.0;
+
+    if (DEBUG_CHILD_FILES) {
+	(void) fprintf(stderr,
+			"\ngrp_cnt %d lambda %6.0f e_to_the_lambda %6.2f\n",
+			Io_working_set.access_group_cnt, lambda,
+			e_to_the_lambda);
+	(void) fflush(stderr);
+    }
+
+    /* assign a range to each group */
+    for (i = 0; i < Io_working_set.access_group_cnt; i++) {
+	/*
+	 * get next value in poisson distribution sequence, using
+	 *    lambda^x / (e^(lambda) * x!) , for x=1,2,3,...,group_cnt
+	 */
+        double probability;
+
+	if( i % generations == 0)
+	{
+    		lambda = (double) (generations / 2);
+    		if (lambda <= 0) lambda = 1;
+    			e_to_the_lambda = exp(lambda);
+    		cumulative_ratio = 1.0;
+	}
+        probability = cumulative_ratio/e_to_the_lambda;
+        if (probability <= 0.0 || probability > 1.0) {
+		(void) fprintf(stderr, "%s: access probability = %g while setting up Io_working_set, i=%d of %d\n",
+ 			sfs_Myname, probability,
+			i, Io_working_set.access_group_cnt);
+ 		(void) generic_kill(0, SIGINT);
+ 		exit(154);
+        }
+
+	/* convert probability to scaled integer */
+	next_value = (int) (PROB_SCALE * probability);
+
+	/* check for negative numbers */
+        if (next_value <= 0) {
+		(void) fprintf(stderr, "%s: next_value = %d while setting up Io_working_set, i=%d of %d\n",
+ 			sfs_Myname, next_value,
+			i, Io_working_set.access_group_cnt);
+ 		(void) generic_kill(0, SIGINT);
+ 		exit(154);
+        }
+
+	previous_range = range;
+	range = previous_range + next_value;
+        if (range <= previous_range || range < 0) {
+		(void) fprintf(stderr, "%s: range = %d previous_range = %d while setting up Io_working_set, i=%d of %d\n",
+ 			sfs_Myname, range, previous_range,
+			i, Io_working_set.access_group_cnt);
+ 		(void) generic_kill(0, SIGINT);
+ 		exit(154);
+        }
+
+	/* assign range value to each file in this group */
+	group_size = Io_working_set.access_group_size;
+	group_cnt = Io_working_set.access_group_cnt;
+	if (i < (Num_working_io_files -
+		 ((Num_working_io_files / group_cnt) * group_cnt)))
+	    group_size += 1;
+	for (j = 0; j < group_size; j++) {
+	    index = i + (j * Io_working_set.access_group_cnt);
+	    Io_working_set.entries[index].range = range;
+	}
+
+	cumulative_ratio *= lambda / (double) ((i%generations)+1);
+
+	if (DEBUG_CHILD_SETUP) {
+	    (void) fprintf(stderr, "group %d next %d range %d\n",
+				i, next_value, range);
+	    (void) fflush(stderr);
+	}
+    }
+    Io_working_set.max_range = range;
+
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "\nIo size=%d cnt=%d max=%d\n",
+			   Io_working_set.access_group_size,
+			   Io_working_set.access_group_cnt,
+			   Io_working_set.max_range);
+	(void) fflush(stderr);
+    }
+#endif /* POISSON_ACCESS */
+
+
+     /* figure out how many files to allocate and initialize */
+
+    /* initialize half the non-I/O files */
+    /* NOTE: initializing half the non-i/o files works ok with the
+	     default op mix.  If the mix is changed affecting the
+	     ratio of creations to removes, there may not be enough
+	     empty slots for file creation (or there may not be
+	     enough created during initialization to handle a lot of
+	     removes that occur early in the test run), and this would
+	     cause do_op() to fail to find a file appropriate for the
+	     chosen op.  This will result in the global variable
+	     Ops[op].no_calls being incremented (turn on child level
+	     debugging to check this count), and the do_op() local
+	     variable aborted_ops to be incremented and checked during
+	     runtime for too many failures.
+     */
+    num_non_io_to_init = Num_non_io_files * RATIO_NON_IO_INIT;
+
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "%s: allocate %d non-i/o files\n",
+			    sfs_Myname, Num_non_io_files);
+	(void) fflush(stderr);
+    }
+    Non_io_files = (sfs_fh_type *)
+		    calloc(Num_non_io_files, sizeof(sfs_fh_type));
+    if (Non_io_files == (sfs_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo nio calloc %d bytes failed",
+ 		sfs_Myname, Num_non_io_files * sizeof(sfs_fh_type));
+ 	(void) generic_kill(0, SIGINT);
+ 	exit(154);
+    }
+    for (i = 0; i < Num_non_io_files; i++) {
+	Non_io_files[i].working_set = 0;
+	Non_io_files[i].state = Nonexistent;
+        if (i <= num_non_io_to_init)
+	    Non_io_files[i].initialize = 1;
+	Non_io_files[i].size = get_file_size(io_file_num % 100);
+	Non_io_files[i].unique_num = Files_created++;
+	/* Allocation of fh_data will happen in init_testdir */
+	Non_io_files[i].fh_data = (sfs_fh_data *)0;
+	io_file_num++;
+    }
+
+    /* Working Set Non i/o Files - Initialize the working files array. */
+    Num_working_non_io_files = Num_non_io_files;
+    Non_io_working_set.entries = (sfs_work_fh_type *)
+				 calloc(Num_working_non_io_files,
+					sizeof(sfs_work_fh_type));
+    if (Non_io_working_set.entries == (sfs_work_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo nwio calloc %d bytes failed",
+		sfs_Myname, Num_working_io_files * sizeof(sfs_work_fh_type));
+	(void) generic_kill(0, SIGINT);
+	exit(155);
+    }
+
+    /*
+     * Non_io_files are accessed uniformly.  Each entry has a
+     * 1/Num_working_non_io_files change of being accessed.
+     * The choice is made by generating a random number in the range
+     * 0 through (Num_working_non_io_files - 1) and finding the entry
+     * with the greatest range value less than the random number.
+     * If the file at Non_io_files[index] is eligible for the operation,
+     * it is accessed, otherwise, the access group that the entry belongs
+     * to is searched sequentially until an eligible file is found.
+     * For non i/o files, all of the working set files are in the same
+     * access group (since they access is uniform, this is ok, and
+     * maximizes the chances of finding an eligible file).
+     */
+    if (init_rand_range(Num_non_io_files)) {
+	(void) fprintf(stderr, "%s: init_fileinfo non_io init_rand_range failed",
+		sfs_Myname);
+	(void) generic_kill(0, SIGINT);
+	exit(186);
+    }
+
+    for (i = 0; i < Num_working_non_io_files; i++) {
+	if (Num_working_non_io_files != Num_non_io_files) {
+	    /* generate a random subset */
+	    index = rand_range(i);
+	} else {
+	    /* match the working set one-to-one with the files */
+	    index = i;
+	}
+	Non_io_files[index].working_set = 1;
+	Non_io_working_set.entries[i].index = index;
+	Non_io_working_set.entries[i].range = i + 1;
+    }
+    Non_io_working_set.access_group_size = Num_working_non_io_files;
+    Non_io_working_set.access_group_cnt = 1;
+    Non_io_working_set.max_range = Num_working_non_io_files;
+
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "\nNon_io	size=%d cnt=%d max=%d\n",
+			    Non_io_working_set.access_group_size,
+			    Non_io_working_set.access_group_cnt,
+			    Non_io_working_set.max_range);
+	(void) fflush(stderr);
+    }
+
+
+    /* Symlinks - Initialize the files info structure. */
+    Num_symlink_files =
+	     Num_symlinks +			/* exist: readlink */
+	     Ops[SYMLINK].target_calls;		/* non-exist: symlink */
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "%s: allocate %d symlinks\n",
+			   sfs_Myname, Num_symlink_files);
+	(void) fflush(stderr);
+    }
+    Symlinks = (sfs_fh_type *)
+		calloc(Num_symlink_files, sizeof(sfs_fh_type));
+    if (Symlinks == (sfs_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo sym calloc %d bytes failed",
+			sfs_Myname, (Num_symlink_files * sizeof(sfs_fh_type)));
+	(void) generic_kill(0, SIGINT);
+	exit(156);
+    }
+    for (i = 0; i < Num_symlink_files; i++) {
+	Symlinks[i].working_set = 0;
+	Symlinks[i].state = Nonexistent;
+	if (i <= Num_symlinks)
+	    Symlinks[i].initialize = 1;
+	Symlinks[i].fh_data = (sfs_fh_data *)0;
+	Symlinks[i].unique_num = i;
+    }
+
+    /* Working Set Symlinks - Initialize the working files array. */
+    /* This appears to cause the following loop to be mostly dead */
+    /* code.  It is unclear why this line is here. One */
+    /* possibility is that Num_symlink_files should be */
+    /* Num_symlinks.  XXX */
+    Num_working_symlinks = Num_symlink_files;
+    Symlink_working_set.entries = (sfs_work_fh_type *)
+				  calloc(Num_working_symlinks,
+					 sizeof(sfs_work_fh_type));
+    if (Symlink_working_set.entries == (sfs_work_fh_type *) 0) {
+	(void) fprintf(stderr,"%s: init_fileinfo wsym calloc %d bytes failed",
+		sfs_Myname, Num_working_symlinks * sizeof(sfs_work_fh_type));
+	(void) generic_kill(0, SIGINT);
+	exit(157);
+    }
+
+    /*
+     * Symlinks are accessed uniformly.  See Non_io_files for a description.
+     */
+    if (init_rand_range(Num_symlink_files)) {
+	(void) fprintf(stderr, "%s: init_fileinfo sym init_rand_range failed",
+		sfs_Myname);
+	(void) generic_kill(0, SIGINT);
+	exit(187);
+    }
+
+    for (i = 0; i < Num_working_symlinks; i++) {
+	if (Num_working_symlinks != Num_symlink_files) {
+	    /* generate a random subset */
+	    index = rand_range(i);
+	} else {
+	    /* match the working set one-to-one with the files */
+	    index = i;
+	}
+
+	Symlinks[index].working_set = 1;
+	Symlink_working_set.entries[i].index = index;
+	Symlink_working_set.entries[i].range = i + 1;
+    }
+    Symlink_working_set.access_group_size = Num_working_symlinks;
+    Symlink_working_set.access_group_cnt = 1;
+    Symlink_working_set.max_range = Num_working_symlinks;
+
+    if (DEBUG_CHILD_SETUP) {
+	(void) fprintf(stderr, "\nSymlink size=%d cnt=%d max=%d\n",
+			    Symlink_working_set.access_group_size,
+			    Symlink_working_set.access_group_cnt,
+			    Symlink_working_set.max_range);
+	(void) fflush(stderr);
+    }
+
+    /*
+     * Free up random number range
+     */
+    (void)init_rand_range(0);
+
+
+} /* init_fileinfo */
+
+/*
+ * allocate and initialize the directory layout of the files
+ *
+ * We can only place files in directories that can't be removed
+ */
+static void
+init_dirlayout(void)
+{
+    int i,j;
+
+    /*
+     * Initially create directories only one level deep so all directories
+     * must be in the parent directory.
+     */
+    for (i = 0; i < Num_dir_files; i++) {
+	Dirs[i].dir = &Export_dir;
+    }
+
+    /*
+     * Files must only be placed in the first Num_dirs entries leaving
+     * a set for directory create and remove.
+     */
+    j = 0;
+    for (i = 0; i < Num_io_files; i++) {
+	if (i != 0 && (i % Files_per_dir) == 0)
+		j++;
+	Io_files[i].dir = &Dirs[j];
+    }
+
+    /*
+     * All non-io and symlink files are placed in the parent directory
+     */
+    for (i = 0; i < Num_non_io_files; i++) {
+	Non_io_files[i].dir = &Export_dir;
+    }
+
+    for (i = 0; i < Num_symlink_files; i++) {
+	Symlinks[i].dir = &Export_dir;
+    }
+}
+
+/*
+ * allocate and initialize client handles
+ */
+static int
+init_rpc(void)
+{
+    /*
+     * Set up the client handles.  We get them all before trying one
+     * out to insure that the client handle for LOOKUP class is allocated
+     * before calling op_getattr().
+     */
+    if (DEBUG_CHILD_GENERAL) {
+    	(void) fprintf(stderr, "%s: set up client handle\n", sfs_Myname);
+    }
+
+    NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+					(uint32_t) NFS_PROGRAM,
+					(uint32_t) nfs_version,
+					RPC_ANYSOCK, &Nfs_timers[0]);
+		
+    if (NFS_client  == ((CLIENT *) NULL)) {
+        return(-1);
+    }
+
+    /*
+     * create credentials using the REAL uid
+     */
+    NFS_client->cl_auth = authunix_create(lad_hostname, (int)Real_uid,
+				      (int)Cur_gid, 0, NULL);
+
+    /* Initialize biod simulation mechanism if desired.  */
+    if (Biod_max_outstanding_reads > 0 || Biod_max_outstanding_writes > 0) {
+	if (biod_init(Biod_max_outstanding_writes,
+		Biod_max_outstanding_reads) == -1) {
+	    return(-1);
+	}
+    }
+
+    return(0);
+} /* init_rpc */
+
+/*
+ * Initialize the test directory 'parentdir'/testdir'dirnum'.
+ *
+ * If the directory already exists, check to see that all of the
+ * files exist and can be written.  If the directory doesn't exist
+ * create it and fill it with the proper files.  The caller is
+ * left with his cwd being the test directory.
+ *
+ * Each child pseudo-mount's his own test directory to get its filehandle.
+ *
+ * Files, directories, and symlinks all have the same name structure
+ * but they are strictly ordered, files first, directories next, then symlinks.
+ * While initializing after a previous run we may have to delete existing
+ * files of the wrong type and then create them later.
+ *
+ * XXX In the future it is probably wiser to have seperate namespaces for
+ * each type of file.
+ */
+static void
+init_testdir(void)
+{
+    int			filenum;
+    int			max_filenum;
+    int			init_size;
+    int			append_size;
+    int			ret;
+    int			non = 0;
+    int 		dealloc;
+    int			alloc_count, dealloc_count;
+    /*
+     * Create directories first so operations that
+     * require them will have a file to work with.
+     */
+    alloc_count=dealloc_count=0;
+    for (filenum = 0; filenum < Num_dir_files; filenum++) {
+	sfs_gettime(&Cur_time);
+
+	Cur_file_ptr = &Dirs[filenum];
+	dealloc=0;
+	if(Cur_file_ptr->fh_data == (sfs_fh_data *)0)
+	{
+		alloc_count++;
+		Cur_file_ptr->fh_data = calloc(1,sizeof(sfs_fh_data));
+		Cur_file_ptr->attributes2.type = NFNON;
+		Cur_file_ptr->attributes3.type = NF3NON;
+		if(Cur_file_ptr->working_set == 1)
+			dealloc=0;
+		else
+			dealloc=1;
+	}
+
+	(void) sprintf(Cur_filename, Dirspec, Cur_file_ptr->unique_num);
+
+	if (DEBUG_CHILD_SETUP) {
+	    (void) fprintf(stderr, "%s: initialize %s (DIR)\n",
+				   sfs_Myname, Cur_filename);
+	    (void) fflush(stderr);
+	}
+
+	if ((ret = lad_lookup(Cur_file_ptr, Cur_filename)) == -1) {
+	    /* some error that I don't know what to do with, quit. */
+	    (void) generic_kill(0, SIGINT);
+	    exit(159);
+	}
+
+	if (ret == 0) {
+	    /* file exists */
+	    if (fh_isdir(Cur_file_ptr) && Cur_file_ptr->initialize)
+	    {
+		if(dealloc == 1)
+		{
+			dealloc_count++;
+			free(Cur_file_ptr->fh_data);
+			Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+		}
+		continue;
+	    }
+
+	    if (lad_remove(Cur_file_ptr, Cur_filename) != 0) {
+	        /* some error that I don't know what to do with, quit. */
+	        (void) generic_kill(0, SIGINT);
+	        exit(160);
+	    }
+        }
+
+	if (!Cur_file_ptr->initialize) {
+		/* dir shouldn't exist */
+	    if(dealloc == 1)
+            {	
+		dealloc_count++;
+		free(Cur_file_ptr->fh_data);
+		Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+            }
+	    continue;
+	}
+
+	/* make the directory */
+	if (lad_mkdir(Cur_file_ptr, Cur_filename) == -1) {
+	    /* some error that I don't know what to do with, quit. */
+	    (void) generic_kill(0, SIGINT);
+	    exit(161);
+	}
+	if(dealloc == 1)
+	{
+		dealloc_count++;
+		free(Cur_file_ptr->fh_data);
+		Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+	}
+    } /* end for each directory */
+
+    /*
+     * Setup for file i/o operations.
+     * Verify that we can read and write all the files.
+     * Make sure we have the attributes && fh for all regular files.
+     * Create any missing files.
+     */
+    max_filenum = Num_io_files + Num_non_io_files;
+    alloc_count=dealloc_count=0;
+    for (filenum = 0; filenum < max_filenum; filenum++) {
+	sfs_gettime(&Cur_time);
+
+	if (filenum < Num_io_files) {
+	    Cur_file_ptr = &Io_files[filenum];
+	} else {
+	    Cur_file_ptr = &Non_io_files[filenum - Num_io_files];
+	    non = 1;
+	}
+	(void) sprintf(Cur_filename, Filespec, Cur_file_ptr->unique_num);
+	dealloc=0;
+	if(Cur_file_ptr->fh_data == (sfs_fh_data *)0)
+	{
+		alloc_count++;
+		Cur_file_ptr->fh_data = calloc(1,sizeof(sfs_fh_data));
+		Cur_file_ptr->attributes2.type = NFNON;
+		Cur_file_ptr->attributes3.type = NF3NON;
+		if(Cur_file_ptr->working_set == 1)
+			dealloc=0;
+		else
+			dealloc=1;
+	}
+
+	/*
+	 * Get the size this file should be initialized to, then reset
+	 * so we don't get confused.
+	 */
+	init_size = Cur_file_ptr->size;
+	Cur_file_ptr->size = 0;
+
+	if (DEBUG_CHILD_SETUP) {
+	    (void) fprintf(stderr, "%s: initialize %s (REG for %sIO)\n",
+				   sfs_Myname, Cur_filename,
+				   (non ? "non-": ""));
+	    (void) fflush(stderr);
+	}
+
+	if ((ret = lad_lookup(Cur_file_ptr, Cur_filename)) == -1) {
+	    /* some error that I don't know what to do with, quit. */
+	    (void) generic_kill(0, SIGINT);
+	    exit(162);
+	}
+
+	if (ret == 0) {
+	    /*
+	     * If file exists and it shouldn't, remove it
+	     */
+	    if (!Cur_file_ptr->initialize) {
+	        if (lad_remove(Cur_file_ptr, Cur_filename) != 0) {
+	            /* some error that I don't know what to do with, quit. */
+	            (void) generic_kill(0, SIGINT);
+	            exit(163);
+	        }
+		if(dealloc == 1)
+		{
+			dealloc_count++;
+			free(Cur_file_ptr->fh_data);
+			Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+		}
+		continue;
+	    }
+
+	    /*
+	     * file exists: make sure it is
+	     *	- a regular file
+	     *	- accessible (permissions ok)
+	     * if not, remove it (if necessary) and recreate it
+	     * or extend or truncate it to the standard length.
+	     */
+	    if (fh_isfile(Cur_file_ptr) &&
+				check_fh_access(Cur_file_ptr) == 0) {
+		goto adjust_size;
+	    }
+	    if (lad_remove(Cur_file_ptr, Cur_filename) != 0) {
+	        /* some error that I don't know what to do with, quit. */
+	        (void) generic_kill(0, SIGINT);
+	        exit(164);
+	    }
+
+	} /* end if the file exists */
+
+	/* the file doesn't exist */
+	if (!Cur_file_ptr->initialize) {
+	    /* file doesn't exist and it shouldn't */
+	    if(dealloc == 1)
+	    {
+		dealloc_count++;
+		free(Cur_file_ptr->fh_data);
+		Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+	    }
+	    continue;
+	}
+
+	/* if the file doesn't exist (or was removed), create it */
+	if (lad_create(Cur_file_ptr, Cur_filename) == -1) {
+	    /* some error that I don't know what to do with, quit. */
+	    (void) generic_kill(0, SIGINT);
+	    exit(165);
+	}
+
+adjust_size:
+	/* the non-i/o regular files can be left empty */
+	if (filenum >= Num_io_files) {
+	    /* Truncate if it has grown */
+	    if (fh_size(Cur_file_ptr) != 0) {
+		if (lad_truncate(Cur_file_ptr, 0)) {
+            	    /* some error that I don't know what to do with, quit. */
+            	    (void) generic_kill(0, SIGINT);
+            	    exit(166);    
+		}
+	    }
+ 	    if(dealloc == 1)
+	    {
+		dealloc_count++;
+		free(Cur_file_ptr->fh_data);
+		Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+	    }
+	    continue;
+        }     
+
+	/* the i/o file must be prefilled, check if file too big */
+	if (fh_size(Cur_file_ptr) > init_size) {
+	    /* Truncate if it has grown */
+	    if (fh_size(Cur_file_ptr) != 0) {
+		if (lad_truncate(Cur_file_ptr, init_size)) {
+            	    /* some error that I don't know what to do with, quit. */
+            	    (void) generic_kill(0, SIGINT);
+            	    exit(167);    
+		}
+	    }
+	    if(dealloc == 1)
+	    {
+		dealloc_count++;
+		free(Cur_file_ptr->fh_data);
+		Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+	    }
+	    continue;
+	}
+
+	/* the i/o file must be prefilled, set up the write arguments. */
+	if (fh_size(Cur_file_ptr) < init_size) {
+	    append_size = init_size - fh_size(Cur_file_ptr);
+
+	    if (lad_write(Cur_file_ptr, fh_size(Cur_file_ptr), append_size)) {
+	        /* some error that I don't know what to do with, quit. */
+	        (void) generic_kill(0, SIGINT);
+	        exit(168);
+	    }
+	}
+	if(dealloc == 1)
+	{
+		dealloc_count++;
+		free(Cur_file_ptr->fh_data);
+		Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+	}
+    } /* end for each regular file */
+
+    /*
+     * Create symlinks so operations that
+     * require them will have a file to work with.
+     */
+    alloc_count=dealloc_count=0;
+    for (filenum = 0; filenum < Num_symlink_files; filenum++) {
+	char	symlink_target[SFS_MAXNAMLEN];
+
+	sfs_gettime(&Cur_time);
+
+	Cur_file_ptr = &Symlinks[filenum];
+	(void) sprintf(Cur_filename, Symspec, Cur_file_ptr->unique_num);
+
+	dealloc=0;
+	if(Cur_file_ptr->fh_data == (sfs_fh_data *)0)
+	{
+		alloc_count++;
+		Cur_file_ptr->fh_data = calloc(1,sizeof(sfs_fh_data));
+		Cur_file_ptr->attributes2.type = NFNON;
+		Cur_file_ptr->attributes3.type = NF3NON;
+		if(Cur_file_ptr->working_set == 1)
+			dealloc=0;
+		else
+			dealloc=1;
+	}
+	if (DEBUG_CHILD_SETUP) {
+	    (void) fprintf(stderr, "%s: initialize %s (SYMLINK)\n",
+				   sfs_Myname, Cur_filename);
+	    (void) fflush(stderr);
+	}
+
+	if ((ret = lad_lookup(Cur_file_ptr, Cur_filename)) == -1) {
+	    /* some error that I don't know what to do with, quit. */
+	    (void) generic_kill(0, SIGINT);
+	    exit(169);
+	}
+
+	if (ret == 0) {
+	    /* file exists */
+	    if (lad_remove(Cur_file_ptr, Cur_filename) != 0) {
+	        /* some error that I don't know what to do with, quit. */
+	        (void) generic_kill(0, SIGINT);
+	        exit(170);
+	    }
+        }
+	
+	/* File doesn't exist */
+	if (Cur_file_ptr->initialize) {
+		/* make	the symlink */
+	    (void) sprintf(symlink_target, Filespec, filenum);
+	    if (lad_symlink(Cur_file_ptr, symlink_target, Cur_filename) != 0) {
+	        /* some error that I don't know what to do with, quit. */
+	        (void) generic_kill(0, SIGINT);
+	        exit(171);
+	    }
+	}
+	if(dealloc == 1)
+	{
+		dealloc_count++;
+		free(Cur_file_ptr->fh_data);
+		Cur_file_ptr->fh_data=(sfs_fh_data *)0;
+	}
+    } /* end for each symlink */
+} /* init_testdir */
+
+/*
+ * Initialize the test results counters.
+ */
+void
+init_counters(void)
+{
+    uint_t i;
+    uint_t start_msec;
+
+    /* Ready to go - initialize operation counters */
+    for (i = 0; i < NOPS + 1; i++) {
+	Ops[i].req_cnt = 0;
+	Ops[i].results.good_calls = 0;
+	Ops[i].results.bad_calls = 0;
+	Ops[i].results.fast_calls = 0;
+	Ops[i].results.time.sec = 0;
+	Ops[i].results.time.usec = 0;
+	Ops[i].results.msec2 = 0;
+    }
+
+    /* initialize use count for each file */
+    for (i = 0; i < Num_io_files; i++) {
+	Io_files[i].use_cnt = 0;
+	Io_files[i].xfer_cnt = 0;
+    }
+    for (i = 0; i < Num_non_io_files; i++)
+	Non_io_files[i].use_cnt = 0;
+    for (i = 0; i < Num_dir_files; i++)
+	Dirs[i].use_cnt = 0;
+    for (i = 0; i < Num_symlink_files; i++)
+	Symlinks[i].use_cnt = 0;
+
+    /* initialize timers and period variables */
+    sfs_gettime(&Starttime);
+    Cur_time = Starttime;
+    start_msec = (Starttime.sec * 1000) + (Starttime.usec / 1000);
+    Previous_chkpnt_msec = start_msec;
+    Calls_this_period = 0;
+    Reqs_this_period = 0;
+    Sleep_msec_this_period = 0;
+    Calls_this_test = 0;
+    Reqs_this_test = 0;
+    Sleep_msec_this_test = 0;
+}
+
+
+
+/*
+ * -------------------------  Load Generation  -------------------------
+ */
+
+/*
+ * The routines below attempt to do over-the-wire operations.
+ * Each op tries to cause one or more of a particular
+ * NFS operation to go over the wire.  Each individual op routine
+ * returns how many OTW calls were made.
+ *
+ * An array of file information is kept for files existing in
+ * the test directory.  File handles, attributes, names, etc
+ * are stored in this array.
+ *
+ */
+
+
+#define	OP_ABORTED	(-1)
+#define	OP_BORROWED	(-2)
+#define	OP_SKIPPED	(-3)
+/*
+ * Randomly perform an operation according to the req mix weightings.
+ */
+static int
+do_op(void)
+{
+    double 	ratio;
+    int		op_count;
+    int		opnum;
+    int		start_opnum;
+    static int	failed_ops = 0;
+    static int	aborted_ops = 0;
+    static int	borrowed_ops = 0;
+
+    if (Testop != -1) {
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr, "testop start op=%s\n", Ops[Testop].name);
+	}
+	op_count = op(Testop);
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr, "end op=%s\n", Ops[Testop].name);
+	}
+	return(op_count);
+    }
+
+    /* get a random number and search the Ops tables for the proper entry */
+    ratio = sfs_random() % 10000;
+    for (opnum = 0; Ops[opnum].req_pcnt <= ratio / 100.0 ; opnum++) {
+	    ;
+    }
+
+    /*
+     * If test targeted a a specific number of ops,
+     * and the call would put us over the call target for this op,
+     * search Ops table sequentially for an op that hasn't
+     * reached its target yet
+     */
+    if (!Timed_run) {
+	start_opnum = opnum;
+	for (; Ops[opnum].results.good_calls >= Ops[opnum].target_calls;) {
+	    opnum = (opnum + 1) % NOPS;
+	    if (opnum == start_opnum)
+		break;
+	}
+    }
+
+    if (DEBUG_CHILD_RPC) {
+	(void) fprintf(stderr, "(%d,%d,%d) ",
+			   Child_num, Ops[TOTAL].results.good_calls, opnum);
+	(void) fflush(stderr);
+    }
+
+    /* attempt the op */
+    op_count = op(opnum);
+
+    /* count the operations as completed or check for too many errors */
+    if (op_count > 0) {
+	Ops[opnum].req_cnt++;
+	Ops[TOTAL].req_cnt++;
+    } else if (op_count == 0) {
+	failed_ops++;
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr, "Child %d - %d failed %d op\n",
+			   Child_num, failed_ops, opnum);
+	    (void) fflush(stderr);
+	}
+	if ((failed_ops % 50) == 0) {
+	    (void) fprintf(stderr, "Child %d - %d failed ops\n",
+			   Child_num, failed_ops);
+	    (void) fflush(stderr);
+	}
+    } else if (op_count == OP_ABORTED) {
+	aborted_ops++;
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr, "Child %d - %d aborted %d op\n",
+			   Child_num, aborted_ops, opnum);
+	    (void) fflush(stderr);
+	}
+	if ((aborted_ops % 50) == 0) {
+	    (void) fprintf(stderr, "Child %d - %d aborted ops\n",
+			   Child_num, aborted_ops);
+	    (void) fflush(stderr);
+	}
+    } else if (op_count == OP_BORROWED) {
+	borrowed_ops++;
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr, "Child %d - %d borrowed %d op\n",
+			   Child_num, borrowed_ops, opnum);
+	    (void) fflush(stderr);
+	}
+    } else if (op_count == OP_SKIPPED) {
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr, "Child %d - skipped %d op\n",
+			   Child_num, opnum);
+	    (void) fflush(stderr);
+	}
+    }
+
+    return(op_count);
+
+} /* do_op */
+
+
+/*
+ * Because file sizes are variable in length, it is possible that
+ * a group chosen for a large transfer size may not contain a file
+ * that large.  Loop calling randfh to try and find another group
+ * with a large enough file, but only up to IO_LOOP_MAX times.
+ */
+#define IO_LOOP_MAX 5
+
+/*
+ * Call the RPC operation generator for op 'opnum'.
+ * The return values of the op generator routines is the count
+ * of operations performed.  This routine also returns that count.
+ * A return of 0 means no operation was attempted,
+ * OP_ABORTED (-1) means that the operation failed.
+ * OP_BORROWED (-2) means that the operation was borrowed.
+ * OP_SKIPPED (-3) means that the operation was not done on purpose.
+ */
+static int
+op(
+    int				opnum)
+{
+    int				op_count;
+    int				trunc_count;
+    sfs_io_op_dist_type		*dist;		/* io size distribution */
+    int				i;
+    int				ratio;
+    int				buf_size;
+    int				frag_size;
+    int				xfer_size;
+    int				file_size;
+    int				trunc_op;
+    uint_t			append_flag = 0;
+    uint_t			randfh_flags = 0;
+    char			*spec;
+    int				io_loop = 0;
+
+    spec = Filespec;
+
+    /* pick a file that make sense for the operation */
+    switch (opnum) {
+
+	case NULLCALL:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_io_file);
+	    break;
+
+	case GETATTR:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_io_file);
+	    break;
+
+	case SETATTR:
+	    if (Setattr_borrowed != 0) {
+		Setattr_borrowed--;
+		return(OP_BORROWED);
+	    }
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_io_file);
+	    break;
+
+	case ROOT:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent, Sfs_non_io_file);
+	    break;
+
+	case LOOKUP:
+	    ratio = (int) (sfs_random() % 100);
+	    if (ratio < Num_failed_lookup)
+		Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent, Sfs_non_io_file);
+	    else
+		Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_io_file);
+	    break;
+
+	case READLINK:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_symlink);
+	    spec = Symspec;
+	    break;
+
+	case READ:
+	    /* special handling for i/o operations */
+	    dist = Io_dist_ptr->read;
+
+	    /* determine number of full buffers and their total size */
+	    ratio = (sfs_random() % 100);
+	    for (i = 0; dist[i].pcnt <= ratio; i++)
+		;
+	    buf_size = dist[i].bufs * Bytes_per_block;
+
+	    /* determine size of fragment */
+	    /* 1KB - (Kb_per_block - 1) KB fragment */
+	    ratio = sfs_random();
+	    if (Kb_per_block > 1)
+		ratio = ratio % (Kb_per_block-1);
+	    else
+		ratio = 0;
+	    ratio = (ratio + 1) * 1024;
+	    frag_size = dist[i].frags * ratio;
+
+	    xfer_size = buf_size + frag_size;
+
+	    do {
+		Cur_file_ptr = randfh(opnum, xfer_size, 0, Exists,
+				  Sfs_io_file);
+	    } while (Cur_file_ptr == (sfs_fh_type *) -1 &&
+						io_loop++ < IO_LOOP_MAX);
+	    break;
+
+	case WRCACHE:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent, Sfs_non_io_file);
+	    break;
+
+	case WRITE:
+	    /* special handling for i/o operations */
+	    dist = Io_dist_ptr->write;
+
+	    /* determine number of full buffers and their total size */
+	    ratio = (sfs_random() % 100);
+	    for (i = 0; dist[i].pcnt <= ratio; i++)
+		;
+	    buf_size = dist[i].bufs * Bytes_per_block;
+
+	    /* determine size of fragment */
+	    /* 1KB - (Kb_per_block - 1) KB fragment */
+	    ratio = sfs_random();
+	    if (Kb_per_block > 1)
+		ratio = ratio % (Kb_per_block-1);
+	    else
+		ratio = 0;
+	    ratio = (ratio + 1) * 1024;
+	    frag_size = dist[i].frags * ratio;
+
+	    xfer_size = buf_size + frag_size;
+
+	    /* decide if it should append or overwrite. */
+	    ratio = (sfs_random() % 100);
+	    if (ratio < Append_percent) {
+		append_flag = 1;
+		randfh_flags &= RANDFH_APPEND;
+	    }
+
+	    /* decide if a truncation will be needed */
+	    if (append_flag &&
+		    ((Cur_fss_bytes + (xfer_size / 1024)) > Limit_fss_bytes)) {
+		randfh_flags &= RANDFH_TRUNC;
+	    }
+
+	    do {
+		Cur_file_ptr = randfh(opnum, xfer_size,
+				  randfh_flags,
+				  Exists, Sfs_io_file);
+	    } while (Cur_file_ptr == (sfs_fh_type *) -1 &&
+						io_loop++ < IO_LOOP_MAX);
+	    break;
+
+	case CREATE:
+	    if (Create_borrowed != 0) {
+		Create_borrowed--;
+		return(OP_BORROWED);
+	    }
+	    if ((Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent,
+			      Sfs_non_io_file)) != (sfs_fh_type *) NULL)
+		break;
+
+	    /* if there are no Nonexistent files, use one that exists */
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists,
+					  Sfs_non_io_file);
+	    /* flag create of existing file for data dump interface */
+	    dump_create_existing_file = TRUE;
+	    break;
+
+	case REMOVE:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_non_io_file);
+	    break;
+
+	case RENAME:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_non_io_file);
+	    break;
+
+	case LINK:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent,
+				  Sfs_non_io_file);
+	    break;
+
+	case SYMLINK:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent, Sfs_symlink);
+	    spec = Symspec;
+	    break;
+
+	case MKDIR:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent, Sfs_dir);
+	    spec = Dirspec;
+	    break;
+
+	case RMDIR:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Empty_dir, Sfs_dir);
+	    spec = Dirspec;
+	    break;
+
+	case READDIR:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_dir);
+	    spec = Dirspec;
+	    break;
+
+	case FSSTAT:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_io_file);
+	    break;
+
+	case ACCESS:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_io_file);
+	    break;
+
+	case COMMIT:
+	    return(OP_SKIPPED);
+
+	case FSINFO:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_non_io_file);
+	    break;
+
+	case MKNOD:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Nonexistent, Sfs_non_io_file);
+	    break;
+
+	case PATHCONF:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_non_io_file);
+	    break;
+
+	case READDIRPLUS:
+	    Cur_file_ptr = randfh(opnum, 0, 0, Exists, Sfs_dir);
+	    spec = Dirspec;
+	    break;
+
+	default:
+	    (void) fprintf(stderr, "%s: invalid operation %d\n", sfs_Myname, opnum);
+	    (void) generic_kill(0, SIGINT);
+	    exit(172);
+    } /* switch on opnum */
+
+    if (Cur_file_ptr == (sfs_fh_type *) NULL ||
+				Cur_file_ptr == (sfs_fh_type *) -1) {
+	Ops[opnum].no_calls++;
+	return(OP_ABORTED);
+    }
+
+    (void) sprintf(Cur_filename, spec, Cur_file_ptr->unique_num);
+
+    /* Call the op routine.  For io operations, maintain file set size info. */
+    switch (opnum) {
+
+	case SETATTR:
+	    op_count = (*Ops[opnum].funct)(-1);
+	    break;
+
+	case READ:
+	    op_count = (*Ops[opnum].funct)(xfer_size);
+	    if (op_count > 0)
+		Cur_file_ptr->xfer_cnt += (xfer_size + 1023)  / 1024;
+	    else if (DEBUG_CHILD_ERROR) {
+		(void) fprintf(stderr, "%s: READ failed\n", sfs_Myname);
+		(void) fflush(stderr);
+	    }
+	    break;
+
+	case WRITE:
+	    trunc_count = 0;
+
+	    /* if appending, we may need to truncate the file first */
+	    if (append_flag &&
+		    ((Cur_fss_bytes + (xfer_size / 1024)) > Limit_fss_bytes)) {
+
+		/* use either SETATTR or CREATE for truncation */
+		file_size = fh_size(Cur_file_ptr);
+		trunc_op = -1; /* assume there are no ops to borrow */
+
+		if (Ops[SETATTR].mix_pcnt == 0 && Ops[CREATE].mix_pcnt == 0)
+		    trunc_op = -1;		/* no ops to borrow */
+
+		else if (Ops[SETATTR].mix_pcnt > 0 && Ops[CREATE].mix_pcnt > 0){
+		    /* only borrow if the target hasn't been met yet */
+		    if (Ops[SETATTR].results.good_calls
+			>= Ops[SETATTR].target_calls) {
+			if (Ops[CREATE].results.good_calls
+			    < Ops[CREATE].target_calls) {
+			    trunc_op = CREATE;		/* borrow a CREATE */
+			}
+		    } else if (Ops[CREATE].results.good_calls
+			       >= Ops[CREATE].target_calls) {
+			trunc_op = SETATTR;		/* borrow a SETATTR */
+		    } else {
+			/* borrow weighted by mix percentage */
+			if ((Ops[SETATTR].mix_pcnt * Create_borrowed) >
+			    (Ops[CREATE].mix_pcnt * Setattr_borrowed))
+			    trunc_op =  SETATTR;
+			else
+			    trunc_op =  CREATE;
+		    }
+
+		} else if (Ops[SETATTR].results.good_calls <
+			   Ops[SETATTR].target_calls) {
+		    /* only borrow if the target hasn't been met yet */
+		    trunc_op = SETATTR;		/* borrow a SETATTR */
+
+		} else if (Ops[CREATE].results.good_calls <
+			   Ops[CREATE].target_calls) {
+		    /* only borrow if the target hasn't been met yet */
+		    trunc_op = CREATE;		/* borrow a CREATE */
+		}
+
+		/* perform the truncation and update the file set size */
+		if (trunc_op != -1) {
+		    dump_truncate_op = TRUE;
+		    if (trunc_op == SETATTR) {
+			trunc_count = (*Ops[SETATTR].funct)(0);
+			if (trunc_count > 0) {
+			    Setattr_borrowed++;
+			    if (DEBUG_CHILD_FILES) {
+				(void) fprintf(stderr, "%s: SETATTR TRUNCATE\n",
+						sfs_Myname);
+				(void) fflush(stderr);
+			    }
+			}
+		    } else if (trunc_op == CREATE) {
+			trunc_count = (*Ops[CREATE].funct)();
+			if (trunc_count > 0) {
+			    Create_borrowed++;
+			    if (DEBUG_CHILD_FILES) {
+				(void) fprintf(stderr, "%s: CREATE TRUNCATE\n",
+					    sfs_Myname);
+				(void) fflush(stderr);
+			    }
+			}
+		    }
+
+		    Cur_fss_bytes -= (file_size / 1024);
+		    if (Cur_fss_bytes < Least_fss_bytes)
+			Least_fss_bytes = Cur_fss_bytes;
+		}
+	    } /* end of if an append is needed */
+
+	    /*
+	     * do the write request
+	     * specify the stable flag to always be off, it is not used
+	     * with V2 servers.
+	     */
+	    op_count = (*Ops[opnum].funct)(xfer_size, append_flag, 0);
+	    if (op_count > 0)
+		Cur_file_ptr->xfer_cnt += (xfer_size + 1023)  / 1024;
+	    else if (DEBUG_CHILD_ERROR) {
+		(void) fprintf(stderr, "%s: WRITE failed\n", sfs_Myname);
+		(void) fflush(stderr);
+	    }
+	    if (append_flag) {
+		Cur_fss_bytes += (xfer_size / 1024);
+		if (Cur_fss_bytes > Most_fss_bytes)
+		    Most_fss_bytes = Cur_fss_bytes;
+	    }
+	    op_count += trunc_count;
+	    break;
+
+	default:
+	    op_count = (*Ops[opnum].funct)();
+	    break;
+
+    } /* send switch on opnum */
+
+    if ((DEBUG_CHILD_ERROR) && (op_count <= 0)) {
+	(void) fprintf(stderr, "%s: OP %d failed\n", sfs_Myname, opnum);
+	(void) fflush(stderr);
+    }
+
+    return(op_count);
+
+} /* op */
+
+
+/*
+ * Return an entry into the fh array for a file of type 'file_type'
+ * with existence state 'file_state'.  When 'opnum' specifies an I/O
+ * operation, the file must be atleast 'xfer_size' bytes long
+ * (except when 'append_flag' is true).  If 'trunc_flag', spare the
+ * first file found that is longer than the base file size (to support
+ * the READ operation).  If only one file is longer than the base file
+ * size, return the the next longest file.
+ */
+sfs_fh_type *
+randfh(
+    int				opnum,
+    int				xfer_size,
+    uint_t			flags,
+    sfs_state_type		file_state,
+    sfs_file_type		file_type)
+{
+    sfs_fh_type *	files;		/* file array */
+    int			fh;		/* index into file array */
+    int			found_fh = -1;	/* index into file array */
+    uint_t		append_flag = flags & RANDFH_APPEND;
+    uint_t		trunc_flag = flags & RANDFH_TRUNC;
+
+    sfs_work_set_type * work_set;	/* work_set array */
+    int			start_file;	/* index into work_set array */
+    int			file;		/* index into work_set array */
+
+    int			nworkfiles;	/* # files in work_set */
+    int			group_cnt;	/* # file groups in work_set */
+    int			group_size;	/* size of each group in work_set */
+    int			group;		/* group index with work_set */
+    int			offset;		/* file index within group */
+
+    int			value;		/* distribution function value */
+    int			previous;	/* binary search for value */
+    int			low;		/* binary search for value */
+    int			high;		/* binary search for value */
+
+    int			found_file = 0; /* count */
+    int			best_delta = 0;
+    static int		op_num = 0;
+    long		rand_int;
+    int			max_range;
+
+    op_num++;
+
+    /*
+     * if the more than one type of file will do, choose one.
+     * Note: this code assumes specific values and order for
+     * the entries in sfs_file_enum_type.
+     */
+    switch (file_type) {
+
+	case Sfs_regular:
+	    file_type = (int) (sfs_random() % 2);
+	    break;
+
+	case Sfs_non_dir:
+	    file_type = (int) (sfs_random() % 3);
+	    break;
+
+	case Sfs_any_file:
+	    file_type = (int) (sfs_random() % 4);
+	    break;
+
+	default:
+	    break;
+
+    } /* end switch on file type */
+
+    /* get the file type arrays */
+    switch (file_type) {
+
+	case Sfs_io_file:
+	    files = Io_files;
+	    work_set = &Io_working_set;
+	    nworkfiles = Num_working_io_files;
+	    break;
+
+	case Sfs_non_io_file:
+	    files = Non_io_files;
+	    work_set = &Non_io_working_set;
+	    nworkfiles = Num_working_non_io_files;
+	    break;
+
+	case Sfs_symlink:
+	    files = Symlinks;
+	    work_set = &Symlink_working_set;
+	    nworkfiles = Num_working_symlinks;
+	    break;
+
+	case Sfs_dir:
+	    files = Dirs;
+	    work_set = &Dir_working_set;
+	    nworkfiles = Num_working_dirs;
+	    break;
+
+	default:
+	    (void) fprintf(stderr, "%s: invalid file type\n", sfs_Myname);
+	    (void) kill(0, SIGINT);
+	    exit(174);
+    } /* end switch on file type */
+
+    /*
+     * Pick the access group.
+     *
+     * Each access group consists of those files in the working set
+     * (numbered according to the file's index in the array) that
+     * have the same value modulo the number of groups.  For example,
+     * a working set of 13 files with 3 groups is organized as
+     *		group   files
+     *		-----	-----------------
+     *		  0  	0,  3,  6,  9, 12	ie, == 0 mod 3
+     *		  1  	1,  4,  7, 10		ie, == 1 mod 3
+     *		  2  	2,  5,  8, 11		ie, == 2 mod 3
+     *
+     * Generate a random number mod the maximum range value of the working set.
+     * and then binary search the first group_cnt entries in the working set
+     * to find the group whose range contains the random number.
+     * (this implements the file access distribution function)
+     */
+    max_range = work_set->max_range;
+    rand_int = (long) sfs_random();
+
+    while ((rand_int / max_range) >= (_M_MODULUS / max_range)) {
+      /*
+       * for large values of max_range, modulo doesn't provide a uniform
+       * distribution unless we exclude these values ...
+       */
+      rand_int = (long) sfs_random();
+    }      
+    value = rand_int % max_range;
+
+    if (DEBUG_CHILD_OPS) {
+	(void) fprintf(stderr, "randfh: size=%d cnt=%d max=%d val=%3d\n",
+			    work_set->access_group_size,
+			    work_set->access_group_cnt,
+			    work_set->max_range, value);
+	(void) fflush(stderr);
+    }
+
+    previous = -1;
+    for (low = 0, high = work_set->access_group_cnt-1, group = (low + high)/2;;
+	 previous = group, group = (low + high)/2) {
+
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr,
+			    "PICK GROUP low=%d hi=%d grp=%d range=%d val=%d\n",
+			    low, high, group, work_set->entries[group].range,
+			    value);
+	    (void) fflush(stderr);
+	}
+
+	if (previous == group)
+	    break;
+	if (work_set->entries[group].range == value)
+	    break;
+	if (work_set->entries[group].range > value) {
+	    if (group == 0)
+		break;
+	    if (work_set->entries[group-1].range < value)
+		break;
+	    else
+		high = group - 1;
+	} else if (work_set->entries[group].range < value) {
+	    if (work_set->entries[group+1].range > value) {
+		group++;
+		break;
+	    } else
+		low = group + 1;
+	}
+    }
+
+    /*
+     * Pick a file within the group to operate on.
+     * Since (working_set_size / group_size) may have a remainder,
+     * groups may have either group_size or (group_size+1) files.
+     */
+    group_cnt = work_set->access_group_cnt;
+    group_size = work_set->access_group_size;
+    if (group < (nworkfiles - ((nworkfiles / group_cnt) * group_cnt)))
+	group_size += 1;
+
+    if (DEBUG_CHILD_OPS) {
+	(void) fprintf(stderr, "Selected group = %d\n", group);
+	(void) fflush(stderr);
+    }
+    /*
+     * Beginning with a random starting point in the group,
+     * search for a file that is eligible for this operation.
+     * 	  index is an index into the files in the group.
+     * 	  file and start_file are indices into the working set array.
+     */
+    if (DEBUG_CHILD_OPS) {
+	(void) fprintf(stderr, "group_size = %d\n", group_size);
+	(void) fflush(stderr);
+    }
+
+    offset = (int) (sfs_random() % group_size);
+    start_file = group + (offset * group_cnt);
+    file = start_file;
+    do {
+	int f_size;
+	int delta;
+
+	fh = work_set->entries[file].index;
+
+	if (DEBUG_CHILD_OPS) {
+	    (void) fprintf(stderr, "PICK FILE op= %d file=%d fh=%d\n",
+				opnum, file, fh);
+	    (void) fprintf(stderr, "fh_state = %d file_state= %d\n",
+				files[fh].state, file_state);
+	    (void) fflush(stderr);
+	}
+
+	/* look for a file that has the right state attribute */
+	if (files[fh].state == file_state) {
+	    f_size = fh_size(&files[fh]);
+
+	    /*
+	     * for read and write ops and setattr truncates,
+	     * the file must be large enough to do the xfer or truncate.
+	     */
+	    if ((opnum == READ) || (opnum == WRITE && !append_flag) ||
+								trunc_flag) {
+
+		/*
+		 * If the request is a read and the transfer size is
+		 * less than or equal to be block size, grab the first
+		 * file that is less than or equal in size.  Should never
+		 * see a transfer size less than block size as it will
+		 * be rounded up for the request.  This allows small files
+		 * to be read.
+		 */
+		if (opnum == READ && xfer_size <= Bytes_per_block) {
+		    if (f_size <= Bytes_per_block) {
+		        found_fh = fh;
+		        break;
+		    }
+		}
+/* #define FIRST_FIT */
+#define BEST_FIT
+#ifdef FIRST_FIT
+		if (f_size >= xfer_size) {
+		    found_fh = fh;
+		    break;
+		}
+#endif
+#ifdef BEST_FIT
+	        if (DEBUG_CHILD_FIT) {
+		    (void) fprintf(stderr,
+"%s: %8d: xfer_size %d f_size %d best_delta %d found %d\n",
+sfs_Myname, op_num, xfer_size, f_size, best_delta, found_file);
+	            (void) fflush(stderr);
+	        }
+
+		/*
+		 * If we find an good enough match we should use it.
+		 * Define good enough to be xfer_size <= X < xfer_size + 8K
+		 * If not we continue to search for the best fit within
+		 * a fixed distance 8.
+		 */
+		if (f_size >= xfer_size) {
+		    if (f_size < (xfer_size + 8 * 1024)) {
+			found_fh = fh;
+			break;
+		    }
+
+		    found_file++;
+		    delta = f_size - xfer_size;
+
+		    if (found_fh == -1) {
+			best_delta = delta;
+			found_fh = fh;
+			/* break; Removed as per Robinson */
+		    }
+
+		    if (delta < best_delta) {
+			found_fh = fh;
+			best_delta = delta;
+		    }
+
+		    if (found_file >= 8) {
+			break;
+		    }
+		}
+#endif
+	    } else {
+		/* for non-i/o ops, only requirement is proper file state */
+		found_fh = fh;
+		break;
+	    }
+	}
+	offset = (offset + 1) % group_size;
+	file = group + (offset * group_cnt);
+    } while (file != start_file);
+
+    if (found_fh == -1) {
+	/* didn't find a file for this operation */
+	if (DEBUG_CHILD_FIT) {
+	    if (opnum == READ || (opnum == WRITE && !append_flag) ||
+		opnum == SETATTR) {
+		(void) fprintf(stderr, "%s: no file for %d byte %d op\n",
+			       sfs_Myname, xfer_size, opnum);
+	    } else {
+		(void) fprintf(stderr, "%s: no file for %d op\n",
+			       sfs_Myname, opnum);
+	    }
+	    (void) fflush(stderr);
+	    return((sfs_fh_type *) -1);
+	}
+	return((sfs_fh_type *) NULL);
+    }
+    /* found it */
+    files[found_fh].use_cnt++;
+    return(&files[found_fh]);
+} /* randfh */
+
+/*
+ * ------------------------ Miscellaneous Subroutines  -----------------------
+ */
+
+/*
+ * check to make sure that we have both read and write permissions
+ * for this file or directory given in 'statb'.
+ * return: 0 == ok, -1 == bad
+ */
+int
+check_access(
+    struct stat		*statb)
+{
+    /* check user */
+    if (statb->st_uid == Real_uid) {
+	if ((statb->st_mode & 0400) && (statb->st_mode & 0200)) {
+	    return(0);
+	} else {
+	    return(-1);
+	}
+    }
+
+    /* check group */
+    if (statb->st_gid == Cur_gid) {
+	if ((statb->st_mode & 040) && (statb->st_mode & 020)) {
+		return(0);
+	    } else {
+		return(-1);
+	    }
+    }
+
+    /* check other */
+    if ((statb->st_mode & 04) && (statb->st_mode & 02)) {
+	return(0);
+    } else {
+	return(-1);
+    }
+
+} /* check_access */
+
+/*
+ * check to make sure that we have both read and write permissions
+ * for this file or directory given in the file attributes.
+ * return: 0 == ok, -1 == bad
+ */
+int
+check_fh_access(sfs_fh_type *file_ptr)
+{
+    /* check user */
+    if (fh_uid(file_ptr) == Real_uid) {
+	if ((fh_mode(file_ptr) & 0400) && (fh_mode(file_ptr) & 0200)) {
+	    return(0);
+	} else {
+	    return(-1);
+	}
+    }
+
+    /* check group */
+    if (fh_gid(file_ptr) == Cur_gid) {
+	if ((fh_mode(file_ptr) & 040) && (fh_mode(file_ptr) & 020)) {
+		return(0);
+	    } else {
+		return(-1);
+	    }
+    }
+
+    /* check other */
+    if ((fh_mode(file_ptr) & 04) && (fh_mode(file_ptr) & 02)) {
+	return(0);
+    } else {
+	return(-1);
+    }
+}
+
+static int last_bad_calls = 0;
+
+/*
+ * Adjust the sleep time per call based on a number of global variables,
+ */
+static void
+check_call_rate()
+{
+    int         call_target_per_period; /* target calls for each period */
+    int         req_target_per_period;  /* target reqs for each period */
+    int         call_target_this_test;  /* target calls for test so far */
+    int         req_target_this_test;   /* target reqs for test so far */
+    int         msec_this_period;       /* actual length of this period */
+    int         msec_this_test;         /* actual length of test so far */
+    uint_t	current_msec;           /* current time in msecs */
+    int         old_target_sleep_mspc;
+    struct ladtime elapsed_time;	/* Current_time - Start_time */
+
+    int         reqs_needed_next_period;/* req target for the next period */
+    float       mspc;                   /* target msec per call, with/sleep */
+    float       work_mspc;              /* actual msec worked / call */
+
+
+    if (Child_num == -1)
+	/* I'm the parent, ignore the signal */
+	return;
+
+    /* update the test so far totals */
+    Calls_this_test += Calls_this_period;
+    Reqs_this_test += Reqs_this_period;
+    Sleep_msec_this_test += Sleep_msec_this_period;
+
+    /* compute per period targets */
+    call_target_per_period = (int) (Child_call_load *
+			     ((float) Msec_per_period / (float) 1000));
+    req_target_per_period = (int) (Child_req_load *
+			    ((float) Msec_per_period / (float) 1000));
+
+    /*
+     * The child() routine retrieved the Cur_time when deciding to call us.
+     * Use Cur_time to compute the elapsed time since the last checkpoint
+     * and the current checkpoint time (ie, elapsed time since test began)
+     */
+    /* sfs_gettime(&Cur_time); */
+    elapsed_time.sec = Cur_time.sec;
+    elapsed_time.usec = Cur_time.usec;
+    SUBTIME(elapsed_time, Starttime);
+
+    msec_this_test = (elapsed_time.sec * 1000) + (elapsed_time.usec / 1000);
+    current_msec = (Cur_time.sec * 1000) + (Cur_time.usec / 1000);
+    msec_this_period = current_msec - Previous_chkpnt_msec;
+
+    if (msec_this_test < Sleep_msec_this_test) {
+	if (DEBUG_CHILD_XPOINT) {
+	    (void) fprintf(stderr,
+                        "Accum. sleep time %d is msecs ahead of wall clock\n",
+                                Sleep_msec_this_test - msec_this_test);
+	    (void) fflush(stderr);
+	}
+	Sleep_msec_this_test = msec_this_test;
+    }
+
+    /* compute targets for test so far */
+    call_target_this_test = (int) ((Child_call_load * (float) msec_this_test)
+				   / (float) 1000);
+    req_target_this_test = (int) ((Child_req_load * (float) msec_this_test)
+				   / (float) 1000);
+
+    /* save the old sleep rate */
+    old_target_sleep_mspc = Target_sleep_mspc;
+
+    /* Compute how long each request has taken on average. */
+    if (Reqs_this_test != 0)
+	work_mspc = ((float) (msec_this_test - Sleep_msec_this_test))
+		     / (float) Reqs_this_test;
+    else
+	work_mspc = (1000.0 / (float) Child_req_load) / 2.0;
+
+    /*
+     * Compute the number of reqs needed in the next period
+     * in order to just meet the reqstarget for the test when that period ends.
+     * (Try to make up the entire shortage or overage in the next period.)
+     * Beware that we might not need to make any reqs next period.
+     */
+    reqs_needed_next_period = (req_target_this_test - Reqs_this_test)
+			      + req_target_per_period;
+
+    if (reqs_needed_next_period <= 0) {
+	/* if no reqs are needed, set the sleep time to the whole period */
+	mspc = 0.0;
+	Target_sleep_mspc = Msec_per_period;
+    } else {
+	/* decide how much time is available for each request */
+	mspc = (float) (Msec_per_period) / (float) (reqs_needed_next_period);
+	Target_sleep_mspc = (int) (mspc - work_mspc);
+    }
+
+    /* Don't increase the target_sleep_mspc by much more than a factor of two,
+        because doing so can lead to violent oscillations. */
+    if (Target_sleep_mspc > 2*(old_target_sleep_mspc + 5)) {
+       Target_sleep_mspc = 2*(old_target_sleep_mspc + 5);
+    }    
+
+    if (Target_sleep_mspc >= Msec_per_period) {
+        Target_sleep_mspc = Msec_per_period;
+	if (DEBUG_CHILD_XPOINT) {
+	    (void) fprintf(stderr,
+    "Child %d: 0 call, rqnd %d mspc %3.2f wmspc %3.2f time %d slp %d reqs %d\n",
+		    Child_num, reqs_needed_next_period, mspc, work_mspc,
+		    msec_this_test, Sleep_msec_this_test, Reqs_this_test);
+	    (void) fflush(stderr);
+	}
+        if (Measurement_in_progress) {
+   	    (void) fprintf(stderr,
+            	"Child %d:  0 calls during measurement interval\n",Child_num);
+   	    (void) fprintf(stderr,
+                    "Child %d:  probably unstable, try more processes.\n",Child_num);
+   	    (void) generic_kill(0, SIGINT);
+   	    (void) fflush(stderr);
+   	    exit(188);
+         }
+    }
+    if (Target_sleep_mspc <= 0) {
+	 Target_sleep_mspc = 0;
+	 if (DEBUG_CHILD_XPOINT) {
+		(void) fprintf(stderr,
+    "Child %d: 0 slp, rqnd %d mspc %3.2f wmspc %3.2f time %d slp %d reqs %d\n",
+			Child_num, reqs_needed_next_period, mspc, work_mspc,
+			msec_this_test, Sleep_msec_this_test, Reqs_this_test);
+		(void) fflush(stderr);
+	 }
+    }
+
+    if (DEBUG_CHILD_XPOINT) {
+	(void) fprintf(stderr, "Child %d\n%s", Child_num,
+	"        msec_prd  calls_prd reqs_prd calls_tot req_tot    mspc_req\n");
+	(void) fprintf(stderr, "target: %8d %9d %8d %9d %8d    %6.2f\n",
+			Msec_per_period,
+			call_target_per_period, req_target_per_period,
+			call_target_this_test, req_target_this_test,
+			1000.0 / (float) req_target_per_period);
+	(void) fprintf(stderr, "actual: %8d %9d %8d %9d %8d  ->%6.2f\n",
+			msec_this_period,
+			Calls_this_period, Reqs_this_period,
+			Calls_this_test, Reqs_this_test,
+			mspc);
+	(void) fprintf(stderr,
+			"        old_sleep_mspc  %5d   new_sleep_mspc  %5d\n\n",
+			old_target_sleep_mspc, Target_sleep_mspc);
+    }
+
+    /*
+     * check for too many failed RPC calls
+     * and print a warning if there are too many.
+     */
+    if (((Ops[TOTAL].results.bad_calls - last_bad_calls) > 100) ||
+	((Ops[TOTAL].results.good_calls > 300) &&
+	 ((Ops[TOTAL].results.bad_calls - last_bad_calls) >
+					Ops[TOTAL].results.good_calls/50))) {
+	(void) fprintf(stderr,
+			"%s: too many failed RPC calls - %d good %d bad\n",
+			sfs_Myname, Ops[TOTAL].results.good_calls,
+			Ops[TOTAL].results.bad_calls);
+	last_bad_calls = Ops[TOTAL].results.bad_calls;
+    }
+
+    /* reset the period counters */
+    Calls_this_period = 0;
+    Reqs_this_period = 0;
+    Sleep_msec_this_period = 0;
+    Previous_chkpnt_msec = current_msec;
+
+} /* check_call_rate */
+
+/* sfs_c_chd.c */
diff --git a/TBBT/trace_play/sfs_c_chd.work b/TBBT/trace_play/sfs_c_chd.work
new file mode 100644
index 0000000..195beb0
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_chd.work
@@ -0,0 +1,3815 @@
+/* Try to change thread scheduling and uses three threads */
+#ifndef lint
+static char sfs_c_chdSid[] = "@(#)sfs_c_chd.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * -------------------------- sfs_c_chd.c -------------------------
+ *
+ *      The sfs child.  Routines to initialize child parameters,
+ *	initialize test directories, and generate load.
+ *
+ *.Exported_Routines
+ *	void child(int, float, int, char *);
+ *	void init_fileinfo(void);
+ *	void init_counters(void);
+ *	sfs_fh_type * randfh(int, int, uint_t, sfs_state_type,
+ *				sfs_file_type);
+ *	int check_access(struct *stat)
+ *	int check_fh_access();
+ *
+ *.Local_Routines
+ *	void check_call_rate(void);
+ *	void init_targets(void);
+ *	void init_dirlayout(void);
+ *	void init_rpc(void);
+ *	void init_testdir(void);
+ *	int do_op(void);
+ *	int op(int);
+ *
+ *.Revision_History
+ *	21-Aug-92	Wittle 		randfh() uses working set files array.
+ *					init_fileinfo() sets up working set.
+ *      02-Jul-92	Teelucksingh    Target file size now based on peak load
+ *					instead of BTDT.
+ *	04-Jan-92	Pawlowski	Added raw data dump hooks.
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+#include "rfs_c_def.h"
+#include "generic_hash.h"
+#include "nfsd_nfsfh_cust.h"
+
+extern struct hostent   *Server_hostent;
+
+#define PROB_SCALE 1000L
+#define _M_MODULUS 2147483647L /* (2**31)-1 */
+
+#define _GROUP_DIVISOR 500
+#define _FILES_PER_GROUP 4
+#define _MIN_GROUPS 12
+#define _WORKING_SET_AT_25_OPS_PER_SEC 975
+
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+extern uint32_t    biod_clnt_call(CLIENT *, uint32_t, xdrproc_t, void *);
+extern enum clnt_stat proc_header(CLIENT *cl, xdrproc_t xdr_results, void *results_ptr);
+extern int  biod_poll_wait(CLIENT *, uint32_t);
+extern enum clnt_stat get_areply_udp (CLIENT * cl, uint32_t *xid, struct timeval *timeout);
+extern char * parse_name (char * t, char * buf);
+
+/* forward definitions for local functions */
+static int init_rpc(void);
+
+/* RFS: forward definitions for local functions */
+void init_ops(void);
+static void init_signal();
+extern void init_file_system (void);
+extern void init_dep_tab (void);
+static int read_trace(void);
+static void read_fh_map();
+static void init_play (char * mount_point);
+static void trace_play(void);
+void print_result(void);
+static int get_nextop(void);
+static int check_timeout(void);
+static struct biod_req * get_biod_req(int dep_tab_index);
+static int lookup_biod_req (int xid);
+static void init_time_offset(void);
+void adjust_play_window (int flag, int * poll_timeout_arg);
+static int poll_and_get_reply (int usecs);
+static char * nfs3_strerror(int status);
+static void check_clock(void);
+static double time_so_far1(void);
+static double get_resolution(void);
+static void usage(void);
+void init_dep_tab_entry (int dep_index);
+extern inline fh_map_t * lookup_fh (char * trace_fh );
+static void finish_request (int biod_index, int dep_index, int status, int dep_flag);
+static inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line);
+static inline char * find_lead_trace_fh(int proc, char * line);
+static inline char * find_reply_trace_fh (char * line);
+
+/*
+ * -------------  Per Child Load Generation Rate Variables  -----------
+ */
+static uint_t Calls_this_period; /* calls made during the current run period */
+static uint_t Calls_this_test;	/* calls made during the test so far */
+static uint_t Reqs_this_period;	/* reqs made during the current run period */
+static uint_t Reqs_this_test;	/* reqs made during the test so far */
+static uint_t Sleep_msec_this_test; /* msec slept during the test so far */
+static uint_t Sleep_msec_this_period;
+static uint_t Previous_chkpnt_msec; /* beginning time of current run period */
+static int Target_sleep_mspc;	/* targeted sleep time per call */
+
+static char io_buf[BUFSIZ];	/* io buffer for print out messages */
+
+char * sfs_Myname;
+int     Log_fd;                         /* log fd */
+char    Logname[NFS_MAXNAMLEN];         /* child processes sync logfile */
+int 	Validate = 0;					/* fake variable */
+int Child_num = 0;						/* fake: child index */
+int Tcp = 0;							/* We implement UDP first */
+int Client_num = 1;						/* fake: number of client */
+uid_t Real_uid;
+gid_t Cur_gid;
+uid_t Cur_uid;
+/* as long as the inital value is different, then it's OK */
+int recv_num = 0;
+int timeout_num = 0;
+int send_num = 0;
+int exit_flag = 0;
+int async_rpc_sem;
+int no_progress_flag = 0;
+int num_out_reqs_statistics[MAX_OUTSTANDING_REQ+1];
+int num_out_reqs_statistics_at_timeout[MAX_OUTSTANDING_REQ+1];
+
+/*
+ * -------------------------  SFS Child  -------------------------
+ */
+
+static int nfs2proc_to_rfsproc[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
+									10, 11, 12, 13, 14, 15, 16, 17};
+static int nfs3proc_to_rfsproc[NFS3_PROCEDURE_COUNT] = {0, 1, 2, 4, 18, 5, 6, 8, 9, 14, 
+													13, 21, 10, 15, 11, 12, 16, 23, 17, 20, 
+													22, 19};
+void print_usage(int pos, int argc, char ** argv)
+{
+	int i;
+	printf("sfs3 hostname:mount_dir trace_file|stdin fh_map_file play_scale warmup_time(in seconds) \n");
+	printf("sfs3 -pair_trace trace_file\n");
+	printf("sfs3 -pair_write trace_file\n");
+	printf("sfs3 -help\n");
+	printf ("pos %d argc %d", pos, argc);
+	for (i=0; i<argc; i++) {
+		printf(" %s", argv[i]);
+	} 
+	printf ("\n");
+	exit;
+}
+
+void print_cyclic_buffers ()
+{
+	CYCLIC_PRINT(memory_trace_index);
+	CYCLIC_PRINT(dep_tab_index);
+	CYCLIC_PRINT(dep_window_index);
+}
+
+void add_to_dep_tab(int i)
+{
+	char * trace_fh;
+	fh_map_t * fh_map_entry;
+	dep_tab_t * ent;
+
+    trace_fh = strstr (memory_trace[i].line, "fh");
+    if (!trace_fh)
+	printf ("memory_trace[%d].line %s\n", i, memory_trace[i].line);
+    RFS_ASSERT (trace_fh);
+    trace_fh += 3;
+    fh_map_entry = lookup_fh (trace_fh);
+    if (fh_map_entry && (fh_map_entry->flag==FH_MAP_FLAG_DISCARD) )  {
+        req_num_with_discard_fh ++;
+		return;
+	}
+    if (fh_map_entry)
+        req_num_with_init_fh ++;
+    else
+        req_num_with_new_fh ++;
+                                                                                                                              
+	RFS_ASSERT (!CYCLIC_FULL(dep_tab_index));
+	ent = &(dep_tab[dep_tab_index.head]);
+
+    ent->disk_index = memory_trace[i].disk_index;
+	ent->memory_index = i;
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+    ent->trace_status = memory_trace[i].trace_status;
+    ent->reply_trace_fh = memory_trace[i].reply_trace_fh;
+#endif
+    ent->line = memory_trace[i].line;
+    init_dep_tab_entry(dep_tab_index.head);
+
+    if (rfs_debug && (i%100000)==0)
+    	printf ("dep_tab[%d].disk_index %d = memory_trace[%d].disk_index %d\n", dep_tab_index.head, ent->disk_index, i, memory_trace[i].disk_index);
+    CYCLIC_MOVE_HEAD(memory_trace_index);
+    CYCLIC_MOVE_HEAD(dep_tab_index);
+}
+
+void init_profile_variables ()
+{
+	init_profile ("total_profile", &total_profile);
+	init_profile ("execute_next_request_profile", &execute_next_request_profile);
+	init_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	init_profile ("invalid_get_nextop_profile",&invalid_get_nextop_profile);
+	init_profile ("prepare_argument_profile", &prepare_argument_profile);
+	init_profile ("biod_clnt_call_profile", &biod_clnt_call_profile);
+	init_profile ("receive_next_reply_profile", &receive_next_reply_profile);
+	init_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	init_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	init_profile ("decode_reply_profile", &decode_reply_profile);
+	init_profile ("check_reply_profile", &check_reply_profile);
+	init_profile ("add_create_object_profile", &add_create_object_profile);
+	init_profile ("check_timeout_profile", &check_timeout_profile);
+	init_profile ("adjust_play_window_profile",&adjust_play_window_profile);
+	init_profile ("fgets_profile",&fgets_profile);
+	init_profile ("read_line_profile",&read_line_profile);
+	init_profile ("read_trace_profile",&read_trace_profile);
+}
+
+static char trace_file[256]="anon-lair62-011130-1200.txt";
+int print_memory_usage()
+{
+	printf("size of fh_map_t %d size of fh_map %d\n", sizeof(fh_map_t), sizeof(fh_map));
+	printf("sizeof dep_tab_t %d sizeof dep_tab %d\n", sizeof(dep_tab_t), sizeof(dep_tab));
+	printf("size of memory_trace_ent_t %d sizeof memory_trace %d\n", sizeof(memory_trace_ent_t), sizeof(memory_trace));
+	printf("size of CREATE3args %d\n", sizeof( CREATE3args));
+	printf("size of MKDIR3args %d\n", sizeof( MKDIR3args));
+	printf("size of READ3args %d\n", sizeof( READ3args));
+	printf("size of WRITE3args %d\n", sizeof( WRITE3args));
+	printf("size of RENAME3args %d\n", sizeof( RENAME3args));
+	printf("size of GETATTR3args %d\n", sizeof( GETATTR3args));
+	printf("size of SETATTR3args %d\n", sizeof( SETATTR3args));
+	printf("size of LINK3args %d\n", sizeof( LINK3args));
+	printf("size of SYMLINK3args %d\n", sizeof( SYMLINK3args));
+	printf("size of MKNOD3args %d\n", sizeof( MKNOD3args));
+	printf("size of RMDIR3args %d\n", sizeof( RMDIR3args));
+	printf("size of REMOVE3args %d\n", sizeof( REMOVE3args));
+	printf("size of LOOKUP3args %d\n", sizeof( LOOKUP3args));
+	printf("size of READDIR3args %d\n", sizeof( READDIR3args));
+	printf("size of READDIRPLUS3args %d\n", sizeof( READDIRPLUS3args));
+	printf("size of FSSTAT3args %d\n", sizeof( FSSTAT3args));
+	printf("size of FSINFO3args %d\n", sizeof( FSINFO3args));
+	printf("size of COMMIT3args %d\n", sizeof( COMMIT3args));
+	printf("size of ACCESS3args %d\n", sizeof( ACCESS3args));
+	printf("size of READLINK3args %d\n", sizeof( READLINK3args));
+
+
+}
+
+void recv_thread()
+{
+	int last_print_time = -1;
+	int busy_flag;
+
+	while (send_num ==0) {
+		usleep(1000);
+	}
+
+	//while (!CYCLIC_EMPTY(dep_tab_index)) {
+	while (!exit_flag) {
+		if ((total_profile.in.tv_sec - last_print_time >= 10)) {
+			static int recv_num_before_10_seconds = 0;
+			last_print_time = total_profile.in.tv_sec;
+			fprintf (stdout, "<<<<< recv_thread recv_num %d time %d num_out_reqs %d \n", recv_num, total_profile.in.tv_sec, num_out_reqs);
+			if (recv_num == recv_num_before_10_seconds) {
+				no_progress_flag = 1;
+				RFS_ASSERT (0);
+			} else 
+				recv_num_before_10_seconds = recv_num;
+		}
+		//start_profile (&check_timeout_profile);
+		check_timeout();
+		//end_profile (&check_timeout_profile);
+
+		pthread_yield();
+		//usleep(1000);
+		start_profile (&receive_next_reply_profile);
+		/* actually the performance of two policy seems to be same */
+//#define SEND_HIGHER_PRIORITY_POLICY
+#define SEND_RECEIVE_EQUAL_PRIORITY_POLICY	
+#ifdef SEND_HIGHER_PRIORITY_POLICY
+		receive_next_reply(IDLE);
+#endif
+#ifdef SEND_RECEIVE_EQUAL_PRIORITY_POLICY
+		busy_flag = IDLE;
+		while (receive_next_reply(busy_flag)!=-1) {
+			busy_flag = BUSY;
+		}
+#endif
+		end_profile (&receive_next_reply_profile);
+	}
+	printf ("<<<< recv thread EXIT\n");
+	exit_flag = 2;
+}
+
+int io_thread ()
+{
+/* number of seconds the I/O thread pauses after each time trying to read the requests */
+#define IO_THREAD_PAUSE_TIME 1
+
+	int i;
+	int j = 0;
+
+	disk_io_status = read_trace ();
+	while (disk_io_status == TRACE_BUF_FULL) {
+
+		usleep (10000);
+        if ((j++%1000)==0) {
+                printf("&&&&&&&&&& io thread, sleep %d seconds\n", j/100);
+        }
+
+		disk_io_status = read_trace ();
+		//printf ("io_thread, after read_trace, disk_index %d\n", disk_index);
+
+#ifdef SEQUEN_READ
+		for (i=0; i<SEQUEN_READ_NUM; i++) {
+			add_to_dep_tab(CYCLIC_MINUS(memory_trace_index.head,1,memory_trace_index.size));
+		}
+#endif
+		//printf ("***************** IO THREAD SLEEP 1 s\n");
+		//print_cyclic_buffers();
+		//pthread_yield();
+	}
+	RFS_ASSERT (disk_io_status == TRACE_FILE_END);
+	printf("io_thread EXIT\n");
+}
+
+int execute_thread()
+{
+	int i;
+	struct timeval playstart_time, playend_time;
+
+	sleep (10);		/* first let io_thread to run for a while */
+	printf ("trace_play\n");
+
+	gettimeofday(&playstart_time, NULL);
+
+	init_time_offset();
+	trace_play ();
+
+	gettimeofday(&playend_time, NULL);
+
+	{
+		int usec, sec;
+		sec = playend_time.tv_sec - playstart_time.tv_sec;
+		usec = sec * 1000000 + (playend_time.tv_usec - playstart_time.tv_usec);
+		sec = usec / 1000000;
+		usec = usec % 1000000;
+		printf("Total play time: %d sec %d usec\n", sec, usec);
+		if (sec > WARMUP_TIME)
+			print_result();
+		else
+			printf ("the trace play time %d is less than WARMUP_TIME %d, no statistical results\n");
+	}
+#ifdef RECV_THREAD
+	exit_flag = 1;
+	while (exit_flag == 1) {
+		usleep (1000);
+	}
+#endif
+
+    clnt_destroy(NFS_client);
+    biod_term();
+}
+
+int init_thread ()
+{
+	pthread_attr_t	attr;
+	int arg;
+	int ret = 0;
+	pthread_t io_thread_var;
+#ifdef RECV_THREAD
+	pthread_t recv_thread_var;
+#endif
+	pthread_t execute_thread_var;
+
+	ret = pthread_attr_init (&attr);
+	if (ret!=0) {
+		perror("pthread_attr_init attr");
+		return ret;
+	}
+#ifdef IO_THREAD
+	ret = pthread_create (&(io_thread_var), &attr, &io_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("io_pthread_attr_init");
+		return ret;
+	}
+#endif
+
+#ifdef RECV_THREAD
+	ret = pthread_create (&(recv_thread_var), &attr, &recv_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("recv_pthread_attr_init");
+		return ret;
+	}
+#endif
+
+/*
+	ret = pthread_create (&(execute_thread_var), &attr, &execute_thread, (void *)&arg );
+	if (ret!=0) {
+		perror("io_pthread_attr_init");
+		return ret;
+	}
+*/
+}
+
+void init_buffers()
+{
+	CYCLIC_INIT("memory_trace_index",memory_trace_index,MAX_MEMORY_TRACE_LINES);
+	CYCLIC_INIT("dep_tab_index     ",dep_tab_index,DEP_TAB_SIZE);
+	CYCLIC_INIT("dep_window_index  ",dep_window_index,DEP_TAB_SIZE);
+}
+
+int main(int argc, char ** argv)
+{
+	extern char * optarg;
+	int i;
+	struct timeval in={1000000, 100};
+	
+	init_profile_variables();
+	if ((argc==1) || (argc==2 && !strcmp(argv[1],"-help"))) {
+		print_usage(0, argc, argv);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-pair_write")) {
+		if (argc==3) 
+			strcpy(trace_file, argv[2]);
+		else
+			strcpy(trace_file, "stdin");
+		pair_write(trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-pair_trace")) {
+		if (argc==3) 
+			strcpy(trace_file, argv[2]);
+		else
+			strcpy(trace_file, "stdin");
+		pair_trace(trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-check_aging")) {
+		if (argc!=3) {
+			print_usage(3, argc, argv);
+			exit(0);
+		}
+		strcpy(trace_file, argv[2]);
+		check_aging (trace_file);
+		exit(0);
+	}
+	if (!strcmp(argv[1], "-check_statistics")) {
+		if (argc!=3) {
+			print_usage(1, argc, argv);
+			exit(0);
+		}
+		strcpy(trace_file, argv[2]);
+		memset(fh_htable, 0, sizeof (fh_htable));
+		check_statistics (trace_file);
+		exit(0);
+	}
+
+	if (argc!=6) {
+		print_usage(2, argc, argv);
+		exit(0);
+	}
+
+	PLAY_SCALE = atoi (argv[4]);
+	RFS_ASSERT (PLAY_SCALE >=1 && PLAY_SCALE <=10000);
+
+	WARMUP_TIME = atoi (argv[5]);
+	RFS_ASSERT (WARMUP_TIME >=0 && WARMUP_TIME <=1000);
+	
+	print_memory_usage();
+	check_clock();
+    getmyhostname(lad_hostname, HOSTNAME_LEN);
+
+    init_ops();
+	/*
+	 * Get the uid and gid information.
+	 */
+	Real_uid = getuid();
+	Cur_gid = getgid();
+	//Real_uid = 513;
+	//Cur_gid = 513;
+
+	Nfs_timers = Nfs_udp_timers;
+
+	init_semaphores();
+	init_file_system ();
+	init_signal();
+	init_play (argv[1]);
+	//init_play ("capella:/p5/RFSFS");
+	init_fh_map();
+	read_fh_map (argv[3]);
+	//read_fh_map ("fh-path-map-play");
+	strcpy(trace_file, argv[2]);
+
+/* If ordered by TIMESTAMP,
+ * memory_trace_index.tail <= dep_tab_index.tail < dep_window_max <=
+ * dep_tab_index.head <= memory_trace_index.head
+ */
+
+	init_global_variables();
+	init_buffers();
+	init_thread();
+	pthread_yield();
+	execute_thread();
+}
+
+int init_global_variables()
+{
+	memset (num_out_reqs_statistics, 0, sizeof(num_out_reqs_statistics));
+	memset (num_out_reqs_statistics_at_timeout, 0, sizeof(num_out_reqs_statistics_at_timeout));
+}
+
+int init_semaphores()
+{
+	async_rpc_sem = dest_and_init_sem (ASYNC_RPC_SEM_KEY, 1, "async_rpc_sem");
+}
+
+void init_ops (void)
+{
+	Ops = nfsv3_Ops;
+	nfs_version = NFS_V3;
+}
+
+/* Set up the signal handlers for all signals */
+void init_signal()
+{
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	struct sigaction sig_act, old_sig_act;
+
+	/* use XOPEN signal handling */
+
+	sig_act.sa_handler = generic_catcher;
+	(void)sigemptyset(&sig_act.sa_mask);
+	sig_act.sa_flags = 0;
+
+	/* signals handlers for signals used by sfs */
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGINT,&sig_act,&old_sig_act) == -1) {
+	    perror("sigaction failed: SIGINT");
+	    exit(135);
+	}
+
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGTERM,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGTERM");
+	    exit(137);
+	}
+#else
+    /* signals handlers for signals used by sfs */
+    (void) signal(SIGINT, sfs_cleanup);
+    // RFS (void) signal(SIGALRM, sfs_alarm);
+	(void) signal(SIGTERM, sfs_cleanup);
+#endif
+}
+
+void
+init_play (
+    char	* mount_point)		/* Mount point for remote FS */
+{
+    char	namebuf[NFS_MAXNAMLEN] = "trace_play";	/* unique name for this program */
+    CLIENT *	mount_client_ptr;	/* Mount client handle */
+
+	if (!rfs_debug);
+    	(void) setvbuf(stderr, io_buf, _IOLBF, BUFSIZ);
+
+    sfs_Myname = namebuf;
+
+    /*
+     * May require root priv to perform bindresvport operation
+     */
+    mount_client_ptr = lad_getmnt_hand(mount_point);
+    if (mount_client_ptr == NULL) {
+		exit(145);
+    }
+
+    /*
+     * should be all done doing priv port stuff
+     */
+
+    if (init_rpc() == -1) {
+		(void) fprintf(stderr, "%s: rpc initialization failed\n", sfs_Myname);
+		(void) generic_kill(0, SIGINT);
+		exit(146);
+    }
+
+
+    /*
+     * finish all priv bindresvport calls
+     * reset uid
+     */
+    if (setuid(Real_uid) != (uid_t)0) {
+	(void) fprintf(stderr,"%s: %s%s", sfs_Myname,
+	    "cannot perform setuid operation.\n",
+	    "Do `make install` as root.\n");
+    }
+
+    init_mount_point(0, mount_point, mount_client_ptr);
+
+
+    /*
+     * Cleanup client handle for mount point
+     */
+    clnt_destroy(mount_client_ptr);
+
+	init_counters();
+}
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+void inline format_line (char * line_before, char * line)
+{
+	char * pv = line_before;
+	char * pl = line;
+	char * p;
+	int i;
+	
+	//printf("format_line before %s\n", line_before);
+	p = strstr (pv, "fh");
+	while (p!=NULL) {
+		while (pv<=p)
+			*pl++ = *pv++;
+		*pl++ = *pv++;
+		if (*pv==2) {
+			*pl++ = *pv++;
+		}
+		*pl++ = *pv++;
+		i = 0;
+		while (*pv !=' ') {
+			RFS_ASSERT ((*pv >='0' && *pv <='9') || (*pv >='a' && *pv<='f'));
+			*pl++ = *pv++;
+			i++;
+		}
+		RFS_ASSERT ((i==48) || (i==40) || (i==24));
+		while (i<48) {
+			*pl++ = '0';
+			i++;
+		}
+		p = strstr (pv, "fh");
+	}
+	while ((*pv)!=NULL) {
+		*pl++ = *pv++;
+	}
+	//printf("format_line after %s\n", line);
+}
+
+char * read_line (int disk_index)
+{
+	static FILE * fp=NULL;
+	static int start=0;
+	static int start_disk_index=0;
+	int i;
+	static int finish_flag = 0;
+	static int varfh_flag = 0;
+#define READ_LINE_BUF_SIZE (MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR+2)
+#define SAFE_BYTES 1000
+#define READ_LINE_LENGTH (MAX_TRACE_LINE_LENGTH+SAFE_BYTES)
+
+	static char line_buf[READ_LINE_BUF_SIZE][READ_LINE_LENGTH];
+	char varfh_line_buf[READ_LINE_LENGTH];
+
+	start_profile (&read_line_profile);
+
+	if (fp==NULL) {
+		if (strcmp(trace_file, "stdin")) {
+			fp = fopen(trace_file, "r");
+
+			if (strstr(trace_file, ".varfh")) {
+				varfh_flag = 1;
+			};
+			if (strstr(trace_file, ".fmt1")) {
+				TRACE_COMMAND_REPLY_FLAG_POS += 12;
+				TRACE_VERSION_POS +=12;
+				TRACE_MSGID_POS +=12;
+				TRACE_FH_SIZE =48;
+			}
+			if (!fp) {
+				printf("can not open files %s\n", fp);
+				perror("open");
+			}
+		} else {
+			fp = stdin;
+		}
+		RFS_ASSERT (fp!=NULL);
+		for (i=0; i<READ_LINE_BUF_SIZE; i++) {
+			start_profile(&fgets_profile);
+			if (varfh_flag) {
+				if (!fgets(varfh_line_buf, READ_LINE_LENGTH, fp)) {
+					RFS_ASSERT (0);
+				}
+				format_line (varfh_line_buf, line_buf[i]);
+			} else {
+				if (!fgets(line_buf[i], READ_LINE_LENGTH, fp)) {
+					RFS_ASSERT (0);
+				}
+			}
+			end_profile(&fgets_profile);
+			//printf ("read_line, line_buf[%d]:%s", i, line_buf[i]);
+		}
+	}
+	
+	if (disk_index > start_disk_index+READ_LINE_BUF_SIZE) {
+		printf ("disk_index %d start_disk_index %d READ_LINE_BUF_SIZE %d\n", 
+			disk_index, start_disk_index, READ_LINE_BUF_SIZE);
+	}
+	RFS_ASSERT (disk_index <= start_disk_index+READ_LINE_BUF_SIZE)
+	if (disk_index==(start_disk_index+READ_LINE_BUF_SIZE)) {
+		if (finish_flag) {
+			return NULL;
+		}
+		start_profile(&fgets_profile);
+		if (!fgets(line_buf[start], READ_LINE_LENGTH, fp)) {
+			end_profile(&fgets_profile);
+			finish_flag = 1;
+			return NULL;
+		}
+		end_profile(&fgets_profile);
+		//printf ("read_line, line_buf[%d]:%s", start, line_buf[start]);
+		start = (start+1) % READ_LINE_BUF_SIZE;
+		start_disk_index ++;
+	}
+	RFS_ASSERT (disk_index < start_disk_index+READ_LINE_BUF_SIZE)
+	i = (start+disk_index-start_disk_index)%READ_LINE_BUF_SIZE;
+
+/*
+	if (!(strlen(line_buf[i])>80)) {
+		printf ("start %d start_disk_index %d disk_index %d strlen %d line_buf[%d] %s\n", start, start_disk_index, disk_index, strlen(line_buf[i]), i, line_buf[i]);
+		RFS_ASSERT (strlen(line_buf[i])>80);
+	}
+	if (!((strlen(line_buf[i])>80) && (strlen(line_buf[i])<MAX_TRACE_LINE_LENGTH)))
+		printf ("disk_index %d strlen %d line_buf[%d] %s\n", disk_index, strlen(line_buf[i]), i, line_buf[i]);
+	RFS_ASSERT ((strlen(line_buf[i])>80) && (strlen(line_buf[i])<MAX_TRACE_LINE_LENGTH));
+*/
+
+	end_profile (&read_line_profile);
+	return (line_buf[i]);
+}
+
+#define OPS_FLAG_INC 0
+#define OPS_FLAG_PRINT 1
+int read_write_fh_statistics (int flag, char * buf, int timestamp)
+{
+	static FILE * fp = NULL;
+	char * p;
+	char c;
+	if (!fp) {
+		fp = fopen ("read_write_fh.output", "w");
+		RFS_ASSERT (fp);
+	}
+	if (flag == OPS_FLAG_INC) {
+		p = strstr (buf, "fh");
+		RFS_ASSERT (p);
+		c = p[40+3];
+		p[40+3]=0;
+		fprintf(fp, "%s\n", p+3+24);
+		p[40+3]=c;
+	};
+	if (flag == OPS_FLAG_PRINT) { 
+		int disk_index = (int) buf;
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+int write_statistics(int flag, char * buf, char * reply_buf, int trace_status)
+{
+	static FILE * fp = NULL;
+	int pre_size, size, count;
+	char * p = reply_buf;
+	if (!fp) {
+		fp = fopen ("write.output", "w");
+		RFS_ASSERT (fp);
+	}
+	if (flag == OPS_FLAG_INC) {
+		p = strstr (p, "pre-size");
+		RFS_ASSERT (p);
+		sscanf (p, "pre-size %x", &pre_size); 
+		p += strlen("pre-size");
+		p = strstr (p, "size");
+		RFS_ASSERT (p);
+		sscanf (p, "size %x", &size); 
+		p = strstr (p, "count");
+		if (!p) 
+			fprintf (fp, "%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+		RFS_ASSERT (p);
+		sscanf (p, "count %x", &count); 
+		fprintf (fp, "%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+	}
+	if (flag == OPS_FLAG_PRINT) {
+		int disk_index = (int) buf;
+		int timestamp = (int) reply_buf;
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+void ops_statistics (int ops_flag, int proc, int timestamp)
+{
+	static FILE * fp = NULL;
+	static struct {
+		int count;
+		int count_K;
+		int update_flag;
+		char name[32];
+	} ops[NOPS]={{0, 0, 0, "NULL"},{0, 0, 0, "GETATTR"},{0, 0, 1, "SETATTR"},{0, 0, 0, "ROOT"},
+				  {0, 0, 0, "LOOKUP"},{0, 0, 0, "READLINK"},{0, 0, 0, "READ"},{0, 0, 1, "WRCACHE"},
+				  {0, 0, 1, "WRITE"}, {0, 0, 1, "CREATE"},{0, 0, 1, "REMOVE"},{0, 0, 1, "RENAME"},
+				  {0, 0, 1, "LINK"}, {0, 0, 1, "SYMLINK"},{0, 0, 1, "MKDIR"},{0, 0, 1, "RMDIR"},
+				  {0, 0, 0, "READDIR"},{0, 0, 0, "FSSTAT"},{0, 0, 0, "ACCESS"},{0, 0, 0, "COMMIT"},
+				  {0, 0, 0, "FSINFO"},{0, 0, 1, "MKNOD"}, {0, 0, 0, "PATHCONF"}, {0, 0, 0, "READDIRPLUS"}};
+
+	if (ops_flag == OPS_FLAG_INC) {
+		RFS_ASSERT (proc>=0 && proc<NOPS);
+		ops[proc].count ++;
+		if (ops[proc].count == 1000) {
+			ops[proc].count_K ++;
+			ops[proc].count = 0;
+		}
+	}
+	if (ops_flag == OPS_FLAG_PRINT) {
+		int i;
+		int update_K=0, update=0, total_K=0, total=0;
+		float f1, f2;
+		int disk_index = proc;
+
+		if (!fp) {
+			fp = fopen ("mix.output", "w");
+			RFS_ASSERT (fp);
+		}
+		for (i=0; i<NOPS; i++) {
+			total_K += ops[i].count_K;
+			total += ops[i].count;
+			if (ops[i].update_flag) {
+				update_K += ops[i].count_K;
+				update += ops[i].count;
+			}
+		}
+		update_K += update/1000;
+		update = update%1000;
+		total_K += total/1000;
+		total = total%1000;
+
+		f1 = total_K;
+		f1 = f1*1000+total;
+		for (i=0; i<NOPS; i++) {
+			f2 = ops[i].count_K;
+			f2 = f2*1000+ops[i].count;
+			fprintf (fp, "%12s %8d,%03d %3.2f\%\n", ops[i].name, ops[i].count_K, ops[i].count, f2*100/f1);	
+			fprintf (stderr, "%12s %8d,%03d %3.2f\%\n", ops[i].name, ops[i].count_K, ops[i].count, f2*100/f1);	
+		}
+		f2 = update_K;
+		f2 = f2*1000+update;
+		fprintf (fp, "       total %8d,%03d\n", total_K, total);
+		fprintf (stderr, "       total %8d,%03d\n", total_K, total);
+		fprintf (fp, "      update %8d,%03d %2.2f\%\n", update_K, update, f2*100/f1);	
+		fprintf (stderr, "      update %8d,%03d %2.2f\%\n", update_K, update, f2*100/f1);	
+		fprintf(fp, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+		fprintf(stderr, "###### disk_index %d timestamp %d\n", disk_index, timestamp);
+	}
+}
+
+
+void truncate_statistics (int flag, int proc, char * buf, char * reply_buf) 
+{
+#define TRACE_FH_SIZE2 16
+#define BLOCK_SIZE 4096
+	static int no_size_num = 0;
+	static int have_size_num = 0;
+	static int equal_size_num = 0;
+	static int first_size_num = 0;
+	static int truncate_num = 0;
+	static int truncate_size = 0;
+	static int truncate_KB = 0;
+	static int truncate_block_num = 0;
+	static int padding_num = 0;
+	static int padding_KB = 0;
+	static int padding_size = 0;
+	static FILE * fp = NULL;
+	char * p;
+	char * trace_fh;
+	int pre_size, size, count;
+	struct generic_entry * ent;
+
+	if (flag == OPS_FLAG_PRINT) {
+		int disk_index = proc;
+		int timestamp = (int)buf;
+		if (!fp) {
+			fp = fopen ("truncate.output", "w");
+			RFS_ASSERT (fp);
+		}
+		truncate_KB += truncate_size/1000;
+		truncate_size %= 1000;
+		padding_KB += padding_size/1000;
+		padding_size %= 1000;
+		fprintf(fp, "###### disk_index %d timestamp %d no_size_req %d have_size_req %d equal_size_req %d trunc_req %d trunc_KB %d trunc_block_num %d padding_num %d padding_KB %d\n", disk_index, timestamp, no_size_num, have_size_num, equal_size_num, truncate_num, truncate_KB, truncate_block_num, padding_num, padding_KB);
+		fprintf(stderr, "###### disk_index %d timestamp %d no_size_req %d have_size_req %d equal_size_req %d trunc_req %d trunc_KB %d trunc_block_num %d padding_num %d padding_KB %d\n", disk_index, timestamp, no_size_num, have_size_num, equal_size_num, truncate_num, truncate_KB, truncate_block_num, padding_num, padding_KB);
+		return;
+	}
+
+	p = strstr (&buf[TRACE_MSGID_POS], "fh");
+	RFS_ASSERT (p);
+	p+=3; 
+	trace_fh = p;
+		
+	if (proc==SETATTR) {
+		p = strstr (buf, " size ");
+	} else {
+		RFS_ASSERT (proc==WRITE);
+		p = strstr (reply_buf, " ftype 1 ");
+		RFS_ASSERT (p);
+		p = strstr (p, " size ");
+		RFS_ASSERT (p);
+		if (strstr(p, " ftype 1 ")) {
+			fprintf (fp, "#### %s%s\n", buf, reply_buf);
+			fprintf (stderr, "#### %s%s\n", buf, reply_buf);
+		}
+		RFS_ASSERT (!strstr(p, " ftype 1 "));
+	}
+	if (!p) {
+		no_size_num ++;
+		return;
+	}
+	have_size_num ++;
+
+	sscanf (p, " size %x", &size); 
+	if (size <0 || size > 2000000000) {
+		fprintf (fp, "#### size too big %x %s %s\n", size, buf, reply_buf);
+		fprintf (stderr, "#### size too big %x %s %s\n", size, buf, reply_buf);
+	}
+							
+	RFS_ASSERT (size >=0 && size <2000000000);		
+   	ent = generic_lookup (trace_fh+24, TRACE_FH_SIZE2, 0, fh_htable, FH_HTABLE_SIZE);
+	if (ent) {
+		if (ent->key3 != size) {
+			if (proc==SETATTR) {
+				//printf ("%s\n", buf);
+				//printf ("size change fh %s pre-size %x size %x\n", trace_fh, ent->key3, size);
+				if (ent->key3 > size) {
+					truncate_num ++;
+					truncate_size += ent->key3 - size;
+					truncate_block_num += (ent->key3+BLOCK_SIZE-1)/BLOCK_SIZE;
+					if (size!=0) {
+						//fprintf (stderr, "truncate: pre_size %x size %x %s\n", ent->key3, size, buf);
+						//fprintf (fp, "truncate: pre_size %x size %x %s\n", ent->key3, size, buf);
+						truncate_block_num -= (size + BLOCK_SIZE-1)/BLOCK_SIZE;
+					}
+					if (truncate_size > 1000000000) {
+						truncate_KB += truncate_size/1000;
+						truncate_size %= 1000;
+					}
+				} else {
+					padding_num ++; 
+					//printf ("%s\n", buf);
+					//printf ("padding fh %s pre-size %x size %x\n", trace_fh, ent->key3, size);
+					padding_size += size - ent->key3;
+					if (padding_size > 1000000000) {
+						padding_KB += padding_size/1000;
+						padding_size %= 1000;
+					}
+				}
+			}
+			ent->key3 = size; 
+		}else 
+			equal_size_num++;
+	} else {
+   		generic_insert(trace_fh+24, TRACE_FH_SIZE2, size, fh_htable, FH_HTABLE_SIZE);
+		first_size_num ++;
+	}
+};
+
+int get_timestamp_usec (char * buf)
+{
+	char str[128];
+	int ret;
+	strncpy(str, buf, 100);
+	RFS_ASSERT (str[10]=='.');
+	RFS_ASSERT (str[17]==' ');
+	str[17]=0;
+	ret = atoi(&str[11]);
+	RFS_ASSERT (ret >=0 && ret <=999999);
+	return ret;
+}
+
+int get_timestamp_sec (char * buf)
+{
+	char str[128];
+	int ret;
+	strncpy(str, buf, 100);
+	RFS_ASSERT (str[10]=='.');
+	str[10]=0;
+	ret = atoi(str);
+	RFS_ASSERT (ret >1000000000 && ret <2000000000);
+	return ret;
+}
+
+int check_aging (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid, proc;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		
+		proc = nfs3proc_to_rfsproc[nfs3proc];
+		ops_statistics (OPS_FLAG_INC, proc, -1);
+		
+		switch (proc) {
+		int off, count, size;
+		char * t;
+		case CREATE: printf("%s\n", "create"); break;
+		case MKDIR: printf("%s\n", "mkdir"); break;
+		case REMOVE: printf("%s\n", "remove"); break;
+		case RMDIR: printf("%s\n", "rmdir"); break;
+		case WRITE: 
+			t = buf;
+			t = strstr (t, "off");
+	        RFS_ASSERT (t);
+   		    t+=4;
+			sscanf (t, "%x", &off);
+			RFS_ASSERT (off>=0 && off<0x7FFFFFFF)
+			t = strstr (t, "count");
+		    RFS_ASSERT (t);
+   			t+=6;
+			sscanf (t, "%x", &count);
+			RFS_ASSERT (count <= 32768);
+			printf("%s off %x count %x\n", "write", off, count); 
+			//printf("%s count %x\n", "write", count); 
+			break;
+		case SETATTR: 
+			t = strstr (buf, " size ");
+			if (t) {
+				sscanf (t, " size %x", &size);
+				printf ("%s size %x\n", "setattr", size);
+			}
+		}
+		if ((disk_index%10000)==0) {
+			fprintf(stderr, "%d disk trace passed\n", disk_index);
+		}
+	};
+
+	fprintf(stderr, "%d disk trace parsed\n", disk_index);
+	ops_statistics (OPS_FLAG_PRINT, disk_index, -1);
+}
+
+
+int check_statistics (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid, proc;
+	static int last_timestamp_sec = -1;
+	int timestamp_sec;
+	int memory_trace_size = 0;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		timestamp_sec = get_timestamp_sec(buf);
+		
+		proc = nfs3proc_to_rfsproc[nfs3proc];
+		ops_statistics (OPS_FLAG_INC, proc, -1);
+		
+		if (proc!= WRITE && proc!=SETATTR && proc!=READ) {
+			continue;
+		}
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE; i++) {
+			reply_buf = read_line(i);
+			if (debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+	               	trace_status = find_reply_status(reply_buf);
+					if (trace_status == NFS3_OK) {
+						if (proc==READ || proc==WRITE) 
+							read_write_fh_statistics (OPS_FLAG_INC, buf, 0);
+						if (proc == WRITE)
+							write_statistics (OPS_FLAG_INC, buf, reply_buf, trace_status);
+						if (proc==WRITE || proc==SETATTR) 
+							truncate_statistics (OPS_FLAG_INC, proc, buf, reply_buf);
+					}
+				};
+   	    	}
+		}
+		//if (memory_trace[memory_trace_size].trace_status == NFS3ERR_RFS_MISS)
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			//printf ("%s no reply\n", buf);
+			missing_reply_num ++;
+		}
+
+#if	0	/* commented out by G. Jason Peng */
+		if *
+		if ((missing_reply_num > memory_trace_size/10) && (missing_reply_num > 100)) {
+			printf ("missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+#endif
+
+		memory_trace_size ++;
+
+		if (last_timestamp_sec == -1) {
+			last_timestamp_sec = timestamp_sec;
+		} else if (timestamp_sec - last_timestamp_sec >=3600) {
+			ops_statistics (OPS_FLAG_PRINT, disk_index, timestamp_sec);
+			truncate_statistics (OPS_FLAG_PRINT, disk_index, (char *)timestamp_sec, NULL);
+			read_write_fh_statistics(OPS_FLAG_PRINT, (char *)disk_index, timestamp_sec);
+			write_statistics(OPS_FLAG_PRINT, (char *)disk_index, (char *)timestamp_sec, -1);
+			last_timestamp_sec = timestamp_sec;
+		}
+/*
+		if ((memory_trace_size%10000)==0) {
+			fprintf(stderr, "%d disk trace parsed, missing_reply %d\n", disk_index, missing_reply_num);
+			ops_statistics (OPS_FLAG_PRINT, -1);
+			truncate_statistics (OPS_FLAG_PRINT, -1, NULL, NULL);
+		}
+*/
+	};
+
+	fprintf(stderr, "%d disk trace parsed, missing_reply %d\n", disk_index, missing_reply_num);
+	ops_statistics (OPS_FLAG_PRINT, disk_index, timestamp_sec);
+	truncate_statistics (OPS_FLAG_PRINT, disk_index, (char *)timestamp_sec, NULL);
+	read_write_fh_statistics(OPS_FLAG_PRINT, (char *)disk_index, timestamp_sec);
+	write_statistics(OPS_FLAG_PRINT, (char *)disk_index, (char *)timestamp_sec, -1);
+}
+
+
+/* This routine output all the requests, together with their replies */
+int pair_trace (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int debug = 0;
+	int nfs3proc, msgid;
+	int ops[NFS3_PROCEDURE_COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	int memory_trace_size = 0;
+	FILE * outputfp;
+	char output_file[1024];
+
+	strcpy (output_file, tracefile);
+	strcat (output_file, ".pair");
+	outputfp = fopen (output_file, "w");
+	RFS_ASSERT (outputfp);
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (disk_index == 258)
+			f();
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		ops[nfs3proc]++;
+
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+		fprintf (outputfp, "%s\n", buf);
+
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR; i++) {
+			reply_buf = read_line(i);
+			if (debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+					fprintf(outputfp, "%s", reply_buf);
+					trace_status = find_reply_status(reply_buf);
+					if (debug)
+						fprintf(stderr, "reply found trace_status %d\n", find_reply_status(reply_buf));
+					break;
+				};
+   	    	}
+		}
+
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			fprintf (stderr, "%s no reply\n", buf);
+			fprintf(outputfp, "missing_reply\n");
+			missing_reply_num ++;
+		}
+
+		if (missing_reply_num > memory_trace_size/10 && missing_reply_num >100) {
+			fprintf (stderr, "missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+
+		memory_trace_size ++;
+
+		if ((memory_trace_size%10000)==0)
+			fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+    //fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+
+}
+/* This routine output all the write requests, together with their replies. It is used for
+ * analysis of write requests: appended bytes, overwrite bytes etc
+ */
+int pair_write (char * tracefile)
+{
+	int disk_index=-1;
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int trace_status;
+	int pair_write_debug = 0;
+	int nfs3proc, msgid;
+	int ops[NFS3_PROCEDURE_COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	int memory_trace_size = 0;
+
+	while ((buf=read_line(++disk_index))!=NULL) {
+		if (buf[TRACE_COMMAND_REPLY_FLAG_POS]!='C') 
+			continue;
+		if (buf[TRACE_VERSION_POS]!='3') 
+			continue;
+		sscanf (&buf[TRACE_MSGID_POS], "%x %x", &msgid, &nfs3proc);
+		
+		RFS_ASSERT (nfs3proc>=0 && nfs3proc<NFS3_PROCEDURE_COUNT);
+		ops[nfs3proc]++;
+
+		if (!strstr(buf, "write")) 
+			continue;
+
+		buf [strlen(buf)-1] = 0;
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("disk_index %d strlen(buf) %d buf %s \n", disk_index, strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+		if (pair_write_debug)
+			printf("read line disk_index %d %s\n", disk_index, buf);
+
+		/* store the request to memory */
+		//strcpy (memory_trace[memory_trace_size].line, buf);
+		//memory_trace[memory_trace_size].disk_index = disk_index;
+
+		/* find and store the reply status and reply fhandle to memory */
+		//memory_trace[memory_trace_size].trace_status = NFS3ERR_RFS_MISS;
+		trace_status = NFS3ERR_RFS_MISS;
+		for (i=disk_index+1; i<disk_index+MAX_COMMAND_REPLY_DISTANCE_FOR_PAIR; i++) {
+			reply_buf = read_line(i);
+			if (pair_write_debug)
+				printf("searching for reply: read line %s\n", reply_buf);
+			if (!reply_buf)
+				break;
+       		if (reply_buf[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+           		p = strchr (&reply_buf[TRACE_MSGID_POS], ' ');
+           		RFS_ASSERT (p);
+           		if (!strncmp(&reply_buf[TRACE_MSGID_POS], &buf[TRACE_MSGID_POS], p-&(reply_buf[TRACE_MSGID_POS]))) {
+					int pre_size, size, count;
+               		//memory_trace[memory_trace_size].trace_status = find_reply_status(reply_buf);
+					if (pair_write_debug)
+						printf("reply found trace_status %d\n", find_reply_status(reply_buf));
+						//break;
+	               	trace_status = find_reply_status(reply_buf);
+					if (trace_status == NFS3_OK) {
+						p = strstr (p, "pre-size");
+						RFS_ASSERT (p);
+						sscanf (p, "pre-size %x", &pre_size); 
+						p += strlen("pre-size");
+						p = strstr (p, "size");
+						RFS_ASSERT (p);
+						sscanf (p, "size %x", &size); 
+						p = strstr (p, "count");
+						if (!p) 
+							printf ("%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+						RFS_ASSERT (p);
+						sscanf (p, "count %x", &count); 
+						printf ("%s status %x pre-size %x size %x count %x\n", buf, trace_status, pre_size, size, count);
+						break;
+					}
+				};
+   	    	}
+		}
+		//if (memory_trace[memory_trace_size].trace_status == NFS3ERR_RFS_MISS)
+		if (trace_status == NFS3ERR_RFS_MISS) {
+			printf ("%s no reply\n", buf);
+			missing_reply_num ++;
+		}
+
+#if	0	/* commented out by G. Jason Peng */
+		if (missing_reply_num > memory_trace_size/10) {
+			printf ("missing_reply_num %d too high for memory_trace_size %d\n", missing_reply_num, memory_trace_size);
+			exit (0);
+		}
+#endif
+
+		memory_trace_size ++;
+
+		/*
+		if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+			fprintf (stderr, "memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+			break;
+		}
+		*/
+		if ((memory_trace_size%10000)==0)
+			fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+	};
+
+	fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, memory_trace_size, missing_reply_num );
+    //fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+
+}
+
+#ifdef notdef
+/* This function is not finished writing */
+int calculate_performance()
+{
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int debug = 0;
+
+typedef struct {
+	struct timeval start;
+	struct timeval stop;
+	int trace_status;
+	int op;
+} trace_performance_ent_t;
+
+	struct timeval req_time;
+	struct timeval reply_time;
+
+	trace_performance_ent_t * ent = NULL;
+
+	while (!CYCLIC_FULL(memory_trace_index)) {
+
+		if (ent!=NULL && (ent->trace_status == NFS3ERR_RFS_MISS))
+			buf = reply_buf;
+		if ((buf=read_line(++disk_index))==NULL) {
+END:		fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, CYCLIC_NUM(memory_trace_index), missing_reply_num );
+    		fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+			end_profile (&read_trace_profile);
+			return TRACE_FILE_END;
+		}
+
+		get_timestamp (&ent->req_time, buf);
+		if (MAX_COMMAND_REPLY_DISTANCE ==1) {
+			ent->trace_status == NFS3ERR_RFS_MISS;
+		} else {
+			reply_buf=read_line(++disk_index);
+			RFS_ASSERT (reply_buf);
+			if (!strcmp(reply_buf, "missing_reply\n")) {
+				ent->trace_status == NFS3ERR_RFS_MISS;
+			} else {
+				get_timestamp (&ent->reply_time, buf);
+				ent->trace_status = find_reply_status(reply_buf);
+			}
+		}
+	}
+}
+#endif
+
+int read_trace ()
+{
+	char *buf; 
+	char *reply_buf;
+	int i;
+	char * p;
+	int debug = 0;
+	memory_trace_ent_t * ent=NULL;
+
+	start_profile (&read_trace_profile);
+
+	while (!CYCLIC_FULL(memory_trace_index)) {
+		if (ent!=NULL && (ent->trace_status == NFS3ERR_RFS_MISS))
+			buf = reply_buf;
+		if ((buf=read_line(++disk_index))==NULL) {
+END:		fprintf(stderr, "total %d disk lines %d memory lines missing_reply_num %d\n", disk_index, CYCLIC_NUM(memory_trace_index), missing_reply_num );
+    		fprintf (stderr, "init_dep_tab, req_num_with_init_fh %d req_num_with_new_fh %d discard %d\n", req_num_with_init_fh, req_num_with_new_fh, req_num_with_discard_fh);
+			end_profile (&read_trace_profile);
+			return TRACE_FILE_END;
+		}
+	
+		if (rfs_debug)
+			printf ("disk_index %d %s\n", disk_index, buf);
+
+		if (disk_index==0) {
+			trace_timestamp1 = get_timestamp_sec (buf);
+			trace_starttime.sec = get_timestamp_sec (buf);
+			trace_starttime.usec = get_timestamp_usec (buf);
+			trace_starttime.esec = 0;
+			printf ("trace starttime %d %d %d\n", trace_starttime.sec, trace_starttime.usec, trace_starttime.esec);
+		} else
+			trace_timestamp2 = get_timestamp_sec (buf);
+
+		/* store the request to memory */
+		ent = &(memory_trace[memory_trace_index.head]);
+		strcpy (ent->line, buf);
+		ent->disk_index = disk_index;
+
+		if (MAX_COMMAND_REPLY_DISTANCE ==1) {
+			ent->trace_status == NFS3ERR_RFS_MISS;
+		} else {
+			reply_buf=read_line(++disk_index);
+			RFS_ASSERT (reply_buf);
+			if (!strcmp(reply_buf, "missing_reply\n")) {
+				ent->trace_status == NFS3ERR_RFS_MISS;
+			} else {
+				ent->trace_status = find_reply_status(reply_buf);
+			}
+		};
+
+		if (ent->trace_status == NFS3ERR_RFS_MISS)
+			missing_reply_num ++;
+
+		if (MAX_COMMAND_REPLY_DISTANCE > 1) {
+			if ((missing_reply_num > disk_index/5) && (missing_reply_num > 100)) {
+				printf ("missing_reply_num %d too high for disk_index %d\n", missing_reply_num, disk_index);
+				exit (0);
+			}
+		}
+
+		/* find and store the reply trace fhandle for create-class requests */
+		if (ent->trace_status==NFS3_OK) {
+			if (strstr(buf, "create") || strstr(buf, "mkdir") 
+				|| (strstr(buf, "symlink") && (buf[TRACE_VERSION_POS]!='2')) 
+				|| strstr(buf, "mknod") ) {
+				p = find_reply_trace_fh(reply_buf);
+				if (p==NULL) {
+					printf("skip line disk_index %d %s \n", disk_index, buf);
+					continue;
+				}
+				memcpy(ent->reply_trace_fh, p, TRACE_FH_SIZE);
+			} else
+				memset(ent->reply_trace_fh, 0, TRACE_FH_SIZE);
+		}
+
+		add_to_dep_tab(memory_trace_index.head);
+
+		if (((disk_index+1)%20000)==0) {
+			fprintf(stderr, "%d disk trace parsed \n", disk_index+1);
+		};
+	};
+
+	end_profile (&read_trace_profile);
+	return TRACE_BUF_FULL;
+}
+#else	/* not defined REDUCE_MEMORY_TRACE_SIZE */
+int read_trace ()
+{
+	FILE * fp;
+	char buf[1024];
+	// char * t=buf;	
+	int disk_index=0;
+
+	fp = fopen(trace_file, "r");
+	RFS_ASSERT (fp!=NULL);
+	while (fgets(buf, MAX_TRACE_LINE_LENGTH, fp)) {
+		if (!((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH)))
+			printf("strlen(buf) %d buf %s \n", strlen(buf), buf);
+		RFS_ASSERT ((strlen(buf)>80) && (strlen(buf)<MAX_TRACE_LINE_LENGTH));
+
+		/* store the request to memory */
+		strcpy (memory_trace[memory_trace_size].line, buf);
+		memory_trace[memory_trace_size].disk_index = disk_index;
+		memory_trace_size ++;
+
+		if (memory_trace_size >= MAX_MEMORY_TRACE_LINES) {
+			fprintf (stderr, "memory trace size %d is not enough\n", MAX_MEMORY_TRACE_LINES);
+			break;
+		}
+		if ((disk_index%100000)==0)
+			fprintf(stderr, "%d disk trace parsed, store %d trace lines to memory\n", disk_index, memory_trace_size);
+		disk_index ++;
+	}
+
+	fprintf(stderr, "total %d disk lines %d memory lines \n", disk_index, memory_trace_size );
+}
+#endif
+
+
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+inline int disk_index_to_memory_index (int disk_index)
+{
+	static int memory_index = 0;
+
+	RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));
+	RFS_ASSERT (memory_trace[memory_trace_index.tail].disk_index <= disk_index);
+	RFS_ASSERT (memory_trace[CYCLIC_MINUS(memory_trace_index.head,1,memory_trace_index.size)].disk_index >=disk_index);
+	if (disk_index > memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index < disk_index) {
+			memory_index = CYCLIC_ADD(memory_index,1,memory_trace_index.size);
+		}
+	};
+	if (disk_index < memory_trace[memory_index].disk_index) {
+		while (memory_trace[memory_index].disk_index > disk_index) {
+			memory_index = CYCLIC_MINUS(memory_index,1,memory_trace_index.size);
+		}
+	};
+
+	RFS_ASSERT (disk_index == memory_trace[memory_index].disk_index);
+	return memory_index;
+}
+#else
+#define disk_index_to_memory_index(disk_index)	disk_index
+#endif
+
+#define get_line_by_disk_index(disk_index) \
+	memory_trace[disk_index_to_memory_index(disk_index)].line
+
+inline char * find_reply_line (char * command_line, int cur_disk_index)
+{
+	int i;
+	char * line;
+	char * p;
+	int request_memory_index = disk_index_to_memory_index (cur_disk_index);
+	for (i=request_memory_index+1; i<request_memory_index+MAX_COMMAND_REPLY_DISTANCE && i<MAX_MEMORY_TRACE_LINES; i++) {
+		line = memory_trace[i].line;
+		if (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R') {
+	        p = strchr (&line[TRACE_MSGID_POS], ' ');
+    	    RFS_ASSERT (p);
+			if (!strncmp(&line[TRACE_MSGID_POS], &command_line[TRACE_MSGID_POS], p-&(line[TRACE_MSGID_POS]))) 
+				return line;
+		}
+	}
+	return NULL;
+}
+
+inline int find_reply_status (char * line)
+{
+	char * p;
+	int i=0;
+
+	if (rfs_debug)
+		printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	if (!(line[TRACE_COMMAND_REPLY_FLAG_POS]=='R')) {
+		printf ("disk_index %d %s\n", disk_index, line);
+	};
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	p = line+TRACE_MSGID_POS+2;	/* at least one letter for msgid and one letter for space */
+	if (strstr(p, "OK"))
+		return NFS3_OK;
+	if (strstr(p, "lookup 2") || strstr(p, "lookup   2"))
+		return 0x2;
+	if (strstr(p, "create d"))
+		return 0xd;
+	if (strstr(p, "setattr 1"))
+		return 0x1;
+	if (strstr(p, "setattr 2712")) /* 10002 NFS3ERR_NOT_SYNC */
+		return 0x2712;
+	if (strstr(p, "lookup d"))
+		return 0xd;
+	if (strstr(p, "read d"))
+		return 0xd;
+	if (strstr(p, "write d"))
+		return 0xd;
+	if (strstr(p, "write 46"))
+		return 0x46;
+	if (strstr(p, "getattr 46"))
+		return 0x46;
+	if (strstr(p, "mkdir d"))
+		return 0xd;
+	printf ("line %s  flag %c return value weird\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	printf ("!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	fprintf (stderr, "line %s  flag %c return value weird\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	fprintf (stderr, "!!!!!!!!!!!!!!!!!!!!!!!!\n");
+}
+
+inline int find_reply_status_old (char * line)
+{
+	char * p;
+	int i=0;
+
+	//printf ("line %s  flag %c\n", line, line[TRACE_COMMAND_REPLY_FLAG_POS]);
+	RFS_ASSERT (line[TRACE_COMMAND_REPLY_FLAG_POS]=='R');
+	if (!strstr(line, "OK")) {
+		p=strstr(line, " 6 read ");
+		if (p) {
+			p+=strlen(" 6 read ");
+		} else {
+			p = strstr (line, "status=XXX");
+			RFS_ASSERT (p);
+			p--;
+			RFS_ASSERT (*p==' ');
+			while (*p==' ')
+				p--;
+			while (*p!=' ') {
+				p--;
+			}
+			p++;
+		}
+		sscanf (p, "%x", &i);
+		if ((i<=0) || (i>10000))
+			printf("line %s\n", line);
+		RFS_ASSERT (i>0 && i<10009);
+	}
+	return i;
+}
+
+inline char * find_reply_trace_fh (char * line)
+{
+	char * p;	
+	p = strstr (line, "OK fh");
+	if (!p) {
+		printf ("disk_index %d find_reply_trace_fh line %s\n", disk_index, line);
+		return NULL;
+	} else
+		return p+6;
+}
+
+#ifndef NO_DEPENDENCY_TABLE
+inline int disk_index_to_dep_index(int cur_dep_index, int disk_index)
+{
+	int i;
+	for (i=cur_dep_index; i>min_dep_index; i--) {
+		if (dep_tab[i].disk_index == disk_index)
+			return i;
+	} 
+	RFS_ASSERT (0);
+}
+#endif
+
+inline int is_play_candidate (int dep_index)
+{
+	int proc = dep_tab[dep_index].proc;
+	int status = dep_tab[dep_index].status;
+	int trace_status = dep_tab[dep_index].trace_status;
+
+#ifndef TAKE_CARE_CREATE_MODE_BY_DAN
+	/* for a failed create in trace, trace_replay just ignore many time the trace create fail
+	 * due to access control, but trace_play will success because our access control
+	 * may be loose (all uid/gid is mapped to single one 513:513, so we just skip these requests 
+	 */
+	if ((proc==CREATE || proc==MKDIR) && (trace_status!=NFS3_OK) && (status!=NFS3ERR_RFS_MISS)) {
+		if (dependency_debug)
+			printf ("disk[%d] ignore failed create/mkdir in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		failed_create_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_OTHER_FAILED_COMMAND
+	if (((trace_status == NFS3ERR_ACCES) && (proc==READ || proc==WRITE || proc==LOOKUP)) || 
+	    ((trace_status == NFS3ERR_PERM) && (proc==SETATTR)) 									){
+		if (dependency_debug)
+			printf ("disk[%d] ignore other failed command in trace, trace_status %d line %s", 
+				dep_tab[dep_index].disk_index, trace_status, dep_tab[dep_index].line);
+		
+		failed_other_command_num ++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+	if ((dep_tab[dep_index].proc==READLINK) ) { /* send request */
+		skipped_readlink_command_num ++;
+		return FALSE;
+	}
+#endif
+/* This is actually take care in get_nextop by checking fh_map error when dep_index==min_dep_index */
+#ifndef TAKE_CARE_CUSTOM_COMMAND
+	/* this line has a file handle which should belong to discard but it is not
+	 * the file handle directly appears as parent directory in a lookup request
+	 * the return value is NOENT, the parent directory should have been initialized
+	 * but the initialization code just ignored all lookup request which didn't success
+	 * including NOENT even though the parent directory is still valid.
+	 */
+/*
+	if ((    ((dep_tab[dep_index].disk_index==262213) || (dep_tab[dep_index].disk_index==214402))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1100.txt")) 
+		) || 
+		(	 ((dep_tab[dep_index].disk_index==238460) || (dep_tab[dep_index].disk_index ==238470))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1000.txt"))
+		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+*/
+	if ((    ((dep_tab[dep_index].disk_index==423727) || (0))
+		  && !(strncmp(trace_file, "anon-lair62-011130-1500.txt", strlen("anon-lair62-011130-1500.txt"))) 
+		) || 
+		(	 ((dep_tab[dep_index].disk_index==238460) || (dep_tab[dep_index].disk_index ==238470))
+		  && !(strcmp(trace_file, "anon-lair62-011130-1000.txt"))
+		)) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+	/* this line is about the mkdir 116d9d originally in anon-lair62-011130-1400.txt */
+	if (!strncmp(dep_tab[dep_index].line, "1007147245.194201", strlen("1007147245.194201"))) {
+		skipped_custom_command_num++;
+		return FALSE;
+	}
+#endif
+#ifndef TAKE_CARE_FSSTAT_COMMAND
+	/* the file handle used in this command is not processed properly by pre-processing */
+	if (proc==FSSTAT) {
+		char * trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+		fh_map_t * fh = lookup_fh (trace_fh);
+		if (!fh) {
+			skipped_fsstat_command_num++;
+			return FALSE;
+		}
+	}
+#endif
+	return TRUE;
+}
+
+inline int is_dir_op (int proc)
+{
+	switch (proc) {
+	case MKDIR:
+	case CREATE:
+	case LINK:
+	case SYMLINK:
+	case MKNOD:
+	case REMOVE:
+	case RMDIR:
+	case RENAME:
+		return 1;
+	default:
+		return 0;
+	}
+}	
+
+inline int is_create_op (int proc)
+{
+	if (proc==CREATE || proc==MKDIR || proc==LINK || proc==SYMLINK || proc==MKNOD || proc==RENAME)
+		return 1;
+	return 0;
+}
+
+inline int is_delete_op (int proc)
+{
+	if (proc==REMOVE || proc==RMDIR || proc==RENAME)
+		return 1;
+	return 0;
+}	
+
+static inline char * find_lead_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh");
+	RFS_ASSERT (p);
+	p+=3; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+inline char * find_another_trace_fh(int proc, char * line)
+{
+	char * p;
+	/* check the file handle availability */ 
+	p = strstr (line, "fh2");
+	RFS_ASSERT (p);
+	p+=4; //printf ("check dependency dep_tab[%d] trace_fh %s line %s \n", dep_index, trace_fh, line);
+	return p;
+}
+
+/* return the index of next request in dep_tab.
+ * Return -1 if there is no suitable request to send
+ */
+inline int get_nextop(void)
+{
+	int i,j, k;
+	int * t;
+	static int dep_index = -2;
+	char * line;
+	char * p;
+#define INIT_MIN_WAIT_VALUE -999
+	static int min_wait_fhandle_dep_index = INIT_MIN_WAIT_VALUE;
+	int proc;
+	int flag;
+
+	if (min_wait_fhandle_dep_index == -999)
+		min_wait_fhandle_dep_index = dep_window_index.head;
+
+	for (i=0; i<CYCLIC_NUM(dep_window_index); i++) {
+		dep_index = (dep_window_index.tail+i) % dep_window_index.size;
+	
+		proc = dep_tab[dep_index].proc;
+		flag = dep_tab[dep_index].flag;
+
+		if (dependency_debug)
+			printf ("get_nextop check dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+#ifdef NO_DEPENDENCY_TABLE
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT) {
+			if (is_play_candidate(dep_index)==TRUE) {
+				/* the trace_fh is the file handle for the operation directory, trace_fh_2 is other file handle
+				 * used in the request */
+				if (proc==LINK || proc==RENAME) {
+					dep_tab[dep_index].trace_fh = find_another_trace_fh (proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].trace_fh_2 = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = 0;
+				} else {
+					dep_tab[dep_index].trace_fh = find_lead_trace_fh(proc, dep_tab[dep_index].line);
+					dep_tab[dep_index].fh = 0;
+					dep_tab[dep_index].fh_2 = (fh_map_t *)1;
+				};
+				dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+#ifdef TIME_PLAY
+				dep_tab[dep_index].skip_sec = skip_sec;
+#endif
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_CANDIDATE\n", dep_tab[dep_index].disk_index);
+			} else {
+				if (dependency_debug)
+					printf ("disk[%d] state DEP_FLAG_INIT to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+				dep_tab[dep_index].flag = DEP_FLAG_DONE;
+				continue;
+			}
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE) ) {
+
+			if (!dep_tab[dep_index].fh)
+				dep_tab[dep_index].fh = lookup_fh (dep_tab[dep_index].trace_fh);
+			if (!dep_tab[dep_index].fh_2)
+				dep_tab[dep_index].fh_2 = lookup_fh (dep_tab[dep_index].trace_fh_2);
+
+			/* need to wait for file handle */
+			if ((!dep_tab[dep_index].fh) || (!dep_tab[dep_index].fh_2)) {
+				if (dependency_debug)
+					printf("disk[%d] can not lookup file handle\n", dep_tab[dep_index].disk_index);
+				if (dep_tab[dep_index].flag == DEP_FLAG_CANDIDATE) {
+					if (dependency_debug)
+						printf ("disk[%d] state DEP_FLAG_CANDIDATE to DEP_FLAG_WAIT_FHANDLE\n", dep_tab[dep_index].disk_index);
+					dep_tab[dep_index].flag = DEP_FLAG_WAIT_FHANDLE;
+					sfs_gettime (&dep_tab[dep_index].start);
+					if (CYCLIC_LESS(dep_tab_index,dep_index,min_wait_fhandle_dep_index)) 
+						min_wait_fhandle_dep_index = dep_index;
+				} else {
+					struct ladtime tmp;
+					if (dep_index==dep_window_index.tail) {
+						if (!profile_debug) 
+							printf ("fh_path_map error disk[%d] state DEP_FLAG_WAIT_FHANDLE to DEP_FLAG_DONE\n", dep_tab[dep_index].disk_index);
+						fh_path_map_err_num ++;
+						dep_tab[dep_index].flag = DEP_FLAG_DONE;
+						continue;
+					}
+					sfs_gettime (&tmp);
+					SUBTIME (tmp, dep_tab[dep_index].start);
+#define DEPENDENCY_TIMEOUT 50
+#ifdef TIME_PLAY
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT + (skip_sec - dep_tab[dep_index].skip_sec));	
+#else
+					if (tmp.sec >= DEPENDENCY_TIMEOUT) {
+						printf("dep_tab[%d].flag %d disk_index %d line %s\n", dep_index,
+							dep_tab[dep_index].flag, dep_tab[dep_index].disk_index,
+							dep_tab[dep_index].line);
+					}
+					RFS_ASSERT (tmp.sec < DEPENDENCY_TIMEOUT );	
+#endif
+				}
+				continue;
+			}
+
+			/* file handle ready, adjust_min_wait_fhandle_dep_index */
+			if ((dep_tab[dep_index].flag == DEP_FLAG_WAIT_FHANDLE)) {
+				if (dep_index == min_wait_fhandle_dep_index) {
+					min_wait_fhandle_dep_index = dep_window_index.head;
+					for (j=CYCLIC_ADD(dep_index,1,dep_window_index.size); CYCLIC_LESS(dep_window_index,j,dep_window_index.head); j++) {
+						if (dep_tab[j].flag ==DEP_FLAG_WAIT_FHANDLE) {
+							min_wait_fhandle_dep_index = j;
+							break;
+						}
+					}
+				}
+			}
+			if (dependency_debug)
+				printf("disk[%d] found file handle\n", dep_tab[dep_index].disk_index);
+			dep_tab[dep_index].flag = DEP_FLAG_FHANDLE_READY;
+
+			/* the normal file operation can be executed now */
+			if (!is_dir_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug)
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			if (dependency_debug)
+				printf("disk[%d] directory operation \n", dep_tab[dep_index].disk_index);
+			/* the directory operation need to lock the directory first */
+			if (dep_tab[dep_index].fh->lock) {
+				if (dependency_debug)
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DIRECTORY\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DIRECTORY;
+				continue;
+			}
+		}
+				
+		if ((dep_tab[dep_index].flag == DEP_FLAG_FHANDLE_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DIRECTORY)) {
+			int j = dep_tab[dep_index].fh - fh_map;
+			if (dependency_debug) {
+				printf ("dep_tab[%d].disk_index %d, fh_map[%d] lock=%d\n",dep_index, dep_tab[dep_index].disk_index, j, dep_tab[dep_index].fh->lock);
+				printf ("trace_fh %s path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+				printf ("trace_fh %s path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+			}
+			if ((dep_tab[dep_index].fh->lock) || ((proc==RENAME) && (dep_tab[dep_index].fh_2->lock)) ) {
+				if (dependency_debug) 
+					printf ("continue to wait for directory lock\n");
+				continue;
+			}
+			if (dependency_debug) 
+				printf ("dep_tab[%d] disk index %d LOCK fh_map[%d] \n", dep_index, dep_tab[dep_index].disk_index, j);
+			dep_tab[dep_index].fh->lock = 1;
+			if (proc==RENAME)
+				dep_tab[dep_index].fh_2->lock = 1;
+
+			/* the non-delete directory operation can proceed now */
+			if (!is_delete_op (dep_tab[dep_index].proc)) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+
+			/* the delete operation can proceed if nobody ahead is waiting for fhandle */
+			/* probably this condition is not strong enough */
+//			if ((min_wait_fhandle_dep_index<dep_index) ) {
+			if (dep_index!=dep_window_index.tail) {
+				if (dependency_debug) 
+					printf ("disk[%d] state %d to DEP_FLAG_WAIT_DELETE\n", dep_tab[dep_index].disk_index, dep_tab[dep_index].flag);
+				dep_tab[dep_index].flag = DEP_FLAG_WAIT_DELETE;
+				continue;
+			} 
+			dep_tab[dep_index].flag = DEP_FLAG_DIRECTORY_READY;
+		}
+
+		if ((dep_tab[dep_index].flag == DEP_FLAG_DIRECTORY_READY) || (dep_tab[dep_index].flag == DEP_FLAG_WAIT_DELETE)) {
+//			if (min_wait_fhandle_dep_index > dep_index) {
+			if (dep_index==dep_window_index.tail) {
+				if (dependency_debug) 
+					printf ("return disk[%d]\n", dep_tab[dep_index].disk_index);
+				return dep_index;
+			}
+		}
+#else /*NO_DEPENDENCY_TABLE undefined */
+	/* this part of code will be invalid after CYCLIC buffer design */
+		if (dep_tab[dep_index].flag == DEP_FLAG_INIT){
+			for (j=0, t=&(dep_tab[dep_index].dep_ops[0]);
+				(j<dep_tab[dep_index].init_dep_num) && (dep_tab[dep_index].cur_dep_num>0); 
+				j++, t++) {
+				if (*t !=-1) {
+					if (dep_tab[disk_index_to_dep_index(dep_index, *t)].flag == DEP_FLAG_DONE) { 
+						/* The depended request has been finished */ 
+						*t = -1;
+						dep_tab[dep_index].cur_dep_num --;
+					}
+				} 
+			}
+
+			if (dep_tab[dep_index].cur_dep_num == 0) {
+				return dep_index;
+			}
+		}
+#endif
+	}
+
+	if (dependency_debug) 
+		printf ("get_nexop return -1\n");
+	return -1;
+}
+
+int check_timeout(void)
+{
+	static int biod_index = 0;
+	int i;
+	int dep_index;	/* index into dep_tab */
+	int proc;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime timeout;
+	struct ladtime current_time;
+
+	sfs_gettime (&current_time);	
+
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (biod_reqp[biod_index].in_use==TRUE) {
+			timeout = biod_reqp[biod_index].timeout;
+			if ((current_time.sec>timeout.sec) ||
+				((current_time.sec==timeout.sec) && (current_time.usec>timeout.usec))) {
+
+				dep_index = biod_reqp[biod_index].dep_tab_index;
+				proc = dep_tab[dep_index].proc;
+				op_ptr = &Ops[proc];
+				op_ptr->results.timeout_calls++;
+				Ops[TOTAL].results.timeout_calls++;
+
+
+				if (is_create_op(proc)) {
+					dep_tab[dep_index].flag = DEP_FLAG_CANDIDATE;
+					printf ("resend dep_tab[%d], disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+					finish_request (biod_index, dep_index, NFS3ERR_RFS_TIMEOUT, DEP_FLAG_CANDIDATE);
+				} else {
+					finish_request (biod_index, dep_index, NFS3ERR_RFS_TIMEOUT, DEP_FLAG_DONE);
+				}
+				timeout_num ++;
+				num_out_reqs_statistics_at_timeout[num_out_reqs]++;
+
+				//RFS_ASSERT (!is_create_op(proc));
+
+				if (per_packet_debug)
+					printf ("timeout request: disk_index %d, dep_index %d biod_reqp[%d].start %d:%d timeout %d:%d current %d:%d\n", dep_tab[dep_index].disk_index, dep_index, biod_index, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, timeout.sec, timeout.usec, current.sec, current.usec);
+			}
+		}
+	}
+}
+
+/* Allocate a biod_req entry to send and receive request dep_tab[dep_index]
+ * build the cross reference between dep_tab entry and biod_req entry
+ */
+struct biod_req * get_biod_req(int dep_index) /* index into dep_tab */
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		if (!biod_reqp[biod_index].in_use) {
+			biod_reqp[biod_index].in_use = 1;
+			biod_reqp[biod_index].dep_tab_index = dep_index;
+			dep_tab[dep_index].biod_req_index = biod_index;
+    		num_out_reqs++;
+			return &(biod_reqp[biod_index]);
+		}
+	}
+	return NULL;
+}
+
+/* Return index into biod_reqp
+ * return -1 upon failure 
+ */
+int lookup_biod_req (int xid)
+{
+	static int biod_index = 0;
+	int i;
+	for (i=0; i<max_biod_reqs; i++, biod_index = (biod_index+1)%max_biod_reqs) {
+		/* give a NULL as timeout pointer may cause indefinitely block */
+		if ((biod_reqp[biod_index].in_use == TRUE) &&( biod_reqp[biod_index].xid == xid)) {
+			return biod_index;
+		}
+	}
+	return -1;
+}
+
+extern struct ladtime test_start;
+void init_time_offset(void)
+{
+	struct ladtime tmp1;
+	struct ladtime tmp2;
+
+	test_start.sec = 0;
+	test_start.usec = 0;
+	sfs_gettime (&tmp1);		/* called at initial time: tmp1 = play_starttime */
+#ifdef SPEED_UP
+	DIVTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime / SCALE */
+#endif
+#ifdef SLOW_DOWN
+	MULTIME (tmp1, PLAY_SCALE) /* tmp1 = play_starttime * SCALE */
+#endif
+
+	tmp2 = trace_starttime; /* tmp2 = trace_starttime */
+	SUBTIME (tmp2, tmp1);	/* tmp2 = trace_starttime - play_starttime *|/ SCALE */
+	time_offset = tmp2;		/* time_offset = trace_starttime - play_starttime *|/ SCALE */ 
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void init_dep_tab_entry (int dep_index)
+{
+	char * line;
+	int version;
+	int nfsproc;
+	int msgid;
+
+	//line = get_line_by_disk_index (dep_tab[dep_index].disk_index);
+	line = dep_tab[dep_index].line;
+	sscanf (line, "%d.%d", &(dep_tab[dep_index].timestamp.tv_sec), &(dep_tab[dep_index].timestamp.tv_usec));
+	sscanf (&line[TRACE_MSGID_POS], "%x %x", &msgid, &nfsproc);
+	//printf ("msgid %x nfsproc %x\n", msgid, nfsproc);
+	if (line[TRACE_VERSION_POS]=='2') {
+		dep_tab[dep_index].proc = nfs2proc_to_rfsproc[nfsproc];
+		RFS_ASSERT (nfsproc <18);
+	} else {
+		/* This is for debug purpose */
+		if (line[TRACE_VERSION_POS] !='3') {
+			fprintf(stderr, "line[TRACE_VERSION_POS] %c line %s\n", line[TRACE_VERSION_POS], line);
+			line = get_line_by_disk_index (dep_tab[dep_index].disk_index-1);
+			if (!line)
+				line = get_line_by_disk_index (dep_tab[dep_index].disk_index-2);
+			RFS_ASSERT (line);
+			fprintf(stderr, "previousline %s\n", line);
+		}
+		RFS_ASSERT (line[TRACE_VERSION_POS] =='3');
+		if (nfsproc >= NFS3_PROCEDURE_COUNT) {
+			fprintf(stderr, "proc %d line %s\n", nfsproc, line);
+			
+		}
+		RFS_ASSERT (nfsproc <NFS3_PROCEDURE_COUNT);
+		dep_tab[dep_index].proc = nfs3proc_to_rfsproc[nfsproc];
+	}
+	RFS_ASSERT (dep_tab[dep_index].proc >= 0 && dep_tab[dep_index].proc < NOPS);
+	dep_tab[dep_index].flag = DEP_FLAG_INIT;
+}
+
+void adjust_play_window (int flag, int * poll_timeout_arg)
+{
+	struct ladtime max_window_time;
+	static struct ladtime max_poll_time = {0, 2000, 0};
+	struct ladtime t;
+	int i;
+	char * line;
+	cyclic_index_t old_dep_window_index = dep_window_index;
+
+#ifdef notdef
+	printf ("^^^^^^^^^^^^^^^ adjust_play_window, begin\n");
+	CYCLIC_PRINT (dep_tab_index);
+	printf ("dep_tab[%d].memory_index %d\n", dep_tab_index.tail, dep_tab[dep_tab_index.tail].memory_index);
+	CYCLIC_PRINT (dep_window_index);
+	CYCLIC_PRINT (memory_trace_index);
+	printf ("                adjust_play_window, begin\n");
+#endif
+
+	while ((!CYCLIC_EMPTY(dep_window_index)) && (dep_tab[dep_window_index.tail].flag == DEP_FLAG_DONE)) {
+#ifdef notdef
+		//CYCLIC_PRINT (memory_trace_index);
+		//printf("MOVE_TAIL_TO memory_index %d\n", dep_tab[dep_tab_index.tail].memory_index);
+		RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));	
+		RFS_ASSERT (CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head));
+		printf("%d is done\n", dep_window_index.tail);
+#endif
+		CYCLIC_MOVE_TAIL(dep_tab_index);
+		CYCLIC_MOVE_TAIL(dep_window_index);
+
+#ifdef notdef
+		CYCLIC_PRINT (dep_tab_index);
+		CYCLIC_PRINT (dep_window_index);
+
+		if (! (dep_tab_index.tail == dep_window_index.tail)) {
+			CYCLIC_PRINT(dep_tab_index);
+			CYCLIC_PRINT(dep_window_index);
+		};
+		RFS_ASSERT ( dep_tab_index.tail == dep_window_index.tail);
+#endif
+
+		if (!CYCLIC_EMPTY(dep_tab_index)) {
+#ifdef notdef
+			RFS_ASSERT (!CYCLIC_EMPTY(memory_trace_index));	
+			if (!(CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head))) {
+				CYCLIC_PRINT(memory_trace_index);
+				CYCLIC_PRINT(dep_tab_index);
+				printf("dep_tab[head-1].memory_index, %d [tail].memory_index %d\n", 
+					dep_tab[CYCLIC_MINUS(dep_tab_index.head,1,dep_tab_index.size)].memory_index,
+					dep_tab[dep_tab_index.tail].memory_index);
+			}
+			RFS_ASSERT (CYCLIC_LESS (memory_trace_index, dep_tab[dep_tab_index.tail].memory_index, memory_trace_index.head));
+#endif
+			CYCLIC_SET_TAIL_TO(&memory_trace_index, dep_tab[dep_tab_index.tail].memory_index);
+			//printf ("set memory_trace_index to %d=%d, dep_tab_index.tail %d\n", memory_trace_index.tail, dep_tab[dep_tab_index.tail].memory_index, dep_tab_index.tail);
+		} else {
+		//	CYCLIC_MOVE_TAIL (memory_trace_index);
+		}
+	}
+
+	while (CYCLIC_EMPTY(dep_tab_index)) {
+		
+		if (disk_io_status == TRACE_FILE_END) 
+			return;
+		else {
+			//printf ("************** ADJUST_PLAY_WINDOW sleep 1 s\n"); 
+			//print_cyclic_buffers();
+			//pthread_yield();
+			//usleep (1000);
+		}
+	}
+
+	/* max_trace_window_time = current *|/ SCALE + trace_starttime */
+	sfs_gettime (&current);
+
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+	MULTIME (current, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+	DIVTIME (current, PLAY_SCALE);
+#endif
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+
+	/* Right now it is not clear how to deal with the situation where MAX_PLAY_WINDOW is reached */
+	if (CYCLIC_NUM(dep_window_index) == MAX_PLAY_WINDOW) {
+		//printf ("can not catch up the speed, dep_tab_size %d dep_window_max %d reach min_dep_index %d+MAX_PLAY_WINDOW\n", dep_tab_size, dep_window_max, min_dep_index);
+		//printf (".");
+		can_not_catch_speed_num ++;
+	}
+	while ((CYCLIC_NUM(dep_window_index) < MAX_PLAY_WINDOW) &&
+		   (CYCLIC_NUM(dep_window_index) < CYCLIC_NUM(dep_tab_index)) ) {
+		struct ladtime t;
+		int dep_index = (dep_window_index.tail+i) % dep_window_index.size;
+        t.sec = dep_tab[dep_index].timestamp.tv_sec;
+        t.usec = dep_tab[dep_index].timestamp.tv_usec;
+		if ((t.sec>max_window_time.sec)||(t.sec==max_window_time.sec && t.usec>max_window_time.usec))
+            break;
+		CYCLIC_MOVE_HEAD(dep_window_index);
+	}
+#else
+	ADDTIME (current, trace_starttime);
+	max_window_time = current;
+	while ((CYCLIC_NUM(dep_window_index) < MAX_PLAY_WINDOW) &&
+		   (CYCLIC_NUM(dep_window_index) < CYCLIC_NUM(dep_tab_index)) ) {
+		CYCLIC_MOVE_HEAD(dep_window_index);
+	}
+#endif
+
+	if (flag == BUSY)
+		*poll_timeout_arg = 0;
+   	else if (CYCLIC_NUM(dep_window_index)==CYCLIC_NUM(dep_tab_index)) {
+		*poll_timeout_arg = 1000;	/* poll_timeout set to 1 second for the last request */
+	} else {
+#ifdef TIME_PLAY
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[dep_window_index.head].timestamp.tv_sec;
+		tmp.usec = dep_tab[dep_window_index.head].timestamp.tv_usec;
+		if (adjust_play_window_debug>=2)
+			printf ("dep_tab[dep_window_index.head %d].timestamp %d:%d, max_window_time %d:%d\n",
+				dep_window_index.head, tmp.sec, tmp.usec, max_window_time.sec, max_window_time.usec);
+
+		SUBTIME (tmp, max_window_time);
+#ifdef SPEED_UP
+		DIVTIME (tmp, PLAY_SCALE);
+#endif
+#ifdef SLOW_DOWN
+		MULTIME (tmp, PLAY_SCALE);
+#endif
+/*
+		tmp1 = tmp;
+
+		if (tmp.sec > max_poll_time.sec) {
+
+			if (rfs_debug) 
+				printf ("dep_tab[%d].timestamp %d:%d, max_window_time %d:%d\n",
+				dep_window_max, dep_tab[dep_window_max].timestamp.tv_sec, dep_tab[dep_window_max].timestamp.tv_usec, max_window_time.sec, max_window_time.usec);
+			printf ("skip %d seconds\n", tmp.sec-max_poll_time.sec);
+			SUBTIME (tmp, max_poll_time);
+			tmp.usec = 0;
+			skip_sec += tmp.sec;
+			SUBTIME (test_start, tmp);
+			tmp = max_poll_time;
+		}
+*/
+
+		//RFS_ASSERT ((tmp.sec < 1000));
+		if (tmp.sec > 1000)
+			tmp.sec = 1000;
+		if ((tmp.sec ==0) && (tmp.usec==0)) {
+			*poll_timeout_arg = 0;
+		} else
+			*poll_timeout_arg = tmp.sec*1000000+tmp.usec;
+#else 
+		/*
+		struct ladtime tmp;
+		struct ladtime tmp1;
+		tmp.sec = dep_tab[dep_window_max].timestamp.tv_sec;
+		tmp.usec = dep_tab[dep_window_max].timestamp.tv_usec;
+		tmp1.sec = dep_tab[dep_window_max-1].timestamp.tv_sec;
+		tmp1.usec = dep_tab[dep_window_max-1].timestamp.tv_usec;
+		SUBTIME (tmp, tmp1);
+		RFS_ASSERT ((tmp.sec < 1000));
+		RFS_ASSERT ((tmp.sec>0) || ((tmp.sec==0) && (tmp.usec>0)));
+		*poll_timeout = tmp.sec*1000000+tmp.usec;
+		*/
+
+		*poll_timeout_arg = 100000;
+#endif
+	}	
+	if (rfs_debug)
+		printf ("adjust_play_window: flag %d min %d -> %d, max %d -> %d poll_timeout_arg %d \n", 
+		flag, old_dep_window_index.tail, dep_window_index.tail, old_dep_window_index.head,
+		dep_window_index.head, *poll_timeout_arg);
+
+#ifdef notdef
+	printf ("^^^^^^^^^^^^^^^ adjust_play_window, end\n");
+	CYCLIC_PRINT (dep_tab_index);
+	printf ("dep_tab[%d].memory_index %d\n", dep_tab_index.tail, dep_tab[dep_tab_index.tail].memory_index);
+	CYCLIC_PRINT (dep_window_index);
+	CYCLIC_PRINT (memory_trace_index);
+	printf ("	 adjust_play_window, end\n\n");
+#endif
+	//CYCLIC_ASSERT(4);
+}
+
+/* poll for usecs and receive, after receive one reply,
+ * return index in biod_reqp of the corresponding request
+ */
+int poll_and_get_reply (int usecs)
+{
+	int biod_index = -1;
+	int xid;
+	int error;
+	struct timeval zero_time = {0, 0}; /* Immediately return */
+
+#ifdef RECV_THREAD
+	//printf("recv thread waitsem 1\n");
+	waitsem (async_rpc_sem);
+	//printf("recv thread got sem 1\n");
+#endif
+	do {
+		error = biod_poll_wait (NFS_client, usecs);
+		switch (error) {
+		case -1:
+			if (errno == EINTR) {
+				error = 1;
+				continue;
+			}
+			if (rfs_debug) {
+				(void) fprintf(stderr, "biod_poll_wait error\n");
+				perror ("");
+			    (void) fflush(stderr);
+			}
+			break;
+		case 0:
+			break;
+		default:
+#ifdef UDP
+			//printf("recv thread waitsem 2\n");
+			//waitsem (async_rpc_sem);
+			//printf("recv thread got sem 2\n");
+			error = get_areply_udp (NFS_client, &xid, &zero_time);
+			//postsem (async_rpc_sem);
+			//printf("recv thread postsem 2\n");
+			// RFS_ASSERT (error!= RPC_TIMEOUT);	/* we have polled and know there is data */
+			// RFS_ASSERT (error!= RPC_CANTRECV);
+			RFS_ASSERT (error == RPC_SUCCESS);
+
+			biod_index = lookup_biod_req (xid);
+			sfs_gettime (&(biod_reqp[biod_index].stop));
+#else
+			RFS_ASSERT (0);
+#endif
+		}
+	} while (0);
+#ifdef RECV_THREAD
+	postsem (async_rpc_sem);
+	//printf("recv thread postsem 1\n");
+#endif
+	return biod_index;
+}
+
+void print_result(void)
+{
+	int i, j;
+	struct ladtime t;
+	int dep_index;
+	int avg_msecs;
+	unsigned long long tmp;
+	int avg_usecs;
+
+    if (DEBUG_CHILD_GENERAL) {
+		(void) fprintf(stdout, "trace play result:\n");
+		(void) fprintf(stdout, "\t    percentage good_cnt bad_cnt timeout_cnt\telapsed time\t\t\taverage time\n");
+		for (i=0; i<NOPS+1; i++) {
+			if (Ops[i].results.good_calls==0) {
+				avg_msecs = 0;
+				avg_usecs = 0;
+			} else {
+				tmp = Ops[i].results.time.sec*1000000 + Ops[i].results.time.usec;
+				avg_msecs = 0;
+				avg_usecs = tmp/Ops[i].results.good_calls;
+/*
+				avg_msecs = (Ops[i].results.time.sec*1000 + Ops[i].results.time.usec/1000)/Ops[i].results.good_calls;
+				avg_usecs = (Ops[i].results.time.usec%1000)/Ops[i].results.good_calls;
+*/
+			}
+			(void) fprintf(stdout,	"%11s\t%4.1f\t%4d\t%4d\t%4d\t\tsec %8d usec %8d \tusec %8d\n", 
+				Ops[i].name, 
+				(float)(100*Ops[i].results.good_calls)/(float)Ops[TOTAL].results.good_calls, 
+				Ops[i].results.good_calls, Ops[i].results.bad_calls, Ops[i].results.timeout_calls,
+				Ops[i].results.time.sec, Ops[i].results.time.usec, avg_msecs*1000+avg_usecs);
+		}
+		(void) fflush (stdout);
+    }
+
+#if	0	/* commented out by G. Jason Peng */
+	RFS_ASSERT (read_data_owe_GB==0);
+	printf("read_data_total %d GB and %d bytes, owe %d GB and %d bytes, %d percent, adjusted %d times \n",read_data_total_GB, read_data_total, read_data_owe_GB, read_data_owe, (read_data_owe)/(read_data_total/100), read_data_adjust_times);
+	printf("write_data_total %d GB and %d bytes, owe %d GB and %d bytes, %d percent, adjusted %d times \n",write_data_total_GB, write_data_total, write_data_owe_GB, write_data_owe, (write_data_owe)/(write_data_total/100), write_data_adjust_times);
+	printf("poll_timeout_0_num %d poll_timeout_pos_num %d\n", poll_timeout_0_num, poll_timeout_pos_num);
+	printf("failed_create_command_num_in_original_trace %d\nfailed_other_command_num_in_original_trace %d\nskipped_readlink_command_num %d\nskipped_custom_command_num %d\nfh_path_map_err_num %d\nskipped_fsstat_command_num %d\nmissing_reply_num %d\nrename_rmdir_noent_reply_num %d\nrmdir_not_empty_reply_num %d\nloose_access_control_reply_num %d\nlookup_err_due_to_rename %d\nlookup_err_due_to_parallel_remove %d\nlookup_eaccess_enoent_mismatch %d\nread_io_err_num %d\nstale_fhandle_err_num %d abnormal_EEXIST_num %d abnormal_ENOENT_num %d proper_reply_num %d run_stage_proper_reply_num %d\n", 
+			failed_create_command_num,
+			failed_other_command_num,
+			skipped_readlink_command_num, 
+			skipped_custom_command_num,
+			fh_path_map_err_num, 
+			skipped_fsstat_command_num, 
+			missing_reply_num, 
+			rename_rmdir_noent_reply_num, 
+			rmdir_not_empty_reply_num, 
+			loose_access_control_reply_num, 
+			lookup_err_due_to_rename_num, 
+			lookup_err_due_to_parallel_remove_num,
+			lookup_eaccess_enoent_mismatch_num, 
+			read_io_err_num, 
+			stale_fhandle_err_num,
+			abnormal_EEXIST_num,
+			abnormal_ENOENT_num,
+			proper_reply_num, run_stage_proper_reply_num);
+#endif
+
+//  print_dump(Client_num, Child_num);
+} 
+
+/*
+ * allocate and initialize client handles
+ */
+static int
+init_rpc(void)
+{
+	int dummy = 0;
+
+    /*
+     * Set up the client handles.  We get them all before trying one
+     * out to insure that the client handle for LOOKUP class is allocated
+     * before calling op_getattr().
+     */
+    if (DEBUG_CHILD_GENERAL) {
+    	(void) fprintf(stderr, "%s: set up client handle\n", sfs_Myname);
+    }
+
+    NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
+					(uint32_t) NFS_PROGRAM,
+					(uint32_t) nfs_version,
+					RPC_ANYSOCK, &Nfs_timers[0]);
+		
+    if (NFS_client  == ((CLIENT *) NULL)) {
+        return(-1);
+    }
+
+    /*
+     * create credentials using the REAL uid
+     */
+    NFS_client->cl_auth = authunix_create(lad_hostname, (int)Real_uid,
+				      (int)Cur_gid, 0, NULL);
+
+	if (biod_init(dummy, dummy) == -1) {
+		    return(-1);
+	}
+
+    return(0);
+} /* init_rpc */
+
+void
+init_counters(void)
+{
+    uint_t i;
+    uint_t start_msec;
+
+    /* Ready to go - initialize operation counters */
+    for (i = 0; i < NOPS + 1; i++) {
+	Ops[i].req_cnt = 0;
+	Ops[i].results.good_calls = 0;
+	Ops[i].results.bad_calls = 0;
+	Ops[i].results.timeout_calls = 0;	// RFS
+	Ops[i].results.fast_calls = 0;
+	Ops[i].results.time.sec = 0;
+	Ops[i].results.time.usec = 0;
+	Ops[i].results.msec2 = 0;
+    }
+
+    /* initialize timers and period variables */
+    sfs_gettime(&Starttime);
+    Cur_time = Starttime;
+    start_msec = (Starttime.sec * 1000) + (Starttime.usec / 1000);
+    Previous_chkpnt_msec = start_msec;
+    Calls_this_period = 0;
+    Reqs_this_period = 0;
+    Sleep_msec_this_period = 0;
+    Calls_this_test = 0;
+    Reqs_this_test = 0;
+    Sleep_msec_this_test = 0;
+}
+
+static char *
+nfs3_strerror(int status)
+{
+    static char str[40];
+    switch (status) {
+	case NFS3_OK:
+	    (void) strcpy(str, "no error");
+	    break;
+	case NFS3ERR_PERM:
+	    (void) strcpy(str, "Not owner");
+	    break;
+	case NFS3ERR_NOENT:
+	    (void) strcpy(str, "No such file or directory");
+	    break;
+	case NFS3ERR_IO:
+	    (void) strcpy(str, "I/O error");
+	    break;
+	case NFS3ERR_NXIO:
+	    (void) strcpy(str, "No such device or address");
+	    break;
+	case NFS3ERR_ACCES:
+	    (void) strcpy(str, "Permission denied");
+	    break;
+	case NFS3ERR_EXIST:
+	    (void) strcpy(str, "File exists");
+	    break;
+	case NFS3ERR_XDEV:
+	    (void) strcpy(str, "Cross-device link");
+	    break;
+	case NFS3ERR_NODEV:
+	    (void) strcpy(str, "No such device");
+	    break;
+	case NFS3ERR_NOTDIR:
+	    (void) strcpy(str, "Not a directory");
+	    break;
+	case NFS3ERR_ISDIR:
+	    (void) strcpy(str, "Is a directory");
+	    break;
+	case NFS3ERR_INVAL:
+	    (void) strcpy(str, "Invalid argument");
+	    break;
+	case NFS3ERR_FBIG:
+	    (void) strcpy(str, "File too large");
+	    break;
+	case NFS3ERR_NOSPC:
+	    (void) strcpy(str, "No space left on device");
+	    break;
+	case NFS3ERR_ROFS:
+	    (void) strcpy(str, "Read-only file system");
+	    break;
+	case NFS3ERR_MLINK:
+	    (void) strcpy(str, "Too many links");
+	    break;
+	case NFS3ERR_NAMETOOLONG:
+	    (void) strcpy(str, "File name too long");
+	    break;
+	case NFS3ERR_NOTEMPTY:
+	    (void) strcpy(str, "Directory not empty");
+	    break;
+	case NFS3ERR_DQUOT:
+	    (void) strcpy(str, "Disc quota exceeded");
+	    break;
+	case NFS3ERR_STALE:
+	    (void) strcpy(str, "Stale NFS file handle");
+	    break;
+	case NFS3ERR_REMOTE:
+	    (void) strcpy(str, "Object is remote");
+	    break;
+	case NFS3ERR_BADHANDLE:
+	    (void) strcpy(str, "Bad file handle");
+	    break;
+	case NFS3ERR_NOT_SYNC:
+	    (void) strcpy(str, "Not sync write");
+	    break;
+	case NFS3ERR_BAD_COOKIE:
+	    (void) strcpy(str, "Bad cookie");
+	    break;
+	case NFS3ERR_NOTSUPP:
+	    (void) strcpy(str, "Operation not supported");
+	    break;
+	case NFS3ERR_TOOSMALL:
+	    (void) strcpy(str, "Value too small");
+	    break;
+	case NFS3ERR_SERVERFAULT:
+	    (void) strcpy(str, "Server fault");
+	    break;
+	case NFS3ERR_BADTYPE:
+	    (void) strcpy(str, "Bad type");
+	    break;
+	case NFS3ERR_JUKEBOX:
+	    (void) strcpy(str, "Jukebox");
+	    break;
+	case NFS3ERR_RFS_TIMEOUT:
+		(void) strcpy(str, "Timeout");
+		break;
+	default:
+	    (void) sprintf(str, "Unknown status %d", status);
+	    break;
+    }
+    return (str);
+}
+
+/*
+ * Check the gettimeofday() resolution. If the resolution
+ * is in chunks bigger than SFS_MIN_RES then the client
+ * does not have a usable resolution for running the 
+ * benchmark.
+ */
+static void
+check_clock(void)
+{
+	double time_res;
+	char tmp_hostname[HOSTNAME_LEN];
+
+	time_res = get_resolution();
+    	getmyhostname(tmp_hostname, HOSTNAME_LEN);
+	if( time_res > (double)SFS_MIN_RES )
+	{
+		(void) fprintf(stderr,
+		"\n%s: Clock resolution too poor to obtain valid results.\n",
+			tmp_hostname);
+		(void) fprintf(stderr,
+		"%s: Clock resolution %f Micro seconds.\n", tmp_hostname,
+			time_res);
+		exit(175);
+	}
+	else
+	{
+		(void) fprintf(stderr,
+		"\n%s: Good clock resolution [ %f ] Micro seconds.\n", 
+			tmp_hostname, time_res);
+	}
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns the resolution of the gettimeofday() function 
+ * in microseconds.
+ */
+static double
+get_resolution(void)
+{
+        double starttime, finishtime, besttime;
+        long  j,delay;
+	int k;
+
+        finishtime=time_so_far1(); /* Warm up the instruction cache */
+        starttime=time_so_far1();  /* Warm up the instruction cache */
+        delay=j=0;                 /* Warm up the data cache */
+	for(k=0;k<10;k++)
+	{
+	        while(1)
+       	 	{
+       	         	starttime=time_so_far1();
+       	         	for(j=0;j< delay;j++)
+       	                ;
+       	         	finishtime=time_so_far1();
+       	         	if(starttime==finishtime)
+       	                 	delay++;
+       	         	else
+			{
+				if(k==0)
+					besttime=(finishtime-starttime);
+				if((finishtime-starttime) < besttime)
+					besttime=(finishtime-starttime);
+                       	 	break;
+			}
+		}
+        }
+         return(besttime);
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns current result of gettimeofday() in microseconds.
+ */
+/************************************************************************/
+/* Time measurement routines.                                           */
+/* Return time in microseconds                                          */
+/************************************************************************/
+
+static double
+time_so_far1(void)
+{
+        /* For Windows the time_of_day() is useless. It increments in 55 */
+	/* milli second increments. By using the Win32api one can get */
+	/* access to the high performance measurement interfaces. */
+	/* With this one can get back into the 8 to 9 microsecond */
+	/* resolution.  */
+#ifdef Windows
+        LARGE_INTEGER freq,counter;
+        double wintime;
+        double bigcounter;
+
+        QueryPerformanceFrequency(&freq);
+        QueryPerformanceCounter(&counter);
+        bigcounter=(double)counter.HighPart *(double)0xffffffff +
+                (double)counter.LowPart;
+        wintime = (double)(bigcounter/(double)freq.LowPart);
+        return((double)wintime*1000000.0);
+#else
+#if defined (OSFV4) || defined(OSFV3) || defined(OSFV5)
+  struct timespec gp;
+
+  if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1)
+    perror("getclock");
+  return (( (double) (gp.tv_sec)*1000000.0) +
+    ( ((float)(gp.tv_nsec)) * 0.001 ));
+#else
+  struct timeval tp;
+
+  if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
+    perror("gettimeofday");
+  return ((double) (tp.tv_sec)*1000000.0) +
+    (((double) tp.tv_usec) );
+#endif
+#endif
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "trace play usage");
+}
+extern void init_file_system (void)
+{
+	return;
+}
+
+void show_fhandle (nfs_fh3 * fhp)
+{
+	struct knfs_fh * kfhp = (struct knfs_fh *)fhp;
+
+	int dev;
+
+	if (quiet_flag)
+		return;
+		
+	RFS_ASSERT (kfhp->fh_version == 1);
+	RFS_ASSERT (kfhp->fh_fsid_type == 0);
+	RFS_ASSERT (kfhp->fh_auth_type == 0);
+
+	dev = ntohs(kfhp->fh_dev_major);
+	dev = dev<<8;
+	dev = dev + ntohs(kfhp->fh_dev_minor);
+
+	/* kfhp->fh_dev_ino hold the inode number of export point of the mounted
+	 * file system. For example, if /tmp/t1 is exported, /tmp/t1/t2 is mounted,
+	 * then fh_dev_ino hold the inode number of t1, not t2
+	 */
+
+	switch (kfhp->fh_fileid_type) {
+		case 0:
+			printf("fh:type 0 root dev 0x%x dev_ino %d\n", dev, kfhp->fh_dev_ino); 
+			break;
+		case 1:
+			printf("fh:type 1 %d %x dev %x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, dev, kfhp->fh_dev_ino);
+			break;
+		case 2:
+			printf("fh:type2 %d %x dirino %d dev 0x%x dev_ino %x\n", 
+				kfhp->fh_ino, kfhp->fh_generation, kfhp->fh_dirino, dev, kfhp->fh_dev_ino);
+			break;
+		default:
+			RFS_ASSERT (0);
+	}
+}
+
+nfs_fh3 zero_fhandle;
+int init_fh_map ()
+{
+	memset (fh_map, 0, sizeof (fh_map));
+	memset(fh_htable, 0, sizeof (fh_htable));
+	memset (&zero_fhandle, 0, sizeof(nfs_fh3));
+	printf ("SIZE of fh map %d KB\n", sizeof (fh_map)/1000);
+	fh_i = 0;
+}
+
+int add_fh (int map_flag, char * trace_fh, char * path, nfs_fh3 * play_fh)
+{
+	char * old_trace_fh;
+
+	/* first lookup if the entry for fh is already in the table */
+    struct generic_entry * p;
+
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (p) {
+		RFS_ASSERT (fh_map[p->key3].flag = FH_MAP_FLAG_PARTIAL);
+		RFS_ASSERT (map_flag ==FH_MAP_FLAG_COMPLETE);
+		fh_map[p->key3].flag = map_flag;
+		//RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+		if (memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE)) {
+			int i;
+			printf ("fh_map[%d].trace_fh %s trace_fh %s", p->key3, fh_map[p->key3].trace_fh, trace_fh);
+			for (i=0; i<fh_i; i++) {
+				int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+				int * p = (int *)fh_map[i].trace_fh;
+				printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+				printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+				 i, fh_map[i].trace_fh, fh_map[i].path,
+				 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+			}
+#endif
+			RFS_ASSERT (0);
+		}
+		RFS_ASSERT (!strcmp(fh_map[p->key3].path, path));
+		/* It's possible that in fh-path-map, many trace_fh are corresponding to one path
+		 * some of it may be the result of lookup after symlink, which is not handled
+		 * properly as new created objects 
+		 */
+#ifdef TAKE_CARE_SYMBOLIC_LINK
+		RFS_ASSERT (!memcmp(&fh_map[p->key3].play_fh, &zero_fhandle, sizeof(nfs_fh3)));
+#endif
+		memcpy (&fh_map[p->key3].play_fh, play_fh, sizeof (nfs_fh3));
+		if ((fh_map_debug==1)) // || (stage ==TRACE_PLAY_STAGE)) 
+			printf ("update the play_fh for trace_fh %s path %s \n", trace_fh, path);
+		return 0;
+	}
+
+	fh_map[fh_i].flag = map_flag;
+	fh_map[fh_i].lock = 0;
+	strncpy(fh_map[fh_i].trace_fh, trace_fh, TRACE_FH_SIZE);
+
+	RFS_ASSERT (strlen(path) < MAX_PLAY_PATH_SIZE);
+	strcpy (fh_map [fh_i].path, path);
+	if (map_flag==FH_MAP_FLAG_COMPLETE)
+		memcpy (&fh_map[fh_i].play_fh, play_fh, sizeof(nfs_fh3));
+	else 
+		memset (&fh_map[fh_i].play_fh, 0, sizeof(nfs_fh3));
+
+	if ((fh_map_debug==1)) { // || (stage ==TRACE_PLAY_STAGE)) {
+		printf ("insert trace_fh %s path %s play_fh:\n", trace_fh, path);
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			//show_fhandle(play_fh);
+		} else 
+			printf("null\n");
+	}
+
+/*
+	if (map_flag == FH_MAP_FLAG_DISCARD)
+		printf ("insert flag %d trace_fh %s path %s play_fh:\n", map_flag, trace_fh, path);
+*/
+
+    generic_insert(trace_fh, TRACE_FH_SIZE, fh_i, fh_htable, FH_HTABLE_SIZE);
+	
+	fh_i = (fh_i+1);
+	RFS_ASSERT (fh_i < FH_MAP_SIZE);
+
+    return 0;
+};
+
+inline fh_map_t * lookup_fh (char * trace_fh )
+{
+    struct generic_entry * p;
+    p = generic_lookup (trace_fh, TRACE_FH_SIZE, 0, fh_htable, FH_HTABLE_SIZE);
+	if (fh_map_debug==1)
+		printf ("lookup trace_fh %s\n", trace_fh);
+
+    if (p) {
+		if (fh_map_debug==1) {
+			printf ("found: fh_i[%d] trace_fh %s path %s play_fh:\n", p->key3, fh_map[p->key3].trace_fh, fh_map[p->key3].path);
+			//show_fhandle(&fh_map[p->key3].play_fh);
+		}
+		RFS_ASSERT (!memcmp(fh_map[p->key3].trace_fh, trace_fh, TRACE_FH_SIZE));
+        return (&(fh_map[p->key3]));
+    } else {
+		//printf ("lookup_fh %s not found\n", trace_fh);
+		if (stage != READ_DEP_TAB_STAGE && (fh_map_debug==1)) {
+			printf ("lookup not found trace_fh %s\n", trace_fh);
+		}
+        return NULL;
+	}
+	RFS_ASSERT (0);
+}
+
+int delete_fh (char * trace_fh, int fh_map_index)
+{
+    generic_delete (trace_fh, TRACE_FH_SIZE, fh_map_index, fh_htable, FH_HTABLE_SIZE);
+    return 0;
+};
+
+int lookup_init_filesystem (nfs_fh3 * parent, char * name, nfs_fh3 * result)
+{
+    LOOKUP3args		args;
+    LOOKUP3res		reply;		/* the reply */
+    enum clnt_stat	rpc_stat;	/* result from RPC call */
+    struct ladtime	start;
+    struct ladtime	stop;
+	static int i=0;
+
+    /* set up the arguments */
+    (void) memcpy((char *) &args.what.dir, (char *) parent,
+							sizeof (nfs_fh3));
+    args.what.name = name;
+    (void) memset((char *) &reply.resok.object, '\0', sizeof (nfs_fh3));
+
+    /* make the call */
+    sfs_gettime(&start);
+    rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP,
+			xdr_LOOKUP3args, (char *) &args,
+			xdr_LOOKUP3res, (char *) &reply,
+			Nfs_timers[Init]);
+    sfs_gettime(&stop);
+
+	if (rpc_stat !=RPC_SUCCESS) {
+		printf("rpc_stat %d\n", rpc_stat);
+		perror("");
+	}
+    RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+	(void) memcpy((char *) result, (char *) &reply.resok.object, sizeof (nfs_fh3));
+	return (reply.status);
+}
+
+void read_fh_map(char * fh_map_file)
+{
+	FILE * fp;
+	int i = 0;
+	char buf[1024];
+	char trace_fh[MAX_TRACE_FH_SIZE];
+	char intbuf[9];
+	char * trace_path;
+	char * p;
+	int map_flag;
+#define MAX_PATH_DEPTH 20
+	nfs_fh3 parents[MAX_PATH_DEPTH];
+	char * lookup_path_ptr[MAX_PATH_DEPTH];
+	char lookup_path [MAX_PLAY_PATH_SIZE];
+	int depth;
+	int new_dir_flag = 0;
+	int lineno = 0;
+
+	depth = 0;
+	memset(lookup_path_ptr, 0, sizeof(lookup_path_ptr));
+	memcpy(&parents[depth], &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+	strcpy(lookup_path, "/");
+	lookup_path_ptr[depth]=&lookup_path[0];
+
+	fp = fopen(fh_map_file, "r");
+	if (!fp) {
+		printf ("can not opern %s\n", fh_map_file);
+		perror("open");
+		exit (0);
+	}
+	RFS_ASSERT (fp!=NULL);
+	if (strstr(fh_map_file, "fmt1")) {
+		TRACE_FH_SIZE = 48;
+	}
+	
+	intbuf[8]=0;
+
+	memset(buf, 0, sizeof(buf));
+	while (fgets(buf, 1024, fp)) {
+		lineno ++;
+		if (fh_i % 10000==0)
+			printf("%d fh_map entry read\n", fh_i);
+
+		RFS_ASSERT (buf[strlen(buf)-1]=='\n');
+		buf[strlen(buf)-1]=0;
+		if (fh_map_debug) {
+			printf("%d fgets return %s\n", fh_i, buf);
+			printf("depth %d lookup_path %s\n", depth, lookup_path);
+		}
+		//for (i=0; i<=depth; i++) 
+			//printf("lookup_path_ptr[%d] %s ", i, lookup_path_ptr[i]);
+		//printf("\n");
+#ifdef COMPRESS_TRACE_FH 
+		for (i=0; i<TRACE_FH_SIZE/8; i++) {
+			strncpy(intbuf, buf+i*8, 8);
+			sscanf(intbuf, "%x", trace_fh+i*8); // maybe it should be 4, anyway we don't compress for now 
+		}
+		trace_path = buf+TRACE_FH_SIZE*2+1;		/* +1 the trace contains only initial file handle */
+#else
+		memcpy(trace_fh, buf, TRACE_FH_SIZE);
+		trace_path = buf + TRACE_FH_SIZE +1;
+#endif
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		trace_path = +=2;	/* +3 if the trace contains both initial and later created file handle */
+#endif
+
+#ifdef NO_DEPENDENCY_TABLE
+		if (!strncmp (trace_path, "DISCARD", 7) ||
+			!strncmp (trace_path, "LN", 2)			) {
+			map_flag = FH_MAP_FLAG_DISCARD;
+			add_fh (map_flag, buf, trace_path, 0);
+			continue;
+		}
+#endif
+		
+		p = trace_path+strlen(trace_path)-2;
+		while (*p!='/')
+			p--;
+		p++;
+		//RFS_ASSERT (p-trace_path<=strlen(lookup_path)+1);
+		//RFS_ASSERT (p>trace_path);
+
+		if (strncmp(lookup_path, trace_path, p-trace_path)) {
+			printf("strncmp lookup_path %s trace_path %s for length %d\n", lookup_path, trace_path, p-trace_path);
+		}
+		RFS_ASSERT (!strncmp(lookup_path, trace_path, p-trace_path));
+		//while (strncmp(lookup_path, trace_path, p-trace_path)) {	/* one step deeper */
+		while (strlen(lookup_path)>p-trace_path && depth>0) {
+			//printf("depth--\n");
+			if (depth<=0) 
+				printf ("lookup_path %s trace_path %s p-trace_path %d depth %d\n", lookup_path, trace_path, p-trace_path, depth);
+			RFS_ASSERT (depth>0);
+			*lookup_path_ptr[depth]=0;
+			lookup_path_ptr[depth]=0;
+			depth--;
+		}
+		RFS_ASSERT (strlen(lookup_path)==(p-trace_path) || (depth==0));
+
+
+#ifdef TRACE_CONTAIN_LATER_FHANDLE
+		if (buf[TRACE_FH_SIZE*2+1]=='Y') {
+			map_flag = FH_MAP_FLAG_COMPLETE;
+		} else {
+			map_flag = FH_MAP_FLAG_PARTIAL;
+			RFS_ASSERT (buf[TRACE_FH_SIZE*2+1]=='N');
+		}
+#else
+		map_flag = FH_MAP_FLAG_COMPLETE;
+#endif
+		if ((*(p+strlen(p)-1))=='/') {
+			*(p+strlen(p)-1)=0;
+			new_dir_flag = 1;
+		} else 
+			new_dir_flag = 0;
+
+		if (map_flag == FH_MAP_FLAG_COMPLETE) {
+			int ret = lookup_init_filesystem (&parents[depth], p, &parents[depth+1]);		
+			if (ret!=NFS3_OK) {
+				printf ("lineno %d %s\n", lineno, buf);
+			}
+ 			RFS_ASSERT (ret == NFS3_OK);
+			add_fh (map_flag, buf, trace_path, &parents[depth+1]);	
+		} else 
+			add_fh (map_flag, buf, trace_path, 0);
+
+		if (new_dir_flag) {
+			/* the new fhandle is of a directory */
+			lookup_path_ptr[depth+1] = lookup_path+strlen(lookup_path);
+			strcat (lookup_path, p);
+			strcat (lookup_path, "/");
+
+			//printf("depth++\n");
+			depth++;
+		}
+
+		memset(buf, 0, sizeof(buf));
+	}
+			
+	if (fh_map_debug) {
+		for (i=0; i<fh_i; i++) {
+			int * p1 = (int *)&(fh_map[i].play_fh);
+#ifdef COMPRESS_TRACE_FH
+			int * p = (int *)fh_map[i].trace_fh;
+			printf("fh_map[%d].trace_fh %8x%8x%8x%8x%8x%8x%8x%8x path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+#else
+			printf("fh_map[%d].trace_fh %s path %s \nnew_filehandle %8x%8x%8x%8x%8x%8x%8x%8x\n",
+			 i, fh_map[i].trace_fh, fh_map[i].path,
+			 *p1, *(p1+1), *(p1+2), *(p1+3), *(p1+4), *(p1+5), *(p1+6), *(p1+7));
+		}
+#endif
+
+		fprintf(stderr, "total %d requests \n", i);
+	}
+}
+
+int f()
+{
+	return 1;
+}
+
+inline free_biod_req (int biod_index)
+{
+	RFS_ASSERT (biod_reqp[biod_index].in_use == TRUE);
+	biod_reqp[biod_index].in_use = FALSE;
+	num_out_reqs --;
+}
+
+void finish_request (int biod_index, int dep_index, int status, int dep_flag)
+{
+	static int i = 0;
+	/* the ending operation, same as when a request time out */
+
+	dep_tab[dep_index].stop = biod_reqp[biod_index].stop;	/* RFS: to dump data */
+	free_biod_req (biod_index);
+
+	dep_tab[dep_index].status = status;
+
+	if (event_order_index < EVENT_ORDER_SIZE)
+		event_order[event_order_index++] = -dep_tab[dep_index].disk_index;
+
+	dep_tab[dep_index].flag = dep_flag;
+	if (is_dir_op(dep_tab[dep_index].proc)) {
+		int j;
+		RFS_ASSERT (dep_tab[dep_index].fh->lock = 1);
+		dep_tab[dep_index].fh->lock = 0;
+		if (dep_tab[dep_index].proc==RENAME)
+			dep_tab[dep_index].fh_2->lock = 0;
+		j = dep_tab[dep_index].fh-fh_map;
+		if (dependency_debug) {
+			printf ("fh_map[%d] is UNlocked\n",j);
+			printf ("trace_fh %d path %s\n", dep_tab[dep_index].fh->trace_fh, dep_tab[dep_index].fh->path);
+			printf ("trace_fh %d path %s\n", fh_map[j].trace_fh, fh_map[j].path);
+		}
+	}
+}
+
+/* the request argument may have pointers pointing to buffers, e.g. the name in lookup, 
+ * the target of symlink, the write data */
+char arg_res[MAX_ARG_RES_SIZE];
+char buf1 [MAX_BUF1_SIZE]; 
+char buf2 [MAX_BUF2_SIZE];
+
+int execute_next_request ()
+{
+	int dep_index;
+	int proc;
+	char * line;
+	struct biod_req * reqp;
+	sfs_op_type *op_ptr;		/* per operation info */
+	struct ladtime call_timeout;
+	static int last_print_time = -1;
+
+	if (num_out_reqs == max_biod_reqs) {
+		return -1;
+	}
+
+	start_profile (&valid_get_nextop_profile);
+	start_profile (&invalid_get_nextop_profile);
+	dep_index = get_nextop();
+	if (dep_index == -1) {
+		end_profile (&invalid_get_nextop_profile);
+		return dep_index;
+	};
+	end_profile (&valid_get_nextop_profile);
+
+	start_profile (&prepare_argument_profile);
+	line = dep_tab[dep_index].line;
+
+	if (per_packet_debug)
+		fprintf (stdout, "time %d processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+
+	end_profile(&total_profile);
+	if ((total_profile.in.tv_sec - last_print_time >= 10)) {
+		last_print_time = total_profile.in.tv_sec;
+		//fprintf (stdout, "time %d processing dep_tab[%d] disk_index %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, dep_index, dep_tab[dep_index].disk_index, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+/*
+		CYCLIC_PRINT (dep_tab_index);
+		{
+			int tmp = CYCLIC_MINUS(dep_tab_index.head,1,dep_tab_index.size);
+			printf("dep_tab_index.head-1 %d disk_index %d tail %d disk_index %d\n", tmp, dep_tab[tmp].disk_index,
+			dep_tab_index.tail, dep_tab[dep_tab_index.tail].disk_index);
+		}
+*/
+#ifdef TIME_PLAY
+#ifdef SPEED_UP
+/*
+		if (can_not_catch_speed_num < 2000) {
+			PLAY_SCALE ++;
+			printf ("set PLAY_SCALE to %d\n", PLAY_SCALE);
+		};
+		if (can_not_catch_speed_num > 50000) {
+			PLAY_SCALE /= 2;
+		} else {
+			if (can_not_catch_speed_num > 5000) {
+				PLAY_SCALE -= 2;
+				if (PLAY_SCALE < 1)
+					PLAY_SCALE = 1;
+			}
+		}
+*/
+#endif
+		if ((total_profile.in.tv_sec > 100)) {
+			can_not_catch_speed_num_total += can_not_catch_speed_num;
+		}
+		can_not_catch_speed_num = 0;
+#endif
+	}
+	if (rfs_debug)
+		printf ("processing dep_tab[%d] disk_index %d %s\n", dep_index, dep_tab[dep_index].disk_index, line);
+
+	proc = dep_tab[dep_index].proc;
+	rfs_Ops[proc].setarg (dep_index, line, arg_res, buf1, buf2);
+
+	op_ptr = &Ops[proc];
+	reqp = get_biod_req (dep_index);
+	RFS_ASSERT (reqp);
+
+#ifdef	notdef	/* place to set request timeout. G. Jason Peng */
+	call_timeout.sec = 2; //Nfs_timers[op_ptr->call_class].tv_sec;
+	call_timeout.usec = Nfs_timers[op_ptr->call_class].tv_usec;
+#else
+	call_timeout.sec = 0;
+	call_timeout.usec = 300000;
+	//call_timeout.usec = 14000;
+	//call_timeout.usec = 13000;
+	//call_timeout.usec = 6000;
+	//call_timeout.usec = 8000;
+	//call_timeout.usec = 10000;
+#endif
+
+    /* make the call */
+    sfs_gettime(&(reqp->start));
+	end_profile (&prepare_argument_profile);
+	start_profile (&biod_clnt_call_profile);
+#define REAL_PLAY
+#ifdef REAL_PLAY
+
+#ifdef RECV_THREAD
+	//printf ("send thread waitsem\n");
+	waitsem(async_rpc_sem);
+	//printf ("send thread got sem\n");
+#endif
+    reqp->xid = biod_clnt_call(NFS_client, rfs_Ops[proc].nfsv3_proc, 
+					rfs_Ops[proc].xdr_arg, arg_res);
+#ifdef RECV_THREAD
+	postsem(async_rpc_sem);
+	//printf ("send thread postsem\n");
+#endif
+
+#else	// REAL_PLAY
+	reqp->xid = dep_index+1;	/* just fake a message id and let it expire */
+#endif
+    RFS_ASSERT (reqp->xid != 0);
+    reqp->timeout = reqp->start;
+    ADDTIME (reqp->timeout, call_timeout);
+    dep_tab[dep_index].flag = DEP_FLAG_SENT;
+	if (event_order_index < EVENT_ORDER_SIZE)
+		event_order[event_order_index++] = dep_tab[dep_index].disk_index;
+
+	dep_tab[dep_index].start = reqp->start;	/* RFS: to dump data */
+	end_profile (&biod_clnt_call_profile);
+
+	send_num ++;
+}
+
+void check_reply (int proc, int biod_index, int dep_index, int status, char * errmsg, int trace_status)
+{
+	if (((status!=trace_status)) && (status!=NFS3_OK) && (trace_status!=NFS3ERR_RFS_MISS)) {
+		if (!profile_debug)
+			printf ("receive problem reply, xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d command disk index %d\n", biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec, dep_tab[dep_index].disk_index); 
+#ifndef TAKE_CARE_UNLOOKED_UP_NON_NEW_FILES
+		/* these files is not looked up and is not create/mkdir/symlink/link/mknod ed before they
+		 * are refered by name through rename, remove
+		 */
+		if ((proc==RENAME || proc==REMOVE) && (status==NFS3ERR_NOENT) && (trace_status ==0)) {
+			/* current initialization doesnot take care of rename source, if there is no
+			 * create or lookup before that source, the source object will not exist when
+			 * rename occurs
+			 */
+			rename_rmdir_noent_reply_num++;
+		} else 
+#endif
+#ifndef TAKE_CARE_SYMBOLIC_LINK
+		if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_status==NFS3ERR_NOENT)) {
+			/* in the original trace, first lookup return NOENT, then symlink is executed, then lookup return OK
+			 * the initialization considers only the lookup return OK and created the file in the initialization
+			 * so in trace play the first lookup return OK
+			 */
+			RFS_ASSERT (1);
+		} else // if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) && (trace_status == 0)) {
+				/* trace_status could be EAGAIN */
+			if ((proc==SYMLINK) && (status == NFS3ERR_EXIST) ) {
+			/* due to similar reason as above, the initialization code initializes the symbolic link as a normal
+			 * file already
+			 */
+			RFS_ASSERT (1);
+		} else
+#endif
+#ifndef TAKE_CARE_NOEMPTY_RMDIR
+		/* the remove packet seems got lost in the trace capture, so replay can not finish */
+		if ((proc==RMDIR) && (status==NFS3ERR_NOTEMPTY)) {
+   			RENAME3args		args;
+   			RENAME3res		reply;		/* the reply */
+			RMDIR3args * rmdir_argp;
+			enum clnt_stat rpc_stat;	/* result from RPC call */
+
+			rfs_Ops[proc].setarg (dep_index, dep_tab[dep_index].line, arg_res, buf1, buf2);
+			rmdir_argp = (RMDIR3args *)arg_res;
+
+			memcpy(&args.from, &(rmdir_argp->object), sizeof (diropargs3));
+			memcpy(&args.to.dir, &(Export_dir.fh_data->sfs_fh_un.f_fh3), sizeof(nfs_fh3));
+			args.from.name = buf1;	/* the buf1 is already filled when parsing rmdir */
+			args.to.name = buf2;
+			sprintf(buf2, "rmdir_%d_%s", dep_tab[dep_index].disk_index, rmdir_argp->object.name);
+
+  			rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME,
+			xdr_RENAME3args, (char *) &args,
+			xdr_RENAME3res, (char *) &reply,
+				Nfs_timers[Init]);
+			RFS_ASSERT (rpc_stat == RPC_SUCCESS);
+			if (reply.status!=NFS3_OK)
+				printf ("change rmdir into rename, reply.status %d\n", reply.status);
+			RFS_ASSERT (reply.status==NFS3_OK);
+			rmdir_not_empty_reply_num ++;
+#endif
+#ifndef TAKE_CARE_ACCESS_ERROR
+		} else if ((status==0) && (trace_status==NFS3ERR_ACCES)) {
+			loose_access_control_reply_num ++;
+#endif
+#ifdef NO_DEPENDENCY_TABLE 
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3_OK)) {
+			lookup_err_due_to_rename_num ++;
+		} else if ((proc==LOOKUP) && (status==NFS3_OK) && (trace_status == NFS3ERR_NOENT)) {
+			/* if there is a remove in front of the lookup, but it is
+ 			 * actually executed later than the lookup
+			 */
+			lookup_err_due_to_parallel_remove_num ++;
+#endif
+#ifndef TAKE_CARE_LOOKUP_EACCESS_ENOENT_MISMATCH
+		/* if the looked return EACCESS in the trace, means the object still exists
+		 * should have initialized, right not don't initialize it, hence play status 
+		 * could be ENOENT
+		 */
+		} else if ((proc==LOOKUP) && (status==NFS3ERR_NOENT) && (trace_status==NFS3ERR_ACCES)) {
+			lookup_eaccess_enoent_mismatch_num ++;
+#endif
+#ifdef TOLERANT_READ_IO_ERR
+		} else if ((proc==READ) && (status==NFS3ERR_IO) && (trace_status==NFS3_OK)) {
+			read_io_err_num ++;
+#endif
+#ifdef TOLERANT_STALE_FHANDLE_ERR
+		} else if ((status==NFS3ERR_STALE) && (trace_status==NFS3_OK)) {
+			printf ("!!!!!!! STALE FILE HANDLE \n");
+			//sleep(1);
+			stale_fhandle_err_num ++;
+#endif
+		} else {
+			int i;
+			for (i=dep_window_index.tail; CYCLIC_LESS(dep_window_index,i,dep_window_index.head); i++) {
+				if (dep_tab[i].flag!=1)
+					printf ("dep_tab[%d].disk_index %d, flag %d line %s\n", i, dep_tab[i].disk_index, dep_tab[i].flag, dep_tab[i].line);
+			}
+
+			if (status==EEXIST) {
+				abnormal_EEXIST_num ++;
+			} else if (status == ENOENT) {
+				abnormal_ENOENT_num ++;
+			} else {
+				printf ("!!!!!!!!!!!!!1 should fail\n");
+				//RFS_ASSERT (0);
+			}
+		}
+	} else {
+		proper_reply_num ++;
+		if (total_profile.in.tv_sec >= WARMUP_TIME) 
+			run_stage_proper_reply_num ++;
+	}
+
+}
+
+/* return -1 if there is no reply being received 
+ * return the dep_index if the corresponding reply has been received
+ */
+int receive_next_reply (int busy_flag)
+{
+	int dep_index;
+	int biod_index;
+	int proc;
+	char * line;
+	char * reply_line;
+	sfs_op_type *op_ptr;		/* per operation info */
+	int ret;
+	int status;
+	int trace_status;
+	char * errmsg;
+	int poll_timeout = 0;		/* timeout in usecs */
+
+	/* wait for reply */
+	start_profile (&valid_poll_and_get_reply_profile);
+	start_profile (&invalid_poll_and_get_reply_profile);
+
+	if (busy_flag == BUSY) {
+		poll_timeout = 0;
+		poll_timeout_0_num ++;
+	} else {
+		poll_timeout = 2000;	/* 10000 or 2000 is a better number in non-debugging state */
+		//poll_timeout = 0;	/* 10000 or 2000 is a better number in non-debugging state */
+		poll_timeout_pos_num ++;
+	}
+
+	biod_index = poll_and_get_reply (poll_timeout);
+	if (biod_index==-1) {
+		end_profile (&invalid_poll_and_get_reply_profile);
+		return -1;
+	};
+	end_profile (&valid_poll_and_get_reply_profile);
+
+	start_profile (&decode_reply_profile);
+	/* check the corresponding request */
+	dep_index = biod_reqp[biod_index].dep_tab_index;
+	if (biod_reqp[biod_index].in_use==1) {
+		RFS_ASSERT (dep_tab[dep_index].biod_req_index == biod_index);
+	} else {
+		printf ("biod_index %d reply received but the request has been time out\n", biod_index);
+		return -1;
+	}
+
+	proc = dep_tab[dep_index].proc;
+	op_ptr = &Ops[proc];
+
+	if (dep_tab[dep_index].flag != DEP_FLAG_SENT) {
+		printf("dep_tab[%d].flag %d proc %d status %d start %d:%d stop %d:%d\n",
+			dep_index, dep_tab[dep_index].flag, proc, dep_tab[dep_index].status, 
+			dep_tab[dep_index].start.sec, dep_tab[dep_index].start.usec,
+			dep_tab[dep_index].stop.sec, dep_tab[dep_index].stop.usec );
+		printf ("received reply for timeout requests dep_tab[%d].disk_index %d\n", dep_index, dep_tab[dep_index].disk_index);
+		return dep_index;
+	}
+	RFS_ASSERT (dep_tab[dep_index].flag == DEP_FLAG_SENT);
+
+	/* decode the reply */
+	rfs_Ops[proc].setres (arg_res, buf1);
+	ret = proc_header (NFS_client, rfs_Ops[proc].xdr_res, arg_res);
+	RFS_ASSERT (ret == RPC_SUCCESS);
+	status = *((int *)arg_res);
+	errmsg = nfs3_strerror (status);
+	end_profile (&decode_reply_profile);
+
+	start_profile (&check_reply_profile);
+	/* compare with the reply in the trace */
+	line = dep_tab[dep_index].line;
+	reply_line = dep_tab[dep_index].reply_line;
+	trace_status = dep_tab[dep_index].trace_status;
+
+	if (per_packet_debug || rfs_debug )
+		fprintf (stdout, "dep_tab[%d], disk_index %d, receive reply, rpc_ret %d xid %x nfs_ret %d %s trace_status %d start %d:%d stop %d:%d \n", dep_index, dep_tab[dep_index].disk_index, ret, biod_reqp[biod_index].xid, status, errmsg, trace_status, biod_reqp[biod_index].start.sec, biod_reqp[biod_index].start.usec, biod_reqp[biod_index].stop.sec, biod_reqp[biod_index].stop.usec);
+
+	/* error checking */
+	check_reply (proc, biod_index, dep_index, status, errmsg, trace_status);
+
+	/* free resources */
+	finish_request (biod_index, dep_index, status, DEP_FLAG_DONE);
+	recv_num ++;
+	
+	/* we set 100 seconds warm up time */
+	if ((total_profile.in.tv_sec >= WARMUP_TIME)) {
+	/* get statistics */
+	if (status == trace_status || (status==NFS3_OK && trace_status==NFS3ERR_RFS_MISS) ) {
+		op_ptr->results.good_calls++;
+		Ops[TOTAL].results.good_calls++;
+	} else {
+		op_ptr->results.bad_calls++;
+		Ops[TOTAL].results.bad_calls++;
+	}
+	sfs_elapsedtime (op_ptr, &(biod_reqp[biod_index].start), &(biod_reqp[biod_index].stop));
+	end_profile (&check_reply_profile);
+	}
+	
+	//start_profile (&add_create_object_profile);
+
+	if (trace_status == NFS3_OK && (proc==CREATE || proc==MKDIR || proc==SYMLINK || proc==MKNOD)) {
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+		RFS_ASSERT (reply_line);
+#endif
+		if (status!=NFS3_OK) {
+			/* commented out for 1022 */
+			printf ("!!!!!! Should have been an ASSERTION FAILURE \n");
+			RFS_ASSERT (proc==SYMLINK);
+			RFS_ASSERT (0);
+		} else {
+			if (proc!=SYMLINK || line[TRACE_VERSION_POS]!='2')
+				add_new_file_system_object(proc, dep_index, line, reply_line);
+		}
+	}
+	//end_profile (&add_create_object_profile);
+}
+
+inline void add_new_file_system_object (int proc, int dep_index, char * line, char * reply_line)
+{
+	char * child_trace_fh;
+	fh_map_t * parent_entryp;
+	char component_name[MAX_PLAY_PATH_SIZE];
+	char * parent_trace_fh;
+	char child_path[MAX_PLAY_PATH_SIZE];
+	post_op_fh3 * post_op_fh3_child;
+	char * reply_trace_fh;
+	nfs_fh3 * child_fh3;
+
+	parent_trace_fh = strstr (line, "fh");
+	RFS_ASSERT (parent_trace_fh);
+	parent_trace_fh +=3;
+	parent_entryp = lookup_fh (parent_trace_fh);
+	RFS_ASSERT (parent_entryp);
+	parse_name (parent_trace_fh+65, component_name);
+	strcpy (child_path, parent_entryp->path);
+	strcat (child_path, "/");
+	strcat (child_path, component_name);
+				
+	/* find the corresponding create request */
+	//printf ("before find reply trace_fh reply_line %s\n", reply_line);
+#ifdef REDUCE_MEMORY_TRACE_SIZE
+	reply_trace_fh = dep_tab[dep_index].reply_trace_fh;
+#else
+	reply_trace_fh = find_reply_trace_fh (reply_line);
+#endif
+	RFS_ASSERT (reply_trace_fh != NULL);
+	switch (proc) {
+	case CREATE:
+		RFS_ASSERT (((CREATE3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((CREATE3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKDIR:
+		RFS_ASSERT (((MKDIR3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKDIR3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case SYMLINK:
+		RFS_ASSERT (((SYMLINK3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((SYMLINK3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case MKNOD:
+		RFS_ASSERT (((MKNOD3res *)arg_res)->res_u.ok.obj.handle_follows==TRUE);
+		child_fh3 = &((MKNOD3res *)arg_res)->res_u.ok.obj.handle;
+		break;
+	case LOOKUP:
+		RFS_ASSERT (proc==LOOKUP);
+		child_fh3 = &((LOOKUP3res *)arg_res)->res_u.ok.object;
+		break;
+	default:
+		RFS_ASSERT (0);
+	}
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+	RFS_ASSERT (reply_trace_fh[TRACE_FH_SIZE]==' ');
+#endif
+	reply_trace_fh[TRACE_FH_SIZE] = 0;
+	add_fh (FH_MAP_FLAG_COMPLETE, reply_trace_fh, child_path, child_fh3); 	/* exist flag is not used now, set to 1 */
+#ifndef REDUCE_MEMORY_TRACE_SIZE
+	/* just to preserve the original reply line not changed */
+	reply_trace_fh[TRACE_FH_SIZE] = ' ';
+#endif
+}
+
+/* initialize timestamp and proc field of dep_tab entry */
+void trace_play(void)
+{
+	
+	/* The flag to indicate whether trace_player is BUSY. Trace_player is BUSY
+	 * when either there is request to send or there is reply being
+	 * received. Otherwise it is IDLE. The timeout for polling replies 
+	 * is set to 0 when BUSY, it is set to the waiting time to the first
+	 * request outside of current <min_dep_index, dep_window_max> window when IDLE.
+	 */
+   	int busy_flag = BUSY;		
+	//int dep_index;		/* index into dependency table: dep_tab */
+	//int biod_index; 	/* index into outstanding requests: biod_reqp */
+	static int last_print_time = -1;
+	int poll_timeout = 0;
+
+#ifndef IO_THREAD
+	disk_io_status = read_trace();
+#endif
+
+	RFS_ASSERT (!CYCLIC_EMPTY(dep_tab_index));
+	CYCLIC_MOVE_HEAD(dep_window_index);
+
+	adjust_play_window(busy_flag, &poll_timeout);
+
+	start_profile (&total_profile);
+	while (!CYCLIC_EMPTY(dep_tab_index)) {
+		end_profile(&total_profile);
+		if ((total_profile.in.tv_sec - last_print_time >= 10)) {
+			int i;
+
+			last_print_time = total_profile.in.tv_sec;
+			fprintf (stdout, ">>>> sendng thread: time %d send_num %d recv_num %d timeout_num %d num_out_reqs %d can_not_catch_speed_num %d PLAY_SCALE %d \n", total_profile.in.tv_sec, send_num, recv_num, timeout_num, num_out_reqs, can_not_catch_speed_num, PLAY_SCALE);
+			for (i=0; i<=MAX_OUTSTANDING_REQ; i++) {
+				if (num_out_reqs_statistics[i]!=0) {
+					printf("num_out_req[%d]=%d,", i, num_out_reqs_statistics[i]);
+					num_out_reqs_statistics[i]=0;
+				}
+			}
+			printf("\n");
+			for (i=0; i<=MAX_OUTSTANDING_REQ; i++) {
+				if (num_out_reqs_statistics_at_timeout[i]!=0) {
+					printf("num_out_req_at_timeout[%d]=%d,", i, num_out_reqs_statistics_at_timeout[i]);
+					num_out_reqs_statistics_at_timeout[i]=0;
+				}
+			}
+			printf("\n");
+			//	CYCLIC_PRINT(dep_tab_index);
+		}
+
+		if ((total_profile.in.tv_sec > 6000)) {
+			printf ("the process has run for more than 600 seconds, exit\n");
+			goto END;
+		}
+
+		if (busy_flag == IDLE) {
+#ifndef RECV_THREAD
+			//start_profile (&check_timeout_profile);
+			check_timeout();
+			//end_profile (&check_timeout_profile);
+#endif
+#ifndef IO_THREAD
+			if (disk_io_status!=TRACE_FILE_END) {
+				disk_io_status = read_trace();
+			};
+#endif
+		}
+
+		//start_profile (&adjust_play_window_profile);
+	 	adjust_play_window (busy_flag, &poll_timeout);
+		if (rfs_debug)
+			printf("num_out_reqs %d\n", num_out_reqs);
+		num_out_reqs_statistics[num_out_reqs]++;
+		busy_flag = IDLE;
+		//end_profile (&adjust_play_window_profile);
+
+		start_profile (&execute_next_request_profile);
+		while (execute_next_request()!=-1) {
+			busy_flag = BUSY;
+		}
+		end_profile (&execute_next_request_profile);
+
+#ifndef RECV_THREAD
+		start_profile (&receive_next_reply_profile);
+		/* actually the performance of two policy seems to be same */
+//#define SEND_HIGHER_PRIORITY_POLICY
+#define SEND_RECEIVE_EQUAL_PRIORITY_POLICY	
+
+#ifdef SEND_HIGHER_PRIORITY_POLICY
+		receive_next_reply(IDLE);
+#endif
+#ifdef SEND_RECEIVE_EQUAL_PRIORITY_POLICY
+		busy_flag = IDLE;
+		while (receive_next_reply(busy_flag)!=-1)
+			busy_flag = BUSY;
+#endif
+		end_profile (&receive_next_reply_profile);
+#endif
+		CYCLIC_ASSERT (0);
+	}
+	end_profile (&total_profile);
+
+	RFS_ASSERT (disk_io_status == TRACE_FILE_END);
+	if (num_out_reqs !=0 ) {
+		printf ("num_out_reqs %d\n", num_out_reqs);
+		CYCLIC_PRINT(dep_tab_index);
+	}
+	RFS_ASSERT(num_out_reqs==0);
+
+END:
+	printf ("trace starttime %d, trace_end_time %d trace_duration %d\n", trace_timestamp1, trace_timestamp2,
+		trace_timestamp2 - trace_timestamp1);
+	printf ("can_not_catch_speed_num_total %d can_not_catch_speed_num_last_10_seconds %d", 
+		can_not_catch_speed_num_total, can_not_catch_speed_num);
+	printf ("total_profile.about: %s\n", total_profile.about);
+	print_profile ("total_profile", &total_profile);
+	printf("\n");
+	//print_profile ("check_timeout", &check_timeout_profile);
+	//printf("\n");
+	//print_profile ("adjust_play_window", &adjust_play_window_profile);
+	//printf("\n");
+	print_profile ("execute_next_request_profile", &execute_next_request_profile);
+	print_profile ("valid_get_nextop_profile", &valid_get_nextop_profile);
+	print_profile ("invalid_get_nextop_profile", &invalid_get_nextop_profile);
+	print_profile ("prepare_argument_profile", &prepare_argument_profile);
+	print_profile ("biod_clnt_call_profile", &biod_clnt_call_profile);
+	printf("\n");
+	print_profile ("receive_next_reply_profile", &receive_next_reply_profile);
+	print_profile ("valid_poll_and_get_reply_profile", &valid_poll_and_get_reply_profile);
+	print_profile ("invalid_poll_and_get_reply_profile", &invalid_poll_and_get_reply_profile);
+	print_profile ("decode_reply_profile", &decode_reply_profile);
+	print_profile ("check_reply_profile", &check_reply_profile);
+	print_profile ("fgets_profile", &fgets_profile);
+	print_profile ("read_line_profile", &read_line_profile);
+	print_profile ("read_trace_profile", &read_trace_profile);
+	//print_profile ("add_create_object", &add_create_object_profile);
+	printf("\n");
+	
+	printf ("dep_tab_index.tail %d dep_tab_index.head %d num_out_reqs %d\n", dep_tab_index.tail, dep_tab_index.head, num_out_reqs);
+}
+
+
+int CYCLIC_SET_TAIL_TO(cyclic_index_t * index, int dest) 
+{ 
+	cyclic_index_t indextmp, indextmp2;
+	int oldnum, num;
+	indextmp = *index;
+	indextmp2 = indextmp;
+	oldnum = CYCLIC_NUM(indextmp); 
+
+	if (! ((dest>=0) && (dest<indextmp.size))) {
+		CYCLIC_PRINT(indextmp);
+		printf("dest %d\n", dest);
+	}
+	RFS_ASSERT ((dest>=0) && (dest<indextmp.size));
+	index->tail = dest; 
+	indextmp2.tail = dest;
+	num = CYCLIC_NUM(indextmp2); 
+
+	if (num > oldnum) { 
+		CYCLIC_PRINT(indextmp);
+		CYCLIC_PRINT(indextmp2);
+		printf("dest %d old_num %d num %d\n", dest, oldnum, num);
+	}
+	RFS_ASSERT (num <= oldnum);
+}
+
+int flush_junk()
+{
+	int i;
+	for (i=0; i<500; i++) {
+		printf ("*************************************************************\n");
+	}
+	fflush(stdout);
+}
+
+int CYCLIC_ASSERT (int i)
+{
+	int j;
+	if (!(dep_tab_index.tail == dep_window_index.tail)) {
+		printf("%s head %d tail %d, size %d\n", dep_tab_index.name, dep_tab_index.head, dep_tab_index.tail, dep_tab_index.size);
+		printf("%s head %d tail %d, size %d\n", dep_window_index.name, dep_window_index.head, dep_window_index.tail, dep_window_index.size);
+		printf("pos %d\n", i); 
+		flush_junk();
+		sleep (10);
+		RFS_ASSERT (0);
+	};
+ 
+	if (!((dep_window_index.head == dep_tab_index.head) || 
+		   CYCLIC_LESS(dep_tab_index, dep_window_index.head, dep_tab_index.head ) )) {
+		printf("%s head %d tail %d, size %d\n", dep_tab_index.name, dep_tab_index.head, dep_tab_index.tail, dep_tab_index.size);
+		printf("%s head %d tail %d, size %d\n", dep_window_index.name, dep_window_index.head, dep_window_index.tail, dep_window_index.size);
+		printf("pos %d\n", i); 
+		flush_junk();
+		sleep (10);
+		RFS_ASSERT (0);
+	};
+	for (i=0, j=0; i<max_biod_reqs; i++) {
+		if (biod_reqp[i].in_use == 1)
+			j++;
+	}
+#ifndef RECV_THREAD
+	RFS_ASSERT (num_out_reqs==j);
+#endif
+/*
+		RFS_ASSERT ((dep_window_index.head == dep_tab_index.head) || 
+			   CYCLIC_LESS(dep_tab_index, dep_window_index.head, dep_tab_index.head ));
+*/
+}
+
+/* sfs_c_chd.c */
diff --git a/TBBT/trace_play/sfs_c_clk.c b/TBBT/trace_play/sfs_c_clk.c
new file mode 100644
index 0000000..afe9a44
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_clk.c
@@ -0,0 +1,309 @@
+#ifndef lint
+static char sfs_c_clkSid[] = "@(#)sfs_c_clk.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_c_clk.c ---------------------
+ *
+ *      Clock handling.  Routines to read the clock, measure elapsed
+ *	time and sleep for a timed interval.
+ *
+ *.Exported_Routines
+ *	void sfs_gettime(struct ladtime	*)
+ *	void sfs_elapsedtime(sfs_op_type *, struct ladtime *,
+ *				struct ladtime *)
+ *	int msec_sleep(int)
+ *
+ *.Local_Routines
+ *	None.
+ *
+ *.Revision_History
+ *	05-Jan-92	Pawlowski	Added raw data dump hooks.
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+#include <sys/time.h>
+#include <sys/times.h>
+ 
+#include <sys/signal.h>
+
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+#if !(defined(USE_GETTIMEOFDAY) || defined(USE_TIMES))
+#define USE_GETTIMEOFDAY
+#endif
+
+#define CLK_RESOLUTION		10	/* clock resolution in msec */
+
+/*
+ * -------------------------  Clock Handling  -------------------------
+ */
+
+#if defined(USE_GETTIMEOFDAY)
+/*
+ * The time that the test first starts, all times are relative to this
+ * value to prevent integer overflows.
+ */
+extern struct ladtime	test_start = {0, 0, 0};
+
+/*
+ * Get the time of day, offset by 'tz_ptr', and return it in 'time_ptr'.
+ * This is a local time of day interface to allow support for system
+ * dependent clock resolution.
+ */
+void
+sfs_gettime(
+    struct ladtime	*time_ptr)
+{
+	time_t		t;
+	struct timeval	tv;
+
+	(void) gettimeofday(&tv, NULL);
+	/*
+	 * Use standard time function to get epoch time since 1970 for
+	 * setattr/create.
+	 */
+	t = time((time_t *)NULL);
+
+	if (test_start.sec == 0 && test_start.usec == 0) {
+		test_start.sec = tv.tv_sec;
+		test_start.usec = 0;
+	}
+	time_ptr->sec = tv.tv_sec - test_start.sec;
+	time_ptr->usec = tv.tv_usec;
+
+	time_ptr->esec = (int32_t)t;
+} /* sfs_gettime */
+#endif /* USE_GETTIMEOFDAY */
+
+#if defined(USE_TIMES)
+static uint32_t	test_start = 0;
+
+void
+sfs_gettime(
+	struct ladtime	*time_ptr)
+{
+	time_t		t;
+	uint32_t	clock_ticks;
+	struct tms	tms;
+	int32_t		ticks_per_sec = 100;
+
+	/*
+	 * Try use possible conversions from least accurate to most accurate
+	 */
+#if defined(HZ)
+	ticks_per_sec = HZ;
+#endif /* HZ */
+#if defined(CLK_TCK)
+	ticks_per_sec = CLK_TCK;
+#endif /* CLK_TCK */
+#if defined(_SC_CLK_TCK)
+	ticks_per_sec = sysconf(_SC_CLK_TCK);
+#endif /* _SC_CLK_TCK */
+
+	if ((clock_ticks = (uint32_t)times(&tms)) == -1) {
+		(void) fprintf(stderr, "%s: can't get time of day from system: %s\n",
+			sfs_Myname, strerror(errno));
+		(void) generic_kill(0, SIGINT);
+		exit(175);
+	}
+
+	/*
+	 * Use standard time function to get epoch time since 1970 for
+	 * setattr/create.
+	 */
+	t = time((time_t *)NULL);
+
+	if (test_start == 0) {
+		test_start = clock_ticks;
+	}
+
+	time_ptr->sec = (clock_ticks - test_start) / ticks_per_sec;
+	time_ptr->usec = ((clock_ticks - test_start) -
+					(time_ptr->sec * ticks_per_sec)) *
+					(1000000/ticks_per_sec);
+	time_ptr->esec = (int32_t)t;
+}
+#endif /* USE_TIMES */
+
+/*
+ * Compute the elapsed time between 'stop_ptr' and 'start_ptr', and
+ * add the result to the time acculated for operation 'op_ptr'.
+ */
+void
+sfs_elapsedtime(
+	sfs_op_type *	op_ptr,
+	struct ladtime *	start_ptr,
+	struct ladtime *	stop_ptr)
+{
+	double	msec2;
+	struct ladtime time_ptr1, time_ptr2;
+
+	/* get the elapsed time */
+	if (stop_ptr->usec >= 1000000) {
+		stop_ptr->sec += (stop_ptr->usec / 1000000);
+		stop_ptr->usec %= 1000000;
+	}
+
+	if (stop_ptr->usec < start_ptr->usec) {
+		stop_ptr->usec += 1000000;
+		stop_ptr->sec--;
+	}
+
+	if (stop_ptr->sec < start_ptr->sec) {
+		stop_ptr->sec = 0;
+		stop_ptr->usec = 0;;
+	} else {
+		stop_ptr->usec -= start_ptr->usec;
+		stop_ptr->sec -= start_ptr->sec;
+	}
+
+	/* count ops that take zero time */
+	if ((stop_ptr->sec == 0) && (stop_ptr->usec == 0))
+		op_ptr->results.fast_calls++;
+
+	/* add the elapsed time to the total time for this operation */
+
+	time_ptr1 = op_ptr->results.time;
+	time_ptr2 = *stop_ptr;
+
+	ADDTIME(time_ptr1, time_ptr2);
+
+	op_ptr->results.time = time_ptr1;
+	stop_ptr = &time_ptr2;
+
+	/* square the elapsed time */
+	msec2 = (stop_ptr->sec * 1000.0) + (stop_ptr->usec / 1000.0);
+	msec2 *= msec2;
+
+	/* add the squared elapsed time to the total of squared elapsed time */
+	op_ptr->results.msec2 += msec2;
+
+	/*
+	 * Log this point if logging is on. The (op_ptr - Ops)
+	 * calculation is a baroque way of deriving the "NFS Operation
+	 * code" we just executed--given available information.
+	 *
+	 * stop_ptr at this time contains the *elapsed* time, or
+	 * response time of the operation.
+	 */
+	 log_dump(start_ptr, stop_ptr, op_ptr - Ops);
+
+} /* sfs_elapsedtime */
+
+long cumulative_resets;
+long cumulative_adjusts;
+long msec_calls;
+/*
+ * Use select to sleep for 'msec' milliseconds.
+ * Granularity is CLK_RESOLUTION msec.
+ * Return the amount we actually slept.
+ */
+int
+msec_sleep(
+	int 		msecs)
+{
+	int		actual_msecs;
+	static long	cumulative_error_msecs = 0;
+	int		select_msecs;
+	struct timeval	sleeptime;
+	int		Saveerrno;
+	struct ladtime	start;
+	struct ladtime	end;
+
+	sfs_gettime(&start);
+
+	select_msecs = msecs + cumulative_error_msecs;
+        if (select_msecs < 0) {
+		sleeptime.tv_sec = 0;
+		sleeptime.tv_usec = 0;
+        } else {
+		sleeptime.tv_sec = select_msecs / 1000;
+		sleeptime.tv_usec = (select_msecs % 1000) * 1000;
+        }
+
+	/* sleep */
+	if (select(0, NULL, NULL, NULL, &sleeptime) == -1) {
+		if (errno != EINTR) {
+			Saveerrno = errno;
+			(void) fprintf(stderr, "%s: select failed ",
+								sfs_Myname);
+			errno = Saveerrno;
+			perror("select");
+			(void) generic_kill(0, SIGINT);
+			exit(176);
+		}
+	}
+	sfs_gettime(&end);
+
+	SUBTIME(end, start);
+	actual_msecs = ((end.sec * 1000) + (end.usec / 1000));
+
+	cumulative_error_msecs += (msecs - actual_msecs);
+	if(cumulative_error_msecs > 100 ||
+		cumulative_error_msecs < -100) /* Clip tops */
+	{
+			cumulative_error_msecs = 0;
+			cumulative_resets++;
+	}
+	else
+	{
+		if(cumulative_error_msecs != 0) 
+			cumulative_adjusts++;
+	}
+	msec_calls++;
+	return actual_msecs;
+} /* msec_sleep */
+
+
+/* sfs_c_clk.c */
diff --git a/TBBT/trace_play/sfs_c_clnt.c b/TBBT/trace_play/sfs_c_clnt.c
new file mode 100644
index 0000000..6c18e0d
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_clnt.c
@@ -0,0 +1,108 @@
+#ifndef lint
+static char sfs_c_clntSid[] = "@(#)sfs_c_clnt.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+#if !defined(_XOPEN_SOURCE)
+#include <sys/socket.h>
+#else
+#define	AF_INET		2
+#endif
+
+CLIENT *
+lad_clnt_create(int prot, struct hostent *hostent, uint32_t program,
+		uint32_t version, int sock, struct timeval *wait)
+{
+	struct sockaddr_in	sin;
+	CLIENT			*client_ptr;
+	uint_t			sendsz = 0;
+	uint_t			recvsz = 0;
+
+	/* set up the socket address for the remote call */
+	(void) memset((char *) &sin, '\0',  sizeof(sin));
+	(void) memmove((char *) &sin.sin_addr,
+			hostent->h_addr,
+			hostent->h_length);
+        sin.sin_family = AF_INET;
+
+	switch (prot) {
+	case 0:			/* UDP */
+		if (sendsz == 0)
+			client_ptr = sfs_cudp_create(&sin, program, version,
+						*wait, &sock);
+		else
+			client_ptr = sfs_cudp_bufcreate(&sin, program, version,
+						*wait, &sock,
+						sendsz, recvsz);
+		break;
+	case 1:			/* TCP */
+		sendsz = NFS_MAXDATA + 1024;
+		recvsz = NFS_MAXDATA + 1024;
+
+		client_ptr = sfs_ctcp_create(&sin, program, version, &sock,
+						sendsz, recvsz);
+		break;
+	}
+
+	if (client_ptr == ((CLIENT *) NULL)) {
+		char	buf[128];
+
+		(void) sprintf(buf, "%s: server not responding",
+                            sfs_Myname);
+		clnt_pcreateerror(buf);
+		return((CLIENT *) NULL);
+	}
+
+	return (client_ptr);
+}
diff --git a/TBBT/trace_play/sfs_c_dat.c b/TBBT/trace_play/sfs_c_dat.c
new file mode 100644
index 0000000..a5fc22e
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_dat.c
@@ -0,0 +1,339 @@
+#ifndef lint
+static char sfs_c_datSid[] = "@(#)sfs_c_dat.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ *
+ * ------------------------- sfs_c_dat.c --------------------------
+ *
+ *      Space declarations for sfs.
+ *
+ *.Revision_History
+ *      11-Jul-94	ChakChung Ng	Add codes for NFS/v3
+ *      24-Aug-92	Wittle		New file set access.
+ *      05-Jan-92	Pawlowski	Added hooks for raw data dump.
+ *      04-Dec-91	Bruce Keith	Include string.h for SYSV/SVR4.
+ *	17-May-90	Richard Bean	Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+
+/*
+ * -------------------------  NFS Operations  -------------------------
+ */
+
+/*
+ * RPC timeout values by call type.
+ * Index'ed by #defines in sfs_def.h.
+ */
+struct timeval *Nfs_timers;
+
+struct timeval Nfs_udp_timers[] = {
+
+	/* secs  usecs */
+	{  10,	  0 },		/* All commands during initialization phase */
+	{   1,	  0 },		/* Lookup during warmup and test run phases */
+	{   2,	  0 },		/* Read during warmup and test run phases */
+	{   3,	  0 },		/* Write during warmup and test run phases */
+};
+
+/*
+ * TCP is a "reliable" protocol so timeouts should never occur.  Set
+ * the values to be large enough to ensure all servers will respond
+ * but not too large so a broken implementation will still complete.
+ */
+struct timeval Nfs_tcp_timers[] = {
+
+	/* secs  usecs */
+	{  60,	  0 },		/* All commands during initialization phase */
+	{  60,	  0 },		/* Lookup during warmup and test run phases */
+	{  60,	  0 },		/* Read during warmup and test run phases */
+	{  60,	  0 },		/* Write during warmup and test run phases */
+};
+
+/*
+ * -----------------------  Transfer Size Distribution  -----------------------
+ *
+ * Over-the-wire transfer sizes are divided into 2 cases: read and write.
+ * For each case, a percentile rank determines the basic size unit of the
+ * transfer which is multiplied by a count to give the total size for the
+ * percentile.
+ *
+ * The block transfer size distribution is specified by a table of values.
+ * The first column gives the percent of operations that will be a
+ * specific block transfer size.  The second column gives the number of
+ * blocks units that will be transferred.  Normally the block unit size
+ * is 8KB.  The third column is a boolean specifying whether a trailing
+ * fragment block should be transferred.  The fragment size for each transfer
+ * is a random multiple of 1 KB, up to the block size - 1 KB.  Two tables
+ * are needed, one for read operation and one for write operations.  The
+ * following table gives the default distributions.
+ *
+ * 	Read  - Default Block Transfer Size Distribution Table
+ * percent   block count   fragment	resulting transfer (8KB block size)
+ * -------   -----------   --------	-----------------------------------
+ *    0        0             0 		 0%    1 -   7 KB
+ *   85        1             0 		85%    9 -  15 KB
+ *    8        2             1 		 8%   17 -  23 KB
+ *    4        4             1 		 4%   33 -  39 KB
+ *    2        8             1 		 2%   65 -  71 KB
+ *    1       16             1 		 1%  129 - 135 KB
+ *
+ * 	Write  - Default Block Transfer Size Distribution Table
+ * percent   block count   fragment	resulting transfer (8KB block size)
+ * -------   -----------   --------	-----------------------------------
+ *   49        0             1		49%    1 -   7 KB
+ *   36        1             1		36%    9 -  15 KB
+ *    8        2             1           8%   17 -  23 KB
+ *    4        4             1		 4%   33 -  39 KB
+ *    2        8             1		 2%   65 -  71 KB
+ *    1       16             1		 1%  129 - 135 KB
+ *
+ * The user may specify a a different distribution by using the '-b' option.
+ * The format for the block size distribution file consists of the first
+ * three columns given above: percent, block count, and fragment.  Read
+ * and write distribution tables are identified by the keywords "Read" and
+ * "Write".  An example input file, using the default values, is given below:
+ *
+ * 		Read
+ *		 0  0  0
+ *		85  1  0
+ *		 8  2  1
+ *		 4  4  1
+ *		 2  8  1
+ *		 1 16  1
+ *		Write
+ *		49  0  1
+ *		36  1  1
+ *		 8  2  1
+ *	         4  4  1
+ *               2  8  1
+ *               1 16  1
+ *
+ * A second parameter controlled by the block transfer size distribution table
+ * is the network transport packet size.  The distribution tables define the
+ * relative proportion of full blocks packets to fragment packets.  For
+ * instance, the default tables have been constructed to produce a specific
+ * distribution of ethernet packet sizes for i/o operations by controlling
+ * the amount of data in each packet.  The write packets produced consist
+ * of 50% 8-KB packets, and 50% 1-7 KB packets.  The read packets consist
+ * of 85% 8-KB packets, and 15% 1-7 KB packets.  These figures are
+ * determined by multiplying the percentage for the type of transfer by
+ * the number of blocks and fragments generated, and adding the totals.
+ * These conmputations are performed below for the default block size
+ * distribution tables:
+ *
+ * 		Read		blocks		fragments
+ *		 0  0  0	  0		  0
+ *		85  1  0	 85	  	  0
+ *		 8  2  1	 16       	  8
+ *		 4  4  1	 16	  	  4
+ *		 2  8  1	 16	  	  2
+ *		 1 16  1	 16	  	  1
+ *				---		---
+ *				149 (90%)	 15 (10%)
+ *
+ *		Write
+ *		49  0  1	  0		 49
+ *		36  1  1	 36		 36
+ *		 8  2  1	 16		  8
+ *	         4  4  1	 16		  4
+ *               2  8  1	 16		  2
+ *               1 16  1	 16		  1
+ *				---		---
+ *				100 (50%)	100 (50%)
+ *
+ *
+ */
+static sfs_io_op_dist_type Default_read_size_dist[] = {
+	/* percentile	8KB xfers	fragments 			*/
+	{	 0,	 0,		0 },	/*   0%    1 -   7 KB	*/
+	{	85,	 1,		0 },	/*  85%    8       KB	*/
+	{	93,	 2,		1 },	/*   8%   17 -  23 KB	*/
+	{	97,	 4,		1 },	/*   4%   33 -  39 KB	*/
+	{	99,	 8,		1 },	/*   2%   65 -  71 KB	*/
+	{      100,	16,		1 },	/*   1%  129 - 135 KB	*/
+};
+
+static sfs_io_op_dist_type Default_write_size_dist[] = {
+	/* percentile	8KB xfers	fragments 			*/
+	{	49,	 0,		1 },	/*  49%    1 -   7 KB	*/
+	{	85,	 1,		1 },	/*  36%    9 -  15 KB	*/
+	{	93,	 2,		1 },	/*   8%   17 -  23 KB	*/
+	{	97,	 4,		1 },	/*   4%   33 -  39 KB	*/
+	{	99,	 8,		1 },	/*   2%   65 -  71 KB	*/
+	{      100,	16,		1 },	/*   1%  129 - 135 KB	*/
+};
+
+static sfs_io_dist_type Default_io_dist = {
+	Default_read_size_dist,		/* read size distribution */
+	Default_write_size_dist,	/* write size distribution */
+	17,				/* max file size in Block_size units */
+	1.64,				/* average read ops / request */
+	2				/* average write ops / request */
+};
+
+sfs_io_file_size_dist Default_file_size_dist[] = {
+	/* percentage	KB size */
+	{	 33,	  1},			/* 33% */
+	{	 54,	  2},			/* 21% */
+	{	 67,	  4},			/* 13% */
+	{	 77,	  8},			/* 10% */
+	{	 85,	 16},			/*  8% */
+	{	 90,	 32},			/*  5% */
+	{	 94,	 64},			/*  4% */
+	{	 97,	128},			/*  3% */
+	{	 99,	256},			/*  2% */
+	{	100,   1024},			/*  1% */
+	{	  0,	  0}
+};
+
+/*
+ * -------------------------  Remote File Information  -------------------------
+ */
+int  Num_io_file_sizes;			/* # of different size of files */
+int  Num_io_files;			/* # of files used for i/o */
+int  Num_non_io_files;			/* # of non-i/o regular files */
+int  Num_dirs;				/* # of pre-created directories */
+int  Num_dir_files;			/* # of directories */
+int  Num_symlinks;			/* # of pre-created symlinks */
+int  Num_symlink_files;			/* # of symlinks  */
+
+int  Num_working_io_files;		/* # of i/o files in working set */
+int  Num_working_non_io_files;		/* # of non i/o files in working set */
+int  Num_working_dirs;			/* # of dirs in working set */
+int  Num_working_symlinks;		/* # of symlinks in working set */
+int  files_per_megabyte;		/* # of files created of each MB */
+
+
+sfs_io_dist_type *Io_dist_ptr=	 /* block transfer distribution info */
+			&Default_io_dist;
+
+sfs_fh_type		*Io_files;	/* list of i/o files  */
+sfs_fh_type		*Non_io_files;	/* list of non-i/o files */
+sfs_fh_type		*Dirs;		/* list of directories */
+sfs_fh_type		*Symlinks;	/* list of symlinks */
+
+sfs_fh_type	*Cur_file_ptr;		/* current file */
+char	Cur_filename[SFS_MAXNAMLEN];	/* current dir entry name */
+char	Filespec[SFS_MAXNAMLEN]	/* sprintf spec for file names */
+		     = "file_en.%05d";
+char	Dirspec[SFS_MAXNAMLEN]	/* sprintf spec for directory names */
+		     = "dir_ent.%05d";
+char	Symspec[SFS_MAXNAMLEN]	/* sprintf spec for symlink names */
+		     = "symlink.%05d";
+
+/*
+ * -------------------------  Run Parameters -------------------------
+ */
+
+int	nfs_version;
+sfs_phase_type	Current_test_phase;	/* current phase of the test */
+
+sfs_fh_type 	Export_dir;			/* filehandle for exported fs */
+CLIENT *	NFS_client;			/* RPC client handle */
+CLIENT * 	NFS_client_recv;	/* RPC client handle used for recv_thread */
+
+bool_t	Timed_run = TRUE;	       		/* Timed run or call target ? */
+int	Runtime = DEFAULT_RUNTIME;     		/* seconds in benchmark run */
+int	Warmuptime = DEFAULT_WARMUP;   		/* seconds to warmup */
+int	Access_percent = DEFAULT_ACCESS;        /* % of file set to access */
+int	Append_percent = DEFAULT_APPEND;        /* % of writes that append */
+int	Fss_delta_percent = DEFAULT_DELTA_FSS;	/* allowed change to file set */
+int	Kb_per_block = DEFAULT_KB_PER_BLOCK;	/* i/o pkt block sz in KB */
+int	Bytes_per_block = DEFAULT_KB_PER_BLOCK * 1024;/* i/o pkt sz in bytes */
+int	Num_failed_lookup = DEFAULT_FAILED_LOOKUP; /* percent failed lookups */
+int	Testop = -1;				/* test mode operation number */
+int	Interactive = 0;			/* test synchronized by user*/
+int	Populate_only = 0;			/* populate test dirs & quit */
+int	Debug_level = 0xFFFF;			/* debugging switch */
+
+
+/*
+ * ---------------------  Biod Simulation Variables ---------------------
+ */
+
+int	Biod_max_outstanding_writes = DEFAULT_BIOD_MAX_WRITE;
+int	Biod_max_outstanding_reads = DEFAULT_BIOD_MAX_READ;
+
+
+/*
+ * -------------------  File Set Size Control -------------------------
+ */
+
+int	avg_bytes_per_file = 136*1024;	/* calculated average file size */
+int 	Base_fss_bytes = 0;		/* base file set size in bytes */
+int	Most_fss_bytes = 0;		/* most bytes ever in file set */
+int	Least_fss_bytes = 0;		/* least bytes ever in file set */
+int	Limit_fss_bytes = 0;		/* target upper limit on fileset size */
+int	Cur_fss_bytes = 0;		/* bytes currently in file set */
+int	Total_fss_bytes = 0;		/* Total bytes created */
+
+
+/*
+ * -------------  Per Child Load Generation Rate Variables  -----------
+ */
+
+int	Msec_per_period;	/* total msec during the current run period */
+
+
+/*
+ * -------------------------  Miscellaneous  -------------------------
+ */
+
+struct ladtime	Cur_time;		/* current time of day */
+struct ladtime	Starttime;		/* start of test */
+int		start_run_phase = 0; 
+
+char	lad_hostname[HOSTNAME_LEN];
+/* sfs_c_dat.c */
diff --git a/TBBT/trace_play/sfs_c_def.h b/TBBT/trace_play/sfs_c_def.h
new file mode 100644
index 0000000..e35e73d
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_def.h
@@ -0,0 +1,634 @@
+#ifndef _sfs_c_def_h
+#define _sfs_c_def_h
+
+#define RFS
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * @(#)sfs_c_def.h	2.1	97/10/23
+ *
+ * -------------------------- sfs_c_def.h -----------------------
+ *
+ *      Literals and types for the sfs program.
+ *
+ *.Revision_History
+ *      Wittle          24-Aug-92     - New file set access code.
+ *      Bruce Keith     04-Dec-91     - Fix SVR4 definitions for NGROUPS.
+ *                                    - Include param.h/limits.h as
+ *                                      appropriate (BSD/SVR4).
+ *                                    - Use bcopy, bzero, bcmp for BSD;
+ *                                      memcpy, memset, memcmp for SYSV.
+ *      Richard Bean    17-May-90       Created.
+ */
+
+#include <sys/stat.h>
+
+#include <limits.h>
+
+#if !defined(_XOPEN_SOURCE)
+/*
+ * Some non-XOPEN_compilent systems are missing these definitions 
+ */
+#if !defined(SVR4)			/* Assume BSD */
+#include <sys/param.h>
+#endif /* SVR4 */
+#endif /* !_XOPEN_SOURCE */
+
+#include <sys/time.h>
+
+#if defined(SVR4)
+#include <sys/select.h>
+#endif
+
+#include "rpc/rpc.h"
+
+#if (defined (SVR4) || defined (AIX))
+#include <netinet/in.h>
+#endif
+
+#include <netdb.h>
+
+#define SFS_MIN_RES 		100		/* 100 usec resolution */
+#define	SFS_MAXNAMLEN		32		/* max test file name length */
+#define	SFS_MAXPATHLEN		1024		/* max test path name length */
+#define HOSTNAME_LEN		31		/* length of client's hostname */
+
+#include "sfs_c_nfs.h"
+
+/* --------------------------  Constants  ----------------------- */
+
+#define	SFS_VERSION_DATE	"11 July 2001"
+#define	SFS_VERSION_NUM		"3.0"
+
+/*
+ * Debugging levels
+ */
+#define	CHILD_TO_DEBUG		0	/* per child debugging uses child 0 */
+
+#define	DEBUG_NEW_CODE		(Debug_level & 0x00000001)		/* 1 */
+#define	DEBUG_PARENT_GENERAL	(Debug_level & 0x00000002)		/* 2 */
+#define	DEBUG_PARENT_SIGNAL	(Debug_level & 0x00000004)		/* 3 */
+#define	DEBUG_CHILD_ERROR	(Debug_level & 0x00000008)		/* 4 */
+#define	DEBUG_CHILD_SIGNAL	(Debug_level & 0x00000010)		/* 5 */
+#define	DEBUG_CHILD_XPOINT	(Debug_level & 0x00000020)		/* 6 */
+#define	DEBUG_CHILD_GENERAL	((Debug_level & 0x00000040) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 7 */
+#define	DEBUG_CHILD_OPS		((Debug_level & 0x00000080) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 8 */
+#define	DEBUG_CHILD_FILES	((Debug_level & 0x00000100) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 9 */
+#define	DEBUG_CHILD_RPC		((Debug_level & 0x00000200) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 10 */
+#define	DEBUG_CHILD_TIMING	((Debug_level & 0x00000400) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 11 */
+#define	DEBUG_CHILD_SETUP	((Debug_level & 0x00000800) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 12 */
+#define	DEBUG_CHILD_FIT		((Debug_level & 0x00001000) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 13 */
+#define	DEBUG_CHILD_BIOD	((Debug_level & 0x00002000) && \
+					(Child_num == CHILD_TO_DEBUG))	/* 14 */
+
+
+/*
+ * General constants for benchmark
+ */
+#define	DEFAULT_LOAD		60		/* calls per sec */
+#define	DEFAULT_CALLS		5000		/* number of calls */
+#define	DEFAULT_NPROCS		4		/* number of children to run */
+#define	DEFAULT_RUNTIME		(5 * 60)	/* runtime in seconds */
+#define	DEFAULT_WARMUP		(5 * 60)	/* warmup time in seconds */
+#define	DEFAULT_ACCESS		10		/* % of file set accessed */
+#define	DEFAULT_APPEND		70		/* % of writes that append */
+#define	DEFAULT_DELTA_FSS	10		/* % change to file set size */
+#define	DEFAULT_KB_PER_BLOCK	8		/* block xfer size in KB */
+#define DEFAULT_BYTES_PER_OP    (10*1024*1024)  /* bytes per unit load */
+#define	DEFAULT_NFILES		100		/* # of regular NON-IO files */
+#define	DEFAULT_FILES_PER_DIR	30		/* # of files per directories */
+#define	DEFAULT_NSYMLINKS	20		/* # of symlinks  */
+#define	DEFAULT_FAILED_LOOKUP	35		/* # of failed lookups  */
+
+#define	DEFAULT_WARM_RATE_CHECK	2		/* check progress each 2 secs */
+#define	DEFAULT_RUN_RATE_CHECK	10		/* check progress each 10 sec */
+#define	DEFAULT_MAX_BUFSIZE	NFS_MAXDATA	/* max buffer size for i/o */
+
+#define DEFAULT_BIOD_MAX_WRITE	2		/* max outstanding biod write */
+#define DEFAULT_BIOD_MAX_READ	2		/* max outstanding biod reads */
+#define MAX_BIODS		32
+
+
+/*
+ * For now we only read a fixed number of  files from a directory.  Ideally
+ * we would like to read a random number from 0-MAX but we will need a new
+ * workload.
+ */
+#define SFS_MAXDIRENTS	128
+
+/*
+ * If you change the default Chi_Sqr value,
+ * then also change the field label in the results print out.
+ */
+#define DEFAULT_CHI_SQR_CI	CHI_SQR_95	/* chi-sqr value to use */
+#define	CHI_SQR_90		2.71		/* chi-sqr value for 90% CI */
+#define	CHI_SQR_95		3.84		/* chi-sqr value for 95% CI */
+#define	CHI_SQR_975		5.02		/* chi-sqr value for 97.5% CI */
+#define	CHI_SQR_99		6.63		/* chi-sqr value for 99% CI */
+#define	CHI_SQR_995		7.88		/* chi-sqr value for 99.5% CI */
+
+/*
+ * NFS operation numbers
+ */
+#define	NULLCALL	0
+#define	GETATTR		1
+#define	SETATTR		2
+#define	ROOT		3
+#define	LOOKUP		4
+#define	READLINK	5
+#define	READ		6
+#define	WRCACHE		7
+#define	WRITE		8
+#define	CREATE		9
+#define	REMOVE		10
+#define	RENAME		11
+#define	LINK		12
+#define	SYMLINK		13
+#define	MKDIR		14
+#define	RMDIR		15
+#define	READDIR		16
+#define	FSSTAT		17
+#define ACCESS          18
+#define COMMIT          19
+#define FSINFO          20
+#define MKNOD           21
+#define PATHCONF        22
+#define READDIRPLUS     23
+#define	NOPS		(READDIRPLUS+1)		/* number of NFS ops */
+#define	TOTAL		NOPS			/* slot for totals */
+
+/*
+ * Constants for i/o distribution table
+ */
+#define IO_DIST_START   0
+#define IO_DIST_READ    1
+#define IO_DIST_WRITE   2
+
+/*
+ * Ratio of non_io_files that are initialized
+ * NOTE: initializing half the non-i/o files works ok with the
+ *    default op mix.  If the mix is changed affecting the
+ *    ratio of creations to removes, there may not be enough
+ *    empty slots for file creation (or there may not be
+ *    enough created during initialization to handle a lot of
+ *    removes that occur early in the test run), and this would
+ *    cause do_op() to fail to find a file appropriate for the
+ *    chosen op.  This will result in the global variable
+ *    Ops[op].no_calls being incremented (turn on child level
+ *    debugging to check this count), and the do_op() local
+ *    variable aborted_ops to be incremented and checked during
+ *    runtime for too many failures.
+ */
+#define	RATIO_NON_IO_INIT 0.5
+
+/*
+ *---------------------------- TCP stuff ---------------------
+ */
+
+#define	TCPBUFSIZE	1024 * 32 + 200
+
+/* --------------------------  Macros  ----------------------- */
+
+struct ladtime {
+        uint32_t    sec;         /* seconds */
+        uint32_t    usec;        /* and microseconds */
+        uint32_t    esec;        /* seconds since standard epoch */
+};
+
+#define SUBTIME(t1, t2) { \
+	if ((t1.sec < t2.sec) || \
+		((t1.sec == t2.sec) && (t1.usec < t2.usec))) { \
+		t1.sec = t1.usec = 0 ; \
+	} else { \
+		if (t1.usec < t2.usec) { \
+			t1.usec += 1000000; \
+			t1.sec--; \
+		} \
+		t1.usec -= t2.usec; \
+		t1.sec -= t2.sec; \
+	} \
+}
+
+#define	ADDTIME(t1, t2)	{if ((t1.usec += t2.usec) >= 1000000) {\
+				t1.sec += (t1.usec / 1000000); \
+				t1.usec %= 1000000; \
+			 } \
+			 t1.sec += t2.sec; \
+			}
+
+#define MINIMUM(a, b) ((a < b) ? (a) : (b))
+#define MAXIMUM(a, b) ((a > b) ? (a) : (b))
+
+#define MULTIME(t1, s) { \
+	t1.usec *=s; \
+	t1.sec *=s; \
+	if (t1.usec >= 1000000) {\
+		t1.sec += (t1.usec/1000000); \
+		t1.usec %= 1000000; \
+	}\
+	}
+#define DIVTIME(t1, s) { \
+	t1.usec += (t1.sec % s ) *1000000; \
+	t1.sec /= s; \
+	t1.usec /= s; \
+	}
+#define LARGERTIME(t1, t2) \
+ ((t1.sec>t2.sec) || ((t1.sec==t2.sec) && (t1.usec>t2.usec))) 
+
+/* --------------------------  Types  ----------------------- */
+
+/*
+ * SFS test phases.  Values are well-ordered for use of "<" operations.
+ */
+#define	Mount_phase      1  /* test directories are being mounted */
+#define	Populate_phase   2  /* files being created in the test directories */
+#define	Warmup_phase     3  /* reach steady state (load is being generated) */
+#define	Testrun_phase    4  /* timed test run (load is being generated) */
+#define	Results_phase    5  /* results collection and reporting */
+typedef int sfs_phase_type;
+
+/*
+ * Index constants for lookups into the RPC timer array.
+ */
+#define	Init	0
+#define	Lookup	1
+#define	Read	2
+#define	Write	3
+
+/*
+ * SFS results information structure
+ */
+typedef struct {
+	int		good_calls;	/* successful calls */
+	int		bad_calls;	/* failed (timed out) calls */
+	int 	timeout_calls;	/* RFS timeout calls */
+	int 		fast_calls;	/* calls that competed in 0 time */
+	struct ladtime	time; 		/* cumulative execution time */
+	double		msec2;		/* cumulative squared time - msecs**2 */
+} sfs_results_type;
+
+/*
+ * SFS information reported from child back to parent.
+ */
+typedef struct {
+	int			version;
+	sfs_results_type	results_buf[NOPS+1];
+	int			total_fss_bytes;
+	int			least_fss_bytes;
+	int			most_fss_bytes;
+	int			base_fss_bytes;
+} sfs_results_report_type;
+
+
+/*
+ * SFS operation information structure
+ */
+
+typedef struct {
+	char *		name;		/* operation name */
+	int		mix_pcnt;	/* percentage of call target */
+#ifndef RFS
+	int		(*funct)();	/* op routine */
+#endif
+	int		call_class;	/* call class: client handle & timeo */
+	int		target_calls;	/* number of calls to make */
+	int		no_calls;	/* # of times a call couldn't be made */
+	double		req_pcnt;	/* cumulative request percentile */
+	int		req_cnt;	/* number of requests made */
+	int		target_reqs;	/* number of req to be made */
+	sfs_results_type results;	/* test results */
+} sfs_op_type;
+
+
+/*
+ * Flags used with randfh
+ */
+#define RANDFH_TRUNC		0x01	/* pick a file to truncate */
+#define RANDFH_APPEND		0x02	/* pick a file to append to */
+
+/*
+ * SFS file information structure
+ * The particular values assiged are used to perform mod operations.
+ */
+#define	Sfs_io_file		0	/* read, write ops only (0) */
+#define	Sfs_non_io_file		1	/* other regular file ops only (1) */
+#define	Sfs_symlink		2	/* symlink ops only (2) */
+#define	Sfs_dir			3	/* dir ops only (3) */
+#define	Sfs_regular		4	/* any regular file (0,1) */
+#define	Sfs_non_dir		5	/* any non-directory file (0,1,2) */
+#define	Sfs_any_file		6	/* any file, link, or dir (0,1,2,3) */
+typedef int sfs_file_type;
+
+#define	Exists		1	/* op needs an object that already exists */
+#define	Nonexistent	2	/* op will create an object */
+#define	Empty_dir	3	/* op needs an empty directory */
+typedef char sfs_state_type;
+
+/*
+ * One file (dir, or symlink) in the file set.
+ */
+typedef struct sfs_fh_data {
+	union {
+		fhandle_t	f_fh2;            /* the NFS V2 file handle */
+		nfs_fh3		f_fh3;            /* the NFS V3 file handle */
+	} sfs_fh_un;
+	union {
+		fattr		a_attributes2;    /* its V2 attributes */
+		fattr3		a_attributes3;    /* its V3 attributes */
+	} sfs_fattr_un;
+	char                    file_name[SFS_MAXNAMLEN]; /* path component*/
+} sfs_fh_data;
+
+typedef struct sfs_fh_type {
+	struct sfs_fh_type	*dir;	        /* Parent Directory */
+	struct sfs_fh_data	*fh_data;	/* Data area */
+	int			size;		/* its size */
+	int			unique_num;	/* unique part of filename */
+	int			use_cnt;	/* count of op to this file */
+	int			xfer_cnt;	/* count of KB xfered */
+	sfs_state_type		state;		/* existence state */
+	char			working_set;	/* is in the working set */
+	char			initialize;	/* should be initialized */
+#define	attributes2	fh_data->sfs_fattr_un.a_attributes2
+#define	attributes3	fh_data->sfs_fattr_un.a_attributes3
+#define	fh2	fh_data->sfs_fh_un.f_fh2
+#define	fh3	fh_data->sfs_fh_un.f_fh3
+#define	file_name 	fh_data->file_name
+} sfs_fh_type;
+
+#define fh_size(fhptr)	(nfs_version == NFS_VERSION ? \
+						(fhptr)->attributes2.size : \
+						(fhptr)->attributes3.size._p._l)
+
+#define fh_uid(fhptr)	(nfs_version == NFS_VERSION ? \
+				(uint32_t)((fhptr)->attributes2.uid) : \
+				(uint32_t)((fhptr)->attributes3.uid))
+
+#define fh_gid(fhptr)	(nfs_version == NFS_VERSION ? \
+				(uint32_t)((fhptr)->attributes2.gid) : \
+				(uint32_t)((fhptr)->attributes3.gid))
+
+#define fh_mode(fhptr)	(nfs_version == NFS_VERSION ? \
+				(uint32_t)((fhptr)->attributes2.mode) : \
+				(uint32_t)((fhptr)->attributes3.mode))
+
+#define fh_isdir(fhptr)	(nfs_version == NFS_VERSION ? \
+				((fhptr)->attributes2.type == NFDIR) : \
+				((fhptr)->attributes3.type == NF3DIR))
+
+#define fh_isfile(fhptr) (nfs_version == NFS_VERSION ? \
+				((fhptr)->attributes2.type == NFREG) : \
+				((fhptr)->attributes3.type == NF3REG))
+
+/*
+ * One file (dir, or symlink) in the working file set.
+ */
+typedef struct {
+	int		range;		/* random access range for this file */
+	int		index;		/* points into actual file array */
+} sfs_work_fh_type;
+
+typedef struct {
+	sfs_work_fh_type	*entries;          /* array of working files */
+	int 			access_group_size; /* # files in a group */
+	int			access_group_cnt;  /* # groups in workset */
+	int 			max_range;	   /* access range of workset */
+} sfs_work_set_type;
+
+
+
+/*
+ * SFS file size distribution structures
+ */
+typedef struct {
+	int		pcnt;		/* percentile */
+	int		bufs;		/* Block_size KB xfers */
+	int		frags; 		/* boolean - is a frag present */
+} sfs_io_op_dist_type;
+
+typedef	struct {
+	sfs_io_op_dist_type	*read;		/* read size table */
+	sfs_io_op_dist_type	*write;		/* write size table */
+	int			max_bufs;	/* max # of Block_size xfers */
+	double		avg_ops_per_read_req;	/* avg read ops/req */
+	double		avg_ops_per_write_req;	/* avg write ops/req */
+} sfs_io_dist_type;
+
+typedef struct {
+	int		pcnt;		/* percentile */
+	int		size;		/* file size in KB */
+} sfs_io_file_size_dist;
+
+
+/* sfs child processes synchronization logfile */
+#define	CHILD_SYNC_LOG	"/tmp/sfs_log"
+#define	SFS_PNT_PID	"/tmp/sfs_pnt_pid"
+#define	SFS_PRM_PID	"/tmp/sfs_prm_pid"
+#define	SFS_SYNCD_PID	"/tmp/sfs_syncd_pid"
+
+/*
+ * Values for invalid runs
+ */
+#define INVALID_UNKNOWN		1	/* Old value reserved as unknown */
+#define INVALID_IODIST		2
+#define INVALID_MIX		3
+#define INVALID_RUNTIME		4
+#define INVALID_ACCESS		5
+#define INVALID_APPEND		6
+#define INVALID_KB		7
+#define INVALID_NDIRS		8
+#define INVALID_FSS		9
+#define INVALID_BIODREAD	10
+#define INVALID_NSYMLINKS	11
+#define INVALID_BIODWRITE	12
+#define INVALID_WARMUP		13
+#define INVALID_GOODCALLS	14
+#define INVALID_FAILEDRPC	15
+#define INVALID_NOTMIX		16
+#define INVALID_MAX		(INVALID_NOTMIX + 1)
+
+/*
+ * External variable declarations
+ */
+extern int		Access_percent;
+extern int		Append_percent;
+extern int		Base_fss_bytes;
+extern int		Biod_max_outstanding_reads;
+extern int		Biod_max_outstanding_writes;
+extern int		Bytes_per_block;
+extern int		Child_num;
+extern int		Client_num;
+extern sfs_fh_type	*Cur_file_ptr;
+extern char		Cur_filename[];
+extern gid_t		Cur_gid;
+extern struct ladtime	Cur_time;
+extern uid_t		Cur_uid;
+extern sfs_phase_type	Current_test_phase;
+extern int		Debug_level;
+extern sfs_io_file_size_dist Default_file_size_dist[];
+extern sfs_fh_type	*Dirs;
+extern uint32_t		Dump_count;
+extern int		dump_create_existing_file;
+extern int		Dump_data;
+extern uint32_t		Dump_length;
+extern uint32_t		Dump_offset;
+extern int		dump_truncate_op;
+extern sfs_fh_type	Export_dir;
+extern char		Filespec[];
+extern char		Dirspec[];
+extern char		Symspec[];
+extern int		avg_bytes_per_file;
+extern int		files_per_megabyte;
+extern int		Fss_delta_percent;
+extern int		Interactive;
+extern sfs_io_dist_type * Io_dist_ptr;
+extern sfs_fh_type	*Io_files;
+extern int		Kb_per_block;
+extern char *		sfs_Myname;
+extern int		Least_fss_bytes;
+extern int		Limit_fss_bytes;
+extern int		Cur_fss_bytes;
+extern int		Total_fss_bytes;
+extern int		Log_fd;
+extern char		Logname[];
+extern int		Most_fss_bytes;
+extern int		Msec_per_period;
+extern CLIENT *		NFS_client;
+extern CLIENT *		NFS_client_recv;
+extern struct timeval	*Nfs_timers;
+extern struct timeval	Nfs_udp_timers[];
+extern struct timeval	Nfs_tcp_timers[];
+extern int		nfs_version;
+extern sfs_fh_type	*Non_io_files;
+extern int		Num_dirs;
+extern int		Num_dir_files;
+extern int		Num_failed_lookup;
+extern int		Num_io_files;
+extern int		Num_non_io_files;
+extern int		Num_symlinks;
+extern int		Num_symlink_files;
+extern int		Num_working_dirs;
+extern int		Num_working_io_files;
+extern int		Num_working_non_io_files;
+extern int		Num_working_symlinks;
+extern sfs_op_type	*Ops;
+extern int		Populate_only;
+extern char *		Prime_client;
+extern uid_t		Real_uid;
+extern int		Runtime;
+extern struct ladtime	Starttime;
+extern int		start_run_phase;
+extern sfs_fh_type	*Symlinks;
+extern int		Tcp;
+extern int		Testop;
+extern int		Files_per_dir;
+extern int		Tot_client_num_io_files;
+extern int		Tot_client_num_non_io_files;
+extern int		Tot_client_num_symlinks;
+extern int		Timed_run;
+extern int		Validate;
+extern int		Warmuptime;
+extern char		*invalid_str[];
+extern char		lad_hostname[];
+
+
+/*
+ * External function declarations
+ */
+extern int	biod_init(int, int);
+extern void	biod_term(void);
+extern void	biod_turn_on(void);
+extern int	check_access(struct stat *);
+extern int	check_fh_access(sfs_fh_type *);
+extern void	child(int, int, float, int, char **);
+extern void	generic_catcher(int);
+extern int	generic_kill(int, int);
+extern void	init_counters(void);
+extern void	init_fileinfo(void);
+extern void	init_mount_point(int, char *, CLIENT *);
+extern void	init_ops(void);
+extern char *	init_write_buffer(void);
+extern CLIENT * lad_getmnt_hand(char *);
+extern CLIENT *	lad_clnt_create(int, struct hostent *, uint32_t,
+			uint32_t, int, struct timeval *);
+extern char *	lad_timestamp(void);
+extern int	set_debug_level(char *s);
+extern void	sfs_alarm(int);
+extern void	sfs_cleanup(int);
+extern void	sfs_elapsedtime(sfs_op_type *, struct ladtime *,
+                                struct ladtime *);
+extern void	sfs_gettime(struct ladtime  *);
+extern int32_t	sfs_random(void);
+extern void	sfs_srandom(int);
+extern int	init_rand_range(int);
+extern int	rand_range(int);
+extern void	sfs_startup(int);
+extern void	sfs_stop(int);
+extern void	log_dump(struct ladtime *, struct ladtime *, int);
+extern void	parent(int, int, char *, char *);
+extern void	print_dump(int, int);
+extern sfs_fh_type *
+		randfh(int, int, uint_t, sfs_state_type, sfs_file_type);
+extern int	msec_sleep(int);
+extern void	Validate_ops(int, char **);
+
+/* Reliable RPC functions for initialization */
+extern int	lad_lookup(sfs_fh_type *, char *);
+extern int	lad_remove(sfs_fh_type *, char *);
+extern int	lad_rmdir(sfs_fh_type *, char *);
+extern int	lad_symlink(sfs_fh_type *, char *, char *);
+extern int	lad_mkdir(sfs_fh_type *, char *);
+extern int	lad_write(sfs_fh_type *, int32_t, int32_t);
+extern int	lad_create(sfs_fh_type *, char *);
+extern int	lad_truncate(sfs_fh_type *, int32_t);
+
+/* RFS: moved the definition from sfs_c_bio.c to here because it is used in 
+ * sfs_c_chd.c in the new code, information associated with outstanding requests
+ */
+struct biod_req {
+    uint32_t		xid;		/* RPC transmission ID	*/
+    bool_t		in_use;		/* Indicates if the entry is in use */
+	int	dep_tab_index;			/* corresponding index in dep_tab */
+    unsigned int	count;		/* Count saved for Dump routines */
+    unsigned int	offset;		/* Offset saved for Dump routines */
+    struct ladtime	start;		/* Time RPC call was made */
+    struct ladtime	stop;		/* Time RPC reply was received */
+    struct ladtime	timeout;	/* Time RPC call will time out */
+};
+
+#endif /* sfs_def.h */
diff --git a/TBBT/trace_play/sfs_c_dmp.c b/TBBT/trace_play/sfs_c_dmp.c
new file mode 100644
index 0000000..82d9a38
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_dmp.c
@@ -0,0 +1,298 @@
+#ifndef lint
+static char sfs_c_dmpSid[] = "@(#)sfs_c_dmp.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_c_dmp.c ---------------------
+ *
+ *      Raw data dump routines for SFS.
+ *
+ *	The routines contained here capture and dump the raw data
+ *	points (operation, response time) to allow the researcher
+ *	to perform detailed analysis on the response time characteristics
+ *	of an NFS server.
+ *
+ *.Exported Routines
+ *	void log_dump(ladtime *, ladtime *, int)
+ *	void print_dump(int, int)
+ *
+ *.Local Routines
+ *	None.
+ *
+ *.Revision_History
+ *	11-Jul-94	ChakChung Ng	Add codes for NFS/v3
+ *	03-Feb-92	0.0.20 Pawlowski
+ *					Use of "Current_test_phase"
+ *					obviates need for dump init
+ *					routine, so it has been deleted.
+ *	10-Jan-92	0.0.19 Teelucksingh
+ *					Changed dump file names to be
+ *					< 14 chars. Added header to
+ *					output.
+ *      04-Jan-92	0.0.18 Pawlowski
+ *					Added raw data dump code.
+ */
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include "sfs_c_def.h"
+
+struct savedata {
+    struct savedata	*next;
+    int32_t	rtv_sec;	/* The response time */
+    int32_t	rtv_usec;
+    int32_t	stv_sec;	/* The start time */
+    int32_t	stv_usec;
+    uint32_t	count;		/* Used only for read and write */
+    uint32_t	offset;		/* Used only for read and write */
+    uint32_t	length;		/* Used only for read and write */
+    uint16_t	unique_num;	/* unique id for file */
+    unsigned int flags;		/* Things like whether truncating, etc. */
+    int16_t	op;
+};
+
+uint32_t	Dump_count;	/* place to put read and write count */
+uint32_t	Dump_offset;	/* place to put r/w offset */
+uint32_t	Dump_length;	/* place to put r/w offset */
+int		Dump_data;	/* Flag set by command line option */
+int		dump_create_existing_file = FALSE;
+int		dump_truncate_op = FALSE;
+
+/*
+ * ----------------------  Static Declarations  ----------------------
+ */
+
+static struct savedata *saveary = 0;
+
+/*
+ * --------------------------  Constants  --------------------------
+ */
+
+/* flags bit values */
+#define CREATE_OF_EXISTING_FILE	0x0001
+#define TRUNCATE_OPERATION	0x0002
+
+/*
+ * ----------------------  Dump Routines  ----------------------
+ */
+
+/*
+ * log_dump()
+ *
+ * This function is called on the completion of every operation
+ * to log the data point. We log the operation and the elapsed time
+ * (storing the microsecond component also).
+ *
+ * The data is kept in a singly linked list, elements dynamically
+ * allocated as needed.
+ *
+ * Dynamic allocation of elements using malloc and single link list
+ * pointer adds overhead to the storage space for the data for each
+ * point. Dynamic allocation can result in system calls to get more
+ * space for elements, adding to execution overhead. However, if you're
+ * doing a raw data dump run, you assume costs are negligible.
+ */
+
+void
+log_dump(
+    struct ladtime *start,
+    struct ladtime *elapsed,
+    int op)
+{
+    static struct savedata *saveptr = 0;
+
+    if (!Dump_data || Current_test_phase != Testrun_phase)
+	return;
+
+    if (saveary == (struct savedata *)NULL) {
+	if ((saveary = (struct savedata *)
+			malloc(sizeof(struct savedata)))
+				== (struct savedata *)NULL) {
+	    (void) fprintf(stderr, "Unable to allocate dump element\n");
+	    return;
+	}
+	saveptr = saveary;
+    } else {
+	if ((saveptr->next = (struct savedata *)
+			malloc(sizeof(struct savedata)))
+				== (struct savedata *)NULL) {
+	    (void) fprintf(stderr, "Unable to allocate dump element\n");
+	    return;
+	}
+	saveptr = saveptr->next;
+    }
+    saveptr->next = (struct savedata *)NULL;
+    saveptr->flags = 0;
+    saveptr->op = op;
+    saveptr->rtv_sec = elapsed->sec;
+    saveptr->rtv_usec = elapsed->usec;
+    saveptr->stv_sec = start->sec;
+    saveptr->stv_usec = start->usec;
+    saveptr->unique_num = Cur_file_ptr->unique_num;
+    if (op == NFSPROC3_READ || op == NFSPROC3_WRITE ||
+	op == NFSPROC_READ || op == NFSPROC_WRITE) {
+	saveptr->count = (uint16_t) Dump_count;
+	saveptr->offset = Dump_offset;
+	saveptr->length = Dump_length;
+    }
+
+    if (dump_create_existing_file == TRUE) {
+	saveptr->flags |= CREATE_OF_EXISTING_FILE;
+	dump_create_existing_file = FALSE;
+    }
+
+    if (dump_truncate_op == TRUE) {
+	saveptr->flags |= TRUNCATE_OPERATION;
+	dump_truncate_op = FALSE;
+    }
+}
+
+/*
+ * print_dump()
+ *
+ * Dumps the raw data to a file in the format:
+ *
+ *	opcode	sec.msec  sec.msec file-unique-id <length> <offset> <count>
+ *	opcode	sec.msec  sec.msec file-unique-id
+ *	     . . .
+ *
+ * The opcode is the numeric NFS operation code as defined in the
+ * NFS protocol specification. The first "sec.msec" field is the
+ * response time of the operation. The second "sec.msec" field
+ * is the start time of the operation. For read and write calls,
+ * the "length", "offset" and "count" from the operation arguments are put out
+ * as the fourth, fifth, and sixth field.
+ *
+ * This simple (x, y) pairing should be suitable input for a wide variety
+ * of plotting programs.
+ *
+ * Note that the raw data is precious! Several points to be observed:
+ *
+ *	1. The raw data for each individual child is dumped to
+ *	   its own data file. So each individual child process
+ *	   data can be inspected (possibly useful to debug client
+ *	   load generation per child process anomalies).
+ *
+ *	2. More importantly, each raw data dump file presents
+ *	   the operations generated by the child in their exact
+ *	   order of generation. This can be used to analyze possible
+ *	   time dependent behaviour of the server.
+ *
+ * Client process output files can be merged for analysis using cat(1).
+ *
+ * If any other data (additional fields) are added to raw data dump
+ * file, please add those fields after primary fields. awk(1) scripts
+ * and the like can be used to re-arrange data files, but it would
+ * be nice if the primary (x, y) data points are the default format.
+ */
+
+void
+print_dump(
+    int clientnum,
+    int childnum)
+{
+    char buf[256];
+    FILE *datap;
+    struct savedata *p = saveary;
+
+    buf[0] = 0;
+
+    if (!Dump_data)
+	return;
+
+    /*
+     * We write raw data files to the /tmp directory, and
+     * the manager will retrieve to the prime client.
+     *
+     * Removed preladraw prefix from file names to fit
+     * in 14 chars - K.T.
+     */
+
+    (void) sprintf(buf, "/tmp/c%3.3d-p%3.3d", clientnum, childnum);
+
+    if ((datap = fopen(buf, "w")) == NULL) {
+	(void) fprintf(stderr, "couldn't open %s for writing\n", buf);
+	return;
+    }
+
+    (void) fprintf(datap,"%s\n%s\n%s\n%s\n",
+"-----------------------------------------------------------------------------",
+"         Op Response           Start         Unique  File",
+"       Code     Time            Time        File Id  Length  Offset  Size",
+"-----------------------------------------------------------------------------");
+
+    p = saveary;
+    while(p) {
+	(void) fprintf(datap, "%11s %8.3f %19.3f %8d",
+		Ops[p->op].name,
+		(p->rtv_sec * 1000.0) + (p->rtv_usec / 1000.0),
+		(p->stv_sec * 1000.0) + (p->stv_usec / 1000.0),
+		p->unique_num);
+	if (p->op == NFSPROC3_READ || p->op == NFSPROC3_WRITE ||
+		p->op == NFSPROC_READ || p->op == NFSPROC_WRITE) {
+	    (void) fprintf(datap,
+		" %8d %8d %5d\n", p->length, p->offset, p->count);
+	}
+	else if (p->op == NFSPROC3_SETATTR || p->op == NFSPROC3_CREATE ||
+		p->op == NFSPROC_SETATTR || p->op == NFSPROC_CREATE) {
+	    if (p->flags & TRUNCATE_OPERATION) {
+		(void) fprintf(datap, "  %s", "TRUNCATE");
+	    }
+	    if (p->flags & CREATE_OF_EXISTING_FILE) {
+		(void) fprintf(datap, "  %s", "CREATE_EXISTING");
+	    }
+	    (void) fprintf(datap, "\n");
+	}
+	else {
+		(void) fprintf(datap, "\n");
+	}
+	p = p->next;
+    }
+
+    (void) fprintf(datap,
+"-----------------------------------------------------------------------------\n\n");
+    (void) fclose(datap);
+}
diff --git a/TBBT/trace_play/sfs_c_man.c b/TBBT/trace_play/sfs_c_man.c
new file mode 100644
index 0000000..33bf28a
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_man.c
@@ -0,0 +1,1998 @@
+#ifndef lint
+static char sccsid_hp[] = "@(#)sfs_c_man.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*
+ * Generates an artifical NFS client load based on a given mix of operations,
+ * and block transfer distribution.
+ *
+ * Usage: sfs [-l load] [-p procs] [-w warmup] [-t time]
+ *               [-m mix_file] [-B block_size] [-b blocksz_file]
+ *		 [-f file_set_delta] [-a access_pnct]
+ *		 [-A append_pcnt] [-D dir_cnt] [-F file_cnt] [-S symlink_cnt]
+ *		 [-d debug_level] [-i] [-P] [-T op_num]
+ *		 [-V validation_level] [-z] [-Q]
+ *		 [-R biod_reads] [-W biod_writes]
+ *		 [-M prime_client_hostname] [-N client_cnt]
+ *
+ * NOTE: REFER TO SFS MAN PAGE (sfs.1) FOR A DESCRIPTION OF ALL
+ * 	 SFS OPTIONS
+ *
+ *
+ * Single Client Options
+ *
+ * option	   description				 	    default
+ * --------------- ------------------------------------------------ -----------
+ * -a access_pcnt  % of file set to access 			    20% access
+ * -A append_pcnt  % of writes that append rather than overwrite    70% append
+ * -b blocksz_file file specifying distribution of block xfer sizes (see below)
+ * -B block_size   # of KB in block, up to 8 KB			    8 KB
+ * -Q              Do TCP connection for NFS rather than UDP        off
+ * -d debug_level  debug level (higher number gives more output)    off
+ * -D dir_cnt	   # directories used for directory operations      20 dirs
+ * -f fileset_delta % change in file set size allowed               10%
+ * -F file_cnt	   # files used for read and write operations	    100 files
+ * -i 		   interactive; wait for input before starting test off
+ * -l load	   # NFS calls/second to generate from each client  60 calls/sec
+ * -m mix_file	   file specifying NFS call distribution	    (see below)
+ * -p procs	   # processes used to generate load on each client 7 procs
+ * -P		   populate test directories, but don't run a test  off
+ * -R biod_reads   max # of outstanding read requests at one time   2 reqs
+ * -S symlink_cnt  # symbolic links used for symlink operations     20 symlinks
+ * -t time	   # seconds to generate load for the timed test    600 secs
+ * -T op_num	   test the NFS operation specified one time        off
+ * -V		   validate correctness of server's NFS             off
+ * -W biod_writes   max # of outstanding writes req at one time     2 reqs
+ * -w warmup	   # secs to generate load before starting test     60 secs
+ * -z		   If specified, collect and dump raw data.         off
+ *
+ *
+ * Multi Client Options
+ *
+ * option	   		description		 	    default
+ * ------------------------     ----------------------------------- -----------
+ * -M prime_client_hostname	hostname of prime client	    no default
+ * -N client_cnt		# client machines in test	    no default
+ *
+ *
+ *
+ * Block Transfer Size Distribution
+ *
+ * The block transfer size distribution is specified by a table of values.
+ * The first column gives the percent of operations that will be a
+ * specific block transfer size.  The second column gives the number of
+ * blocks units that will be transferred.  Normally the block unit size
+ * is 8KB.  The third column is a boolean specifying whether a trailing
+ * fragment block should be transferred.  The fragment size for each transfer
+ * is a random multiple of 1 KB, up to the block size - 1 KB.  Two tables
+ * are needed, one for read operation and one for write operations.  The
+ * following table gives the default distributions.
+ *
+ * 	Read  - Default Block Transfer Size Distribution Table
+ * percent   block count   fragment	resulting transfer (8KB block size)
+ * -------   -----------   --------	-----------------------------------
+ *    0        0             0 		 0%    1 -   7 KB
+ *   85        1             0 		85%    9 -  15 KB
+ *    8        2             1 		 8%   17 -  23 KB
+ *    4        4             1 		 4%   33 -  39 KB
+ *    2        8             1 		 2%   65 -  71 KB
+ *    1       16             1 		 1%  129 - 135 KB
+ *
+ * 	Write  - Default Block Transfer Size Distribution Table
+ * percent   block count   fragment	resulting transfer (8KB block size)
+ * -------   -----------   --------	-----------------------------------
+ *   49        0             1		49%    1 -   7 KB
+ *   36        1             1		36%    9 -  15 KB
+ *    8        2             1           8%   17 -  23 KB
+ *    4        4             1		 4%   33 -  39 KB
+ *    2        8             1		 2%   65 -  71 KB
+ *    1       16             1		 1%  129 - 135 KB
+ *
+ * The user may specify a a different distribution by using the '-b' option.
+ * The format for the block size distribution file consists of the first
+ * three columns given above: percent, block count, and fragment.  Read
+ * and write distribution tables are identified by the keywords "Read" and
+ * "Write".  An example input file, using the default values, is given below:
+ *
+ * 		Read
+ *		 0  0  0
+ *		85  1  0
+ *		 8  2  1
+ *		 4  4  1
+ *		 2  8  1
+ *		 1 16  1
+ *		Write
+ *		49  0  1
+ *		36  1  1
+ *		 8  2  1
+ *	         4  4  1
+ *               2  8  1
+ *               1 16  1
+ *
+ * A second parameter controlled by the block transfer size distribution
+ * table is ethernet packet size.  The distribution tables define the
+ * relative proportion of full blocks packets to fragment packets.  For
+ * instance, the default tables have been constructed to produce a specific
+ * distribution of ethernet packet sizes for i/o operations by controlling
+ * the amount of data in each packet.  The write packets produced consist
+ * of 50% 8-KB packets, and 50% 1-7 KB packets.  The read packets consist
+ * of 85% 8-KB packets, and 15% 1-7 KB packets.  These figures are
+ * determined by multiplying the percentage for the type of transfer by
+ * the number of blocks and fragments generated, and adding the totals.
+ * These conmputations are performed below for the default block size
+ * distribution tables:
+ *
+ * 		Read		blocks		fragments
+ *		 0  0  0	  0		  0
+ *		85  1  0	 85	  	  0
+ *		 8  2  1	 16       	  8
+ *		 4  4  1	 16	  	  4
+ *		 2  8  1	 16	  	  2
+ *		 1 16  1	 16	  	  1
+ *				---		---
+ *				149 (90%)	 15 (10%)
+ *
+ *		Write
+ *		49  0  1	  0		 49
+ *		36  1  1	 36		 36
+ *		 8  2  1	 16		  8
+ *	         4  4  1	 16		  4
+ *               2  8  1	 16		  2
+ *               1 16  1	 16		  1
+ *				---		---
+ *				100 (50%)	100 (50%)
+ *
+ *
+ *
+ *
+ *
+ * NFS Operation Mix
+ *
+ * The operation mix is described assigning a percentage to each type
+ * of NFS operation.  The default mix of operations is:
+ *
+ * operation	percent
+ * ---------	-------
+ * null		 0
+ * getattr	13
+ * setattr	 1
+ * root		 0
+ * lookup	34
+ * readlink	 8
+ * read		22
+ * wrcache	 0
+ * write	15
+ * create	 2
+ * remove	 1
+ * rename	 0
+ * link		 0
+ * symlink	 0
+ * mkdir	 0
+ * rmdir	 0
+ * readdir	 3
+ * fsstat	 1
+ *
+ * The user may specify a a different operation mix by using the '-m' option.
+ * The format for the mix file consists of the output from an nfsstat(1)
+ * command, which lists an operation count and percentage for each NFS
+ * operation.
+ *
+ *
+ * File Set Size
+ *
+ * !!! needs to be re-written - mew 8/24
+ * This still needs to be rewritten
+ *   - The default number of i/o files is based on load level.
+ *   - For non I/O files, the number of initialized versus empty
+ *     slots is hardcoded
+ *  - dr 2/8/94
+ *
+ * The file set used by SFS is determined by 2 factors. First,
+ * SFS creates a base set of files.  By default this consists of
+ * 100 files for i/o operations, 100 files for non-i/o operations, 20
+ * directories, and 20 symbolic links.  These default values can be
+ * changed from the command line by using the "-F", "-D", and "-S" options.
+ * This file set is divided evenly among the set of processes used to
+ * generate load.
+ *
+ * Then, enough resources are allocated to allow for the eventual creation
+ * of new files, directories and symlinks by the creat, link, mkdir,
+ * and symlink operations.  The number of extra slots allocated depends
+ * on the mix percentages assigned to each of the create and deletion
+ * operations, multiplied by an estimate of the total number of operations
+ * to be performed.  For instance, the default number of extra files names
+ * allocated for non-i/o operations is computed as follows:
+ *	300 secs * 60 ops/sec = 18000 total operations
+ *	2% create * 18000 ops = 360 create ops
+ *	1% remove * 18000 ops = 180 remove ops
+ *	260 creates ops - 180 remove ops = 180 extra files to be created.
+ * These 90 files are distributed evenly among the processes used to
+ * generate load.  With the default settings, no extra directories are
+ * created or removed, so no extra allocation is done for directories
+ * beyond the base file set.  The same is true for symbolic links.
+ *
+ * Thus, the total default file set size is:
+ *	100 files for i/o operations
+ *	280 files for non-i/o operations
+ *	 20 directories
+ *	 20 symlinks
+ *
+ * By allocating all required space before the test begins, any space
+ * allocation problems encountered by SFS are discovered before the
+ * test is started.
+ *
+ *
+ * Program Control
+ *
+ * Strategy: loop for some number of NFS calls doing a random sleep
+ * followed by a call to one of the op generator routines. The routines
+ * are called based on a weighting factor determined by the set of
+ * default percentages or a mix supplied by the user.
+ *
+ * The generator routines are able to keep an accurate count of the
+ * NFS operations they are generating by using the NFS protocol
+ * directly and not going through the kernel.  This eliminates the
+ * effects of kernel name caches and retry mechanisms that
+ * complicate control of what actually hits the wire.  The calling
+ * routine benefits by avoiding having to get the NFS statistics
+ * from the kernel because they KNOW what calls they've made.
+ *
+ * By using the NFS protocol directly :
+ *	"lookup" operations sidestep the client kernel name cache,
+ *	"getattr" operations avoid the client kernel attribute cache,
+ *	"read" operations avoid the client kernel buffer cache,
+ *	and so on.
+ *
+ * A consequence of not going thru the client kernel is that the sfs
+ * program must maintain a table of file handles rather than open
+ * file descriptors.
+ *
+ * The parent process starts children to do the real work of generating load.
+ * The parent coordinates them so that they all start at the same time, and
+ * collects statistics from them when they are done. To coordinate the
+ * start up, the parent waits for each child to write one byte into
+ * a common log file (opened in append mode to avoid overwriting).
+ * After they write a byte the children pause, and the parent send SIGUSR1
+ * when it has heard from all of the kids. The children write their statistics
+ * into the same common log file and the parent reads and accumulates the
+ * statistics and prints them out.
+ *
+ *
+ *.Exported_Routines
+ *	int main(int, char*)
+ *
+ *.Local_Routines
+ *	void init_logfile(void)
+ *	void usage(void)
+ *	int setmix(char *)
+ *	int setiodist(FILE *)
+ *	int parseiodist(FILE *, int)
+ *	void init_iodist(sfs_io_dist_type *)
+ *	void init_fss(void)
+ *	void init_filedist(void)
+ *	int lad_substr(char *, char *)
+ *
+ *.Revision_History
+ *	21-Aug-92	0.1.11	 Wittle File set access code.
+ *      14-Jul-92	0.1.9    Teelucksingh
+ *				 	Implemented Mark Wittle's proposal to
+ *					base File Set Size on peak load value,
+ *					added "-L peak_load" option.
+ *	10-Jan-92	0.0.0.19 Teelucksingh
+ *					Reworked setpgrp() usage to
+ *					better handle BSD vs SYSV variations.
+ *      04-Jan-92       0.0.0.18 Pawlowski
+ *                                      Added raw data dump code.
+ *      04-Dec-91	0.0.0.15 Keith
+ *					Include string.h if SVR4.
+ *	28-Nov-91	0.0.0.13 Teelucksingh
+ *					Modified code to use unique sfs /tmp
+ *					logfiles; sfs can now be used on
+ *					clients that have a shared /tmp area.
+ *					Added ANSI C features. Fixed 'multiple
+ *					signals from the Prime-Client' problem.
+ *					Added code to allow clients to
+ *					check for and create client specific
+ *					directories under each mount point -
+ *					clients share partitions. (code from
+ *					M.Molloy).
+ *	22-Nov-91		 Wittle Updated program description comment.
+ *					Added new op generation code.
+ *					Added block_dist_table and block_size
+ *					options, removed 8KB packet assumptions.
+ *	04-Oct-91	0.0.0.12 Teelucksingh
+ *					Changed SFS sources and executables
+ *					to use the "prelad" prefix.
+ *	23-Sep-91	0.0.0.11 Teelucksingh
+ *					Changed format of sfs output.
+ *	01-Aug-91	0.0.9 Wiryaman  Use the SPEC random number generator.
+ *					Since this RNG cannot take seed = 0,
+ *					use child_num+1 instead.
+ *	17-Jul-91	0.0.8 Teelucksingh
+ *					Enhance multi-client code and
+ *					documentation.
+ *			      Keith	Map "nhfsstone" to "laddis" in
+ *					README, nhfsstone_mgr.c. Create
+ *					initial DESCR.SFS for SPEC
+ *					submission.
+ *	15-Jul-91	0.0.8 Wiryaman	Add getmnt() for ULTRIX
+ *	25-Jun-91	0.0.7 Wiryaman	Added validation option to test all
+ *					of the NFS operations.
+ *	17-Jun-91	0.0.7 Teelucksingh
+ *					Added multi-client synchronization
+ *					support. By designating a client as
+ *					"Prime client" you can synchronize
+ *					multi-client SFS execution.
+ *	12-May-91	0.0.6 Wittle	Fix standard deviation.
+ *	02-May-91	0.0.5 Wittle	Fix SunOS signal bug; use default
+ *					warmuptime; add local time routine;
+ *					check for calls that underflow elapsed
+ *					time measurement; add std deviation
+ *					statistics; rework verbose output.
+ *					fix init invalid protocol rmdir calls;
+ *	15-Apr-91	0.0.4 Wittle	Test can be repeated without removing
+ *					test directories - initialization
+ *					restores base file set count and sizes.
+ *					Fix lack of call rate & mix accuracy -
+ *					set op_check before artificially
+ *					increasing call_targets.
+ *					Don't pre-create files/dirs that are
+ *					meant to be created during the test.
+ *	10-Mar-91	0.0.3 Wittle	Longer RPC timeout while populating
+ *					testdir; strstr() bug fix;
+ *					'-i' and '-e' options
+ *	06-Mar-91	0.0.2 Wittle	Loop forever pre-filling files.
+ *	22-Feb-91	0.0.1 Wittle	Use signal(2) instead of sigset(2).
+ *	18-Feb-91	0.0.0 Wittle	Change algorythm for determining i/o
+ *					sizes, preserve i/o file working set
+ *					by using separate files; bugs fixes.
+ *
+ *	nhfsstone renamed to laddis
+ *
+ *	31-Oct-90	2.0.4 Wittle	Many bug fixes.
+ *	24-Aug-90	2.0.3 Wittle	Output compatible w/graphing tools.
+ *	24-July-90	2.0.2 Wittle	Handle mounting below symlinks.
+ *	24-June-90	2.0.1 Wittle	Prefill files with data.
+ *	17-May-90	2.0.0 Bean	Rewrote the guts to use NFS
+ *					protocol directly.
+ *					Cleaned up self-pacing mechanism.
+ *	08-Nov-89	Guillermo Roa	Ported original version to DG/UX.
+ *	07-Jul-89	Legato Systems	Created.
+ */
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <sys/signal.h>
+
+#include <sys/file.h>
+#include <fcntl.h>
+
+#include <unistd.h>
+
+extern getmyhostname(char *, int);
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+/*
+ * -------------------------  External Definitions  -------------------------
+ */
+
+/* external routines from RPC and system libraries */
+#if defined(SETPGRP_BSD)
+extern int setpgrp(int, int);
+#endif /* SETPGRP_BSD */
+#if defined(SETPGRP_SYSV)
+extern pid_t setpgrp(void);
+#endif /* SETPGRP_SYSV */
+
+/* forward definitions for local routines */
+static void init_logfile(void);
+static void usage(void);
+static int setmix(char *);
+static int setiodist(FILE *);
+static int parseiodist(FILE *, int);
+static void init_iodist(sfs_io_dist_type *);
+static void init_fss(void);
+static void init_filedist(void);
+static int lad_substr(char *, char *);
+static double time_so_far1(void);
+static double get_resolution(void);
+static void check_clock(void);
+
+int	Tot_client_num_io_files = 0;    /* # of files used for i/o per client */
+int	Tot_client_num_non_io_files =   /* # of files used for i/o per client */
+				DEFAULT_NFILES;
+int	Files_per_dir =		        /* # of pre-created dirs */
+				DEFAULT_FILES_PER_DIR;
+int	Tot_client_num_symlinks =       /* # of pre-created symlinks/client */
+				DEFAULT_NSYMLINKS;
+int	Child_num;
+char *  Prime_client = NULL;            /* Prime client hostname */
+int     Client_num = 1;                 /* My client number */
+int     Tcp = 0;                        /* Flag set on command line */
+char    *sfs_Myname;                 /* name program invoked under */
+int     Log_fd;                         /* log fd */
+char    Logname[NFS_MAXNAMLEN];         /* child processes sync logfile */
+uid_t   Real_uid;                       /* real uid */
+uid_t   Cur_uid;                        /* my uid */
+gid_t   Cur_gid;                        /* my gid list */
+
+static char Client_logname[SFS_MAXNAMLEN];
+
+/*
+ * -----------------  SFS Main and Initialization Code  -----------------
+ */
+
+/*
+ * Read the command line arguments, fork off child processes to
+ * generate NFS load, and perform the local (ie, on this client)
+ * book-keeping for the test and the results.
+ */
+int
+main(
+    int		argc,
+    char	*argv[])
+{
+
+    char	*mix_file;		/* name of mix file */
+    char	*iodist_file;		/* name of block i/o dist table file */
+    int		children;		/* number of children */
+    int		child_num;		/* child index */
+    int		total_load;		/* total client load factor */
+    float	child_load;		/* per child load factor */
+    int		pid;			/* process id */
+    FILE	*pid_fp;
+    FILE	*iodist_fp;		/* block io dist table file */
+    int		i;
+    int		c;
+    int		Saveerrno;
+    int		ret;
+    int		nsigs = 32;		/* reasonable default */
+    extern char *optarg;
+    extern int optind;
+
+    /*
+     * Place pid in pid log file
+     */
+    if ((pid_fp = fopen(SFS_PNT_PID, "a+")) == NULL) {
+	perror(SFS_PNT_PID);
+	exit(1);
+    }
+
+    (void) fprintf(pid_fp, "%d\n", getpid());
+
+    /* Get program name for stderr printing */
+    sfs_Myname = argv[0];
+
+    check_clock();
+    getmyhostname(lad_hostname, HOSTNAME_LEN);
+
+    init_ops();
+
+/*
+ * Get the uid and gid information.
+ */
+    Real_uid = getuid();
+    Cur_gid = getgid();
+
+/*
+ * Form a new process group so our syncrhonization signals don't
+ * cause our parent shell to exit.  Clear the umask.
+ * Default is to use the standard setsid
+ */
+#ifdef SETPGRP3
+    ret = setpgrp3(); /* Work around HP-UX bug */
+#else
+#ifdef SETPGRP_SYSV
+    ret = setpgrp();
+#else
+#ifdef SETPGRP_BSD
+    ret = setpgrp(0, getpid());
+#else
+    ret = setsid();
+#endif /* SETPGRP_BSD */
+#endif /* SETPGRP_SYSV */
+#endif /* SETPGRP3 */
+
+    if (ret == -1) {
+	(void) fprintf(stderr, "%s: failed on setsid/setpgrp\n",
+		sfs_Myname);
+	exit(95);
+    }
+
+    (void) umask(0);
+
+/* Set up default parameters */
+    Validate = 0;
+
+    children = DEFAULT_NPROCS;
+    total_load = DEFAULT_LOAD;
+    mix_file = 0;
+    iodist_file = 0;
+    Nfs_timers = Nfs_udp_timers;
+
+    /* Parse command line arguments */
+    while ((c = getopt(argc, argv, "a:A:b:B:cd:D:f:F:il:m:M:N:p:PQR:S:T:t:V:W:w:z")) != EOF)
+	switch (c) {
+
+	case 'a': /* Percent of files to access */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal access value %s\n",
+					sfs_Myname, optarg);
+		exit(96);
+	    }
+	    Access_percent = atoi(optarg);
+	    if (Access_percent < 0 || Access_percent > 100) {
+		(void) fprintf(stderr,
+		       "%s: %% access must be between 0 and 100\n",
+			sfs_Myname);
+		exit(97);
+	    }
+	    break;
+
+	case 'A': /* Percent of writes that append */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal append value %s\n",
+				sfs_Myname, optarg);
+		exit(98);
+	    }
+	    Append_percent = atoi(optarg);
+	    if (Append_percent < 0 || Append_percent > 100) {
+		(void) fprintf(stderr,
+		       "%s: %% append must be between 0 and 100\n",
+			sfs_Myname);
+		exit(99);
+	    }
+	    break;
+
+	case 'b': /* Set block size distribution table from file */
+	    if ((iodist_fp = fopen(optarg, "r")) == NULL) {
+		Saveerrno = errno;
+		(void) fprintf(stderr, "%s: bad block size file",
+				sfs_Myname);
+		errno = Saveerrno;
+		perror(optarg);
+		exit(100);
+	    }
+	    if (setiodist(iodist_fp) < 0) {
+		exit(101);
+	    }
+	    iodist_file = optarg;
+	    (void) fclose(iodist_fp);
+	    break;
+
+	case 'B': /* Set the per packet maximum block size */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr,
+				"%s: illegal block size value %s\n",
+				sfs_Myname, optarg);
+		exit(102);
+	    }
+	    Kb_per_block = atoi(optarg);
+	    if ((Kb_per_block < 1) ||
+		(Kb_per_block > (DEFAULT_MAX_BUFSIZE/1024))) {
+		(void) fprintf(stderr,
+				"%s: illegal block size value %s\n",
+				sfs_Myname, optarg);
+		exit(103);
+	    }
+	    Bytes_per_block = Kb_per_block * 1024;
+	    break;
+
+
+	case 'c': /* Set number of calls */
+	    (void) fprintf(stderr, "%s: '-c option no longer supported\n",
+				    sfs_Myname);
+	    exit(104);
+	    break;
+
+	case 'd': /* Set debugging level */
+	    Debug_level = set_debug_level(optarg);
+	    break;
+
+	case 'D': /* Set number of directories */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal dirs value %s\n",
+				sfs_Myname, optarg);
+		exit(105);
+	    }
+	    Files_per_dir = atoi(optarg);
+	    break;
+
+	case 'f': /* Percent change in file set size */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal file set delta value %s\n",
+				sfs_Myname, optarg);
+		exit(106);
+	    }
+	    Fss_delta_percent = atoi(optarg);
+	    if (Fss_delta_percent < 0 || Fss_delta_percent > 100) {
+		(void) fprintf(stderr,
+		   "%s: %% file set delta must be between 0 and 100\n",
+		    sfs_Myname);
+		exit(107);
+	    }
+	    break;
+
+	case 'F': /* Set number of io files */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal files value %s\n",
+				sfs_Myname, optarg);
+		exit(108);
+	    }
+	    Tot_client_num_io_files = atoi(optarg);
+	    break;
+
+	case 'i': /* Set interactive mode */
+	    if (Prime_client != NULL) {
+		(void) fprintf(stderr,
+			    "%s: -i and -M options are incompatible\n",
+			    sfs_Myname);
+		exit(109);
+	    }
+	    Interactive++;
+	    break;
+
+	case 'l': /* Set load */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal load value %s\n",
+				sfs_Myname, optarg);
+		exit(110);
+	    }
+	    total_load = atoi(optarg);
+	    if (total_load < 0) {
+		(void) fprintf(stderr, "%s: load must be > 0\n",
+				sfs_Myname);
+		exit(111);
+	    }
+	    break;
+
+	case 'm': /* Set mix from a file */
+	    mix_file = optarg;
+	    if (setmix(mix_file) < 0) {
+		exit(112);
+	    }
+	    break;
+
+	case 'M': /* Set prime_client host name for multi-client sync */
+	    if (Interactive) {
+		(void) fprintf(stderr,
+			    "%s: -M and -i options are incompatible\n",
+			    sfs_Myname);
+		exit(113);
+	    }
+	    Prime_client = optarg;
+	    break;
+
+	case 'N': /* Set client number in multi-client run */
+	    Client_num = atoi(optarg);
+	    if (Client_num <= 0) {
+		(void) fprintf(stderr,
+				"%s: client number must be > 0\n",
+				sfs_Myname);
+		exit(114);
+	    }
+	    break;
+
+	case 'p': /* Set number of child processes */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal procs value %s\n",
+				sfs_Myname, optarg);
+		exit(115);
+	    }
+	    children = atoi(optarg);
+	    if (children < 0) {
+		(void) fprintf(stderr, "%s: number of children must be > 0\n",
+				sfs_Myname);
+		exit(116);
+	    }
+	    break;
+
+	case 'P': /* Populate only */
+	    Populate_only++;
+	    break;
+
+	case 'Q': /* Set NFS/TCP behaviour */
+	    Tcp = 1;
+	    Nfs_timers = Nfs_tcp_timers;
+	    break;
+
+	case 'R': /* set maximum async read concurrency level */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal read count value %s\n",
+				sfs_Myname, optarg);
+		exit(117);
+	    }
+	    Biod_max_outstanding_reads = atoi(optarg);
+	    if (Biod_max_outstanding_reads < 0 ||
+			Biod_max_outstanding_reads > MAX_BIODS) {
+		(void) fprintf(stderr,
+				"%s: read count must be >= 0 and <= %d\n",
+				sfs_Myname, MAX_BIODS);
+		exit(118);
+	    }
+	    break;
+
+	case 'S': /* Set number of symlinks */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr,
+				"%s: illegal symlinks value %s\n",
+				sfs_Myname, optarg);
+		exit(119);
+	    }
+	    Tot_client_num_symlinks = atoi(optarg);
+	    break;
+
+	case 'T': /* Set test mode, number following is opnum */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal test value %s\n",
+				sfs_Myname, optarg);
+		exit(120);
+	    }
+	    Testop = atoi(optarg);
+	    if (Testop >= NOPS) {
+		(void) fprintf(stderr, "%s: illegal test value %d\n",
+				sfs_Myname, Testop);
+		exit(121);
+	    }
+	    break;
+
+	case 't': /* Set run time */
+	    if (Ops[TOTAL].target_calls > 0) {
+		(void) fprintf(stderr,
+			    "%s: -t and -c options are incompatible\n",
+			    sfs_Myname);
+		exit(122);
+	    }
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal time value %s\n",
+				sfs_Myname, optarg);
+		exit(123);
+	    }
+	    Runtime = atoi(optarg);
+	    if (Runtime < 0) {
+		(void) fprintf(stderr, "%s: run time must be >= 0\n",
+				sfs_Myname);
+		exit(124);
+	    }
+	    break;
+
+	case 'V': /* Set Validate Level */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal validate value %s\n",
+					sfs_Myname, optarg);
+		exit(125);
+	    }
+	    Validate = atoi(optarg);
+	    if (Validate < 1 || Validate > 3) {
+		(void) fprintf(stderr, "%s: validate must be between 1 and 3\n",
+				    sfs_Myname);
+		exit(126);
+	    }
+	    break;
+
+	case 'W': /* set maximum async write concurrency level */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal write count value %s\n",
+					sfs_Myname, optarg);
+		exit(127);
+	    }
+	    Biod_max_outstanding_writes = atoi(optarg);
+	    if (Biod_max_outstanding_writes < 0 ||
+			Biod_max_outstanding_writes > MAX_BIODS) {
+		(void) fprintf(stderr,
+				"%s: write count must be >= 0 and <= %d\n",
+				sfs_Myname, MAX_BIODS);
+		exit(128);
+	    }
+	    break;
+
+	case 'w': /* Set warmup time */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal warmup value %s\n",
+				sfs_Myname, optarg);
+		exit(129);
+	    }
+	    Warmuptime = atoi(optarg);
+	    if (Warmuptime < 0) {
+		(void) fprintf(stderr, "%s: warmup time must be >= 0\n",
+				sfs_Myname);
+		exit(130);
+	    }
+	    break;
+
+	case 'z': /* Do raw data dumps */
+	    Dump_data++;
+	    break;
+
+	case '?':
+	default:
+	    usage();
+	    exit(131);
+
+	} /* end switch on arg */
+
+
+   /* compute ops/request for i/o operations */
+   init_iodist(Io_dist_ptr);
+
+   /* compute bytes/file and number of files */
+   init_filedist();
+
+    /* validate all the NFS operations that sfs will use */
+    if (Validate > 0) {
+	/*
+	 * -F <number of files > or else
+	 * DEFAULT_NFILES
+	 */
+	if (Tot_client_num_io_files == 0) {
+		Tot_client_num_io_files = DEFAULT_NFILES;
+	}
+	Num_io_files = Tot_client_num_io_files/children + 1;
+	/* number of non-io files, dir and symlinks base on constants */
+	Num_non_io_files = Tot_client_num_non_io_files/children + 1;
+	Num_dirs = Num_io_files/Files_per_dir + 1;
+	Num_symlinks = Tot_client_num_symlinks/children + 1;
+
+	/* io operations access a subset of the files */
+	Num_working_io_files = ((Num_io_files * Access_percent) / 100) + 1;
+	/* non-io and other operations access all of the files */
+	Num_working_non_io_files = Num_io_files;
+	Num_working_dirs = Num_dirs;
+	Num_working_symlinks = Num_symlinks;
+
+	Validate_ops(argc - optind, &argv[optind]);
+	exit(133);
+    }
+
+    /*
+     * Initial check on the mount arguments, must be at least an
+     * even multiple of the number of procs.
+     */
+    if ((argc - optind) % children) {
+        (void) fprintf(stderr,
+"%s: Invalid mount point list: Not a multiple of number of procs\n",
+                        sfs_Myname);
+        exit(182);
+    }
+
+    /*
+     * -F <number of io files > or else
+     * base files set on load ; this in NON-SPEC though
+     */
+    if (Tot_client_num_io_files == 0) {
+       Tot_client_num_io_files = ((DEFAULT_BYTES_PER_OP / 1024  * total_load)
+			     / (1024)) * files_per_megabyte;
+    }
+    Num_io_files = Tot_client_num_io_files/children + 1;
+
+    /*   
+     * Number of non-io files scales with load and is set at 2% of all files,
+     * but at least DEFAULT_NFILES worth.
+     */  
+    Tot_client_num_non_io_files = Tot_client_num_io_files * 0.02;
+    if (Tot_client_num_non_io_files < DEFAULT_NFILES)
+        Tot_client_num_non_io_files = DEFAULT_NFILES;
+    Num_non_io_files = Tot_client_num_non_io_files/children + 1;
+ 
+    /* number of dir and symlinks base on constants */
+    Num_dirs = Num_io_files/Files_per_dir + 1;
+    Num_symlinks = Tot_client_num_symlinks/children + 1;
+
+    /* io operations access a subset of the files */
+    Num_working_io_files = ((Num_io_files * Access_percent) / 100) + 1;
+
+    /* non-io and other operations access all of the files */
+    Num_working_non_io_files = Num_io_files;
+    Num_working_dirs = Num_dirs;
+    Num_working_symlinks = Num_symlinks;
+
+    /*
+     * If we are doing a timed test, we still need an
+     * estimate of how many calls are needed in order to
+     * judge our progress.
+     * If we are doing a test for a number of calls, we still need an
+     * estimate of how long the test will take in order to
+     * establish the time interval between progress checks.
+     */
+    if (Timed_run) {
+	/*
+	 * the total number of calls will be divided between the children
+	 * when they are forked off.
+	 */
+	Ops[TOTAL].target_calls = Runtime * total_load;
+    } else {
+	Runtime = (int) ((float) Ops[TOTAL].target_calls / (float) total_load);
+    }
+
+    /*
+     * multi-client sync support
+     * offset the Runtime value by MULTICLIENT_OFFSET seconds.
+     * This offset prevents the client from finishing before
+     * the Prime Client tells it to 'STOP'. The MULTICLIENT_OFFSET is larger
+     * than the time_out value on the Prime-Client; so in case the client
+     * does not stop when it's told to, the Prime-client should time_out.
+     */
+    if (Prime_client && Timed_run)
+	Runtime += MULTICLIENT_OFFSET;
+
+    /* compute file set sizes */
+    init_fss();
+
+    /* Set up synchronization and results log file */
+    init_logfile();
+
+    /*
+     * setup value of nsigs
+     */
+#ifdef __NSIG
+    nsigs = __NSIG;
+#endif
+#ifdef _NSIG
+    nsigs = _NSIG;
+#endif
+#ifdef NSIG
+    nsigs = NSIG;
+#endif
+#if defined(SOLARIS2) && !defined(_sys_nsig)
+    nsigs = _sys_siglistn;
+#endif
+
+    /* Set up the signal handlers for all signals */
+
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    {
+	struct sigaction sig_act, old_sig_act;
+
+	/* use XOPEN signal handling */
+
+	sig_act.sa_handler = generic_catcher;
+	(void)sigemptyset(&sig_act.sa_mask);
+	sig_act.sa_flags = 0;
+
+	if (DEBUG_PARENT_GENERAL) {
+	    if (nsigs == 0) {
+		(void) fprintf (stderr,
+		    "WARNING: nsigs not defined, no extra signals caught\n");
+	    }
+	    for (i = 1; i < nsigs; i++) {
+/* attempt to set up signal handler for these signals give an error !! K.T. */
+	        if (i!=SIGCHLD && i!=SIGKILL && i!=SIGSTOP && i!=SIGCONT) {
+		    if (sigaction(i,&sig_act,&old_sig_act) == -1) {
+			if (errno == EINVAL) {
+			    (void) fprintf (stderr,
+					"Skipping invalid signal %d\n", i);
+			} else {
+			    perror("sigaction failed");
+			    exit(134);
+			}
+		    }
+		}
+	    }
+        }
+
+	/* signals handlers for signals used by sfs */
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGINT,&sig_act,&old_sig_act) == -1) {
+	    perror("sigaction failed: SIGINT");
+	    exit(135);
+	}
+
+	sig_act.sa_handler = sfs_alarm;
+	if (sigaction(SIGALRM,&sig_act,&old_sig_act) != 0) {
+	    perror("sigaction failed: SIGALRM");
+	    exit(136);
+	}
+
+	sig_act.sa_handler = sfs_cleanup;
+	if (sigaction(SIGTERM,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGTERM");
+	    exit(137);
+	}
+
+	sig_act.sa_handler = sfs_startup;
+	if (sigaction(SIGUSR1,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGUSR1");
+	    exit(138);
+	}
+
+	sig_act.sa_handler = sfs_stop;
+	if (sigaction(SIGUSR2,&sig_act,&old_sig_act) != 0)  {
+	    perror("sigaction failed: SIGUSR2");
+	    exit(139);
+	}
+    }
+#else
+    if (DEBUG_PARENT_GENERAL) {
+	if (nsigs == 0) {
+	    (void) fprintf (stderr,
+		    "WARNING: nsigs not defined, no extra signals caught\n");
+	}
+	for (i = 1; i < nsigs; i++) {
+	    if (i!=SIGCHLD)
+		(void) signal(i, generic_catcher);
+	}
+    }
+    /* signals handlers for signals used by sfs */
+    (void) signal(SIGINT, sfs_cleanup);
+    (void) signal(SIGALRM, sfs_alarm);
+    (void) signal(SIGTERM, sfs_cleanup);
+    (void) signal(SIGUSR1, sfs_startup);
+    (void) signal(SIGUSR2, sfs_stop);
+#endif
+
+    /* Fork children */
+    for (child_num = 0; child_num < children; child_num++) {
+	pid = fork();
+	if (pid == -1) {
+	    Saveerrno = errno;
+	    (void) fprintf(stderr, "%s: can't fork children.", sfs_Myname);
+	    errno = Saveerrno;
+	    perror("fork");
+	    (void) generic_kill(0, SIGINT);
+	    exit(140);
+	} else if (pid == 0) {
+	    break;	/* get out of child creation */
+	}
+	(void) fprintf(pid_fp, "%d\n", pid);
+    } /* end for forking kids */
+    (void) fclose(pid_fp);
+
+    /*
+     * Parent: wait for kids to get ready, start them, wait for them to
+     * finish, read and accumulate results.
+     */
+    if (pid != 0) {
+	if (setuid(Real_uid) != 0) {
+	   (void) fprintf(stderr,"%s: %s%s\n",
+		   sfs_Myname, "cannot perform setuid operation.\n",
+		   "Do `make install` as root.\n");
+	}
+
+	/* I'm the parent - let the common code signal handlers know it */
+	Child_num = -1;
+
+	parent(children, total_load, mix_file, iodist_file);
+
+	/* Clean up and exit. */
+	(void) close(Log_fd);
+	(void) unlink(Logname);
+	exit(0);
+
+    } /* parent */
+
+    /*
+     * Children : initialize, then notify parent through log file,
+     * wait to get signal, beat the snot out of the server, write
+     * stats to the log file, and exit.
+     */
+    if (pid == 0) {
+
+	/* I'm a child - let the common code signal handlers know it */
+	Child_num = child_num;
+
+	/*
+	 * Determine my share of the calls and load (including any left over)
+	 * The call target for each child differs by at most 1 call.
+	 * The load rate for each child differs by at most 1 call/sec.
+	 */
+	Ops[TOTAL].target_calls = Ops[TOTAL].target_calls / children;
+	if (child_num <= Ops[TOTAL].target_calls % children) {
+	    Ops[TOTAL].target_calls++;
+	}
+	child_load = (float) total_load / (float) children;
+
+	/*
+	 * Sleep a bit so the parent can catch up after procreating all us
+	 * children.
+	 */
+	(void) sleep(10);
+
+	child(child_num, children, child_load, argc - optind, &argv[optind]);
+	exit(0);
+
+    } /* child */
+
+    (void) unlink(SFS_PNT_PID);
+
+    return(0);
+
+} /* main */
+
+
+/*
+ * -----------------  Initalization of Parent/Child  ---------------------
+ */
+
+/*
+ * Open the multi-client synchronization file with append mode.
+ */
+static void
+init_logfile(void)
+{
+    FILE	*cl_log_fd;
+    int		Saveerrno;
+
+    (void) sprintf(Logname, "%s%d", CHILD_SYNC_LOG, Client_num);
+    Log_fd = open(Logname, (O_RDWR | O_CREAT | O_TRUNC | O_APPEND), 0666);
+    if (Log_fd == -1) {
+	Saveerrno = errno;
+	(void) fprintf(stderr, "%s: can't open log file %s ", sfs_Myname, Logname);
+	errno = Saveerrno;
+	perror(Logname);
+	exit(141);
+    }
+    if (chown(Logname, Real_uid, Cur_gid) ==-1) {
+	perror("chown");
+	(void) fprintf(stderr, "%s: chown failed\n", sfs_Myname);
+    }
+
+    /* if multi-client execution then init client sync log */
+    if (Prime_client != NULL) {
+	/* init logfile and write process id */
+	(void) sprintf(Client_logname, "%s%d",
+			SFS_CLIENT_SYNC_LOG, Client_num);
+	cl_log_fd = fopen(Client_logname, "w+");
+	if (chown(Client_logname, Real_uid, Cur_gid) ==-1) {
+		perror("chown");
+		(void) fprintf(stderr, "%s: chown failed\n", sfs_Myname);
+	}
+	if (cl_log_fd == NULL) {
+	    Saveerrno = errno;
+	    (void) fprintf(stderr,
+		"%s: can't open Client synchronization file %s ",
+			    sfs_Myname, Client_logname);
+	    errno = Saveerrno;
+	    perror(Client_logname);
+	    exit(142);
+	} else {
+	    /* store parent pid */
+	    (void) fprintf(cl_log_fd, "%d", (int)getpid());
+	    (void) fclose(cl_log_fd);
+	}
+    } /* init multi-client sync log */
+
+} /* init_logfile */
+
+/*
+ * ------------------------  Utility Routines  --------------------------
+ */
+
+
+/*
+ * Print the program's usage message.
+ * Usage: sfs [-l load] [-p procs] [-w warmup] [-t time]
+ *               [-m mix_file] [-B block_size] [-b blocksz_file]
+ *		 [-f file_set_delta] [-a access_pnct]
+ *		 [-A append_pcnt] [-D dir_cnt] [-F file_cnt] [-S symlink_cnt]
+ *		 [-d debug_level] [-i] [-P] [-T op_num]
+ *		 [-V validation_level] [-z] [-Q]
+ *		 [-R biod_reads] [-W biod_writes]
+ *		 [-M prime_client_hostname] [-N client_cnt]
+ */
+static void
+usage(void)
+{
+    (void) fprintf(stderr,
+      "Usage: %s [-l load] [-p procs] [-w warmup] [-t time]\n", sfs_Myname);
+    (void) fprintf(stderr,
+      "              [-m mix_file] [-B block_size] [-b blocksz_file]\n");
+    (void) fprintf(stderr,
+      "              [-f file_set_delta] [-a access_pnct]\n");
+    (void) fprintf(stderr,
+      "              [-A append_pcnt] [-D dir_cnt] [-F file_cnt] [-S symlink_cnt]\n");
+    (void) fprintf(stderr,
+      "              [-d debug_level] [-i] [-P] [-T op_num]\n");
+    (void) fprintf(stderr,
+      "              [-V validation_level] [-z] [-Q]\n");
+    (void) fprintf(stderr,
+      "              [-R biod_reads] [-W biod_writes]\n");
+    (void) fprintf(stderr,
+      "              [-M prime_client_hostname] [-N client_cnt]\n");
+} /* usage */
+
+
+
+/*
+ * --------------  Command Line File Parsing  -------------------
+ */
+
+/*
+ * Constants for mix file
+ */
+#define LINELEN         128             /* max bytes/line in mix file */
+#define MIX_START       0
+#define MIX_DATALINE    1
+#define MIX_DONE        2
+#define MIX_FIRSTLINE   3
+
+/*
+ * Parse the operation mix file 'mix_file'.
+ *
+ * ORIGINAL PRE-SFS1.2 format:
+ *	Assumes that the input file is in the same format as
+ *	the output of the nfsstat(8) command.
+ *
+ *	Uses a simple state transition to keep track of what to expect.
+ *	Parsing is done a line at a time.
+ *
+ *	State	   	Input			action		New state
+ *	MIX_START	".*nfs:.*"		skip one line	MIX_FIRSTLINE
+ *	MIX_FIRSTLINE   ".*[0-9]*.*"		get calls	MIX_DATALINE
+ *	MIX_DATALINE    "[0-9]* [0-9]*%"X6	get op counts	MIX_DATALINE
+ *	MIX_DATALINE    "[0-9]* [0-9]*%"X4	get op counts	MIX_DONE
+ *	MIX_DONE	EOF			return
+ *
+ *	We read operation counts from the mix file
+ *	and compute our own mix percentages,
+ *	rather than using those in the mix file.
+ *
+ * NEW SFS1.2 format version #2:
+ *	SFS MIXFILE VERSION 2		Version header (must come first line)
+ *	"^#.*"				Comment (any line except first)
+ *	"%s [0-9]*%"			Op name Op percentage
+ */
+static int
+setmix(
+    char *	mix_file)
+{
+    int		state;		/* current state of state machine */
+    int		got;		/* number of items read from input line */
+    int		opnum;		/* operation number index */
+    int		calls;		/* total number of calls in mix */
+    char	line[LINELEN];	/* input line buffer */
+    char	op_name[LINELEN];	/* name buffer */
+    int		mix_pcnt;
+    unsigned int	len;	/* length of input line */
+    FILE	*mix_fp;	/* mix file */
+    int		vers;		/* mix file version number */
+    sfs_op_type *op_ptr;
+
+    if ((mix_fp = fopen(mix_file, "r")) == NULL) {
+	(void) fprintf(stderr, "%s: bad mix file", sfs_Myname);
+	perror(mix_file);
+	return(-1);
+    }
+
+    if (fgets(line, LINELEN, mix_fp) == NULL) {
+	(void) fprintf(stderr, "%s: bad mix format - unexpected empty file\n",
+					sfs_Myname);
+    	(void) fclose(mix_fp);
+	return (-1);
+    }
+
+    opnum = 0;
+
+    /*
+     * Look for initial version string
+     */
+    got = sscanf(line, "SFS MIXFILE VERSION %d", &vers);
+    if (got != 1) {
+	/*
+	 * Check to see if this is old mixfile
+	 */
+	len = strlen(line);
+	if (len < 4 || lad_substr(line, "nfs:") == 0) {
+	    (void) fprintf(stderr, "%s: bad mix format - initial line '%s'\n",
+					sfs_Myname, line);
+	    (void) fclose(mix_fp);
+	    return (-1);
+	}
+	vers = 1;
+    }
+
+    if (vers == 1) {
+	/*
+	 * Old style mix file
+	 */
+	state = MIX_START;
+	while (state != MIX_DONE && fgets(line, LINELEN, mix_fp)) {
+
+	    switch (state) {
+	        case MIX_START:
+		    /*
+		     * Ate first line after nfs:
+		     */
+		    state = MIX_FIRSTLINE;
+		    break;
+
+	        case MIX_FIRSTLINE:
+		    got = sscanf(line, "%d", &calls);
+		    if (got != 1) {
+		        (void) fprintf(stderr,
+			"%s: bad mix format - can't find 'calls' value %d\n",
+				    sfs_Myname,got);
+	    			(void) fclose(mix_fp);
+				return (-1);
+		    }
+		    if (fgets(line, LINELEN, mix_fp) == NULL) {
+		        (void) fprintf(stderr,
+			"%s: bad mix format - unexpected EOF after 'calls'\n",
+				    sfs_Myname);
+	    	        (void) fclose(mix_fp);
+		        return (-1);
+		    }
+		    state = MIX_DATALINE;
+		    break;
+
+	        case MIX_DATALINE:
+		    got = sscanf(line,
+	       "%d %*d%% %d %*d%% %d %*d%% %d %*d%% %d %*d%% %d %*d%% %d %*d%%",
+			    &Ops[opnum].mix_pcnt,
+			    &Ops[opnum + 1].mix_pcnt,
+			    &Ops[opnum + 2].mix_pcnt,
+			    &Ops[opnum + 3].mix_pcnt,
+			    &Ops[opnum + 4].mix_pcnt,
+			    &Ops[opnum + 5].mix_pcnt,
+			    &Ops[opnum + 6].mix_pcnt);
+
+		    if (got == 4 && opnum == 14) {
+		        /* looks like the last line */
+		        state = MIX_DONE;
+		    } else if (got == 7) {
+		        opnum += 7;
+		        if (fgets(line, LINELEN, mix_fp) == NULL) {
+			    (void) fprintf(stderr,
+			"%s: bad mix format - unexpected EOF after 'calls'\n",
+					sfs_Myname);
+		            (void) fclose(mix_fp);
+			    return (-1);
+		        }
+		    } else {
+		        (void) fprintf(stderr,
+			    "%s: bad mix format - can't find %d op values\n",
+				sfs_Myname, got);
+	                (void) fclose(mix_fp);
+		        return (-1);
+		    }
+		    break;
+
+	        default:
+		    (void) fprintf(stderr,
+				"%s: error parsing mix file - bad state %d\n",
+				sfs_Myname, state);
+	            (void) fclose(mix_fp);
+		    return (-1);
+	    } /* end switch on state */
+        } /* end while there are lines to read */
+
+        if (state != MIX_DONE) {
+	    (void) fprintf(stderr, "%s: bad mix format - unexpected EOF\n",
+		sfs_Myname);
+	    (void) fclose(mix_fp);
+	    return (-1);
+        }
+        for (opnum = 0; opnum < NOPS; opnum++) {
+	    Ops[opnum].mix_pcnt = Ops[opnum].mix_pcnt * 100 / calls
+			     + ((Ops[opnum].mix_pcnt * 1000 / calls % 10) >= 5);
+        }
+        (void) fclose(mix_fp);
+        return (0);
+    }
+    if (vers == 2) {
+	/*
+	 * New style mix file
+	 */
+	while (fgets(line, LINELEN, mix_fp) != NULL) {
+	    if (line[0] == '#')			/* Comment line */
+		continue;
+	    got = sscanf(line, "%s %d", op_name, &mix_pcnt);
+	    if (got != 2) {
+	        (void) fprintf(stderr,
+			    "%s: bad mix format - can't find op values: %s\n",
+				sfs_Myname, line);
+	        (void) fclose(mix_fp);
+		return (-1);
+	    }
+	    op_ptr = Ops;
+	    while (strcmp(op_ptr->name, "TOTAL") != 0) {
+	        if (strcmp(op_ptr->name, op_name) == 0) {
+		    op_ptr->mix_pcnt = mix_pcnt;
+		    break;
+	        }
+	        op_ptr++;
+	    }
+	    if (strcmp(op_ptr->name, "TOTAL") == 0) {
+	        (void) fprintf(stderr,
+			    "%s: unknown op name: %s\n",
+				sfs_Myname, op_name);
+	        (void) fclose(mix_fp);
+		return (-1);
+	    }
+        }
+	/*
+	 * Make sure that the total mix percentages == 100
+	 */
+        op_ptr = Ops;
+	mix_pcnt = 0;
+        while (strcmp(op_ptr->name, "TOTAL") != 0) {
+	    mix_pcnt += op_ptr->mix_pcnt;
+	    op_ptr++;
+        }
+	if (mix_pcnt != 100) {
+	    (void) fprintf(stderr,
+			    "%s: WARNING total mix percentage %d != 100\n",
+				sfs_Myname, mix_pcnt);
+	}
+        (void) fclose(mix_fp);
+	return (0);
+    }
+
+    (void) fprintf(stderr, "%s: Unknown mix file version number %d\n",
+				sfs_Myname, vers);
+    (void) fclose(mix_fp);
+    return (-1);
+} /* setmix */
+
+
+/*
+ * Parse the block I/O distribution file 'fp'.
+ */
+static int
+setiodist(
+    FILE *	fp)
+{
+    int		i;
+
+    /* first, read and parse the i/o distribution file for syntax and size */
+    if (parseiodist(fp, 1) == -1) {
+	exit(143);
+    }
+    (void) fseek(fp, 0, SEEK_SET);
+
+    /* read the i/o distribution file into the i/o dist table */
+    if (parseiodist(fp, 2) == -1) {
+	exit(144);
+    }
+
+    if (DEBUG_PARENT_GENERAL) {
+	(void) fprintf(stdout, "I/o Distribution Table\n");
+	(void) fprintf(stdout, "Read:\n");
+	(void) fprintf(stdout, "\tpcnt bufs frags\n");
+	for (i = 0 ; ; i++) {
+	    (void) fprintf(stdout, "\t%4d %4d %5d\n", Io_dist_ptr->read[i].pcnt,
+			Io_dist_ptr->read[i].bufs, Io_dist_ptr->read[i].frags);
+	    if (Io_dist_ptr->read[i].pcnt == 100)
+		break;
+	}
+
+	(void) fprintf(stdout, "Write:\n");
+	(void) fprintf(stdout, "\tpcnt bufs frags\n");
+	for (i = 0; ; i++) {
+	    (void) fprintf(stdout, "\t%4d %4d %5d\n",
+			    Io_dist_ptr->write[i].pcnt,
+			    Io_dist_ptr->write[i].bufs,
+			    Io_dist_ptr->write[i].frags);
+	    if (Io_dist_ptr->write[i].pcnt == 100)
+		break;
+	}
+	(void) fprintf(stdout, "Maximum file size: %d KB (%d * %d KB)\n",
+			Io_dist_ptr->max_bufs * Kb_per_block,
+			Io_dist_ptr->max_bufs, Kb_per_block);
+    }
+    return(0);
+} /* setiodist */
+
+
+/*
+ * Block/File Distribution file parser.
+ * Assumes that the input file is in the following format:
+ *
+ *
+ *	READ_KEY_WORD
+ *	percent		block_cnt		fragment_flag
+ *	   .		     .			      .
+ *	   .		     .			      .
+ *	   .		     .			      .
+ *	WRITE_KEY_WORD
+ *	percent		block_cnt		fragment_flag
+ *	   .		     .			      .
+ *	   .		     .			      .
+ *	   .		     .			      .
+ *
+ *
+ * Notes:
+ *	- The READ_KEY_WORD is "Read", the WRITE_KEY_WORD is "Write".
+ *	- For each key word, the percent fields must sum to 100.
+ *	- Fragment is either true (1) or false (0)
+ *	- Maximum file size (and transfer size) is the largest
+ *	  eight_k_cnt * 8KB plus 7 Kb for fragments
+ *
+ *
+ * Uses a simple state transition to keep track of what to expect.
+ * Parsing is done a line at a time.
+ *
+ * State	Input			action		New state
+ * -----	--------------------	-------------	---------
+ * START	"Read"			skip one line	READ
+ * START	"Write"			skip one line	WRITE
+ * READ		"[0-9]* [0-9]* [01]"	get values	READ
+ * READ		"Write"			skip one line	WRITE
+ * WRITE	"[0-9]* [0-9]* [01]"	get values	WRITE
+ * WRITE	"Read"			skip one line	READ
+ * DONE		EOF			return
+ *
+ * Pass 1 reads the file and allocates table space.
+ * Pass 2 reads the file data into the tables.
+ */
+static int
+parseiodist(
+    FILE *	fp,
+    int		pass)
+{
+    int		state;		/* current state of state machine */
+    int		got;		/* number of items read from input line */
+    int		pcnt;		/* percent read from input line */
+    int		bufs;		/* eight_kb_buffer_cnt read from input line */
+    int		frags;		/* fragment flag read from input line */
+    int		rbucket;	/* current read distribution table bucket */
+    int		wbucket;	/* current write distribution table bucket */
+    int		rpcnt;		/* cumulative percent for read buckets */
+    int		wpcnt;		/* cumulative percent for write buckets */
+    char	key[5];		/* keyword buffer */
+    char	line[LINELEN];	/* input line buffer */
+    int		nextline;
+
+    /*
+     * Pass 1 reads, sizes, and error checks the input
+     * and then allocates space for the distribution tables.
+     * Pass 2 reads the input into the allocated tables.
+     */
+
+    rbucket = 0;
+    wbucket = 0;
+    rpcnt = 0;
+    wpcnt = 0;
+    state = IO_DIST_START;
+
+    while (fgets(line, LINELEN, fp)) {
+
+	nextline = 0;
+	while (nextline == 0) {
+
+	    if (state == IO_DIST_READ) {
+		got = sscanf(line, "%d %d %d", &pcnt, &bufs, &frags);
+		if (got != 3) {
+		    state = IO_DIST_START;
+		    continue; /* same line, but goto new state */
+		}
+		if (pass == 1) {
+		    rbucket++;
+		    rpcnt += pcnt;
+		    if (frags != 0 && frags != 1) {
+			(void) fprintf(stderr,
+			    "%s: bad i/o dist format - bad fragment value\n",
+					sfs_Myname);
+			return(-1);
+		    }
+		} else {
+		    rpcnt += pcnt;
+		    Io_dist_ptr->read[rbucket].pcnt = rpcnt;
+		    Io_dist_ptr->read[rbucket].bufs = bufs;
+		    Io_dist_ptr->read[rbucket].frags = frags;
+		    rbucket++;
+		}
+		if (DEBUG_CHILD_FILES) {
+		    (void) fprintf(stdout, "p=%d b=%d f=%d rpcnt=%d\n",
+				    pcnt, bufs, frags, rpcnt);
+		    (void) fflush(stdout);
+		}
+
+		/* read next line in file */
+		nextline++;
+		break;
+	    }
+
+	    if (state == IO_DIST_WRITE) {
+		got = sscanf(line, "%d %d %d", &pcnt, &bufs, &frags);
+		if (got != 3) {
+		    state = IO_DIST_START;
+		    continue; /* same line, but goto new state */
+		}
+		if (pass == 1) {
+		    wbucket++;
+		    wpcnt += pcnt;
+		    if (frags != 0 && frags != 1) {
+			(void) fprintf(stderr,
+			    "%s: bad i/o dist format - bad fragment value\n",
+					sfs_Myname);
+			return(-1);
+		    }
+		} else {
+		    wpcnt += pcnt;
+		    Io_dist_ptr->write[wbucket].pcnt = wpcnt;
+		    Io_dist_ptr->write[wbucket].bufs = bufs;
+		    Io_dist_ptr->write[wbucket].frags = frags;
+		    wbucket++;
+		}
+		if (DEBUG_CHILD_FILES) {
+		    (void) fprintf(stdout, "p=%d b=%d f=%d wpcnt=%d\n",
+				    pcnt, bufs, frags, wpcnt);
+		    (void) fflush(stdout);
+		}
+		/* read next line in file */
+		nextline++;
+		break;
+	    }
+
+	    if (state == IO_DIST_START) {
+		got = sscanf(line, "%s", key);
+		if (got != 1 || (strlen(key) != 5)){
+		    (void) fprintf(stderr,
+			    "%s: bad i/o dist format - invalid keyword %s\n",
+				    sfs_Myname, key);
+		    return(-1);
+		}
+		if (!strcmp(key, "Read") || !strcmp(key, "read")) {
+		    if (rbucket != 0) {
+			(void) fprintf(stderr,
+			"%s: bad i/o dist format - too many read keywords\n",
+					sfs_Myname);
+			return(-1);
+		    }
+		    rpcnt = 0;
+		    state = IO_DIST_READ;
+
+		    /* read next line in file */
+		    nextline++;
+		    break;
+		}
+		if (!strcmp(key, "Write") || !strcmp(key, "write")) {
+		    if (wbucket != 0) {
+			(void) fprintf(stderr,
+		       "%s: bad i/o dist format - too many write keywords\n",
+					sfs_Myname);
+			return(-1);
+		    }
+		    wpcnt = 0;
+		    state = IO_DIST_WRITE;
+
+		    /* read next line in file */
+		    nextline++;
+		    break;
+		}
+		(void) fprintf(stderr,
+			    "%s: bad i/o dist format - unknown keyword %s\n",
+				sfs_Myname, key);
+		return(-1);
+	    }
+
+	} /* end while processing this line */
+    } /* end while more lines */
+
+    if (pass == 1) {
+
+	/* error check the input */
+	if (rbucket == 0) {
+	    (void) fprintf(stderr,
+		    "%s: bad i/o dist format - no read distribution data\n",
+			    sfs_Myname);
+	    return(-1);
+	}
+	if (rpcnt != 100) {
+	    (void) fprintf(stderr,
+			"%s: bad i/o dist format - read total percent != 100\n",
+			    sfs_Myname);
+	    return(-1);
+	}
+	if (wbucket == 0) {
+	    (void) fprintf(stderr,
+		    "%s: bad i/o dist format - no write distribution data\n",
+			    sfs_Myname);
+	    return(-1);
+	}
+	if (wpcnt != 100) {
+	    (void) fprintf(stderr,
+		    "%s: bad i/o dist format - write percent total != 100\n",
+			    sfs_Myname);
+	    return(-1);
+	}
+
+	/* allocate space for the table */
+	if ((Io_dist_ptr = (sfs_io_dist_type *)
+		malloc(sizeof(sfs_io_dist_type))) == NULL) {
+	    (void) fprintf(stderr,
+		    "%s: block i/o distribution table allocation failed\n",
+			    sfs_Myname);
+		return(-1);
+	}
+	if ((Io_dist_ptr->read = (sfs_io_op_dist_type *)
+		malloc(rbucket*sizeof(sfs_io_op_dist_type))) == NULL) {
+	    (void) fprintf(stderr,
+		    "%s: read distribution table allocation failed\n", sfs_Myname);
+	    return(-1);
+	}
+	if ((Io_dist_ptr->write = (sfs_io_op_dist_type *)
+		malloc(wbucket*sizeof(sfs_io_op_dist_type)))==NULL) {
+	    (void) fprintf(stderr,
+		    "%s: write distribution table allocation failed\n", sfs_Myname);
+	    return(-1);
+	}
+
+    }
+    return(0);
+
+} /* parseiodist */
+
+
+/*
+ * Compute the max i/o transfer size and average ops per request
+ * for the block transfer distribution table.
+ */
+static void
+init_iodist(
+    sfs_io_dist_type	*	io_dist_ptr)
+{
+    int				max_bufs;
+    double			weighted_ops;
+    double			previous_pcnt;
+    int				i;
+
+    /*
+     * compute expected number of ops for multi-op requests.
+     * the calculation assumes that if a i/o distribution table
+     * entry specifies that a fragment is to be generated, then
+     * exactly one OTW operation will result.
+     */
+    max_bufs = 0;
+
+    weighted_ops = 0.0;
+    previous_pcnt = 0.0;
+    for (i = 0; ; i++) {
+	weighted_ops += (io_dist_ptr->read[i].pcnt - previous_pcnt) *
+		      (io_dist_ptr->read[i].bufs + io_dist_ptr->read[i].frags);
+	previous_pcnt = io_dist_ptr->read[i].pcnt;
+	if (io_dist_ptr->read[i].bufs > max_bufs)
+	    max_bufs = io_dist_ptr->read[i].bufs;
+	if (io_dist_ptr->read[i].pcnt == 100)
+	    break;
+    }
+    io_dist_ptr->avg_ops_per_read_req = weighted_ops / 100.0;
+
+    weighted_ops = 0.0;
+    previous_pcnt = 0.0;
+    for (i = 0; ; i++) {
+	weighted_ops += (io_dist_ptr->write[i].pcnt - previous_pcnt) *
+		    (io_dist_ptr->write[i].bufs + io_dist_ptr->write[i].frags);
+	previous_pcnt = io_dist_ptr->write[i].pcnt;
+	if (io_dist_ptr->write[i].bufs > max_bufs)
+	    max_bufs = io_dist_ptr->write[i].bufs;
+	if (io_dist_ptr->write[i].pcnt == 100)
+	    break;
+    }
+    io_dist_ptr->avg_ops_per_write_req = weighted_ops / 100.0;
+
+    io_dist_ptr->max_bufs = max_bufs + 1;
+
+} /* init_iodist */
+
+static void
+init_filedist()
+{
+    int i;
+    int cur_pcnt;
+    int num_files = 0;
+    int prev_pcnt = 0;
+    int tot_size = 0;
+
+    /*
+     * Calculate the average number of bytes per file
+     */
+    for (i = 0; Default_file_size_dist[i].size != 0; i++) {
+        cur_pcnt = Default_file_size_dist[i].pcnt - prev_pcnt;
+        num_files += cur_pcnt;
+	tot_size += (Default_file_size_dist[i].size * 1024) * cur_pcnt;
+	prev_pcnt = Default_file_size_dist[i].pcnt;
+    }
+
+    avg_bytes_per_file = tot_size / num_files;
+    files_per_megabyte = (((1024*1024) + avg_bytes_per_file) \
+                                        / avg_bytes_per_file);
+}
+
+static void
+init_fss()
+{
+    int Delta_fss_bytes;
+
+    Base_fss_bytes = Num_working_io_files * (avg_bytes_per_file / 1024);
+    Total_fss_bytes = Num_io_files * (avg_bytes_per_file / 1024);
+    Cur_fss_bytes = Base_fss_bytes;
+    Delta_fss_bytes = (Base_fss_bytes * Fss_delta_percent) / 100;
+    Limit_fss_bytes = Base_fss_bytes + Delta_fss_bytes;
+    Most_fss_bytes = Base_fss_bytes;
+    Least_fss_bytes = Base_fss_bytes;
+}
+
+/*
+ * return true if 'sp' contains the substring 'subsp', false otherwise
+ */
+static int
+lad_substr(
+    char *		sp,
+    char *		subsp)
+{
+    unsigned int	found;
+    int			want;
+    char *		s2;
+
+    if (sp == NULL || subsp == NULL) {
+	return (0);
+    }
+
+    want = strlen(subsp);
+
+    while (*sp != '\0') {
+	while (*sp != *subsp && *sp != '\0') {
+	    sp++;
+	}
+	found = 0;
+	s2 = subsp;
+	while (*sp == *s2 && *sp != '\0') {
+	    sp++;
+	    s2++;
+	    found++;
+	}
+	if (found == want) {
+	    return (1);
+	}
+    }
+    return (0);
+
+} /* lad_substr */
+
+/*
+ * Check the gettimeofday() resolution. If the resolution
+ * is in chunks bigger than SFS_MIN_RES then the client
+ * does not have a usable resolution for running the 
+ * benchmark.
+ */
+static void
+check_clock(void)
+{
+	double time_res;
+	char tmp_hostname[HOSTNAME_LEN];
+
+	time_res = get_resolution();
+    	getmyhostname(tmp_hostname, HOSTNAME_LEN);
+	if( time_res > (double)SFS_MIN_RES )
+	{
+		(void) fprintf(stderr,
+		"\n%s: Clock resolution too poor to obtain valid results.\n",
+			tmp_hostname);
+		(void) fprintf(stderr,
+		"%s: Clock resolution %f Micro seconds.\n", tmp_hostname,
+			time_res);
+		exit(175);
+	}
+	else
+	{
+		(void) fprintf(stderr,
+		"\n%s: Good clock resolution [ %f ] Micro seconds.\n", 
+			tmp_hostname, time_res);
+	}
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns the resolution of the gettimeofday() function 
+ * in microseconds.
+ */
+static double
+get_resolution(void)
+{
+        double starttime, finishtime, besttime;
+        long  j,delay;
+	int k;
+
+        finishtime=time_so_far1(); /* Warm up the instruction cache */
+        starttime=time_so_far1();  /* Warm up the instruction cache */
+        delay=j=0;                 /* Warm up the data cache */
+	for(k=0;k<10;k++)
+	{
+	        while(1)
+       	 	{
+       	         	starttime=time_so_far1();
+       	         	for(j=0;j< delay;j++)
+       	                ;
+       	         	finishtime=time_so_far1();
+       	         	if(starttime==finishtime)
+       	                 	delay++;
+       	         	else
+			{
+				if(k==0)
+					besttime=(finishtime-starttime);
+				if((finishtime-starttime) < besttime)
+					besttime=(finishtime-starttime);
+                       	 	break;
+			}
+		}
+        }
+         return(besttime);
+}
+
+/*
+ * Lifted code from Iozone with permission from author. (Don Capps)
+ * Returns current result of gettimeofday() in microseconds.
+ */
+/************************************************************************/
+/* Time measurement routines.                                           */
+/* Return time in microseconds                                          */
+/************************************************************************/
+
+static double
+time_so_far1(void)
+{
+        /* For Windows the time_of_day() is useless. It increments in 55 */
+	/* milli second increments. By using the Win32api one can get */
+	/* access to the high performance measurement interfaces. */
+	/* With this one can get back into the 8 to 9 microsecond */
+	/* resolution.  */
+#ifdef Windows
+        LARGE_INTEGER freq,counter;
+        double wintime;
+        double bigcounter;
+
+        QueryPerformanceFrequency(&freq);
+        QueryPerformanceCounter(&counter);
+        bigcounter=(double)counter.HighPart *(double)0xffffffff +
+                (double)counter.LowPart;
+        wintime = (double)(bigcounter/(double)freq.LowPart);
+        return((double)wintime*1000000.0);
+#else
+#if defined (OSFV4) || defined(OSFV3) || defined(OSFV5)
+  struct timespec gp;
+
+  if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1)
+    perror("getclock");
+  return (( (double) (gp.tv_sec)*1000000.0) +
+    ( ((float)(gp.tv_nsec)) * 0.001 ));
+#else
+  struct timeval tp;
+
+  if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
+    perror("gettimeofday");
+  return ((double) (tp.tv_sec)*1000000.0) +
+    (((double) tp.tv_usec) );
+#endif
+#endif
+}
+
+/* sfs_c_chd.c */
+/* sfs_c_man.c */
+
diff --git a/TBBT/trace_play/sfs_c_mnt.c b/TBBT/trace_play/sfs_c_mnt.c
new file mode 100644
index 0000000..8f60387
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_mnt.c
@@ -0,0 +1,573 @@
+#ifndef lint
+static char sfs_c_mntSid[] = "@(#)sfs_c_mnt.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_c_mnt.c ---------------------
+ *
+ *      The sfs child.  Routines to handle mount points.
+ *
+ *.Exported_Routines
+ *	void init_mount_point(int, char *, CLIENT *)
+ *
+ *.Local_Routines
+ *	int pseudo_mount(char *, int, char *, CLIENT *)
+ *
+ *.Revision_History
+ *	2-Jul-92	Teelucksingh    Added code for OSF/1
+ *					use of getmntinfo().
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include <fcntl.h>
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+struct hostent   *Server_hostent;
+
+/*
+ * -------------------------  Constants  -------------------------
+ */
+
+/*
+ * Number of times a load generating process will retry amount.
+ * Each load generating process also picks a client shifted
+ * mount start time, and executes a backoff on retry time on
+ * failure.
+ */
+#define NUMBER_MOUNT_RETRIES	10
+
+/*
+ * -------------------------  External Definitions  -------------------------
+ */
+
+/* forward definitions for local routines */
+CLIENT * lad_getmnt_hand(char *);
+static int pseudo_mount(char *, int, char *, CLIENT *);
+
+/*
+ * Mounts are retried when an RPC timeout occurs, in the mainline
+ * code. They are not retried by the RPC clnt_call routine, as the
+ * timeout values are set now.
+ */
+static struct timeval Mount_timer = {  10,  0 };
+
+
+/*
+ * -------------------------  Mount Point Routines  -------------------------
+ */
+
+
+/*
+ * mount the testdir 'dirnum' under the parent directory 'parentdir'.
+ */
+void
+init_mount_point(
+    int		dirnum,
+    char *	parentdir,
+    CLIENT *	mount_client_ptr)
+{
+    char	pnt_dir[SFS_MAXPATHLEN];      /* test dir component name */
+    char	testdirname[SFS_MAXPATHLEN];  /* test dir component name */
+    char	export_fsname[SFS_MAXPATHLEN]; /* "host:path" exported fs */
+    sfs_fh_type file_handle;
+    char	*fh_ptr;
+    char	*cp;
+    int		ret;
+    sfs_fh_data *fh_datap, *Ex_fh_datap;
+
+    fh_datap= calloc(1,sizeof(sfs_fh_data));
+    (void) memset((char *)fh_datap, 0, sizeof(sfs_fh_data));
+    (void) memset((char *)&file_handle, 0, sizeof(file_handle));
+    file_handle.fh_data = fh_datap;
+    file_handle.dir = &Export_dir;
+
+    Ex_fh_datap = (sfs_fh_data *) calloc(1,sizeof(sfs_fh_data));
+    Export_dir.fh_data = Ex_fh_datap;
+
+    (void) strcpy(pnt_dir, parentdir);
+
+    cp = strchr(pnt_dir, ':');
+    if (cp == NULL) {
+	(void) fprintf(stderr, "%s: malformed fsname %s\n",
+			sfs_Myname, parentdir);
+	if (!Validate)
+	    (void) generic_kill(0, SIGINT);
+	exit(86);
+    }
+
+    *cp++ = '\0';
+
+    /*
+     * Now we have the parent directory in the form:
+     *		host:host_path
+     *
+     * First we get the file handle for parent directory
+     *
+     * Verify that the server is running the correct version of
+     * the NFS protocol specification and then proceed to get
+     * the exported fh from the server.
+     */
+    (void) strcpy(testdirname, pnt_dir);
+    (void) strcat(testdirname, ":");
+    (void) strcat(testdirname, cp);
+    (void) strcpy(export_fsname, testdirname);
+
+    if (nfs_version == NFS_VERSION) {
+	(void) memset((char *) &Export_dir.fh2, '\0', sizeof (Export_dir.fh2));
+	fh_ptr = (char *)&Export_dir.fh2;
+    } else if (nfs_version == NFS_V3) {
+	(void) memset((char *) &Export_dir.fh3, '\0', sizeof (Export_dir.fh3));
+	fh_ptr = (char *)&Export_dir.fh3;
+    }
+
+    ret = pseudo_mount(export_fsname, nfs_version,
+					fh_ptr, mount_client_ptr);
+    if (ret < 0) {
+	if (ret == -2)  {
+	    (void) fprintf(stderr,
+		"%s: NFS Protocol Version %lu verification failed.\n",
+		sfs_Myname, (uint32_t)nfs_version);
+	}
+	else  {
+	    (void) fprintf(stderr, "%s: can't pseudo mount %s\n",
+			sfs_Myname, export_fsname);
+	}
+	if (!Validate)
+	    (void) generic_kill(0, SIGINT);
+	exit(87);
+    }
+
+    /*
+     * Setup initial state of export directory
+     */
+    Export_dir.state = Exists;
+    (void) strcpy(Export_dir.file_name, testdirname);
+    Export_dir.dir = &Export_dir;
+
+#ifndef RFS
+    /*
+     * Check for and create the client directory. Stat it first, if not
+     * there then mkdir, if that fails with EEXIST we lost the race but
+     * that's OK.
+     */
+    if (Validate) {
+	(void) sprintf(testdirname, "%s", "validatedir");
+    } else {
+	(void) sprintf(testdirname, "CL%d", Client_num);
+    }
+
+    if ((ret = lad_lookup(&file_handle, testdirname)) == -1) {
+	if (!Validate)
+	    (void) generic_kill(0, SIGINT);
+	exit(88);
+    }
+
+    if (ret == 1) {
+	/*
+	 * Directory doesn't exist so create it
+	 * if it already exists thats OK
+	 */
+        if ((ret = lad_mkdir(&file_handle, testdirname)) == -1) {
+	    if (!Validate)
+	        (void) generic_kill(0, SIGINT);
+	    exit(89);
+        }
+	/*
+	 * If someone else created this out from underneath us simply
+	 * lookup the result and continue on.
+	 */
+        if (ret != 0 && (ret = lad_lookup(&file_handle, testdirname)) == -1) {
+	    if (!Validate)
+	        (void) generic_kill(0, SIGINT);
+	    exit(90);
+        }
+    }
+
+    /* testdirname now exists, verify it is a directory and writeable */
+    if (!fh_isdir(&file_handle) ||
+		(check_fh_access(&file_handle) == -1)) {
+	(void) fprintf(stderr,
+		"%s: %s is either not a directory or not accessible\n",
+			sfs_Myname, testdirname);
+	if (!Validate)
+	    (void) generic_kill(0, SIGINT);
+	exit(91);
+    }
+
+    /*
+     * logically chdir into CL directory
+     */
+   /*  Export_dir = file_handle; Implied bcopy here */
+    (void) memmove(&Export_dir,&file_handle,sizeof(sfs_fh_type));
+    Export_dir.fh_data = Ex_fh_datap;
+    (void ) memmove(Export_dir.fh_data, file_handle.fh_data, 
+			sizeof(sfs_fh_data));
+    (void) memset((char *)&file_handle, 0, sizeof(file_handle));
+    (void) memset((char *)fh_datap, 0, sizeof(sfs_fh_data));
+    file_handle.fh_data = fh_datap;
+    file_handle.dir = &Export_dir;
+
+    /*
+     * Validation only occurs one directory deep so we can exit early
+     */
+    if (Validate)
+        return;
+
+    (void) sprintf(testdirname, "testdir%d", dirnum);
+
+    if ((ret = lad_lookup(&file_handle, testdirname)) == -1) {
+	(void) generic_kill(0, SIGINT);
+	exit(92);
+    }
+
+    if (ret == 1) {
+	/*
+	 * Directory doesn't exist so create it
+	 */
+        if (lad_mkdir(&file_handle, testdirname) != 0) {
+	    (void) fprintf(stderr, "%s: Unable to create %s\n",
+			sfs_Myname, testdirname);
+	    (void) generic_kill(0, SIGINT);
+	    exit(93);
+        }
+    }
+
+    /* testdirname now exists, verify it is a directory and writeable */
+    if (!fh_isdir(&file_handle) ||
+		(check_fh_access(&file_handle) == -1)) {
+	(void) fprintf(stderr,
+		"%s: %s is either not a directory or not accessible\n",
+			sfs_Myname, testdirname);
+	(void) generic_kill(0, SIGINT);
+	exit(94);
+    }
+
+    /*
+     * logically chdir into testdir directory
+     */
+    /* Export_dir = file_handle;*/
+    (void) memmove(&Export_dir, &file_handle, sizeof(struct sfs_fh_type));
+    Export_dir.fh_data = Ex_fh_datap; /* Put pointer back */
+    (void) memmove(Export_dir.fh_data, file_handle.fh_data, sizeof
+			(sfs_fh_data));
+#endif
+} /* init_mount_point */
+
+/*
+ * Get the filehandle for 'mount_fsname', and return it
+ * Returns NULL for error ... not mounted || no NFS client.
+ *
+ * Children should only call this routine 1 time.
+ */
+CLIENT *
+lad_getmnt_hand(
+    char *		mount_point)
+{
+    char 		mnt_pnt[SFS_MAXPATHLEN];    /* working buffer */
+    char 		host[SFS_MAXPATHLEN];     /* host with exported fs */
+    static struct hostent 	hp;
+    struct hostent	*thp;
+    CLIENT		*mount_client_ptr;	/* Mount client handle */
+    char		*cp;
+    int			rpc_result; 		/* rpc call result */
+    uint32_t		mount_vers = 0;
+
+    /*
+     * If the mount point is of the form host:path just use the explicit
+     * name instead of grovelling through the mount table.
+     */
+    (void) strcpy(mnt_pnt, mount_point);
+    cp = strchr(mnt_pnt, ':');
+    if (cp == NULL) {
+	(void) fprintf(stderr, "%s: malformed fsname %s\n",
+			sfs_Myname, mount_point);
+	return(NULL);
+    }
+
+    *cp++ = '\0';
+    (void) strcpy(host, mnt_pnt);
+
+    /* Verify NFS Version */
+    rpc_result = callrpc(host,
+			(uint32_t) NFS_PROGRAM,
+			(uint32_t) nfs_version,
+			(uint32_t) NFSPROC_NULL, (xdrproc_t) xdr_void,
+			(char *) NULL, (xdrproc_t) xdr_void, (char *) NULL);
+    if (rpc_result != 0) {
+	 clnt_perrno((enum clnt_stat)rpc_result);
+	 (void) fprintf(stderr,
+"\nUnable to contact NFS server %s.\n", host);
+	 (void) fprintf(stderr,
+"Verify NFS server daemon supporting version %u is running and\n",
+		(uint32_t)nfs_version);
+	 (void) fprintf(stderr, "registered with the portmapper.\n");
+	return(NULL);
+    }
+
+    /* Get host's address */
+    if ((thp = gethostbyname(host)) == NULL) {
+	/* Failure may be due to yellow pages, try again */
+	if ((thp = gethostbyname(host)) == NULL) {
+	    (void) fprintf(stderr, "%s: %s not in hosts database\n",
+			    sfs_Myname, host);
+	    return(NULL);
+	}
+    }
+
+    hp = *thp;
+    Server_hostent = &hp;
+
+    if (nfs_version == NFS_VERSION)
+	mount_vers = MOUNTVERS;
+    if (nfs_version == NFS_V3)
+	mount_vers = MOUNTVER3;
+
+    mount_client_ptr = lad_clnt_create(0, Server_hostent,
+                                        (uint32_t) MOUNTPROG,
+                                        mount_vers,
+                                        RPC_ANYSOCK, &Mount_timer);
+                
+
+    if (mount_client_ptr == ((CLIENT*) NULL)) {
+	(void) fprintf(stderr,
+			"%s: portmap/mountd %s server not responding",
+			sfs_Myname, mount_point);
+	return(NULL);
+    }
+
+    mount_client_ptr->cl_auth = authunix_create_default();
+    return (mount_client_ptr);
+
+} /* lad_getmnt_hand */
+
+
+/*
+ * Get the filehandle for 'mount_fsname', and return it in 'fh_ptr'.
+ * Returns 0 for OK, -1 for error ... not mounted || no NFS client.
+ *
+ * Children should only call this routine 1 time.
+ */
+static int
+pseudo_mount(
+    char *		mount_fsname,
+    int			version,
+    char *		fh_ptr,
+    CLIENT *		mount_client_ptr)
+{
+    char *		host_ptr;		/* host with exported fs */
+    char *		path_ptr;		/* ptr to path for RPC */
+
+    struct fhstatus 	fhs;			/* status of mountd call */
+    nfs_fh3 *		fh_ptr3;
+    mountres3	 	mntres3;		/* status of mountd call */
+    char *		cp;
+    enum clnt_stat 	rpc_stat;
+    int			tries = 0;		/* Number of retries */
+				/* Space by 200ms intervals. */
+    int			pacesleep = Child_num * 200;
+
+    /* Parse the fsname for host and path strings */
+    cp = strchr(mount_fsname, ':');
+
+    if (cp == NULL) {
+	(void) fprintf(stderr, "%s: malformed fsname %s\n",
+			sfs_Myname, mount_fsname);
+	return(-1);
+    }
+
+    *cp++ = '\0';
+    host_ptr = mount_fsname;
+    path_ptr = cp;
+
+    /* Check host's address */
+    if (gethostbyname(host_ptr) == NULL) {
+	/* Failure may be due to yellow pages, try again */
+	if (gethostbyname(host_ptr) == NULL) {
+	    (void) fprintf(stderr, "%s: %s not in hosts database\n",
+			    sfs_Myname, host_ptr);
+	    return(-1);
+	}
+    }
+
+    if (DEBUG_CHILD_GENERAL) {
+	(void) fprintf(stderr, "%s: mount clnt_call\n", sfs_Myname);
+    }
+
+    /* get fhandle of remote path from host's mountd */
+
+retry_mount:
+    /*
+     * Many children on many clients hammer a server with
+     * mounts. Crude fix is to pace them. Some run rule interpretations
+     * are to have *many* children on each client. This can
+     * cause problems.
+     */
+    (void) msec_sleep(pacesleep);
+
+    if (version == NFS_VERSION) {
+	(void) memset((char *) &fhs, '\0', sizeof (fhs));
+	rpc_stat = clnt_call(mount_client_ptr, MOUNTPROC_MNT, xdr_path,
+			(char *) &path_ptr,xdr_fhstatus,(char *) &fhs,
+			Mount_timer);
+    } else if (version == NFS_V3) {
+	(void) memset((char *) &mntres3, '\0', sizeof (mntres3));
+	rpc_stat = clnt_call(mount_client_ptr, MOUNTPROC_MNT, xdr_dirpath,
+			(char *) &path_ptr, xdr_mntres3, (char *) &mntres3,
+			Mount_timer);
+    } else
+	rpc_stat = RPC_PROGVERSMISMATCH;
+
+    errno = 0;
+    if (rpc_stat != RPC_SUCCESS) {
+
+	switch (rpc_stat) {
+
+	    case RPC_TIMEDOUT:
+		errno = ETIMEDOUT;
+		(void) fprintf(stderr,
+		    "%s: mounting %s:%s server not responding: %s (%d)\n",
+			    sfs_Myname, host_ptr, path_ptr,
+			    strerror(errno), errno);
+		if (tries++ < NUMBER_MOUNT_RETRIES) {
+		    /* Randomize the backoff on retry */
+		    pacesleep = pacesleep + (sfs_random() % 2000);
+		    goto retry_mount;
+		}
+		break;
+
+
+	    case RPC_PMAPFAILURE:
+		errno = ENETDOWN;	/* reasonable error */
+		(void) fprintf(stderr,
+			    "%s: mounting %s portmap call failed: %s (%d)\n",
+			    sfs_Myname, host_ptr, strerror(errno), errno);
+		break;
+
+	    case RPC_PROGNOTREGISTERED:
+		errno = ENETDOWN;	/* reasonable error */
+		(void) fprintf(stderr,
+			    "%s: mounting %s nfsd not registered: %s (%d)\n",
+			    sfs_Myname, host_ptr, strerror(errno), errno);
+		break;
+
+	    case RPC_AUTHERROR:
+		errno = EACCES;
+		(void) fprintf(stderr,
+			"%s: mounting %s authentication failed: %s (%d)\n",
+			sfs_Myname, host_ptr, strerror(errno), errno);
+		break;
+
+	    default:
+		errno = ENETDOWN;	/* reasonable error */
+		(void) fprintf(stderr,
+			    "%s: mounting %s:%s failed: %s (%d)\n",
+			    sfs_Myname, host_ptr, path_ptr,
+			    strerror(errno), errno);
+		break;
+	}
+
+	clnt_perror(mount_client_ptr, "");
+	return(-1);
+
+    } /* MOUNTPROC_MNT call failed */
+
+    if (version == NFS_VERSION) {
+	if (fhs.fhs_status != 0) {
+	    if (fhs.fhs_status == EACCES) {
+		(void) fprintf(stderr, "%s: mounting %s:%s - access denied\n",
+			   sfs_Myname, host_ptr, path_ptr);
+	    } else {
+		(void) fprintf(stderr,
+			    "%s: mounting %s:%s - bad fh status %d\n ",
+			    sfs_Myname, host_ptr, path_ptr, fhs.fhs_status);
+	    }
+	    return(-1);
+	} /* bad fhs status */
+
+	/*
+	 * fill in the caller's file handle
+	 */
+	(void) memmove(fh_ptr, (char *) &fhs.fhs_fh, NFS_FHSIZE);
+
+    } else if (version == NFS_V3) {
+
+	if (mntres3.fhs_status != MNT_OK) {
+	    if (mntres3.fhs_status == MNT3ERR_ACCES) {
+		(void) fprintf(stderr, "%s: mounting %s:%s - access denied\n",
+			   sfs_Myname, host_ptr, path_ptr);
+	    } else {
+		(void) fprintf(stderr,
+			    "%s: mounting %s:%s - bad fh status %d\n ",
+		    sfs_Myname, host_ptr, path_ptr, mntres3.fhs_status);
+	    }
+	    return(-1);
+	} /* bad fhs status */
+
+	/*
+	 * fill in the caller's file handle
+	 * space pointed by fhandle3_val is allocated through xdr_mntres3
+	 */
+	fh_ptr3 = (nfs_fh3 *)fh_ptr;
+	fh_ptr3->fh3_length = mntres3.mntres3_u.mntinfo.fhandle.fhandle3_len;
+	(void) memmove((char *) fh_ptr3->fh3_u.data,
+			(char *) mntres3.mntres3_u.mntinfo.fhandle.fhandle3_val,
+			fh_ptr3->fh3_length);
+    }
+
+    return(0);
+
+} /* pseudo_mount */
+
+
+/* sfs_c_mnt.c */
diff --git a/TBBT/trace_play/sfs_c_nfs.h b/TBBT/trace_play/sfs_c_nfs.h
new file mode 100644
index 0000000..eb34652
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_nfs.h
@@ -0,0 +1,1470 @@
+#ifndef __sfs_c_nfs_h
+#define __sfs_c_nfs_h
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * @(#)sfs_c_nfs.h	2.1	97/10/23
+ *
+ * -------------------------- sfs_c_nfs.h -------------------------
+ *
+ *	Literals and types for the NFS protocol, Version 2.
+ *
+ *.Revision_History
+ *
+ *	Richard Bean	17-May-90	Created.
+ */
+
+
+/*
+ * for RPC calls
+ */
+/* #define NFS_PORT	2049 */
+#define NFS_PROGRAM	((uint32_t)100003)
+#define NFS_VERSION	((uint32_t)2)
+#define NFS_V3		((uint32_t)3)
+
+/*
+ * fixed sizes
+ */
+#define NFS_MAXDATA	8192
+//#define NFS_MAXDATA	16384
+#define NFS_MAXPATHLEN	1024
+#define NFS_MAXNAMLEN	255
+#define NFS_COOKIESIZE	4
+#define NFS_FHSIZE	32
+
+
+#if !defined(AIX)
+typedef struct {
+	char	data[NFS_FHSIZE];
+} fhandle_t;
+#endif  /* AIX  */
+
+/*
+ * Definition of "standard" mount parameters
+ */
+#define MOUNTPROG	100005
+#define MOUNTVERS	1
+#define MOUNTPROC_MNT	1
+
+struct fhstatus {
+        int fhs_status;
+        fhandle_t fhs_fh;
+};
+
+typedef fhandle_t nfs_fh;
+
+/*
+ * fattr modes
+ */
+/*
+ * The mode mask is used to mask off server vendor specific mode bits
+ * from the mode field.  This allows clients from different vendors to
+ * validate servers from different vendors.
+ */
+#define NFSMODE_MASK 0177777
+#define NFSMODE_FMT 0170000
+#define NFSMODE_DIR 0040000
+#define NFSMODE_CHR 0020000
+#define NFSMODE_BLK 0060000
+#define NFSMODE_REG 0100000
+#define NFSMODE_LNK 0120000
+#define NFSMODE_SOCK 0140000
+#define NFSMODE_FIFO 0010000
+
+
+/*
+ * NFS Procedures
+ */
+#define NFSPROC_NULL		0
+#define NFSPROC_GETATTR		1
+#define NFSPROC_SETATTR		2
+#define NFSPROC_ROOT		3
+#define NFSPROC_LOOKUP		4
+#define NFSPROC_READLINK	5
+#define NFSPROC_READ		6
+#define NFSPROC_WRITECACHE	7
+#define NFSPROC_WRITE		8
+#define NFSPROC_CREATE		9
+#define NFSPROC_REMOVE		10
+#define NFSPROC_RENAME		11
+#define NFSPROC_LINK		12
+#define NFSPROC_SYMLINK		13
+#define NFSPROC_MKDIR		14
+#define NFSPROC_RMDIR		15
+#define NFSPROC_READDIR		16
+#define NFSPROC_STATFS		17
+#define NFS_PROCEDURE_COUNT	(NFSPROC_STATFS + 1)
+
+
+/*
+ * call and return types
+ */
+enum nfsstat {
+	NFS_OK =		0,
+	NFSERR_PERM =		1,
+	NFSERR_NOENT =		2,
+	NFSERR_IO =		5,
+	NFSERR_NXIO =		6,
+	NFSERR_ACCES =		13,
+	NFSERR_EXIST =		17,
+	NFSERR_XDEV =		18,
+	NFSERR_NODEV =		19,
+	NFSERR_NOTDIR =		20,
+	NFSERR_ISDIR =		21,
+	NFSERR_INVAL =		22,
+	NFSERR_FBIG =		27,
+	NFSERR_NOSPC =		28,
+	NFSERR_ROFS =		30,
+	NFSERR_OPNOTSUPP =	45,
+	NFSERR_NAMETOOLONG =	63,
+	NFSERR_NOTEMPTY =	66,
+	NFSERR_DQUOT =		69,
+	NFSERR_STALE =		70,
+	NFSERR_REMOTE =		71,
+	NFSERR_WFLUSH =		99
+};
+typedef enum nfsstat nfsstat;
+
+
+enum ftype {
+	NFNON = 0,
+	NFREG = 1,
+	NFDIR = 2,
+	NFBLK = 3,
+	NFCHR = 4,
+	NFLNK = 5,
+	NFSOCK = 6,
+	NFBAD = 7,
+	NFFIFO = 8
+};
+typedef enum ftype ftype;
+#define NUM_TYPES 5
+
+
+struct nfstime {
+	unsigned int seconds;
+	unsigned int useconds;
+};
+typedef struct nfstime nfstime;
+
+
+struct fattr {
+	ftype type;
+	unsigned int mode;
+	unsigned int nlink;
+	unsigned int uid;
+	unsigned int gid;
+	unsigned int size;
+	unsigned int blocksize;
+	unsigned int rdev;
+	unsigned int blocks;
+	unsigned int fsid;
+	unsigned int fileid;
+	nfstime atime;
+	nfstime mtime;
+	nfstime ctime;
+};
+typedef struct fattr fattr;
+
+
+struct sattr {
+	unsigned int mode;
+	unsigned int uid;
+	unsigned int gid;
+	unsigned int size;
+	nfstime atime;
+	nfstime mtime;
+};
+typedef struct sattr sattr;
+
+
+typedef char *filename;
+
+
+typedef char *nfspath;
+
+
+struct attrstat {
+	nfsstat status;
+	union {
+		fattr attributes;
+	} attrstat_u;
+};
+typedef struct attrstat attrstat;
+
+
+struct sattrargs {
+	nfs_fh file;
+	sattr attributes;
+};
+typedef struct sattrargs sattrargs;
+
+
+struct diropargs {
+	nfs_fh dir;
+	filename name;
+};
+typedef struct diropargs diropargs;
+
+
+struct diropokres {
+	nfs_fh file;
+	fattr attributes;
+};
+typedef struct diropokres diropokres;
+
+
+struct diropres {
+	nfsstat status;
+	union {
+		diropokres diropres;
+	} diropres_u;
+};
+typedef struct diropres diropres;
+
+
+struct readlinkres {
+	nfsstat status;
+	struct {
+		nfspath data;
+		int len;	/* for convenience only, not in the protocol */
+	} readlinkres_u;
+};
+typedef struct readlinkres readlinkres;
+
+
+struct readargs {
+	nfs_fh file;
+	unsigned int offset;
+	unsigned int count;
+	unsigned int totalcount;	/* unused field, but in the protocol */
+};
+typedef struct readargs readargs;
+
+
+struct readokres {
+	fattr attributes;
+	struct {
+		unsigned int data_len;
+		char *data_val;
+	} data;
+};
+typedef struct readokres readokres;
+
+
+struct readres {
+	nfsstat status;
+	union {
+		readokres reply;
+	} readres_u;
+};
+typedef struct readres readres;
+
+
+struct writeargs {
+	nfs_fh file;
+	unsigned int beginoffset;	/* unused field, but in the protocol */
+	unsigned int offset;
+	unsigned int totalcount;	/* unused field, but in the protocol */
+	struct {
+		unsigned int data_len;
+		char *data_val;
+	} data;
+};
+typedef struct writeargs writeargs;
+
+
+struct createargs {
+	diropargs where;
+	sattr attributes;
+};
+typedef struct createargs createargs;
+
+
+struct renameargs {
+	diropargs from;
+	diropargs to;
+};
+typedef struct renameargs renameargs;
+
+
+struct linkargs {
+	nfs_fh from;
+	diropargs to;
+};
+typedef struct linkargs linkargs;
+
+
+struct symlinkargs {
+	diropargs from;
+	nfspath to;
+	sattr attributes;
+};
+typedef struct symlinkargs symlinkargs;
+
+
+struct mkdirargs {
+	diropargs where;
+	sattr attributes;
+};
+typedef struct mkdirargs mkdirargs;
+
+
+typedef char nfscookie[NFS_COOKIESIZE];
+
+
+struct readdirargs {
+	nfs_fh dir;
+	nfscookie cookie;
+	unsigned int count;
+};
+typedef struct readdirargs readdirargs;
+
+
+struct entry {
+	bool_t valid;	/* bool for entry is present */
+	unsigned int fileid;
+	uint16_t name_len;
+	filename name;
+	nfscookie cookie;
+};
+typedef struct entry entry;
+
+
+struct dirlist {
+	int max_entries;	/* for convenience only, not in the protocol */
+	entry *entries;		/* a stream of consecutive entry's */
+	bool_t eof;
+};
+typedef struct dirlist dirlist;
+
+
+struct readdirres {
+	nfsstat status;
+	union {
+		dirlist reply;
+	} readdirres_u;
+};
+typedef struct readdirres readdirres;
+
+
+struct statfsokres {
+	unsigned int tsize;
+	unsigned int bsize;
+	unsigned int blocks;
+	unsigned int bfree;
+	unsigned int bavail;
+};
+typedef struct statfsokres statfsokres;
+
+
+struct statfsres {
+	nfsstat status;
+	union {
+		statfsokres reply;
+	} statfsres_u;
+};
+typedef struct statfsres statfsres;
+
+
+/*
+ *	Literals and types for the NFS protocol, Version 3.
+ */
+
+
+/*
+ * for RPC calls
+ */
+
+/*
+ * fixed sizes
+ */
+#define NFS3_FHSIZE	64
+#define NFS3_COOKIEVERFSIZE	8
+#define NFS3_CREATEVERFSIZE	8
+#define NFS3_WRITEVERFSIZE	8
+
+#define nfs3nametoolong	((char *)-1)
+
+/*
+ * Not all systems have a built in long long type so we define a
+ * special version for sfs to use.
+ */
+typedef union {
+	struct {
+		uint32_t _u;
+		uint32_t _l;
+	} _p;
+	char _f[8];
+} nfs_uint64_t;
+
+typedef char *filename3;
+
+typedef char *nfspath3;
+
+typedef char cookieverf3[NFS3_COOKIEVERFSIZE];
+
+typedef char createverf3[NFS3_CREATEVERFSIZE];
+
+typedef char writeverf3[NFS3_WRITEVERFSIZE];
+
+struct nfs_fh3 {
+	unsigned int fh3_length;
+	union nfs_fh3_u {
+		struct {
+			char _u[NFS_FHSIZE];
+			char _l[NFS_FHSIZE];
+		} _p;
+		char data[NFS3_FHSIZE];
+	} fh3_u;
+};
+#define fh3_fsid	fh3_u.nfs_fh3_i.fh3_i.fh_fsid
+#define fh3_len		fh3_u.nfs_fh3_i.fh3_i.fh_len /* fid length */
+#define fh3_data	fh3_u.nfs_fh3_i.fh3_i.fh_data /* fid bytes */
+#define fh3_xlen	fh3_u.nfs_fh3_i.fh3_i.fh_xlen
+#define fh3_xdata	fh3_u.nfs_fh3_i.fh3_i.fh_xdata
+typedef struct nfs_fh3 nfs_fh3;
+
+struct diropargs3 {
+	nfs_fh3 dir;
+	filename3 name;
+};
+typedef struct diropargs3 diropargs3;
+
+struct nfstime3 {
+	uint32_t seconds;
+	uint32_t nseconds;
+};
+typedef struct nfstime3 nfstime3;
+
+struct specdata3 {
+	uint32_t specdata1;
+	uint32_t specdata2;
+};
+typedef struct specdata3 specdata3;
+
+
+/*
+ * call and return types
+ */
+enum nfsstat3 {
+	NFS3_OK = 0,
+	NFS3ERR_PERM = 1,
+	NFS3ERR_NOENT = 2,
+	NFS3ERR_IO = 5,
+	NFS3ERR_NXIO = 6,
+	NFS3ERR_ACCES = 13,
+	NFS3ERR_EXIST = 17,
+	NFS3ERR_XDEV = 18,
+	NFS3ERR_NODEV = 19,
+	NFS3ERR_NOTDIR = 20,
+	NFS3ERR_ISDIR = 21,
+	NFS3ERR_INVAL = 22,
+	NFS3ERR_FBIG = 27,
+	NFS3ERR_NOSPC = 28,
+	NFS3ERR_ROFS = 30,
+	NFS3ERR_MLINK = 31,
+	NFS3ERR_NAMETOOLONG = 63,
+	NFS3ERR_NOTEMPTY = 66,
+	NFS3ERR_DQUOT = 69,
+	NFS3ERR_STALE = 70,
+	NFS3ERR_REMOTE = 71,
+	NFS3ERR_BADHANDLE = 10001,
+	NFS3ERR_NOT_SYNC = 10002,
+	NFS3ERR_BAD_COOKIE = 10003,
+	NFS3ERR_NOTSUPP = 10004,
+	NFS3ERR_TOOSMALL = 10005,
+	NFS3ERR_SERVERFAULT = 10006,
+	NFS3ERR_BADTYPE = 10007,
+	NFS3ERR_JUKEBOX = 10008,
+	NFS3ERR_RFS_TIMEOUT = 10009,			// RFS
+	NFS3ERR_RFS_MISS = 10010		// RFS reply missed in trace
+};
+typedef enum nfsstat3 nfsstat3;
+
+enum ftype3 {
+	NF3NON = 0,
+	NF3REG = 1,
+	NF3DIR = 2,
+	NF3BLK = 3,
+	NF3CHR = 4,
+	NF3LNK = 5,
+	NF3SOCK = 6,
+	NF3FIFO = 7
+};
+typedef enum ftype3 ftype3;
+#define NUM_TYPES 5
+
+
+struct fattr3 {
+	ftype3		type;
+	uint32_t		mode;
+	uint32_t		nlink;
+	uint32_t		uid;
+	uint32_t		gid;
+	nfs_uint64_t	size;
+	nfs_uint64_t	used;
+	specdata3	rdev;
+	nfs_uint64_t	fsid;
+	nfs_uint64_t	fileid;
+	nfstime3	atime;
+	nfstime3	mtime;
+	nfstime3	ctime;
+};
+typedef struct fattr3 fattr3;
+
+struct post_op_attr {
+	bool_t	attributes;
+	fattr3	attr;
+};
+typedef struct post_op_attr post_op_attr;
+
+struct wcc_attr {
+	nfs_uint64_t	size;
+	nfstime3	mtime;
+	nfstime3	ctime;
+};
+typedef struct wcc_attr wcc_attr;
+
+struct pre_op_attr {
+	bool_t		attributes;
+	wcc_attr	attr;
+};
+typedef struct pre_op_attr pre_op_attr;
+
+struct wcc_data {
+	pre_op_attr	before;
+	post_op_attr	after;
+};
+typedef struct wcc_data wcc_data;
+
+struct post_op_fh3 {
+	bool_t	handle_follows;
+	nfs_fh3 handle;
+};
+typedef struct post_op_fh3 post_op_fh3;
+
+enum time_how {
+	DONT_CHANGE = 0,
+	SET_TO_SERVER_TIME = 1,
+	SET_TO_CLIENT_TIME = 2
+};
+typedef enum time_how time_how;
+
+struct set_mode3 {
+	bool_t set_it;
+	uint32_t mode;
+};
+typedef struct set_mode3 set_mode3;
+
+struct set_uid3 {
+	bool_t set_it;
+	uint32_t uid;
+};
+typedef struct set_uid3 set_uid3;
+ 
+struct set_gid3 {
+	bool_t set_it;
+	uint32_t gid;
+};
+typedef struct set_gid3 set_gid3;
+ 
+struct set_size3 {
+	bool_t		set_it;
+	nfs_uint64_t	size;
+};
+typedef struct set_size3 set_size3;
+ 
+struct set_atime {
+	time_how set_it;
+	nfstime3 atime;
+};
+typedef struct set_atime set_atime;
+ 
+struct set_mtime {
+	time_how set_it;
+	nfstime3 mtime;
+};
+typedef struct set_mtime set_mtime;
+ 
+struct sattr3 {
+	set_mode3	mode;
+	set_uid3	uid;
+	set_gid3	gid;
+	set_size3	size;
+	set_atime	atime;
+	set_mtime	mtime;
+};
+typedef struct sattr3 sattr3;
+
+
+#define resok   res_u.ok
+#define resfail res_u.fail
+
+struct GETATTR3args {
+	nfs_fh3 object;
+};
+typedef struct GETATTR3args GETATTR3args;
+
+struct GETATTR3resok {
+	fattr3 obj_attributes;
+};
+typedef struct GETATTR3resok GETATTR3resok;
+
+struct GETATTR3res {
+	nfsstat3 status;
+	union {
+		GETATTR3resok ok;
+	} res_u;
+};
+typedef struct GETATTR3res GETATTR3res;
+
+struct sattrguard3 {
+	bool_t		check;
+	nfstime3	obj_ctime;
+};
+typedef struct sattrguard3 sattrguard3;
+
+struct SETATTR3args {
+	nfs_fh3		object;
+	sattr3		new_attributes;
+	sattrguard3	guard;
+};
+typedef struct SETATTR3args SETATTR3args;
+
+struct SETATTR3resok {
+	wcc_data obj_wcc;
+};
+typedef struct SETATTR3resok SETATTR3resok;
+
+struct SETATTR3resfail {
+	wcc_data obj_wcc;
+};
+typedef struct SETATTR3resfail SETATTR3resfail;
+
+struct SETATTR3res {
+	nfsstat3 status;
+	union {
+		SETATTR3resok	ok;
+		SETATTR3resfail fail;
+	} res_u;
+};
+typedef struct SETATTR3res SETATTR3res;
+
+struct LOOKUP3args {
+	diropargs3 what;
+};
+typedef struct LOOKUP3args LOOKUP3args;
+
+struct LOOKUP3resok {
+	nfs_fh3		object;
+	post_op_attr	obj_attributes;
+	post_op_attr	dir_attributes;
+};
+typedef struct LOOKUP3resok LOOKUP3resok;
+
+struct LOOKUP3resfail {
+	post_op_attr dir_attributes;
+};
+typedef struct LOOKUP3resfail LOOKUP3resfail;
+
+struct LOOKUP3res {
+	nfsstat3 status;
+	union {
+		LOOKUP3resok	ok;
+		LOOKUP3resfail	fail;
+	} res_u;
+};
+typedef struct LOOKUP3res LOOKUP3res;
+
+struct ACCESS3args {
+	nfs_fh3	object;
+	uint32_t	access;
+};
+typedef struct ACCESS3args ACCESS3args;
+#define ACCESS3_READ	0x1
+#define ACCESS3_LOOKUP	0x2
+#define ACCESS3_MODIFY	0x4
+#define ACCESS3_EXTEND	0x8
+#define ACCESS3_DELETE	0x10
+#define ACCESS3_EXECUTE 0x20
+
+struct ACCESS3resok {
+	post_op_attr obj_attributes;
+	uint32_t access;
+};
+typedef struct ACCESS3resok ACCESS3resok;
+
+struct ACCESS3resfail {
+	post_op_attr obj_attributes;
+};
+typedef struct ACCESS3resfail ACCESS3resfail;
+
+struct ACCESS3res {
+	nfsstat3 status;
+	union {
+		ACCESS3resok	ok;
+		ACCESS3resfail	fail;
+	} res_u;
+};
+typedef struct ACCESS3res ACCESS3res;
+
+struct READLINK3args {
+	nfs_fh3 symlink;
+};
+typedef struct READLINK3args READLINK3args;
+
+struct READLINK3resok {
+	post_op_attr	symlink_attributes;
+	nfspath3	data;
+};
+typedef struct READLINK3resok READLINK3resok;
+
+struct READLINK3resfail {
+	post_op_attr symlink_attributes;
+};
+typedef struct READLINK3resfail READLINK3resfail;
+
+struct READLINK3res {
+	nfsstat3 status;
+	union {
+		READLINK3resok		ok;
+		READLINK3resfail	fail;
+	} res_u;
+};
+typedef struct READLINK3res READLINK3res;
+
+struct READ3args {
+	nfs_fh3		file;
+	nfs_uint64_t	offset;
+	uint32_t		count;
+};
+typedef struct READ3args READ3args;
+
+struct READ3resok {
+	post_op_attr file_attributes;
+	uint32_t count;
+	bool_t eof;
+	struct {
+		unsigned int data_len;
+		char *data_val;
+	} data;
+	unsigned int size;
+};
+typedef struct READ3resok READ3resok;
+
+struct READ3resfail {
+	post_op_attr file_attributes;
+};
+typedef struct READ3resfail READ3resfail;
+
+struct READ3res {
+	nfsstat3 status;
+	union {
+		READ3resok ok;
+		READ3resfail fail;
+	} res_u;
+};
+typedef struct READ3res READ3res;
+
+enum stable_how {
+	UNSTABLE = 0,
+	DATA_SYNC = 1,
+	FILE_SYNC = 2
+};
+typedef enum stable_how stable_how;
+
+struct WRITE3args {
+	nfs_fh3 file;
+	nfs_uint64_t offset;
+	uint32_t count;
+	stable_how stable;
+	struct {
+		unsigned int data_len;
+		char *data_val;
+	} data;
+};
+typedef struct WRITE3args WRITE3args;
+
+struct WRITE3resok {
+	wcc_data file_wcc;
+	uint32_t count;
+	stable_how committed;
+	writeverf3 verf;
+};
+typedef struct WRITE3resok WRITE3resok;
+
+struct WRITE3resfail {
+	wcc_data file_wcc;
+};
+typedef struct WRITE3resfail WRITE3resfail;
+
+struct WRITE3res {
+	nfsstat3 status;
+	union {
+		WRITE3resok ok;
+		WRITE3resfail fail;
+	} res_u;
+};
+typedef struct WRITE3res WRITE3res;
+
+enum createmode3 {
+	UNCHECKED = 0,
+	GUARDED = 1,
+	EXCLUSIVE = 2
+};
+typedef enum createmode3 createmode3;
+
+struct createhow3 {
+	createmode3 mode;
+	union {
+		sattr3 obj_attributes;
+		createverf3 verf;
+	} createhow3_u;
+};
+typedef struct createhow3 createhow3;
+
+struct CREATE3args {
+	diropargs3 where;
+	createhow3 how;
+};
+typedef struct CREATE3args CREATE3args;
+
+struct CREATE3resok {
+	post_op_fh3 obj;
+	post_op_attr obj_attributes;
+	wcc_data dir_wcc;
+};
+typedef struct CREATE3resok CREATE3resok;
+
+struct CREATE3resfail {
+	wcc_data dir_wcc;
+};
+typedef struct CREATE3resfail CREATE3resfail;
+
+struct CREATE3res {
+	nfsstat3 status;
+	union {
+		CREATE3resok ok;
+		CREATE3resfail fail;
+	} res_u;
+};
+typedef struct CREATE3res CREATE3res;
+
+struct MKDIR3args {
+	diropargs3 where;
+	sattr3 attributes;
+};
+typedef struct MKDIR3args MKDIR3args;
+
+struct MKDIR3resok {
+	post_op_fh3 obj;
+	post_op_attr obj_attributes;
+	wcc_data dir_wcc;
+};
+typedef struct MKDIR3resok MKDIR3resok;
+
+struct MKDIR3resfail {
+	wcc_data dir_wcc;
+};
+typedef struct MKDIR3resfail MKDIR3resfail;
+
+struct MKDIR3res {
+	nfsstat3 status;
+	union {
+		MKDIR3resok ok;
+		MKDIR3resfail fail;
+	} res_u;
+};
+typedef struct MKDIR3res MKDIR3res;
+
+struct symlinkdata3 {
+	sattr3 symlink_attributes;
+	nfspath3 symlink_data;
+};
+typedef struct symlinkdata3 symlinkdata3;
+
+struct SYMLINK3args {
+	diropargs3 where;
+	symlinkdata3 symlink;
+};
+typedef struct SYMLINK3args SYMLINK3args;
+
+struct SYMLINK3resok {
+	post_op_fh3 obj;
+	post_op_attr obj_attributes;
+	wcc_data dir_wcc;
+};
+typedef struct SYMLINK3resok SYMLINK3resok;
+
+struct SYMLINK3resfail {
+	wcc_data dir_wcc;
+};
+typedef struct SYMLINK3resfail SYMLINK3resfail;
+
+struct SYMLINK3res {
+	nfsstat3 status;
+	union {
+		SYMLINK3resok ok;
+		SYMLINK3resfail fail;
+	} res_u;
+};
+typedef struct SYMLINK3res SYMLINK3res;
+
+struct devicedata3 {
+	sattr3 dev_attributes;
+	specdata3 spec;
+};
+typedef struct devicedata3 devicedata3;
+
+struct mknoddata3 {
+	ftype3 type;
+	union {
+		devicedata3 device;
+		sattr3 pipe_attributes;
+	} mknoddata3_u;
+};
+typedef struct mknoddata3 mknoddata3;
+
+struct MKNOD3args {
+	diropargs3 where;
+	mknoddata3 what;
+};
+typedef struct MKNOD3args MKNOD3args;
+
+struct MKNOD3resok {
+	post_op_fh3 obj;
+	post_op_attr obj_attributes;
+	wcc_data dir_wcc;
+};
+typedef struct MKNOD3resok MKNOD3resok;
+
+struct MKNOD3resfail {
+	wcc_data dir_wcc;
+};
+typedef struct MKNOD3resfail MKNOD3resfail;
+
+struct MKNOD3res {
+	nfsstat3 status;
+	union {
+		MKNOD3resok ok;
+		MKNOD3resfail fail;
+	} res_u;
+};
+typedef struct MKNOD3res MKNOD3res;
+
+struct REMOVE3args {
+	diropargs3 object;
+};
+typedef struct REMOVE3args REMOVE3args;
+
+struct REMOVE3resok {
+	wcc_data dir_wcc;
+};
+typedef struct REMOVE3resok REMOVE3resok;
+
+struct REMOVE3resfail {
+	wcc_data dir_wcc;
+};
+typedef struct REMOVE3resfail REMOVE3resfail;
+
+struct REMOVE3res {
+	nfsstat3 status;
+	union {
+		REMOVE3resok ok;
+		REMOVE3resfail fail;
+	} res_u;
+};
+typedef struct REMOVE3res REMOVE3res;
+
+struct RMDIR3args {
+	diropargs3 object;
+};
+typedef struct RMDIR3args RMDIR3args;
+
+struct RMDIR3resok {
+	wcc_data dir_wcc;
+};
+typedef struct RMDIR3resok RMDIR3resok;
+
+struct RMDIR3resfail {
+	wcc_data dir_wcc;
+};
+typedef struct RMDIR3resfail RMDIR3resfail;
+
+struct RMDIR3res {
+	nfsstat3 status;
+	union {
+		RMDIR3resok ok;
+		RMDIR3resfail fail;
+	} res_u;
+};
+typedef struct RMDIR3res RMDIR3res;
+
+struct RENAME3args {
+	diropargs3 from;
+	diropargs3 to;
+};
+typedef struct RENAME3args RENAME3args;
+
+struct RENAME3resok {
+	wcc_data fromdir_wcc;
+	wcc_data todir_wcc;
+};
+typedef struct RENAME3resok RENAME3resok;
+
+struct RENAME3resfail {
+	wcc_data fromdir_wcc;
+	wcc_data todir_wcc;
+};
+typedef struct RENAME3resfail RENAME3resfail;
+
+struct RENAME3res {
+	nfsstat3 status;
+	union {
+		RENAME3resok ok;
+		RENAME3resfail fail;
+	} res_u;
+};
+typedef struct RENAME3res RENAME3res;
+
+struct LINK3args {
+	nfs_fh3 file;
+	diropargs3 link;
+};
+typedef struct LINK3args LINK3args;
+
+struct LINK3resok {
+	post_op_attr file_attributes;
+	wcc_data linkdir_wcc;
+};
+typedef struct LINK3resok LINK3resok;
+
+struct LINK3resfail {
+	post_op_attr file_attributes;
+	wcc_data linkdir_wcc;
+};
+typedef struct LINK3resfail LINK3resfail;
+
+struct LINK3res {
+	nfsstat3 status;
+	union {
+		LINK3resok ok;
+		LINK3resfail fail;
+	} res_u;
+};
+typedef struct LINK3res LINK3res;
+
+struct READDIR3args {
+	nfs_fh3 dir;
+	nfs_uint64_t cookie;
+	cookieverf3 cookieverf;
+	uint32_t count;
+};
+typedef struct READDIR3args READDIR3args;
+
+struct entry3 {
+	nfs_uint64_t fileid;
+	char name[SFS_MAXNAMLEN];
+	nfs_uint64_t cookie;
+};
+typedef struct entry3 entry3;
+
+struct dirlist3 {
+	entry3 *entries;
+	bool_t eof;
+};
+typedef struct dirlist3 dirlist3;
+
+struct READDIR3resok {
+	post_op_attr dir_attributes;
+	cookieverf3 cookieverf;
+	dirlist3 reply;
+	unsigned int size;
+	unsigned int count;
+	nfs_uint64_t cookie;
+};
+typedef struct READDIR3resok READDIR3resok;
+
+struct READDIR3resfail {
+	post_op_attr dir_attributes;
+};
+typedef struct READDIR3resfail READDIR3resfail;
+
+struct READDIR3res {
+	nfsstat3 status;
+	union {
+		READDIR3resok ok;
+		READDIR3resfail fail;
+	} res_u;
+};
+typedef struct READDIR3res READDIR3res;
+
+struct READDIRPLUS3args {
+	nfs_fh3 dir;
+	nfs_uint64_t cookie;
+	cookieverf3 cookieverf;
+	uint32_t dircount;
+	uint32_t maxcount;
+};
+typedef struct READDIRPLUS3args READDIRPLUS3args;
+
+struct entryplus3 {
+	nfs_uint64_t fileid;
+	char name[SFS_MAXNAMLEN];
+	nfs_uint64_t cookie;
+	post_op_attr name_attributes;
+	post_op_fh3 name_handle;
+};
+typedef struct entryplus3 entryplus3;
+
+struct dirlistplus3 {
+	entryplus3 *entries;
+	bool_t eof;
+};
+typedef struct dirlistplus3 dirlistplus3;
+
+struct READDIRPLUS3resok {
+	post_op_attr dir_attributes;
+	cookieverf3 cookieverf;
+	dirlistplus3 reply;
+	unsigned int size;
+	unsigned int count;
+	unsigned int maxcount;
+	post_op_attr *attributes;
+	post_op_fh3 *handles;
+};
+typedef struct READDIRPLUS3resok READDIRPLUS3resok;
+
+struct READDIRPLUS3resfail {
+	post_op_attr dir_attributes;
+};
+typedef struct READDIRPLUS3resfail READDIRPLUS3resfail;
+
+struct READDIRPLUS3res {
+	nfsstat3 status;
+	union {
+		READDIRPLUS3resok ok;
+		READDIRPLUS3resfail fail;
+	} res_u;
+};
+typedef struct READDIRPLUS3res READDIRPLUS3res;
+
+struct FSSTAT3args {
+	nfs_fh3 fsroot;
+};
+typedef struct FSSTAT3args FSSTAT3args;
+
+struct FSSTAT3resok {
+	post_op_attr obj_attributes;
+	nfs_uint64_t tbytes;
+	nfs_uint64_t fbytes;
+	nfs_uint64_t abytes;
+	nfs_uint64_t tfiles;
+	nfs_uint64_t ffiles;
+	nfs_uint64_t afiles;
+	uint32_t invarsec;
+};
+typedef struct FSSTAT3resok FSSTAT3resok;
+
+struct FSSTAT3resfail {
+	post_op_attr obj_attributes;
+};
+typedef struct FSSTAT3resfail FSSTAT3resfail;
+
+struct FSSTAT3res {
+	nfsstat3 status;
+	union {
+		FSSTAT3resok ok;
+		FSSTAT3resfail fail;
+	} res_u;
+};
+typedef struct FSSTAT3res FSSTAT3res;
+
+struct FSINFO3args {
+	nfs_fh3 fsroot;
+};
+typedef struct FSINFO3args FSINFO3args;
+
+struct FSINFO3resok {
+	post_op_attr obj_attributes;
+	uint32_t rtmax;
+	uint32_t rtpref;
+	uint32_t rtmult;
+	uint32_t wtmax;
+	uint32_t wtpref;
+	uint32_t wtmult;
+	uint32_t dtpref;
+	nfs_uint64_t maxfilesize;
+	nfstime3 time_delta;
+	uint32_t properties;
+};
+typedef struct FSINFO3resok FSINFO3resok;
+
+struct FSINFO3resfail {
+	post_op_attr obj_attributes;
+};
+typedef struct FSINFO3resfail FSINFO3resfail;
+#define FSF3_LINK 0x1
+#define FSF3_SYMLINK 0x2
+#define FSF3_HOMOGENEOUS 0x8
+#define FSF3_CANSETTIME 0x10
+
+struct FSINFO3res {
+	nfsstat3 status;
+	union {
+		FSINFO3resok ok;
+		FSINFO3resfail fail;
+	} res_u;
+};
+typedef struct FSINFO3res FSINFO3res;
+
+struct PATHCONF3args {
+	nfs_fh3 object;
+};
+typedef struct PATHCONF3args PATHCONF3args;
+
+struct PATHCONF3resok {
+	post_op_attr obj_attributes;
+	uint32_t link_max;
+	uint32_t name_max;
+	bool_t no_trunc;
+	bool_t chown_restricted;
+	bool_t case_insensitive;
+	bool_t case_preserving;
+};
+typedef struct PATHCONF3resok PATHCONF3resok;
+
+struct PATHCONF3resfail {
+	post_op_attr obj_attributes;
+};
+typedef struct PATHCONF3resfail PATHCONF3resfail;
+
+struct PATHCONF3res {
+	nfsstat3 status;
+	union {
+		PATHCONF3resok ok;
+		PATHCONF3resfail fail;
+	} res_u;
+};
+typedef struct PATHCONF3res PATHCONF3res;
+
+struct COMMIT3args {
+	nfs_fh3 file;
+	nfs_uint64_t offset;
+	uint32_t count;
+};
+typedef struct COMMIT3args COMMIT3args;
+
+struct COMMIT3resok {
+	wcc_data file_wcc;
+	writeverf3 verf;
+};
+typedef struct COMMIT3resok COMMIT3resok;
+
+struct COMMIT3resfail {
+	wcc_data file_wcc;
+};
+typedef struct COMMIT3resfail COMMIT3resfail;
+
+struct COMMIT3res {
+	nfsstat3 status;
+	union {
+		COMMIT3resok ok;
+		COMMIT3resfail fail;
+	} res_u;
+};
+typedef struct COMMIT3res COMMIT3res;
+
+/*
+ * NFS Procedures
+ */
+#define NFSPROC3_NULL		0
+#define NFSPROC3_GETATTR	1
+#define NFSPROC3_SETATTR	2
+#define NFSPROC3_LOOKUP		3
+#define NFSPROC3_ACCESS		4
+#define NFSPROC3_READLINK	5
+#define NFSPROC3_READ		6
+#define NFSPROC3_WRITE		7
+#define NFSPROC3_CREATE		8
+#define NFSPROC3_MKDIR		9
+#define NFSPROC3_SYMLINK	10
+#define NFSPROC3_MKNOD		11
+#define NFSPROC3_REMOVE		12
+#define NFSPROC3_RMDIR		13
+#define NFSPROC3_RENAME		14
+#define NFSPROC3_LINK		15
+#define NFSPROC3_READDIR	16
+#define NFSPROC3_READDIRPLUS	17
+#define NFSPROC3_FSSTAT		18
+#define NFSPROC3_FSINFO		19
+#define NFSPROC3_PATHCONF	20
+#define NFSPROC3_COMMIT		21
+#define NFS3_PROCEDURE_COUNT	(NFSPROC3_COMMIT + 1)
+
+
+/*
+ *	mount.h definitions
+ */
+#define MOUNTVER3	((uint32_t)3)
+#define	MNTPATHLEN 1024
+#define	MNTNAMLEN 255
+
+#define MOUNTPROC_NULL ((uint32_t)(0))
+#define MOUNTPROC_DUMP ((uint32_t)(2))
+#define MOUNTPROC_UMNT ((uint32_t)(3))
+#define MOUNTPROC_UMNTALL ((uint32_t)(4))
+#define MOUNTPROC_EXPORT ((uint32_t)(5))
+#define MOUNTPROC_EXPORTALL ((uint32_t)(6))
+#define MOUNTPROC_PATHCONF ((uint32_t)(7))
+
+struct fhandle3 {
+	unsigned int	fhandle3_len;
+	char	*fhandle3_val;
+};
+typedef struct fhandle3 fhandle3;
+
+enum mntstat3 {
+	MNT_OK = 0,
+	MNT3ERR_PERM = 1,
+	MNT3ERR_NOENT = 2,
+	MNT3ERR_IO = 5,
+	MNT3ERR_ACCES = 13,
+	MNT3ERR_NOTDIR = 20,
+	MNT3ERR_INVAL = 22,
+	MNT3ERR_NAMETOOLONG = 63,
+	MNT3ERR_NOTSUPP = 10004,
+	MNT3ERR_SERVERFAULT = 10006
+};
+typedef enum mntstat3 mntstat3;
+
+struct mntres3_ok {
+	fhandle3 fhandle;
+	struct {
+		unsigned int auth_flavors_len;
+		int *auth_flavors_val;
+	} auth_flavors;
+};
+typedef struct mntres3_ok mntres3_ok;
+
+struct mountres3 {
+	mntstat3 fhs_status;
+	union {
+		mntres3_ok mntinfo;
+	} mntres3_u;
+};
+typedef struct mountres3 mountres3;
+
+typedef char *dirpath;
+
+
+/*
+ * External XDR functions
+ */
+
+/*
+ * Mount protocol
+ */
+extern bool_t xdr_path(XDR *, char **);
+extern bool_t xdr_fhstatus(XDR *, struct fhstatus *);
+extern bool_t xdr_dirpath(XDR *, dirpath *);
+extern bool_t xdr_mntres3(XDR *, mountres3 *);
+
+/*
+ * V2
+ */
+extern bool_t xdr_create(XDR *, char *);
+extern bool_t xdr_getattr(XDR *xdrs, char *);
+extern bool_t xdr_link(XDR *xdrs, char *);
+extern bool_t xdr_lookup(XDR *xdrs, char *);
+extern bool_t xdr_mkdir(XDR *xdrs, char *);
+extern bool_t xdr_read(XDR *xdrs, char *);
+extern bool_t xdr_readdir(XDR *xdrs,  char *);
+extern bool_t xdr_readlink(XDR *xdrs, char *);
+extern bool_t xdr_remove(XDR *xdrs, char *);
+extern bool_t xdr_rename(XDR *xdrs, char *);
+extern bool_t xdr_rmdir(XDR *xdrs, char *);
+extern bool_t xdr_setattr(XDR *xdrs, char *);
+extern bool_t xdr_statfs(XDR *xdrs, char *);
+extern bool_t xdr_symlink(XDR *xdrs, char *);
+extern bool_t xdr_write(XDR *xdrs, char *);
+
+/*
+ * V3
+ */
+extern bool_t xdr_GETATTR3args(XDR *, GETATTR3args *);
+extern bool_t xdr_GETATTR3res(XDR *, GETATTR3res *);
+extern bool_t xdr_SETATTR3args(XDR *, SETATTR3args *);
+extern bool_t xdr_SETATTR3res(XDR *, SETATTR3res *);
+extern bool_t xdr_LOOKUP3args(XDR *, LOOKUP3args *);
+extern bool_t xdr_LOOKUP3res(XDR *, LOOKUP3res *);
+extern bool_t xdr_ACCESS3args(XDR *, ACCESS3args *);
+extern bool_t xdr_ACCESS3res(XDR *, ACCESS3res *);
+extern bool_t xdr_READLINK3args(XDR *, READLINK3args *);
+extern bool_t xdr_READLINK3res(XDR *, READLINK3res *);
+extern bool_t xdr_READ3args(XDR *, READ3args *);
+extern bool_t xdr_READ3res(XDR *, READ3res *);
+extern bool_t xdr_WRITE3args(XDR *, WRITE3args *);
+extern bool_t xdr_WRITE3res(XDR *, WRITE3res *);
+extern bool_t xdr_CREATE3args(XDR *, CREATE3args *);
+extern bool_t xdr_CREATE3res(XDR *, CREATE3res *);
+extern bool_t xdr_MKDIR3args(XDR *, MKDIR3args *);
+extern bool_t xdr_MKDIR3res(XDR *, MKDIR3res *);
+extern bool_t xdr_SYMLINK3args(XDR *, SYMLINK3args *);
+extern bool_t xdr_SYMLINK3res(XDR *, SYMLINK3res *);
+extern bool_t xdr_MKNOD3args(XDR *, MKNOD3args *);
+extern bool_t xdr_MKNOD3res(XDR *, MKNOD3res *);
+extern bool_t xdr_REMOVE3args(XDR *, REMOVE3args *);
+extern bool_t xdr_REMOVE3res(XDR *, REMOVE3res *);
+extern bool_t xdr_RMDIR3args(XDR *, RMDIR3args *);
+extern bool_t xdr_RMDIR3res(XDR *, RMDIR3res *);
+extern bool_t xdr_RENAME3args(XDR *, RENAME3args *);
+extern bool_t xdr_RENAME3res(XDR *, RENAME3res *);
+extern bool_t xdr_LINK3args(XDR *, LINK3args *);
+extern bool_t xdr_LINK3res(XDR *, LINK3res *);
+extern bool_t xdr_READDIR3args(XDR *, READDIR3args *);
+extern bool_t xdr_READDIR3res(XDR *, READDIR3res *);
+extern bool_t xdr_READDIRPLUS3args(XDR *, READDIRPLUS3args *);
+extern bool_t xdr_READDIRPLUS3res(XDR *, READDIRPLUS3res *);
+extern bool_t xdr_FSSTAT3args(XDR *, FSSTAT3args *);
+extern bool_t xdr_FSSTAT3res(XDR *, FSSTAT3res *);
+extern bool_t xdr_FSINFO3args(XDR *, FSINFO3args *);
+extern bool_t xdr_FSINFO3res(XDR *, FSINFO3res *);
+extern bool_t xdr_PATHCONF3args(XDR *, PATHCONF3args *);
+extern bool_t xdr_PATHCONF3res(XDR *, PATHCONF3res *);
+extern bool_t xdr_COMMIT3args(XDR *, COMMIT3args *);
+extern bool_t xdr_COMMIT3res(XDR *, COMMIT3res *);
+
+
+#endif  /* __sfs_c_nfs_h */
diff --git a/TBBT/trace_play/sfs_c_pnt.c b/TBBT/trace_play/sfs_c_pnt.c
new file mode 100644
index 0000000..cab4f43
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_pnt.c
@@ -0,0 +1,1163 @@
+#ifndef lint
+static char sfs_c_pntSid[] = "@(#)sfs_c_pnt.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ *
+ *.Exported_Routines
+ *	void parent(int, int, char *, char *)
+ *
+ *.Local_Routines
+ *	void synchronize_children(int)
+ *	int signal_Prime_Client(char *, char *)
+ *	void collect_counters(int)
+ *	int check_parameters(char *, char *, int)
+ *	int check_counters(void)
+ *	void print_results(int, int, char *, int, int, char *)
+ *
+ *.Revision_History
+ *	10-Jan-92	Teelucksingh
+ *				Client passes standard deviation compute
+ *				values to Prime-Client as well as an
+ *				"INVALID RUN" flag.
+ *
+ *	16-Dec-91	Wittle		Created.
+ */
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+#if !defined(_XOPEN_SOURCE)
+#include <sys/socket.h>
+#else
+#define	AF_INET		2
+#endif
+
+/*
+ * -------------------------  External Definitions  -------------------------
+ */
+
+/* forward definitions for local routines */
+static void synchronize_children(int);
+static int signal_Prime_Client(char *, char *);
+static void collect_counters(int);
+static int check_parameters(char *, char *, int);
+static int check_counters(void);
+static void print_results(int, int, char *, int, int, char *);
+static void sfs_reaper(int);
+
+/* Aggregate results storage */
+static char Client_results[(NOPS+3)*MAX_LINE_LEN];
+
+/*
+ * -------------------------  SFS Parent Code  -------------------------
+ */
+
+/*
+ * Parent: wait for kids to get ready, start them, wait for them to
+ * finish, read and accumulate results.
+ */
+void
+parent(
+    int		children,
+    int		load,
+    char *	mix_file,
+    char *	iodist_file)
+{
+    char	string[80];	/* for interactive startup */
+    int		result;
+    int		invalid_run;	/* holds INVALID RUN status */
+    int		runtime_val;	/* store Runtime value to be printed later */
+    int		Saveerrno;
+    char	*nameptr;
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    struct sigaction sig_act, old_sig_act;
+#endif
+
+    /*
+     * Setup a SIGCHLD handler in case one of our beloved children dies
+     * before its time.
+     */
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    /* use XOPEN signal handling */
+
+    sig_act.sa_handler = sfs_reaper;
+    (void)sigemptyset(&sig_act.sa_mask);
+    sig_act.sa_flags = 0;
+    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
+        perror("sigaction failed: SIGCHLD");
+        exit(66);
+    }
+#else
+    (void) signal(SIGCHLD, sfs_reaper);
+#endif
+
+    /* Change my name for error logging */
+    if ((nameptr = strrchr(sfs_Myname, '/')) != NULL)
+        sfs_Myname = ++nameptr;
+
+    /*
+     * store the Runtime value; to be printed in results
+     */
+    if (Prime_client)
+	runtime_val = Runtime - MULTICLIENT_OFFSET;
+    else runtime_val = Runtime;
+
+    /* print logfile header information */
+    (void) fprintf(stdout,"\n");
+    (void) fprintf(stdout,
+    "************************************************************************");
+    (void) fprintf(stdout,"\n");
+    (void) fflush(stdout);
+
+    /* print sfs information */
+    if (Prime_client) {
+	(void) fprintf(stderr,
+		"\nSFS NFS Version %d Benchmark Client Logfile, %s\n",
+			nfs_version, lad_timestamp());
+	(void) fprintf(stderr, "\tClient hostname = %s\n", lad_hostname);
+	(void) fprintf(stderr, "\tPrime Client hostname = %s\n",
+			Prime_client);
+    }
+
+    (void) fprintf(stderr, "\nSPEC SFS Benchmark Version %s, Creation - %s\n",
+				SFS_VERSION_NUM, SFS_VERSION_DATE);
+    (void) fprintf(stderr, "NFS Protocol Version %d\n", nfs_version);
+
+    /* mount test directories */
+    (void) fprintf(stderr, "%s Mounting %d remote test directories.\n",
+		lad_timestamp(), children);
+    synchronize_children(children);
+    (void) fprintf(stderr, "%s Completed.", lad_timestamp());
+
+    /*
+     * if multi-client execution then tell Prime-Client I'm done mounting
+     * test directories.
+     */
+    if (Prime_client) {
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr,
+		       "%s Sending DONE-MOUNT message to Prime Client(%s).\n",
+			lad_timestamp(), Prime_client);
+	if ((result =
+	    (int) signal_Prime_Client("CLIENT_SIGNAL", ""))
+		== (int) RPC_SUCCESS) {
+	    (void) fprintf(stderr, "%s Completed.",lad_timestamp());
+	    (void) fflush(stderr);
+	} else {
+	    (void) fprintf(stderr, "\n");
+	    (void) fprintf(stderr,
+		"%s:  error %d sending DONE-MOUNT message to Prime Client\n",
+		sfs_Myname, result);
+	    /* cleanup and exit */
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	    sig_act.sa_handler = SIG_DFL;
+	    (void)sigemptyset(&sig_act.sa_mask);
+	    sig_act.sa_flags = 0;
+	    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
+	        perror("sigaction failed: SIGCHLD");
+	        exit(67);
+	    }
+#else
+	    (void) signal(SIGCHLD, SIG_DFL);
+#endif
+	    (void) generic_kill(0, SIGINT);
+	    exit(68);
+	}
+
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr,
+		    "%s Waiting on DO-INIT message from Prime Client(%s).\n",
+		    lad_timestamp(), Prime_client);
+	(void) fflush(stderr);
+
+	/*
+	 * wait for DO-INIT message from Prime Client
+	 * sfs_syncd (rpc server) sends a SIGUSR1 signal;
+	 * user can also terminate experiment anytime they wish
+	 * with SIGINT or SIGTERM signal
+	 */
+	(void) pause();
+	(void) fprintf(stderr, "%s Received.",lad_timestamp());
+	(void) fflush(stderr);
+
+    } /* send DONE-MOUNT and got DO-INIT message */
+
+    /* initialize test directories */
+    (void) fprintf(stderr, "\n");
+    (void) fprintf(stderr, "%s Initializing test directories.\n",
+		    lad_timestamp());
+
+    /* send SIGUSR1 to child processes */
+    (void) generic_kill(0, SIGUSR1);
+    synchronize_children(children);
+    (void) fprintf(stderr, "%s Completed.", lad_timestamp());
+    (void) fflush(stderr);
+
+    /*
+     * if multi-client execution then tell Prime-Client I'm done initializing
+     * and wait for synchronized do warmupmessage.
+     */
+    if (Prime_client) {
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr,
+		    "%s Sending DONE-INIT message to Prime Client(%s).\n",
+			lad_timestamp(), Prime_client);
+	if ((result =
+	    (int) signal_Prime_Client("CLIENT_SIGNAL",""))
+		== (int) RPC_SUCCESS) {
+	    (void) fprintf(stderr, "%s Completed.",lad_timestamp());
+	    (void) fflush(stderr);
+	} else {
+	    (void) fprintf(stderr, "\n");
+	    (void) fprintf(stderr,
+		    "%s:  error %d sending DONE-INIT message to Prime Client\n",
+		    sfs_Myname, result);
+	    /* cleanup and exit */
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	    sig_act.sa_handler = SIG_DFL;
+	    (void)sigemptyset(&sig_act.sa_mask);
+	    sig_act.sa_flags = 0;
+	    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
+	        perror("sigaction failed: SIGCHLD");
+	        exit(69);
+	    }
+#else
+	    (void) signal(SIGCHLD, SIG_DFL);
+#endif
+	    (void) generic_kill(0, SIGINT);
+	    exit(70);
+	}
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr,
+		  "%s Waiting on DO-WARMUP message from Prime Client(%s).\n",
+		    lad_timestamp(), Prime_client);
+	(void) fflush(stderr);
+
+	/*
+	 * wait for DO-WARMUP message from Prime Client
+	 * sfs_syncd (rpc server) sends a SIGUSR1 signal;
+	 * user can also terminate experiment anytime they wish
+	 * with SIGINT or SIGTERM signal
+	 */
+	(void) pause();
+	(void) fprintf(stderr, "%s Received.",lad_timestamp());
+	(void) fflush(stderr);
+
+    } /* send DONE-INIT and got DO-WARMUP message */
+
+    if (Populate_only) {
+	(void) fprintf(stderr, "\nPopulating directories and exiting.\n");
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	sig_act.sa_handler = SIG_DFL;
+	(void)sigemptyset(&sig_act.sa_mask);
+	sig_act.sa_flags = 0;
+	if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
+	    perror("sigaction failed: SIGCHLD");
+	    exit(71);
+	}
+#else
+	(void) signal(SIGCHLD, SIG_DFL);
+#endif
+	(void) generic_kill(0, SIGUSR1);
+	while (wait((int *) 0) != -1) {
+	    /* nop */
+	}
+	return;
+    }
+
+    /* do warm-up */
+    if (Warmuptime) {
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr, "%s Performing %d seconds pretest warmup.\n",
+		lad_timestamp(), Warmuptime);
+	(void) generic_kill(0, SIGUSR1);
+	(void) sleep(Warmuptime);
+	(void) fprintf(stderr, "%s Completed.", lad_timestamp());
+	(void) fflush(stderr);
+    }
+
+    if (Interactive) {
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr, "Hit <return> when ready to start test ...");
+	(void) fgets(string,10,stdin);
+    }
+
+    /*
+     * if multi-client execution then tell Prime-Client I'm done warm-up
+     * and wait for synchronized Start message.
+     */
+    if (Prime_client) {
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr,
+			"%s Sending READY message to Prime Client(%s).\n",
+			lad_timestamp(), Prime_client);
+	if ((result =
+	    (int) signal_Prime_Client("CLIENT_SIGNAL",""))
+		== (int) RPC_SUCCESS) {
+	    (void) fprintf(stderr, "%s Completed.",lad_timestamp());
+	    (void) fflush(stderr);
+	} else {
+	    (void) fprintf(stderr, "\n");
+	    (void) fprintf(stderr,
+		    "%s:  error %d sending READY message to Prime Client\n",
+		    sfs_Myname, result);
+	    /* cleanup and exit */
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+	    sig_act.sa_handler = SIG_DFL;
+	    (void)sigemptyset(&sig_act.sa_mask);
+	    sig_act.sa_flags = 0;
+	    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
+	        perror("sigaction failed: SIGCHLD");
+	        exit(72);
+	    }
+#else
+	    (void) signal(SIGCHLD, SIG_DFL);
+#endif
+	    (void) generic_kill(0, SIGINT);
+	    exit(73);
+	}
+
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr,
+		    "%s Waiting on START message from Prime Client(%s).\n",
+		    lad_timestamp(), Prime_client);
+	(void) fflush(stderr);
+
+	/*
+	 * wait for START message from Prime Client
+	 * sfs_syncd (rpc server) sends a SIGUSR1 signal;
+	 * user can also terminate experiment anytime they wish
+	 * with SIGINT or SIGTERM signal
+	 */
+	(void) pause();
+	(void) fprintf(stderr, "%s Received.",lad_timestamp());
+	(void) fflush(stderr);
+
+    } /* send READY and got START message */
+
+    (void) fprintf(stderr, "\n");
+    if (Timed_run) {
+	if (Prime_client) {
+	    (void) fprintf(stderr, "%s Starting %d seconds test run.\n",
+		    lad_timestamp(), Runtime - MULTICLIENT_OFFSET);
+	} else {
+	    (void) fprintf(stderr, "%s Starting %d seconds test run.\n",
+		    lad_timestamp(), Runtime);
+	}
+    } else {
+	(void) fprintf(stderr, "%s Starting %d call test run.\n",
+		lad_timestamp(), Ops[TOTAL].target_calls);
+    }
+    (void) fflush(stderr);
+
+    /* signal child processes to go */
+    (void) generic_kill(0, SIGUSR1);
+
+    if (Timed_run)
+	(void) sleep(Runtime);
+
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    sig_act.sa_handler = SIG_DFL;
+    (void)sigemptyset(&sig_act.sa_mask);
+    sig_act.sa_flags = 0;
+    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
+        perror("sigaction failed: SIGCHLD");
+        exit(74);
+    }
+#else
+    (void) signal(SIGCHLD, SIG_DFL);
+#endif
+
+    if (Timed_run) {
+	/*
+	 * The parent and the prime are both sleeping for Runtime.
+	 * If the parent wakes up first, he'll tell the children to stop.
+	 * If the prime wakes up first, he'll send an SIGALRM (via syncd)
+	 * to the parent.  That alarm may arrive while the parent is still
+	 * asleep, which is ok, or after he has starting running.  Since
+	 * the parent SIGARLM catcher does nothing, there is no harm done
+	 * by the extra signal in this case.
+	 *
+	 * Perhaps, if running multi we should just wait (pause()) for
+	 * the STOP signal, like we waited for the start signal.  It would
+	 * be more obvious.  The only drawback is the OTW rpc delay in
+	 * receiving the stop signal from the prime.
+	 */
+	(void) generic_kill(0, SIGUSR2); /* tell children to finish */
+    }
+
+    /* Wait for all the children to finish/die */
+    while (wait((int *) 0) != -1) {
+	/* nop */
+    }
+
+    (void) fprintf(stderr, "%s Completed.", lad_timestamp());
+    (void) fflush(stdout);
+    (void) fflush(stderr);
+
+    /* Initialize and sum up counters */
+    collect_counters(children);
+    if ((invalid_run = check_counters()) == 0)
+	invalid_run = check_parameters(iodist_file, mix_file, runtime_val);
+
+    /* print test results */
+    print_results(children, load, mix_file,
+		  invalid_run, runtime_val, iodist_file);
+
+    /*
+     * if multi-client execution then tell Prime client that
+     * I'm done with 'real' work and wait for move-data message
+     * and send data across
+     */
+    if (Prime_client) {
+	(void) fprintf(stderr,
+			"%s Sending DONE-TEST message to Prime Client(%s).\n",
+			lad_timestamp(), Prime_client);
+	if ((result =
+	    (int) signal_Prime_Client("CLIENT_SIGNAL",""))
+		== (int) RPC_SUCCESS) {
+	    (void) fprintf(stderr, "%s Completed.", lad_timestamp());
+	    (void) fflush(stderr);
+	} else {
+	    Saveerrno = errno;
+	    (void) fprintf(stderr, "\n");
+	    (void) fprintf(stderr,
+		    "%s:  error %d sending DONE-TEST message to Prime Client\n",
+		    sfs_Myname, result);
+	    errno = Saveerrno;
+	    perror("signal_Prime_Client");
+	    /* cleanup and exit */
+	    (void) generic_kill(0, SIGINT);
+	    exit(75);
+	}
+
+	/*
+	 * wait for MOVE-DATA message from Prime Client before
+	 * sending send results.
+	 */
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr,
+		"%s Waiting on MOVE-DATA message from Prime Client(%s).\n",
+		lad_timestamp(), Prime_client);
+	(void) fflush(stderr);
+	(void) pause();
+	(void) fprintf(stderr, "%s Received.", lad_timestamp());
+	(void) fprintf(stderr, "\n");
+	(void) fprintf(stderr, "%s Sending results to Prime Client(%s)\n",
+		lad_timestamp(), Prime_client);
+	(void) fflush(stderr);
+
+
+	if ((result = (int) signal_Prime_Client("CLIENT_DATA",
+	    Client_results)) == (int) RPC_SUCCESS) {
+	    (void) fprintf(stderr, "%s Completed.\n", lad_timestamp());
+	    (void) fflush(stderr);
+	} else {
+	    Saveerrno = errno;
+	    (void) fprintf(stderr, "\n");
+	    (void) fprintf(stderr,
+		    "%s: error %d sending client's result to Prime Client\n",
+		    sfs_Myname, result);
+	    errno = Saveerrno;
+	    perror("signal_Prime_Client");
+	    /* cleanup and exit */
+	    (void) generic_kill(0, SIGINT);
+	    exit(76);
+	}
+    } /* sent done, got move-data and sent data */
+
+    (void) fprintf(stdout,"\n");
+    (void) fprintf(stdout,
+    "************************************************************************");
+    (void) fprintf(stdout,"\n");
+
+} /* parent */
+
+
+/*
+ * ------------------------  Utility Routines  --------------------------
+ */
+
+
+/*
+ * Monitor Logfile until its size reaches 'children' bytes.
+ * This means that all of the children are waiting for the next instruction.
+ */
+static void
+synchronize_children(
+    int		children)
+{
+    struct stat	statb;	/* for fstat */
+
+    do {
+	(void) sleep(1);
+	if (fstat(Log_fd, &statb) == -1) {
+	    (void) fprintf(stderr, "%s: can't stat log %s", sfs_Myname, Logname);
+	    (void) generic_kill(0, SIGINT);
+	    exit(77);
+	}
+    } while (statb.st_size < children);
+
+    /*
+     * Truncate the log file
+     */
+    (void)close(Log_fd);
+    Log_fd = open(Logname, (O_RDWR | O_CREAT | O_TRUNC | O_APPEND), 0666);
+    if (Log_fd == -1) {
+	(void) fprintf(stderr, "%s: can't truncate log %s",
+				sfs_Myname, Logname);
+	(void) generic_kill(0, SIGINT);
+	exit(78);
+    }
+
+}  /* synchronize_children */
+
+
+/*
+ * Multi-client execution support routine.
+ * Call remote procedure on Prime client
+ * to send message to sfs_prime_clnt program.
+ * The message will contain a type field set to 'type',
+ * and a data field set to 'data'.
+ */
+static int
+signal_Prime_Client(
+    char *		type,
+    char *		data)
+{
+    static CLIENT *	clnt_handle = NULL;
+    static int		transaction_id = 0;
+    int *		result;
+    static int		socket;
+    sync_string		sync_signal;
+    char		transaction_string[MAX_STR1_LEN];
+    char		buf[128];
+
+    if ((int)strlen(data) > MAX_STR2_LEN) {
+	(void) fprintf(stderr,
+			"%s: %s too much data len = %d max = %d\n",
+			sfs_Myname, Prime_client, strlen(data),
+			MAX_STR2_LEN);
+	return((int)RPC_CANTENCODEARGS);
+    }
+
+    if (clnt_handle == NULL) {
+	struct sockaddr_in	prime_addr;
+	struct hostent *	host_info;
+
+	socket = RPC_ANYSOCK;
+
+	/* get host information for prime_client */
+	if ((host_info = gethostbyname(Prime_client)) == NULL) {
+	    (void) fprintf(stderr, "%s: %s is unknown host\n",
+			sfs_Myname, Prime_client);
+	    return ((int) RPC_UNKNOWNHOST);
+	}
+
+	(void) memset((char *) &prime_addr, '\0', sizeof(prime_addr));
+	(void) memmove((char *) &prime_addr.sin_addr,
+			(char *) host_info->h_addr, host_info->h_length);
+
+	prime_addr.sin_family = AF_INET;
+	prime_addr.sin_port =  0;
+
+	/*
+	 * Create client "handle" used for calling SFS_SYNCPROG on the
+	 * Prime Client. We tell the RPC package to use the "tcp"
+	 * protocol when contacting the prime_client.
+	 */
+	clnt_handle = clnttcp_create(&prime_addr, SFS_SYNCPROG,
+			SFS_SYNCVERS, &socket, MAX_STR2_LEN, MAX_STR2_LEN);
+
+	if (clnt_handle == ((CLIENT *) NULL)) {
+	    /*
+	     * Couldn't establish connection with the Prime_Client.
+	     * Print error message and return error.
+	     */
+	    clnt_pcreateerror(Prime_client);
+	    (void) fprintf(stderr,
+		"%s: %s Could not establish client handle to contact %s\n",
+		lad_timestamp(), sfs_Myname, Prime_client);
+	    return((int) RPC_FAILED);
+	}
+    }
+
+    /* fill up xdr structure with data to send to Prime Client */
+    (void) sprintf(transaction_string,"%d_%i", Client_num, ++transaction_id);
+    sync_signal.clnt_type = type;
+    sync_signal.clnt_id = Client_num;
+    sync_signal.clnt_data = data;
+    sync_signal.clnt_transaction = transaction_string;
+
+    /* Call the remote procedure "signal_sfs_1" on the Prime Client */
+    result = signal_sfs_1(&sync_signal, clnt_handle);
+    if (result == NULL) {
+	/*
+	 * An error occurred while making RPC to the Prime Client.
+	 * Print error message and return error.
+	 */
+	sprintf(buf, "%s Transaction %s: Could not call prime client %s",
+			lad_timestamp(), transaction_string, Prime_client);
+	clnt_perror(clnt_handle, buf);
+	return((int) RPC_CANTSEND);
+    }
+
+    /* OK, we successfully called the remote procedure. */
+    if (*result == 0) {
+	/*
+	 * remote procedure was unable to successfully perform required
+	 * operation on the Prime Client.
+	 * Print error message and return error.
+	 */
+	(void) fprintf(stderr,
+			"%s: %s Prime Client couldn't write to PC_sync file \n",
+			sfs_Myname, Prime_client);
+	return((int) RPC_FAILED);
+    }
+
+    /* remote procedure success - wrote to Prime Client sync file */
+    return((int) RPC_SUCCESS);
+
+} /* signal_Prime_Client */
+
+
+/*
+ * Read results arrays for 'children' children from Logfile
+ * and accumulate them in "Ops".
+ * Complain about any problems we see with the log file.
+ */
+static void
+collect_counters(
+    int			children)
+{
+    int				i;
+    int				j;
+    struct stat			statb;
+    sfs_results_report_type	report; /* final results log */
+    int				Saveerrno;
+
+    if (fstat(Log_fd, &statb) == -1) {
+	Saveerrno = errno;
+	(void) fprintf(stderr, "%s: can't stat log %s ", sfs_Myname, Logname);
+	errno = Saveerrno;
+	perror(Logname);
+	(void) generic_kill(0, SIGINT);
+	exit(79);
+    }
+
+    if (statb.st_size != (children * sizeof(report))) {
+	(void) fprintf(stderr, "%s: log file %s has bad format\n",
+			sfs_Myname, Logname);
+	(void) generic_kill(0, SIGINT);
+	exit(80);
+    }
+
+    if (lseek(Log_fd, 0L, 0) == -1) {
+	Saveerrno = errno;
+	(void) fprintf(stderr, "%s: can't lseek log %s ", sfs_Myname, Logname);
+	errno = Saveerrno;
+	perror("lseek");
+	(void) generic_kill(0, SIGINT);
+	exit(81);
+    }
+
+    for (j = 0; j < NOPS + 1; j++) {
+	Ops[j].results.good_calls = 0;
+	Ops[j].results.bad_calls = 0;
+	Ops[j].results.fast_calls = 0;
+	Ops[j].results.time.sec = 0;
+	Ops[j].results.time.usec = 0;
+	Ops[j].results.msec2 = 0;
+    }
+    Total_fss_bytes = 0;
+    Least_fss_bytes = 0;
+    Most_fss_bytes = 0;
+    Base_fss_bytes = 0;
+
+    for (i = 0; i < children; i++) {
+	if (read(Log_fd, (char *) &report, sizeof(report)) == -1) {
+	    Saveerrno = errno;
+	    (void) fprintf(stderr, "%s: can't read log %s", sfs_Myname, Logname);
+	    errno = Saveerrno;
+	    perror("Logname");
+	    (void) generic_kill(0, SIGINT);
+	    exit(82);
+	}
+
+	for (j = 0; j < NOPS + 1; j++) {
+	    Ops[j].results.good_calls += report.results_buf[j].good_calls;
+	    Ops[j].results.bad_calls += report.results_buf[j].bad_calls;
+	    Ops[j].results.fast_calls += report.results_buf[j].fast_calls;
+	    ADDTIME(Ops[j].results.time, report.results_buf[j].time);
+	    Ops[j].results.msec2 += report.results_buf[j].msec2;
+	}
+	Total_fss_bytes += report.total_fss_bytes;
+	Least_fss_bytes += report.least_fss_bytes;
+	Most_fss_bytes += report.most_fss_bytes;
+	Base_fss_bytes += report.base_fss_bytes;
+    }
+
+} /* collect_counters */
+
+
+/*
+ * Check the parameters for validity.
+ */
+static int
+check_parameters(
+char *	iodist_file,
+char *	mix_file,
+int	runtime_val)
+{
+    int retval = 0;
+    char detail[40];
+
+    detail[0] = '\0';
+
+    if (iodist_file != NULL) {
+	retval = INVALID_IODIST;
+    }
+    if (mix_file != NULL) {
+	retval = INVALID_MIX;
+    }
+    if (runtime_val != DEFAULT_RUNTIME) {
+	(void) sprintf(detail, "%d != %d", runtime_val, DEFAULT_RUNTIME);
+	retval = INVALID_RUNTIME;
+    }
+    if (Access_percent != DEFAULT_ACCESS) {
+	(void) sprintf(detail, "%d != %d", Access_percent, DEFAULT_ACCESS);
+	retval = INVALID_ACCESS;
+    }
+    if (Append_percent != DEFAULT_APPEND) {
+	(void) sprintf(detail, "%d != %d", Append_percent, DEFAULT_APPEND);
+	retval = INVALID_APPEND;
+    }
+    if (Kb_per_block != DEFAULT_KB_PER_BLOCK) {
+	(void) sprintf(detail, "%d != %d", Kb_per_block, DEFAULT_KB_PER_BLOCK);
+	retval = INVALID_KB;
+    }
+    if (Files_per_dir != DEFAULT_FILES_PER_DIR) {
+	(void) sprintf(detail, "%d != %d", Files_per_dir, DEFAULT_FILES_PER_DIR);
+	retval = INVALID_NDIRS;
+    }
+    if (Fss_delta_percent != DEFAULT_DELTA_FSS) {
+	(void) sprintf(detail, "%d != %d",
+				Fss_delta_percent, DEFAULT_DELTA_FSS);
+	retval = INVALID_FSS;
+    }
+    if (Biod_max_outstanding_reads < DEFAULT_BIOD_MAX_READ) {
+	(void) sprintf(detail, "%d < %d",
+			Biod_max_outstanding_reads, DEFAULT_BIOD_MAX_READ);
+	retval = INVALID_BIODREAD;
+    }
+    if (Tot_client_num_symlinks != DEFAULT_NSYMLINKS) {
+	(void) sprintf(detail, "%d != %d",
+			Tot_client_num_symlinks, DEFAULT_NSYMLINKS);
+	retval = INVALID_NSYMLINKS;
+    }
+    if (Biod_max_outstanding_writes < DEFAULT_BIOD_MAX_WRITE) {
+	(void) sprintf(detail, "%d < %d",
+			Biod_max_outstanding_writes, DEFAULT_BIOD_MAX_WRITE);
+	retval = INVALID_BIODWRITE;
+    }
+    if (Warmuptime != DEFAULT_WARMUP) {
+	(void) sprintf(detail, "%d != %d",
+			Warmuptime, DEFAULT_WARMUP);
+	retval = INVALID_WARMUP;
+    }
+
+    if (retval != 0)
+	(void) fprintf(stdout,
+		"%s: INVALID RUN, ILLEGAL PARAMETER: Non-standard %s %s\n",
+		sfs_Myname, invalid_str[retval], detail);
+    return (retval);
+}
+
+/*
+ * Check the results in Ops[] for validity.
+ */
+static int
+check_counters(void)
+{
+    double	mix_pcnt;
+    int		bad_pcnt;
+    int		i;
+    int		ret = 0;
+
+    if (Ops[TOTAL].results.good_calls <= 0) {
+	(void) fprintf(stdout, "%s: INVALID RUN %s\n",
+				sfs_Myname, invalid_str[INVALID_GOODCALLS]);
+	ret = INVALID_GOODCALLS;
+    }
+    if (Ops[TOTAL].results.good_calls != 0)
+        bad_pcnt = (Ops[TOTAL].results.bad_calls * 100)
+	       / Ops[TOTAL].results.good_calls;
+    else
+	bad_pcnt = 100;
+
+    if (bad_pcnt >= 1) {
+	(void) fprintf(stdout, "%s: INVALID RUN, %d%% %s\n",
+
+			sfs_Myname, bad_pcnt,
+			invalid_str[INVALID_FAILEDRPC]);
+	ret = INVALID_FAILEDRPC;
+    }
+
+    if (Ops[TOTAL].results.good_calls == 0) {
+	(void) fprintf(stdout, "%s: INVALID RUN, no good calls\n", sfs_Myname);
+	return (INVALID_NOTMIX);
+    }
+
+    for (i = 0; i < NOPS; i++) {
+	mix_pcnt = ((double)Ops[i].results.good_calls /
+					Ops[TOTAL].results.good_calls) * 100.0;
+	if (mix_pcnt != (double)Ops[i].mix_pcnt) {
+	    if ((mix_pcnt - (double)Ops[i].mix_pcnt > 1.5) ||
+	        ((double)Ops[i].mix_pcnt - mix_pcnt > 1.5)) {
+		(void) fprintf(stdout, "%s: INVALID RUN, %s target %d%% actual %4.1f%% %s\n",
+
+			sfs_Myname, Ops[i].name, Ops[i].mix_pcnt, mix_pcnt,
+			invalid_str[INVALID_NOTMIX]);
+		ret = INVALID_NOTMIX;
+	    }
+	}
+    }
+
+    return (ret);
+
+} /* check_counters */
+
+
+/*
+ * Print the test run results, for 'load' load, the operation percentages
+ * in 'mixfile' percentages, and 'children' processes.
+ */
+static void
+print_results(
+    int				children,
+    int				load,
+    char *			mix_file,
+    int				invalid_flag,
+    int				runtime_val,
+    char *			iodist_file)
+{
+    uint_t			runtime;
+    uint_t			total_msec;
+    uint_t			msec;
+    uint_t			total_calls;
+    uint_t			calls;
+    int				i;
+    double			squared_time_msec;
+    double			sum2_msec;
+    double			var_msec;
+    double			stdev_msec;
+    double			sq_conf_interval_msec;
+    double			conf_interval_msec;
+    sfs_op_type *		op_ptr;
+    sfs_results_type *		results_ptr;
+    char			result_string[MAX_LINE_LEN];
+
+
+    /* compute total time for all ops combined */
+    total_msec = 0;
+    for (i = 0; i < NOPS; i++) {
+	total_msec += Ops[i].results.time.sec * 1000;
+	total_msec += Ops[i].results.time.usec / 1000;
+    }
+
+    /*
+     * Report statistics based on successful calls only.  The per
+     * operation routines accumulate time and count only good_calls.
+     */
+    total_calls = Ops[TOTAL].results.good_calls;
+
+
+    /*
+     * Print the client's test parameters
+     */
+    (void) fprintf(stderr, "\n\nClient Test Parameters: \n");
+    (void) fprintf(stderr, "\tNumber of processes = %d\n", children);
+    (void) fprintf(stderr, "\tRequested Load (NFS V%d operations/second) = %d\n",
+		    nfs_version, load);
+    (void) fprintf(stderr, "\tMaximum number of outstanding biod writes = %d\n",
+		    Biod_max_outstanding_writes);
+    (void) fprintf(stderr, "\tMaximum number of outstanding biod reads = %d\n",
+		    Biod_max_outstanding_reads);
+    (void) fprintf(stderr, "\tWarm-up time (seconds) = %d\n\tRun time (seconds) = %d\n",
+		    Warmuptime, runtime_val);
+    if (mix_file)
+	(void) fprintf(stderr,"\tNFS Mixfile = %s\n", mix_file);
+    if (iodist_file)
+	(void) fprintf(stderr,"\tBlock Size Distribution file = %s\n",
+			iodist_file);
+    (void) fprintf(stderr, "\tFile Set = %4d Files created for I/O operations\n",
+		(Tot_client_num_io_files/children + 1) * children);
+    (void) fprintf(stderr, "\t\t   %4d Files accessed for I/O operations\n",
+		(((Tot_client_num_io_files/children + 1) * Access_percent)
+		   / 100) * children);
+    (void) fprintf(stderr, "\t\t   %4d Files for non-I/O operations\n",
+		(Tot_client_num_non_io_files/children + 1) * children);
+    (void) fprintf(stderr, "\t\t   %4d Symlinks\n",
+		(Tot_client_num_symlinks/children + 1) * children);
+    (void) fprintf(stderr, "\t\t   %4d Directories\n",
+		((Tot_client_num_io_files/children + 1) / Files_per_dir ) * children);
+    (void) fprintf(stderr, "\t\t\tAdditional non-I/O files created as necessary\n\n");
+
+    (void) sprintf(Client_results,"%d %d %d %d %d %d\n",
+	nfs_version,
+	(Tot_client_num_io_files/children + 1) * children,
+	(((Tot_client_num_io_files/children + 1) * Access_percent)
+		/ 100) *children,
+	(Tot_client_num_non_io_files/children + 1) * children,
+	(Tot_client_num_symlinks/children + 1) * children,
+	((Tot_client_num_io_files/children + 1) / Files_per_dir ) * children);
+
+    /* print the client's results header information */
+    (void) fprintf(stderr, "\nSPEC SFS Benchmark Version %s, Creation - %s\n",
+                                SFS_VERSION_NUM, SFS_VERSION_DATE);
+    (void) fprintf(stdout, "SFS Single Client (%s) Results, %s\n",
+		    lad_hostname, lad_timestamp());
+    (void) fflush(stdout);
+
+    /* print column headers for per operation statistics */
+    (void) fprintf(stdout,
+"----------------------------------------------------------------------------\n");
+    (void) fprintf(stdout, "\n");
+    (void) fprintf(stdout,
+"NFS V%d     Target Actual   NFS    NFS    Mean     Std Dev  Std Error   Pcnt \n",
+nfs_version);
+    (void) fprintf(stdout,
+"Op           NFS    NFS     Op     Op    Response Response of Mean,95%%  of  \n");
+    (void) fprintf(stdout,
+"Type         Mix    Mix   Success Error   Time     Time    Confidence  Total\n");
+    (void) fprintf(stdout,
+"             Pcnt   Pcnt   Count  Count  Msec/Op  Msec/Op  +- Msec/Op  Time \n");
+    (void) fprintf(stdout,
+"----------------------------------------------------------------------------\n");
+    (void) fflush(stdout);
+
+    /* print per operation statistics */
+    for (i = 0; i < NOPS; i++) {
+	/* init to 0 */
+	squared_time_msec = 0.0;
+	sum2_msec = 0.0;
+	calls = 0;
+	msec = 0;
+	stdev_msec = 0;
+
+	op_ptr = &Ops[i];
+	results_ptr = &op_ptr->results;
+
+	/* get the number successful calls and total time */
+	calls = op_ptr->results.good_calls;
+	msec = (results_ptr->time.sec * 1000)
+	       + (results_ptr->time.usec / 1000);
+
+	/* compute the standard deviation for the mean response time */
+	if (calls <= 1)
+	    stdev_msec = 0;
+	else {
+	    /* get the standard deviation */
+	    squared_time_msec = results_ptr->msec2;
+	    /* compute the square of the total elapsed time */
+	    sum2_msec = (results_ptr->time.sec * 1000.0)
+			 + (results_ptr->time.usec / 1000.0);
+	    sum2_msec *= sum2_msec;
+
+	    /* variance = 1/(n-1) * (sum(x^2) - 1/n * (sum(x))^2) */
+	    var_msec = (squared_time_msec - (sum2_msec / calls)) / (calls-1);
+	    if (var_msec == 0.0) {
+		stdev_msec = 0.0;
+	    } else
+		stdev_msec = sqrt(var_msec);
+	}
+
+	/* compute the confidence interval */
+	if (calls != 0) {
+	    sq_conf_interval_msec = DEFAULT_CHI_SQR_CI * (stdev_msec / calls);
+	    if (sq_conf_interval_msec == 0.0) {
+		conf_interval_msec = 0.0;
+	    } else
+		conf_interval_msec = sqrt(sq_conf_interval_msec);
+	} else
+	    conf_interval_msec = 0.0;
+
+	/* print the per op statistics */
+	(void) fprintf(stdout,
+	"%-12s%3d%%   %4.1f%%   %5d %5d %5.2f %8.2f  %8.2f    %3.1f%%\n",
+	    op_ptr->name,					/* op name */
+	    op_ptr->mix_pcnt, 					/* target mix */
+								/* actual mix */
+	    total_calls ? ((double)calls / total_calls) * 100.0 : 0.0,
+	    results_ptr->good_calls,				/* successes */
+	    results_ptr->bad_calls,				/* errors */
+	    calls ? ((double)msec / calls) : 0.0,		/* msec/call */
+	    stdev_msec,						/* std dev */
+	    conf_interval_msec,					/* conf int */
+								/* % of time */
+	    total_msec ? ((double)msec / total_msec) * 100 : 0.0);
+	(void) fflush(stdout);
+
+	/*
+	 * Store client data in result_string.
+	 * This string is different from client result display.
+	 * The  squared_time_msec and sum2_msec values are passed along
+	 * to be used by the prime client to calculate the stddev value for
+	 * each operation.
+	 */
+	if (Prime_client) {
+	(void) sprintf(result_string,
+	"%-12s   %3d%% %3.1f%% %5d  %5d %4ld.%1ld %6.2f  %3.1f%% %f %f\n",
+	    op_ptr->name,					/* op name */
+	    op_ptr->mix_pcnt,					/* target mix */
+								/* actual mix */
+	    total_calls ? ((double)calls / total_calls) * 100.0 : 0.0,
+	    results_ptr->good_calls,				/* successes */
+	    results_ptr->bad_calls,				/* errors */
+	    results_ptr->time.sec,				/* total time1*/
+	    results_ptr->time.usec / 100000,			/* total time2*/
+	    calls ? ((double)msec / calls) : 0.0,		/* msec/call */
+								/* % of time */
+	    total_msec ? ((double)msec / total_msec) * 100 : 0.0,
+	    squared_time_msec,					/* sum of sqs */
+	    sum2_msec);						/* sq of sums */
+	    (void) strcat(Client_results, result_string);
+	}
+
+    } /* end for each op */
+
+    (void) fprintf(stdout,
+"----------------------------------------------------------------------------\n\n");
+    (void) fflush(stdout);
+
+    /* Average child runtime.  (should this be the longest runtime?) */
+    runtime = Ops[TOTAL].results.time.sec / children;
+
+    /* Print summary */
+    (void) fprintf(stdout,
+	"      ------------------------------------------------------------\n");
+    (void) fprintf(stdout,
+	"      | SPEC SFS VERSION %6s SINGLE CLIENT RESULTS SUMMARY    |\n",
+							SFS_VERSION_NUM);
+    (void) fprintf(stdout,
+	"      ------------------------------------------------------------\n");
+    (void) fprintf(stdout, "NFS V%d THROUGHPUT: ", nfs_version);
+    (void) fprintf(stdout,
+		    "%4d.%02d Ops/Sec   AVG. RESPONSE TIME: %4d.%02d Msec/Op\n",
+		    runtime ? (total_calls / runtime) : 0,
+		    runtime ? ((total_calls % runtime) * 100 / runtime) : 0,
+		    total_calls ? (total_msec / total_calls) : 0,
+		    total_calls ? ((total_msec % total_calls) * 100 / total_calls) : 0);
+    (void) fprintf(stdout, "%s PROTOCOL\n", Tcp ? "TCP" : "UDP");
+    (void) fprintf(stdout, "FAST CALLS: %d\n", Ops[TOTAL].results.fast_calls);
+    (void) fprintf(stdout, "NFS MIXFILE: ");
+    if (mix_file)
+	(void) fprintf(stdout,"%s\n", mix_file);
+    else
+	(void) fprintf(stdout,"[ SFS Default ]\n");
+    (void) fprintf(stdout, "CLIENT REQUESTED LOAD: %d Ops/Sec \n", load);
+    (void) fprintf(stdout,
+			"TOTAL NFS OPERATIONS: %-6d      TEST TIME: %d Sec \n",
+			total_calls, runtime);
+    (void) fprintf(stdout, "FILE SET SIZE CREATED: %d KB\n",
+							Total_fss_bytes);
+    (void) fprintf(stdout,
+		"FILE SET SIZE ACCESSED: %d - %d KB  (%d%% to %d%% of Base)\n",
+		Least_fss_bytes, Most_fss_bytes,
+		(100 * Least_fss_bytes) / Base_fss_bytes,
+		(100 * Most_fss_bytes) / Base_fss_bytes);
+    (void) fprintf(stdout, "\n");
+    (void) fprintf(stdout,
+    "------------------------------------------------------------------------");
+    (void) fprintf(stdout, "\n\n");
+    (void) fflush(stdout);
+
+    /*
+     * store client summary results and Invalid run indicator
+     * to send to the Prime_client
+     */
+    if (Prime_client) {
+	(void) sprintf(result_string,"%d.%02d %d.%02d %d %d %d %d %d %d %d\n",
+	    runtime ? (total_calls / runtime) : 0,	    /* ops/sec1 */
+	    runtime ? ((total_calls % runtime) * 100 / runtime) : 0, /* ops/sec2 */
+	    total_calls ? (total_msec / total_calls) : 0,	/* mean1 */
+	    total_calls ? ((total_msec % total_calls) * 100 / total_calls) : 0, /* mean2 */
+	    runtime,         				    /* run time */
+	    total_calls,	 			    /* # ops */
+	    invalid_flag,    				    /* valid flag */
+	    Total_fss_bytes,   				    /* total fileset */
+	    Least_fss_bytes,   				    /* fileset low */
+	    Most_fss_bytes,				    /* fileset high */
+	    Base_fss_bytes);				    /* fileset base */
+	(void) strcat(Client_results, result_string);
+    }
+
+} /* print_results */
+
+
+/* ARGSUSED */
+static void
+sfs_reaper(
+    int		sig_id)
+{
+    (void) fprintf(stderr, "%s: caught unexpected SIGCHLD. Exiting...\n",
+		       sfs_Myname);
+    /* cleanup and exit */
+    (void) signal_Prime_Client("CLIENT_STOP", "");
+    (void) generic_kill(0, SIGINT);
+    exit(83);
+}
+/* sfs_c_pnt.c */
diff --git a/TBBT/trace_play/sfs_c_rnd.c b/TBBT/trace_play/sfs_c_rnd.c
new file mode 100644
index 0000000..b3a0174
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_rnd.c
@@ -0,0 +1,247 @@
+#ifndef lint
+static char sfs_c_rndSid[] = "@(#)sfs_c_rnd.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_c_rnd.c ---------------------
+ *
+ *      Random number generator.
+ *
+ *.Exported_routines
+ *	int32_t sfs_random(void)
+ *	void sfs_srandom(int)
+ *
+ *.Local_routines
+ *	double ran(void)
+ *	int32_t spec_rand(void)
+ *	void spec_srand(int)
+ *
+ *.Revision_History
+ *	28-Nov-91	Teelucksingh	ANSI C
+ *	01-Aug-91	Wiryaman	sfs_srandom() and sfs_random()
+ *					now use spec_srand() and spec_rand()
+ *					instead of srandom() and random().
+ *      17-Apr-91       Wittle		Created.
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+/*
+ * Here's the source for the random number generator that SPEC uses.
+ * The function to be called is "spec_rand" which returns an integer
+ * between 1 and MAX_INT-1.
+ *
+ * One question we may wanna think about is the seeding of the random
+ * number generator. Do we start with the same seed everytime (for
+ * repeatability) or use a array of possible seeds (some seeds are better
+ * than others and SPEC prople mention that they have a list of 15
+ * "good" seeds).
+ */
+
+
+/*
+ * -------------------------  Static Declarations  -------------------------
+ */
+
+static int32_t seedi = 2231;
+
+
+/*
+ * -------------------------  External Definitions  -------------------------
+ */
+
+static double ran(void);
+static int32_t spec_rand(void);
+static void spec_srand(int);
+
+/*
+ * -----------------------  Random Number Routines  -----------------------
+ */
+
+
+/*
+ * Seed the random number generator.
+ */
+static void
+spec_srand(
+    int seed)
+{
+    seedi = seed;
+}
+
+
+/*
+ * Returns a random number.
+ */
+static int32_t
+spec_rand(void)
+{
+    (void) ran();
+    return(seedi);
+}
+
+
+/*
+ * Compute the next random number.
+ */
+static double
+ran(void)
+
+/* See "Random Number Generators: Good Ones Are Hard To Find", */
+/*     Park & Miller, CACM 31#10 October 1988 pages 1192-1201. */
+/***********************************************************/
+/* THIS IMPLEMENTATION REQUIRES AT LEAST 32 BIT INTEGERS ! */
+/***********************************************************/
+
+#define _A_MULTIPLIER  16807L
+#define _M_MODULUS     2147483647L /* (2**31)-1 */
+#define _Q_QUOTIENT    127773L     /* 2147483647 / 16807 */
+#define _R_REMAINDER   2836L       /* 2147483647 % 16807 */
+{
+    int32_t	lo;
+    int32_t	hi;
+    int32_t	test;
+
+    hi = seedi / _Q_QUOTIENT;
+    lo = seedi % _Q_QUOTIENT;
+    test = _A_MULTIPLIER * lo - _R_REMAINDER * hi;
+    if (test > 0) {
+	seedi = test;
+    } else {
+	seedi = test + _M_MODULUS;
+    }
+    return((float) seedi / _M_MODULUS);
+}
+
+/*
+ * Local interface to seed random number generator.
+ */
+void
+sfs_srandom(
+    int		seed)
+{
+    spec_srand(seed);
+}
+
+
+/*
+ * Local interface to obtain a random number.
+ */
+int32_t
+sfs_random(void)
+{
+    return(spec_rand());
+}
+
+static struct r_array {
+	int n1;
+	int n2;
+} *r_array;
+
+static int r_length = 0;
+
+static int
+r_array_compare(const void *i, const void *j)
+{
+	if (((struct r_array *)i)->n2 > ((struct r_array *)j)->n2)
+		return (1);
+	if (((struct r_array *)i)->n2 < ((struct r_array *)j)->n2)
+		return (-1);
+	return (0);
+}
+
+int
+init_rand_range(int length)
+{
+	int i;
+
+	/*
+	 * If array already exists free it
+	 */
+	if (r_length != 0) {
+		(void)free(r_array);
+		r_length = 0;
+	}
+
+	/*
+	 * If length is zero just free memory and return
+	 */
+	if (length == 0)
+		return (0);
+
+	/*
+	 * Allocate array of sequential numbers and random numbers
+	 */
+	if ((r_array = malloc(length * sizeof(struct r_array))) == NULL)
+		return (1);
+
+	r_length = length;
+
+	/*
+	 * Initialize array of sequential values and random values
+	 */
+	for (i = 0; i < length; i++) {
+		r_array[i].n1 = i;
+		r_array[i].n2 = sfs_random();
+	}
+
+	/*
+	 * Sort random array values to put sequential values in random order
+	 */
+	qsort(r_array, length, sizeof(struct r_array), r_array_compare);
+
+	return (0);
+}
+
+int
+rand_range(int index)
+{
+	return (r_array[index].n1);
+}
+/* sfs_c_rnd.c */
diff --git a/TBBT/trace_play/sfs_c_sig.c b/TBBT/trace_play/sfs_c_sig.c
new file mode 100644
index 0000000..7826377
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_sig.c
@@ -0,0 +1,170 @@
+#ifndef lint
+static char sfs_c_sigSid[] = "@(#)sfs_c_sig.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_c_sig.c ---------------------
+ *
+ *      Signal handling.  Routines to send and catch signals.
+ *
+ *.Exported_Routines
+ *	void sfs_alarm(int)
+ *	void sfs_startup(int)
+ *	void sfs_stop(int)
+ *	void sfs_cleanup(int)
+ *
+ *.Local_Routines
+ *	None.
+ *
+ *.Revision_History
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include <sys/signal.h>
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+#ifndef RFS
+/*
+ * -------------------------  Signal Handlers  -------------------------
+ */
+
+void
+sfs_alarm(
+    int         sig_id)
+{
+#if !(defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    (void) signal(sig_id, sfs_alarm);
+#endif
+    if (DEBUG_CHILD_SIGNAL)
+	(void) fprintf(stderr, "%s: caught Signal %d\n", sfs_Myname, sig_id);
+    (void) fflush(stderr);
+
+} /* sfs_alarm */
+
+
+/*
+ * Signal Handler
+ * Catch the parent's "start" signal.
+ */
+void
+sfs_startup(
+    int 	sig_id)
+{
+#if !(defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    (void) signal(SIGUSR1, sfs_startup);
+#endif
+    if (DEBUG_CHILD_SIGNAL)
+	(void) fprintf(stderr, "%s: caught Signal %d SIGUSR1\n",
+		       sfs_Myname, sig_id);
+
+    if (Child_num == -1)
+	/* I'm the parent, ignore the signal */
+	return;
+
+    /*
+     * SIGUSR1 is used to make all phase transitions, but we
+     * only want to make the Warmup -> Testrun switch here
+     */
+    if (Current_test_phase != Warmup_phase)
+	return;
+
+    Current_test_phase = Testrun_phase;
+    start_run_phase++;
+} /* sfs_startup */
+
+
+/*
+ * Signal Handler
+ * Catch the parent's "stop" signal.
+ */
+void
+sfs_stop(
+    int		sig_id)
+{
+#if !(defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    (void) signal(SIGUSR2, sfs_stop);
+#endif
+    if (DEBUG_CHILD_SIGNAL)
+	(void) fprintf(stderr, "%s: caught Signal %d SIGUSR2\n",
+		       sfs_Myname, sig_id);
+
+    /* end the test */
+    Runtime = 0;
+    Current_test_phase = Results_phase;
+
+} /* sfs_stop */
+
+#endif
+
+
+/*
+ * SIGINT, SIGTERM handler
+ * Clean up and exit due to an error/abort condition.
+ * We assume if NFS_client was valid, then MOUNT_client was also valid.
+ */
+void
+sfs_cleanup(
+    int		sig_id)
+{
+    if (DEBUG_CHILD_SIGNAL)
+	(void) fprintf(stderr, "%s: caught Signal %d SIGINT\n",
+		       sfs_Myname, sig_id);
+
+    (void) unlink(Logname);
+    if (NFS_client != ((CLIENT *) NULL))
+	clnt_destroy(NFS_client);
+    exit(65);
+
+} /* sfs_cleanup */
+
+/* sfs_c_sig.c */
diff --git a/TBBT/trace_play/sfs_c_sub.c b/TBBT/trace_play/sfs_c_sub.c
new file mode 100644
index 0000000..7f91b89
--- /dev/null
+++ b/TBBT/trace_play/sfs_c_sub.c
@@ -0,0 +1,198 @@
+#ifndef lint
+static char sfs_c_subSid[] = "@(#)sfs_c_sub.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * ---------------------- sfs_c_sub.c ---------------------
+ *
+ *      Subroutines common to both sfs and sfs_prime_client.
+ *
+ *.Exported_Routines
+ *	int generic_kill(int, int)
+ *	void generic_catcher(int)
+ *	char * lad_timestamp(void)
+ *
+ *.Local_Routines
+ *	None.
+ *
+ *.Revision_History
+ *	16-Dec-91	Wittle 		Created.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <sys/signal.h>
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+
+/*
+ * Common data shared between sfs and sfs_prime
+ *
+ * Values for invalid runs
+ */
+char *invalid_str[INVALID_MAX] = {
+	"No error",
+	"Unknown",
+	"IO distribution file",
+	"Mix file",
+	"Runtime",
+	"Access percentage",
+	"Append percentage",
+	"KB per block",
+	"Number client directories",
+	"Fileset delta",
+	"Max biod reads",
+	"Number symlinks",
+	"Max biod writes",
+	"Warmup time",
+	"No good calls",
+	"Failed RPC calls",
+	"Op mix missed",
+};
+
+/*
+ * -------------------------  Signal Handlers  -------------------------
+ */
+
+/*
+ * Signal Sender.  Send signal 'sig' to process 'pid'.
+ */
+int
+generic_kill(
+    int 	pid,
+    int 	signal)
+{
+    if (DEBUG_PARENT_SIGNAL)
+	(void) fprintf(stderr,
+			"%s: sending Pid %d Signal %d\n", sfs_Myname, pid ,signal);
+    return(kill((pid_t)pid, signal));
+
+} /* generic_kill */
+
+
+/*
+ * Signal Handler.  Catch and reset the handler for signal 'i'.
+ */
+void
+generic_catcher(
+    int 	i)
+{
+#if !(defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    (void) signal(i, generic_catcher);
+#endif
+    if (DEBUG_CHILD_SIGNAL)
+	(void) fprintf(stderr, "%s: caught Signal %d\n", sfs_Myname, i);
+    (void) fflush(stderr);
+
+} /* generic_catcher */
+
+
+
+/*
+ * get the date and time and return a string, remove the END-OF-LINE (\n)
+ */
+char *
+lad_timestamp(void)
+{
+    static time_t	run_date;
+    static char		date_string[26];
+
+    run_date = time((time_t *)NULL);
+    (void) strncpy((char *) date_string, (char *) ctime(&run_date), 24);
+    return(date_string);
+
+} /* lad_timestamp */
+
+int
+set_debug_level(char *s)
+{
+    unsigned int i;
+    unsigned int first;
+    unsigned int last;
+    unsigned int level = 0;
+
+    if (s == NULL || *s == '\0')
+	return(0);
+
+    for (;;) {
+	if (*s == ',') {
+	    s++;
+	    continue;
+	}
+
+	/* find first flag to set */
+	i = 0;
+	while (isdigit(*s))
+	    i = i * 10 + (*s++ - '0');
+	first = i;
+
+	/* find last flag to set */
+	if (*s == '-') {
+	    i = 0;
+	    while (isdigit(*++s))
+		i = i * 10 + (*s - '0');
+	}
+	last = i;
+
+	if (first != 0 && last != 0 && first < 32 && last < 32) {
+	    for (i = first - 1; i < last; i++) {
+		level |= (1 << i);
+	    }
+	}
+
+	/* more arguments? */
+	if (*s++ == '\0')
+		return (level);
+    }
+}
+
+/* sfs_c_sub.c */
diff --git a/TBBT/trace_play/sfs_ext_mon b/TBBT/trace_play/sfs_ext_mon
new file mode 100755
index 0000000..841e9a1
--- /dev/null
+++ b/TBBT/trace_play/sfs_ext_mon
@@ -0,0 +1,58 @@
+#!/bin/sh
+#	@(#)sfs_ext_mon	2.1	97/10/23
+#
+# This sample shell script can be used to start and stop
+# external processes at the beginning and ending of the
+# sfs load generation period respectively. The name of
+# this program is pased in via the PRIME_MON_SCRIPT variable
+# in the sfs_rc or equivalent file. The sfs_prime program
+# executes this shell script just before it issues the START
+# message to all the clients ie. "script_name START"; and likewise
+# another call after all the clients have completed load generation ie.
+# "script_name DONE".
+#
+# All environment variables exported from sfs_mgr are available for use.
+#
+EXT_MON_ARG=""
+if [ $# -gt 1 ]
+then
+    EXT_MON_ARG="$2"
+fi
+
+#
+#----------------- START section -----------------
+# Code section that handles starting of external processes.
+# ALL PROCESSES SHOULD BE STARTED IN THE BACKGROUND OR ELSE
+# THE TEST WILL BLOCK WAITING FOR THEIR COMPLETION!!
+#
+if [ "$1" = "START" ]; then
+	#
+	# place commands to start performance monitoring utilities as
+	# background processes here.
+	#
+	echo "$0: started external monitoring utilities" >&2
+	exit 0
+fi
+
+#
+#----------------- DONE section -----------------
+# Code section that handles stopping of external processes.
+# ALL PROCESSES SHOULD BE STARTED IN THE BACKGROUND OR ELSE
+# THE TEST WILL BLOCK WAITING FOR THEIR COMPLETION!!
+#
+if [ "$1" = "DONE" ]; then
+	#
+	# place commands to stop performance monitoring utilities as
+	# background processes here.
+	#
+	echo "$0: stopped external monitoring utilities" >&2
+	exit 0
+fi
+
+#
+#----------------- ERROR section -----------------
+# ERROR: BAD PARAMETER
+#
+echo "$0: bad param. " >&2
+echo "usage: $0 START | DONE " >&2
+exit 1
diff --git a/TBBT/trace_play/sfs_m_def.h b/TBBT/trace_play/sfs_m_def.h
new file mode 100644
index 0000000..bd01ec6
--- /dev/null
+++ b/TBBT/trace_play/sfs_m_def.h
@@ -0,0 +1,59 @@
+/*
+ * @(#)sfs_m_def.h	2.1	97/10/23
+ */
+
+/*
+ *	Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+#define MAX_LINE_LEN 160 		/* max per line results string */
+#define MAX_STR1_LEN 31 		/* max msg, number, and xid str len */
+#define MAX_STR2_LEN 2560		/* total results data string length */
+#define MULTICLIENT_OFFSET 500  	/* Runtime offset */
+
+/* multi-client sync logfiles and prefixes */
+#define SFS_CLIENT_SYNC_LOG "/tmp/sfs_CL" /* client logfile prefix */
+#define SFS_PRIME_SYNC_LOG "/tmp/sfs_PC_sync" /* prime client logfile */
+#define PRIME_RESULTS_LOG "/tmp/sfs_res"  /* prime results logfile prefix */
+
+struct sync_string {
+	int clnt_id;				/* client number */
+	char *clnt_type;			/* message type, hard coded */
+	char *clnt_transaction;			/* transaction id */
+	char *clnt_data;			/* results strings */
+};
+typedef struct sync_string sync_string;
+
+#define SFS_SYNCPROG ((uint32_t) 100500)
+#define SFS_SYNCVERS ((uint32_t) 1)
+#define SIGNAL_NULLPROC ((uint32_t) 0)
+#define SIGNAL_SFS ((uint32_t) 1)
+
+extern bool_t	xdr_sync_string(XDR *, sync_string *);
+extern int *    signal_sfs_1(sync_string *, CLIENT *);
diff --git a/TBBT/trace_play/sfs_m_msg.c b/TBBT/trace_play/sfs_m_msg.c
new file mode 100644
index 0000000..80fbeec
--- /dev/null
+++ b/TBBT/trace_play/sfs_m_msg.c
@@ -0,0 +1,103 @@
+#ifndef lint
+static char sfs_m_msgSid[] = "@(#)sfs_m_msg.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ *.Exported_routines
+ *	int * signal_sfs_1(sync_string *, CLIENT *);
+ *
+ *.Local_routines
+ *	None.
+ *
+ *.Revision_history
+ *	04-Dec-91	Keith		Include sfs_def.h for SYSV/SVR4
+ *					mem* routines.
+ *	17-Jun-91	Teelucksingh	Create multi-client synchronization
+ *					rpc definition
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+/*
+ * -----------------------  Static Definitions  -----------------------
+ */
+
+/*
+ * Almost all rpcs are sent over TCP so we have a reliable transport,
+ * unfortunately the initialization phase may highly overload the
+ * server and the previous default of 5 seconds might timeout before
+ * it gets acknowledged.  The risk of a large timeout is that there is
+ * an added period after a stop message is sent.  This is usually not
+ * a problem.
+ */
+static struct timeval TIMEOUT = { 60, 0 };
+
+
+/*
+ * -------------------  Multi-client Message Handling  -------------------
+ */
+
+int *
+signal_sfs_1(
+    sync_string *	argp,
+    CLIENT *		clnt)
+{
+    static int		res;
+
+    (void) memset((char *) &res, '\0', sizeof(res));
+    if (clnt_call(clnt, SIGNAL_SFS, xdr_sync_string, (caddr_t)argp, xdr_int,
+		  (caddr_t)&res, TIMEOUT) != RPC_SUCCESS) {
+	return (NULL);
+    }
+    return (&res);
+} /* signal_sfs_1 */
+
+
+/* sfs_m_msg.c */
diff --git a/TBBT/trace_play/sfs_m_prm.c b/TBBT/trace_play/sfs_m_prm.c
new file mode 100644
index 0000000..5cc5ac3
--- /dev/null
+++ b/TBBT/trace_play/sfs_m_prm.c
@@ -0,0 +1,1545 @@
+#ifndef lint
+static char sccsid[] = "@(#)sfs_m_prm.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ * This program is started from sfs_mgr.  It runs on some system
+ * designated as the Prime Client and synchronizes the the different
+ * phases of a SFS benchmark execution amongst multiple clients by
+ * means of RPCs.  The Prime client can also be running SFS.
+ *
+ *.Exported_routines
+ *	int main(int, char **)
+ *
+ *.Local_routines
+ *	void multi_cleanup(int)
+ *	void do_initialize(int, char **)
+ *	void sync_PC_with_clients(void)
+ *	int signal_sfs_clients(char *, int)
+ *	void print_multi_results(void)
+ *	void prog_usage(void)
+ *	void printdeadclients(void)
+ *
+ *.Revision_history
+ *	11-Jul-94	ChakChung Ng	Add codes for NFS/v3
+ *      02-Jul-92	0.1.9   Teelucksingh
+ *				Use tcp handles for synchronization
+ *				instead of udp ones. Added code to make
+ *                              call to shell script to start and stop
+ *				external monitoring (no longer creates
+ *				/tmp/SFS_START and /tmp/SFS_DONE).
+ *	10-Jan-92	0.00.19 Teelucksingh
+ *				Added code for the Prime-Client to report
+ *				'INVALID RUN' from any of the clients.
+ *			        Also added code to compute and report
+ *				the aggregate 'average response time
+ *				standard deviation values'.
+ *	04-Jan-92	0.00.18 Pawlowski
+ *				Add hooks for raw data dump support.
+ *	04-Dec-91	0.00.15 Keith
+ *				Include string.h for SYSV/SVR4
+ *	28-Nov-91	0.00.13 Teelucksingh
+ *				Fixed 'multiple signals' problem.
+ *				Sync rpcs now pass a 'transaction id'
+ *				to 'sfs_syncd', the sync server.
+ *				'sfs_syncd' keeps track of previous rpc
+ *				calls that successfully executed.
+ *				Added ANSI C features.
+ *
+ *      23-Sep-91	0.00.11 Teelucksingh
+ *                              Modified the format of sfs_prime output
+ *	17-Jun-91	Teelucksingh 	Created.
+ *
+ *
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+ 
+#include <sys/file.h>
+#include <fcntl.h>
+
+#include <unistd.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+#if !defined(_XOPEN_SOURCE)
+#include <sys/socket.h>
+#else
+#define	AF_INET		2
+#endif
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+
+
+/* sfs_mpr.c function declarations */
+/* external sfs routines */
+
+/* forward definitions for local routines */
+static void multi_cleanup(int);
+static void do_initialize(int, char **);
+static void sync_PC_with_clients(void);
+static int signal_sfs_clients(char *);
+static void print_multi_results(void);
+static void prog_usage(void);
+static void printdeadclients(void);
+
+/*
+ * -----------------------  Static Definitions  -----------------------
+ */
+
+#define EXTRA_INIT_TIME 3600  /* extra time to initialize before timing out */
+
+int Debug_level = 0;		/* flag indicates prime client debug mode */
+char *sfs_Myname;			/* program name */
+int nfs_version;
+
+static int Asleep = 0;	        /* flag: parent sfs process is asleep */
+static int Pc_log_fd;	               /* Prime client sync log fd */
+static int Num_clients = 0;  	       /* number of clients used in run */
+static char **Client_names; /* [HOSTNAME_LEN];   array of clients host names */
+			     /* sleep period before issuing a go ahead signal */
+static int Prime_sleep_time = 0;
+			     /* time to wait before exiting with error */
+static int Prime_time_out = 400;
+static int Prime_runtime = DEFAULT_RUNTIME; /* seconds in benchmark run */
+
+/*
+ * the Prime_client only uses the P_* variables
+ * for calculating and reporting the Aggregate
+ * run parameters.
+ */
+static int P_children = DEFAULT_NPROCS; /* processes per client */
+static int P_total_load = DEFAULT_LOAD; /* NFS operations per second */
+static int P_percent_append = DEFAULT_APPEND; /* % of writes that append */
+static int P_percent_access = DEFAULT_ACCESS; /* % of file set accessed */
+static int P_kb_per_block = DEFAULT_KB_PER_BLOCK; /* i/o pkt block sz in KB */
+static int P_dump_data = 0;		/* raw output switch */
+static int P_testop = -1;		/* test mode operation number */
+static int P_percent_fss_delta =	/* allowed change to file set */
+				DEFAULT_DELTA_FSS;
+					/* allowed change to file set */
+static int P_warmuptime = DEFAULT_WARMUP; /* seconds to warmup */
+static char *P_iodist_file = 0;		/* block io dist table file */
+static char *P_mix_file = 0;		/* mix file */
+static char *P_script_name = 0;		/* external script name */
+static char *P_script_args = "";	/* external script parameters */
+static int P_tcp = 0;			/* TCP */
+static FILE *sum_result_fp = NULL;
+
+/*
+ * ---------------------  Biod Simulation Variables ---------------------
+ */
+static int P_biod_max_outstanding_reads = DEFAULT_BIOD_MAX_READ;
+static int P_biod_max_outstanding_writes = DEFAULT_BIOD_MAX_WRITE;
+
+/* list of nfs operations - used to verify results file */
+static char *Ops_name[NOPS] = {	"null", "getattr", "setattr", "root", "lookup",
+				"readlink", "read", "wrcache", "write",
+				"create", "remove", "rename", "link",
+				"symlink", "mkdir", "rmdir", "readdir",
+				"fsstat", "access", "commit", "fsinfo",
+				"mknod", "pathconf", "readdirplus" };
+
+
+/*
+ * --------------------------  Prime-client  --------------------------
+ */
+
+
+/*
+ * SIGINT Signal Handler
+ * - rpc to all clients to cleanup and exit
+ */
+static void
+multi_cleanup(
+    int		sig_id)
+{
+    /* wake up this process if asleep */
+    if (Asleep == 1) {
+	(void) generic_kill(0,SIGALRM);
+    }
+    (void) fprintf(stderr,"\n%s: Caught Signal %d SIGINT\n", sfs_Myname, sig_id);
+    (void) fprintf(stderr,"\nSending interupt signal to clients ... ");
+    (void) fflush(stderr);
+    if ((int) signal_sfs_clients("PRIME_STOP") !=0)
+	exit(9);
+    (void) fprintf(stderr,"done\n");
+    (void) fflush(stderr);
+    (void) close(Pc_log_fd);
+    (void) unlink(SFS_PRIME_SYNC_LOG);
+    exit(10);
+
+} /* multi_cleanup */
+
+
+/*
+ * main
+ * synchronizes multi-client sfs run
+ * - wait for 'DONE-MOUNT' from all clients
+ * - tell them to `DO-INIT`
+ * - wait for `DONE-INIT` from all clients
+ * - tell them to `DO-WARMUP`
+ * - wait for 'READY from all clients
+ * - tells them to 'START' and goes to sleep
+ * - wakes up and tells clients to 'STOP'
+ * - wait for 'DONE-TEST' from all clients
+ * - tells clients to 'MOVE-DATA'
+ * - averages multi-client data and exits
+ */
+int
+main(
+    int		argc,
+    char *	argv[])
+{
+    int		i;
+    char	monitor_cmd[SFS_MAXPATHLEN+5];
+    int		nsigs = 32;		/* reasonable default */
+    FILE	*pid_fp;
+
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    struct sigaction sig_act, old_sig_act;
+#endif
+
+    /*
+     * Place pid in pid log file
+     */  
+    if ((pid_fp = fopen(SFS_PRM_PID, "a+")) == NULL) {
+        perror(SFS_PRM_PID);
+        exit(1);
+    }
+    (void) fprintf(pid_fp, "%d\n", getpid());
+    (void) fclose(pid_fp);
+
+    (void) fprintf(stderr, "\nSPEC SFS Benchmark Version %s, Creation - %s\n",
+                                SFS_VERSION_NUM, SFS_VERSION_DATE);
+    (void) fflush(stderr);
+
+    /* initialize variables, parse input, etc.  */
+    do_initialize(argc, argv);
+
+    /*
+     * setup value of nsigs
+     */
+#ifdef __NSIG
+    nsigs = __NSIG;
+#endif
+#ifdef _NSIG
+    nsigs = _NSIG;
+#endif
+#ifdef NSIG
+    nsigs = NSIG;
+#endif
+#if defined(SOLARIS2) && !defined(_sys_nsig)
+    nsigs = _sys_siglistn;
+#endif
+
+    /* trap for all signals */
+
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    /* use XOPEN signal handling */
+    sig_act.sa_handler = generic_catcher;
+    (void)sigemptyset(&sig_act.sa_mask);
+    sig_act.sa_flags = 0;
+    if (DEBUG_PARENT_GENERAL) {
+	if (nsigs == 0) {
+	    (void) fprintf (stderr,
+		    "WARNING: nsigs not defined, no extra signals caught\n");
+	}
+	for (i = 1; i < nsigs; i++) {
+     /* attempt to set up signal handler for these signals gives an error. */
+	    if (i!=SIGCHLD && i!=SIGKILL && i!=SIGSTOP && i!=SIGCONT) {
+                if (sigaction(i,&sig_act,&old_sig_act) == -1) {
+                        if (errno == EINVAL)
+                                (void) fprintf (stderr,
+					"Skipping invalid signal %d\n", i);
+                        else {
+                                perror("sigaction failed");
+                                exit(11);
+                        }
+                }
+	    }
+	}
+    }
+
+    /* signals handlers for signals used by sfs_prime */
+    sig_act.sa_handler = multi_cleanup;
+    if (sigaction(SIGINT,&sig_act,&old_sig_act) != 0) {
+		perror("sigaction failed: SIGINT");
+		exit(12);
+    }
+#else
+
+    if (DEBUG_PARENT_GENERAL) {
+	if (nsigs == 0) {
+	    (void) fprintf (stderr,
+		    "WARNING: nsigs not defined, no extra signals caught\n");
+	}
+	for (i = 1; i < nsigs; i++) {
+	    (void) signal(i, generic_catcher);
+	}
+    }
+
+    /* set up SIGINT signal handler */
+    (void) signal(SIGINT, multi_cleanup);
+
+#endif /* USE_POSIX_SIGNALS */
+
+    (void) fprintf(stderr, "Executing SFS Benchmark on %d Client(s).\n",
+		    Num_clients);
+    (void) fflush(stderr);
+
+    /* wait for 'DONE-MOUNT message from the clients */
+    (void) fprintf(stderr,
+	   "%s Waiting on DONE-MOUNT message from %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+
+    sync_PC_with_clients();             /* wait for clients DONE-MOUNT */
+
+    (void) fprintf(stderr, "%s Received.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /* send DO-INIT message to all the clients  */
+    (void) fprintf(stderr, "%s Sending DO-INIT message to %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+    if ((int) signal_sfs_clients("PRIME_SIGNAL") !=0)
+	exit(13);
+    (void) fprintf(stderr, "%s Completed.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /* wait for 'DONE-INIT' message from the clients */
+    (void) fprintf(stderr,
+	   "%s Waiting on DONE-INIT message from %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+
+    /*
+     * add an extra time to time_out value.
+     * initializing the SFS testdirs on clients can take a while.
+     */
+    Prime_time_out += EXTRA_INIT_TIME;
+    sync_PC_with_clients();             /* wait for clients DONE-INIT */
+    Prime_time_out -= EXTRA_INIT_TIME;        /* reset time_out */
+
+    (void) fprintf(stderr, "%s Received.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /* send DO-WARMUP message to all the clients  */
+    (void) fprintf(stderr, "%s Sending DO-WARMUP message to %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+    if ((int) signal_sfs_clients("PRIME_SIGNAL") !=0)
+	exit(14);
+    (void) fprintf(stderr, "%s Completed.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /* wait for 'READY' message from the clients */
+    (void) fprintf(stderr, "%s Waiting on READY message from %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+
+    (void) sleep(P_warmuptime);
+
+    sync_PC_with_clients();		/* wait for clients READY */
+
+    (void) fprintf(stderr, "%s Received.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /*
+     * call the program to trigger START of external monitoring
+     */
+     if (P_script_name) {
+	(void) sprintf(monitor_cmd,"%s %s %s",P_script_name,
+			"START",P_script_args);
+	if (system(monitor_cmd) != 0) {
+		(void) fprintf(stderr,"%s: external monitoring command (%s) failed - %d - continuing.\n ",
+			sfs_Myname, monitor_cmd, errno);
+		(void) fflush(stderr);
+		P_script_name = NULL;
+	}
+
+     }
+
+    /*
+     * wait period before telling clients to START - gives external
+     * performance monitoring utilities enough time to start up.
+     * Value set in sfs_rc (PRIME_SLEEP) - default is 0 seconds.
+     */
+    (void) sleep(Prime_sleep_time);
+
+    /* send START message to all the clients  */
+    (void) fprintf(stderr, "%s Sending START message to %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+    if ((int) signal_sfs_clients("PRIME_SIGNAL") !=0)
+	exit(15);
+    (void) fprintf(stderr, "%s Completed.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /*
+     * Sleep for <Prime_runtime> seconds
+     * and then send STOP message to tell the sfs clients
+     * that is time to wrap things up.
+     */
+    /* set the Asleep flag go to sleep while clients are executing sfs */
+    Asleep = 1;
+    (void) sleep(Prime_runtime);
+    Asleep = 0;
+
+    (void) fprintf(stderr, "%s Sending STOP message to %d client(s).\n",
+			lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+    if ((int) signal_sfs_clients("PRIME_ALARM") !=0)
+	exit(16);
+    (void) fprintf(stderr, "%s Completed.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+
+    /* wait for DONE-TEST message from clients indicating they completed run */
+    (void) fprintf(stderr, "%s Waiting on DONE-TEST message from %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+    sync_PC_with_clients();
+    (void) fprintf(stderr, "%s Received.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /*
+     * call the program to trigger STOP of external monitoring
+     */
+     if (P_script_name) {
+	(void) sprintf(monitor_cmd,"%s %s %s",P_script_name,
+			"DONE",P_script_args);
+	if (system(monitor_cmd) != 0) {
+		(void) fprintf(stderr,"%s: external monitoring command (%s) failed - %d - continuing.\n ",
+			sfs_Myname, monitor_cmd, errno);
+		(void) fflush(stderr);
+		P_script_name = NULL;
+	}
+     }
+
+    /* give enough time to stop external performance monitoring utilities.  */
+    (void) sleep(Prime_sleep_time);
+
+    /*
+     * send MOVE-DATA message to Clients to move data across
+     */
+    (void) fprintf(stderr, "%s Sending MOVE-DATA message to %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+    if ((int) signal_sfs_clients("PRIME_SIGNAL") !=0)
+	exit(17);
+    (void) fprintf(stderr, "%s Completed.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /* wait for SEND-DATA message from all the clients */
+    (void) fprintf(stderr,
+		    "%s Waiting on SEND-DATA message from %d client(s).\n",
+		    lad_timestamp(), Num_clients);
+    (void) fflush(stderr);
+    sync_PC_with_clients();
+    (void) fprintf(stderr, "%s Received.\n", lad_timestamp());
+    (void) fflush(stderr);
+
+    /* summarize and print aggregate results */
+    print_multi_results();
+
+    /* close files and exit success */
+    (void) close(Pc_log_fd);
+    (void) unlink(SFS_PRIME_SYNC_LOG);
+    (void) unlink(SFS_PRM_PID);
+    return(0);
+
+}  /* main */
+
+/*
+ * initialize control variables, open logfiles etc.
+ */
+static void
+do_initialize(
+    int		argc,
+    char	*argv[])
+{
+    int		c;
+    FILE	*check_fp;
+    int i;
+    char	*cp;
+    extern char *optarg;
+    extern int optind;
+
+
+    sfs_Myname = argv[0];
+    if (argc <= 1) {
+	prog_usage();
+	/* NOTREACHED */
+    }
+
+    while ((c = getopt(argc, argv, "a:A:b:B:C:d:f:k:K:l:m:p:QR:s:t:T:W:w:x:z")) != EOF)
+	switch (c) {
+	case 'a': /* Percent of file set to access;
+		   * used in aggregate report.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal acces value %s\n",
+					sfs_Myname, optarg);
+		exit(18);
+	    }
+	    P_percent_access = atoi(optarg);
+	    if (P_percent_access < 0 || P_percent_access > 100) {
+		(void) fprintf(stderr,
+		       "%s: %% access must be between 0 and 100\n",
+			sfs_Myname);
+		exit(19);
+	    }
+	    break;
+
+	case 'A': /* Percent of writes that append;
+		   * used in aggregate report.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal append value %s\n",
+					sfs_Myname, optarg);
+		exit(20);
+	    }
+	    P_percent_append = atoi(optarg);
+	    if (P_percent_append < 0 || P_percent_append > 100) {
+		(void) fprintf(stderr,
+			       "%s: %% append must be between 0 and 100\n",
+				sfs_Myname);
+		exit(21);
+	    }
+	    break;
+
+	case 'b': /* Set block size distribution table file
+		   * used in aggregate report.
+		   */
+	    if ((check_fp = fopen(optarg, "r")) == NULL) {
+		cp = strerror(errno);
+		(void) fprintf(stderr, "%s: bad block size file %s: %s\n",
+					sfs_Myname, optarg, cp);
+		exit(22);
+	    }
+	    P_iodist_file = optarg;
+	    (void) fclose(check_fp);
+	    break;
+
+
+	case 'B': /* Set the per packet maximum block size
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal block size value %s\n",
+					sfs_Myname, optarg);
+		exit(23);
+	    }
+	    P_kb_per_block = atoi(optarg);
+	    if ((P_kb_per_block < 1) ||
+			(P_kb_per_block > (DEFAULT_MAX_BUFSIZE/1024))) {
+		(void) fprintf(stderr, "%s: illegal block size value %s\n",
+					sfs_Myname, optarg);
+		exit(24);
+	    }
+	    break;
+
+	case 'C': /*
+		   * Set summary result file
+		   */
+            if ((sum_result_fp = fopen(optarg, "a+")) == NULL) {
+		cp = strerror(errno);
+		(void) fprintf(stderr,
+			"%s: Unable to create summary result file %s: %s\n",
+					sfs_Myname, optarg, cp);
+		exit(222);
+	    }
+	    break;
+
+	case 'd': /*
+		   * Set Debug_level
+		   */
+	    Debug_level = set_debug_level(optarg);
+	    break;
+
+	case 'f': /* Percent change in file set size
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal file set delta value %s\n",
+					sfs_Myname, optarg);
+		exit(26);
+	    }
+	    P_percent_fss_delta = atoi(optarg);
+	    if (P_percent_fss_delta < 0 || P_percent_fss_delta > 100) {
+		(void) fprintf(stderr,
+			   "%s: %% file set delta must be between 0 and 100\n",
+			    sfs_Myname);
+		exit(27);
+	    }
+	    break;
+
+	case 'k': /*
+		   * program to start and stop external
+		   * performance monitoring. Called at start
+		   * and completion of core load generation period.
+		   */
+	    if ((check_fp = fopen(optarg, "r")) == NULL) {
+		cp = strerror(errno);
+		(void) fprintf(stderr,
+			"%s: program %s protected or missing: %s\n",
+			sfs_Myname, optarg, cp);
+		exit(28);
+	    }
+	    P_script_name = optarg;
+	    (void) fclose(check_fp);
+	    break;
+
+	case 'K': /*
+		   * Command-line parameters for the external monitor
+		   * (see the "-k" option, above)
+		   */
+	    P_script_args = optarg;
+	    break;
+
+	case 'l': /* Set load
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal load value %s\n",
+					sfs_Myname, optarg);
+		exit(29);
+	    }
+	    P_total_load = atoi(optarg);
+	    if (P_total_load < 0) {
+		(void) fprintf(stderr, "%s: load must be > 0\n", sfs_Myname);
+		exit(30);
+	    }
+	    break;
+
+	case 'm': /* Set mix from a file
+		   * used in aggregate reporting only.
+		   */
+	    if ((check_fp = fopen(optarg, "r")) == NULL) {
+		cp = strerror(errno);
+		(void) fprintf(stderr, "%s: bad mix file: %s: %s\n",
+				sfs_Myname, optarg, cp);
+		exit(31);
+	    }
+	    P_mix_file = optarg;
+	    (void) fclose(check_fp);
+	    break;
+
+	case 'p': /* Set number of child processes
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal procs value %s\n",
+					sfs_Myname, optarg);
+		exit(32);
+	    }
+	    P_children = atoi(optarg);
+	    if (P_children < 0) {
+		(void) fprintf(stderr, "%s: number of children must be > 0\n",
+				sfs_Myname);
+		exit(33);
+	    }
+	    break;
+
+	case 'Q': /* Set NFS/TCP behaviour */
+	    P_tcp = 1;
+	    break;
+
+	case 'R': /* set maximum async read concurrency level
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal read count value %s\n",
+				sfs_Myname, optarg);
+		exit(34);
+	    }
+	    P_biod_max_outstanding_reads = atoi(optarg);
+	    if (P_biod_max_outstanding_reads < 0) {
+		(void) fprintf(stderr, "%s: read count must be >= 0\n",
+				sfs_Myname);
+		exit(35);
+	    }
+	    break;
+
+	case 's':
+	     /*
+	      * Set sleep time so external processes will
+	      * have time to startup
+	      */
+	      if (!isdigit(optarg[0])) {
+		  (void) fprintf(stderr, "%s: illegal sleep value %s\n",
+				  sfs_Myname, optarg);
+		  exit(36);
+	      }
+	      Prime_sleep_time = atoi(optarg);
+	      break;
+
+	case 't': /* Set SFS Runtime value */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal time value %s\n",
+				sfs_Myname, optarg);
+		exit(37);
+	    }
+	    Prime_runtime = atoi(optarg);
+	    if (Prime_runtime < 0) {
+		(void) fprintf(stderr, "%s: run time must be >= 0\n",
+				sfs_Myname);
+		exit(38);
+	    }
+	    break;
+
+	case 'T': /* Set Test mode operation
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal time_out value %s\n",
+				sfs_Myname, optarg);
+	       exit(39);
+	    }
+	    P_testop = atoi(optarg);
+	    if (P_testop >= NOPS) {
+		(void) fprintf(stderr, "%s: illegal test value %d\n",
+					sfs_Myname, P_testop);
+		exit(40);
+	    }
+	    break;
+
+	case 'W': /* set maximum async write concurrency level
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal write count value %s\n",
+					sfs_Myname, optarg);
+		exit(41);
+	    }
+	    P_biod_max_outstanding_writes = atoi(optarg);
+	    if (P_biod_max_outstanding_writes < 0) {
+		(void) fprintf(stderr, "%s: write count must be >= 0\n",
+				sfs_Myname);
+		exit(42);
+	    }
+	    break;
+
+	case 'w': /* Set warmup time
+		   * used in aggregate reporting only.
+		   */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr, "%s: illegal warmup value %s\n",
+				sfs_Myname, optarg);
+		exit(43);
+	    }
+	    P_warmuptime = atoi(optarg);
+	    if (P_warmuptime < 0) {
+		(void) fprintf(stderr, "%s: warmup time must be >= 0\n",
+				sfs_Myname);
+		exit(44);
+	    }
+	    break;
+
+	case 'x': /* Set Prime-Client time_out value */
+	    if (!isdigit(optarg[0])) {
+		(void) fprintf(stderr,
+				"%s: illegal time_out value %s\n",
+				sfs_Myname, optarg);
+	       exit(45);
+	    }
+	    Prime_time_out = atoi(optarg);
+	    break;
+
+	case 'z': /* Do raw data dumps
+		   *  used in aggregate reporting only.
+		   */
+	    P_dump_data++;
+	    break;
+
+	default:
+	    prog_usage();
+	    /* NOTREACHED */
+	} /* end switch on argument */
+
+    Num_clients = argc - optind;
+
+    /*
+     * allocate space and store clients names
+     */
+    Client_names = (char **) malloc(Num_clients * sizeof(char *));
+    if (Client_names == (char **) 0) {
+	(void) fprintf(stderr, "%s: client name malloc %d bytes failed",
+		    sfs_Myname, Num_clients * sizeof(char **));
+	exit(46);
+    }
+
+    for (i = 0; optind < argc; i++, optind++) {
+	Client_names[i] = argv[optind];
+	if (gethostbyname(argv[optind]) == NULL) {
+	    (void) fprintf(stderr, "\n%s: unknown client - %s\n",
+			sfs_Myname, argv[optind]);
+	    exit(47);
+	}
+    }
+
+    if (sum_result_fp == NULL)
+	sum_result_fp = stdout;
+
+    Pc_log_fd = open(SFS_PRIME_SYNC_LOG, (O_RDWR | O_CREAT), 0666);
+    if (Pc_log_fd == -1) {
+	perror(SFS_PRIME_SYNC_LOG);
+	exit(48);
+    }
+
+} /* do_initialize */
+
+
+/*
+ * Small utility routine to pretty print out the names
+ * of the clients which did not respond to the message.
+ */
+static void
+printdeadclients(void)
+{
+    int	*clients;
+    int client;
+    int i;
+    FILE *fd;
+
+    if ((clients = (int *)malloc(sizeof(int) * Num_clients)) == NULL) {
+	(void) fprintf(stderr, "%s: malloc failed\n", sfs_Myname);
+	(void) fflush(stderr);
+	return;
+    }
+
+    for (i = 0; i < Num_clients; i++) {
+	clients[i] = 0;
+    }
+
+    fd = fopen(SFS_PRIME_SYNC_LOG, "r");
+    if (fd == NULL) {
+	(void) fprintf(stderr,"%s: Cannot open %s\n",
+	    sfs_Myname, SFS_PRIME_SYNC_LOG);
+	(void) fflush(stderr);
+	return;
+    }
+
+    while(fread(&client, sizeof(int), 1, fd) == 1) {
+	if (client > 0 && client <= Num_clients)
+		clients[client - 1] = 1;
+    }
+
+    for (i = 0; i < Num_clients; i++) {
+	if (clients[i] == 0) {
+	    (void) fprintf(stderr, "\n%s: Did not get signal from client %s\n",
+		    sfs_Myname, Client_names[i]);
+	    (void) fflush(stderr);
+	}
+    }
+    (void) fclose(fd);
+    free (clients);
+}
+
+/*
+ * monitor Logfile until all Clients write to it.
+ *
+ * Each client appends its client id to the file. So the size
+ * of the log file divided by sizeof(int) is the number of
+ * clients that have responded.
+ */
+static void
+sync_PC_with_clients(void)
+{
+    struct stat		statb;		/* for fstat */
+    int			num_secs;	/* keep count of time */
+    int			clientsremaining;
+
+    num_secs = 0;
+    do {
+	(void) sleep(1);
+	if (fstat(Pc_log_fd, &statb) == -1) {
+	    (void) fprintf(stderr, "%s: can't stat Prime Client log %s",
+				    sfs_Myname, SFS_PRIME_SYNC_LOG);
+	    exit(49);
+	}
+	num_secs++;
+	clientsremaining = Num_clients - (statb.st_size / sizeof(int));
+    } while ( (clientsremaining > 0) && (num_secs < Prime_time_out));
+
+    /* if clients not responding then terminate experiment */
+    if (clientsremaining > 0) {
+	(void) fprintf(stderr,
+	"\n%s: Prime Client timeout - did not get signal from %d client(s)\n",
+			sfs_Myname, clientsremaining);
+	printdeadclients();
+	/* send message to clients to stop */
+	(int) signal_sfs_clients("PRIME_STOP");
+	exit(50);
+    }
+
+    /* if more clients than exist responded then syncd is telling us to exit */
+    if (clientsremaining < 0) {
+	(void) fprintf(stderr,
+	"\n%s: Prime Client got too many signals - expected %d got %ld\n",
+		sfs_Myname, Num_clients, statb.st_size / sizeof(int));
+	/* send message to clients to stop */
+	(int) signal_sfs_clients("PRIME_STOP");
+	exit(51);
+    }
+
+    /* success, so go ahead and truncate the sync logfile */
+    (void)close(Pc_log_fd);
+    Pc_log_fd = open(SFS_PRIME_SYNC_LOG,
+			(O_RDWR | O_CREAT | O_TRUNC | O_APPEND), 0666);
+    if (Pc_log_fd == -1) {
+	/* problem in truncating sync logfile - stop experiment */
+	(void) fprintf(stderr, "%s: can't truncate Prime Client log %s",
+		       sfs_Myname, SFS_PRIME_SYNC_LOG);
+	(void) fflush(stderr);
+	(int) signal_sfs_clients("PRIME_STOP");
+	exit(52);
+    }
+
+} /* sync_PC_with_clients */
+
+
+#ifdef CLOSE_CLNT_HANDLE
+static int close_clnt_handle = 1;
+#else
+static int close_clnt_handle = 0;
+#endif
+/*
+ * makes RPC to all clients, dependent on message
+ * Save the client handles to keep from doing unnecessary portmapper calls.
+ * This can help if we have to route through the busy server.
+ */
+static int
+signal_sfs_clients(char *message)
+{
+    static int Transac_num = 0;            /* transaction number */
+    static CLIENT **	sfs_clnt_handle = NULL;
+    static int		*sfs_socket = NULL;
+    int *		result;
+    int			i;
+    sync_string		sync_signal;
+    char		transaction_string[MAX_STR1_LEN];
+
+    (void) sprintf(transaction_string,"Prime_%i",++Transac_num);
+    sync_signal.clnt_type = message;
+    sync_signal.clnt_data = "";
+    sync_signal.clnt_transaction = transaction_string;
+
+    if (sfs_clnt_handle == NULL) {
+	sfs_socket = (int *) calloc(Num_clients, sizeof(int));
+	if (sfs_socket == (int *) 0) {
+	   (void) fprintf(stderr, "%s: socket malloc failed.\n",
+			  sfs_Myname);
+	   exit(53);
+	}
+
+	/* allocate space for tcp handles */
+	sfs_clnt_handle =  (CLIENT **) calloc(Num_clients, sizeof(CLIENT));
+	if (sfs_clnt_handle == (CLIENT **)0 ) {
+	     (void) fprintf(stderr, "%s: clnttcp_create out of memory\n",
+			sfs_Myname);
+	     exit(54);
+	}
+    }
+
+    /* set up the tcp handles for all the clients */
+    for (i = 0; i < Num_clients; i++) {
+	if (sfs_clnt_handle[i] == NULL) {
+	    struct hostent	*host_info;
+	    struct sockaddr_in	clnt_addr;
+#ifdef SUNOS
+	    int fd;
+#endif
+
+	    sfs_socket[i] = RPC_ANYSOCK;
+
+	    if ((host_info = gethostbyname(Client_names[i])) == NULL)
+		 return((int) RPC_UNKNOWNHOST);
+	    (void) memset((char *) &clnt_addr, '\0', sizeof(clnt_addr));
+	    (void) memmove((char *) &clnt_addr.sin_addr,
+				(char *) host_info->h_addr,
+				host_info->h_length);
+	    clnt_addr.sin_family = AF_INET;
+	    clnt_addr.sin_port =  0;
+
+	    /*
+	     * Create client "handle" used for calling CL_MESSAGEPROG on the
+	     * sfs client(s). We tell the RPC package to use the "tcp"
+	     * protocol when contacting the clients.
+	     */
+	    sfs_clnt_handle[i] = clnttcp_create(&clnt_addr, SFS_SYNCPROG,
+					SFS_SYNCVERS, &sfs_socket[i],
+					MAX_STR2_LEN, MAX_STR2_LEN);
+
+	    if (sfs_clnt_handle[i] == (CLIENT *) NULL) {
+		/*
+		 * Couldn't establish connection with the sfs Client.
+		 * print error message and return status
+		 */
+		clnt_pcreateerror(Client_names[i]);
+		return((int) RPC_FAILED);
+	    }
+#ifdef SUNOS
+	    /*
+	     * Some commands in 4.X will fail if there are too many file
+	     * descriptors open, if the sfs_ext_mon uses one
+	     * of those then it will fail.  We set the close-on-exec
+	     * flag to help them.
+	     */
+	    if (clnt_control(sfs_clnt_handle[i], CLGET_FD, (char *)&fd) ==
+			FALSE) {
+		clnt_pcreateerror(Client_names[i]);
+		return((int) RPC_FAILED);
+	    }
+	    if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+		perror("F_SETFD");
+		return((int) RPC_FAILED);
+	    }
+#endif
+	} /* end no client handle */
+
+	/*
+	 * Call the remote procedure "signal_sfs_cl_1" on each of the clients
+	 * pass the client number so sfs_syncd will know which client files
+	 * to look for in a shared /tmp area
+	 */
+	sync_signal.clnt_id = i + 1;
+	result = signal_sfs_1(&sync_signal, sfs_clnt_handle[i]);
+
+	if (result == NULL) {
+	    /* Error occurred.  Print error message and return error. */
+	    clnt_perror(sfs_clnt_handle[i], Client_names[i]);
+	    return((int) RPC_CANTSEND);
+	}
+
+	/* Okay, we successfully called the remote procedure.  */
+	if (*result == 0) {
+	    /*
+	     * remote procedure was unable to write to its sync file.
+	     * Print error message and return failure.
+	     */
+	    (void) fprintf(stderr,
+			"\n%s: Unable to perform remote procedure on %s . \n",
+			    sfs_Myname, Client_names[i]);
+	    (void) fflush(stderr);
+	    return((int) RPC_FAILED);
+	}
+	if (close_clnt_handle) {
+		clnt_destroy(sfs_clnt_handle[i]);
+		sfs_clnt_handle[i] = NULL;
+	}
+    } /* end for each client */
+
+    return(0);
+
+} /* signal_sfs_clients */
+
+
+/*
+ * summarize and print multi-client results
+ */
+static void
+print_multi_results(void)
+{
+    FILE *	fd;		/* results files */
+    int 	i;
+    int		k;
+    char	res_file[SFS_MAXPATHLEN];		/* results filename */
+    char	str[MAX_LINE_LEN];
+
+    double	stdev_msec, var_msec;
+    float	tot_squared_time_msec, tot_sum2_msec;
+    float	tot_got, tot_secs, tot_msec_calls, tot_res_time;
+    int		tot_want, tot_calls, tot_errors;
+
+    double	sq_conf_interval_msec;
+    double	conf_interval_msec;
+    int		totals;
+    int		invalid = 0;
+
+#define MAXOPNAME	19
+    struct client_stats {
+	/* First line */
+	int	version;
+	int	num_io_files;
+	int	num_access_io_files;
+	int	num_non_io_files;
+	int	num_symlinks;
+	int	num_dirs;
+	/* NOPS lines */
+	struct client_op_stats {
+		char	op[MAXOPNAME];
+		int	want;
+		float	got;
+		int	calls;
+		int	errors;
+		float	secs;
+		float	msec_calls;
+		float	res_time;
+		float	squared_time_msec;
+		float	sum2_msec;
+	} op_stats[NOPS];
+	/* Last line */
+	float	sum_calls_sec;
+	float	sum_msec_calls;
+	int	sum_secs;
+	int	sum_calls;
+	int	client_invalid_flag;
+	uint32_t total_fss_bytes;
+	uint32_t least_fss_bytes;
+	uint32_t most_fss_bytes;
+	uint32_t base_fss_bytes;
+    } *client_stats;
+
+
+    /*
+     * malloc space for statistics
+     *  Note last entry is for running totals.
+     */
+     client_stats = (struct client_stats *) calloc(Num_clients+1,
+						sizeof(struct client_stats));
+     if (client_stats == (struct client_stats *)0) {
+	(void) fprintf(stderr, "%s: client_stats malloc failed.\n",
+		      sfs_Myname);
+	(void) fflush(stderr);
+	exit(55);
+     }
+
+    totals = Num_clients;
+    /*
+     * Read each client file one at a time gathering statistics
+     */
+    for (i = 0; i < Num_clients;i++) {
+	(void) sprintf(res_file, "%s%i", PRIME_RESULTS_LOG, i + 1);
+	fd = fopen(res_file, "r");
+	if (fd == (FILE *)NULL) {
+	    (void) fprintf(stderr, "%s: Cannot open results file - %s\n",
+			    sfs_Myname, res_file);
+	    (void) fflush(stderr);
+	    exit(56);
+	}
+
+	/*
+	 * the SFS clients compute its File set info. at runtime;
+	 * the clients pass back the computed value in the results
+	 * (RPC) info. Get the fileset info used by the clients and compute
+	 * the aggregate value.
+	 */
+	if (fgets(str, MAX_LINE_LEN, fd) == NULL) {
+	    (void) fprintf(stderr,"%s: can't read data in results file - %s\n",
+				sfs_Myname, res_file);
+	    (void) fflush(stderr);
+	    exit(57);
+	}
+	if (sscanf(str,"%d %d %d %d %d %d",
+				&client_stats[i].version,
+				&client_stats[i].num_io_files,
+				&client_stats[i].num_access_io_files,
+				&client_stats[i].num_non_io_files,
+				&client_stats[i].num_symlinks,
+				&client_stats[i].num_dirs) != 6) {
+	    (void) fprintf(stderr,"%s: data in results file unparseable - %s\n",
+				sfs_Myname, res_file);
+	    (void) fflush(stderr);
+	    exit(58);
+	}
+
+	client_stats[totals].num_io_files += client_stats[i].num_io_files;
+	client_stats[totals].num_access_io_files +=
+					client_stats[i].num_access_io_files;
+	client_stats[totals].num_non_io_files +=
+					client_stats[i].num_non_io_files;
+	client_stats[totals].num_symlinks +=
+					client_stats[i].num_symlinks;
+	client_stats[totals].num_dirs += client_stats[i].num_dirs;
+
+	/* Gather per operation statistics */
+	for (k = 0; k < NOPS; k++) {
+	    if (fgets(str, MAX_LINE_LEN, fd) == NULL) {
+		(void) fprintf(stderr,
+				"%s: can't read data in results file - %s\n",
+				sfs_Myname, res_file);
+		(void) fflush(stderr);
+		exit(59);
+	    }
+	    if (sscanf(str, "%s %d%% %f%% %d %d %f %f %f%% %f %f",
+			client_stats[i].op_stats[k].op,
+			&client_stats[i].op_stats[k].want,
+			&client_stats[i].op_stats[k].got,
+			&client_stats[i].op_stats[k].calls,
+			&client_stats[i].op_stats[k].errors,
+			&client_stats[i].op_stats[k].secs,
+			&client_stats[i].op_stats[k].msec_calls,
+			&client_stats[i].op_stats[k].res_time,
+			&client_stats[i].op_stats[k].squared_time_msec,
+			&client_stats[i].op_stats[k].sum2_msec) != 10) {
+		(void) fprintf(stderr,"%s: data in results file unparseable - %s\n",
+				sfs_Myname, res_file);
+		(void) fflush(stderr);
+		exit(60);
+	    }
+	    if (strcmp(client_stats[i].op_stats[k].op,Ops_name[k]) != 0) {
+		(void) fprintf(stderr, "%s: bad data in results file\n",
+				    sfs_Myname);
+		(void) fflush(stderr);
+		exit(61);
+	    }
+	}
+
+	if (fgets(str, 100, fd) == NULL) {
+	    (void) fprintf(stderr,"%s: can't read data in results file - %s\n",
+				sfs_Myname, res_file);
+		(void) fflush(stderr);
+	    exit(62);
+	}
+	if (sscanf(str,"%f %f %d %d %d %u %u %u %u",
+		&client_stats[i].sum_calls_sec,
+		&client_stats[i].sum_msec_calls,
+		&client_stats[i].sum_secs,
+		&client_stats[i].sum_calls,
+		&client_stats[i].client_invalid_flag,
+		&client_stats[i].total_fss_bytes,
+		&client_stats[i].least_fss_bytes,
+		&client_stats[i].most_fss_bytes,
+		&client_stats[i].base_fss_bytes) != 9) {
+	    (void) fprintf(stderr,"%s: data in results file unparseable - %s\n",
+				sfs_Myname, res_file);
+	    (void) fflush(stderr);
+	    exit(63);
+	}
+
+	client_stats[totals].sum_secs += client_stats[i].sum_secs;
+	client_stats[totals].sum_calls += client_stats[i].sum_calls;
+	client_stats[totals].sum_calls_sec +=
+					client_stats[i].sum_calls_sec;
+	client_stats[totals].sum_msec_calls +=
+					client_stats[i].sum_msec_calls;
+	client_stats[totals].total_fss_bytes +=
+					client_stats[i].total_fss_bytes;
+	client_stats[totals].least_fss_bytes +=
+					client_stats[i].least_fss_bytes;
+	client_stats[totals].most_fss_bytes +=
+					client_stats[i].most_fss_bytes;
+	client_stats[totals].base_fss_bytes +=
+					client_stats[i].base_fss_bytes;
+
+	(void) fclose(fd);
+    } /* for Num_clients */
+
+    nfs_version = client_stats[0].version;
+
+    /*
+     * print the aggregate test parameters
+     */
+    (void) fprintf(stdout, "\nAggregate Test Parameters: \n");
+    (void) fprintf(stdout, "    Number of processes = %d\n",
+		   P_children * Num_clients);
+    (void) fprintf(stdout, "    Requested Load (NFS V%d operations/second) = %d\n",
+			nfs_version, P_total_load * Num_clients);
+    (void) fprintf(stdout, "%s%d\n",
+		    "    Maximum number of outstanding biod writes = ",
+		    P_biod_max_outstanding_writes);
+    (void) fprintf(stdout, "%s%d\n",
+		    "    Maximum number of outstanding biod reads = ",
+		    P_biod_max_outstanding_reads);
+
+    (void) fprintf(stdout, "%s%d\n%s%d\n",
+		    "    Warm-up time (seconds) = ", P_warmuptime,
+		    "    Run time (seconds) = ", Prime_runtime);
+    if (P_mix_file)
+	(void) fprintf(stdout,"%s%s\n", "    NFS Mixfile = ", P_mix_file);
+    if (P_iodist_file)
+	(void) fprintf(stdout,"%s%s\n", "    Block Size Distribution file = ",
+			P_iodist_file);
+
+
+    (void) fprintf(stdout, "%s%6d%s\n", "    File Set = ",
+		client_stats[totals].num_io_files,
+		" Files created for I/O operations");
+    (void) fprintf(stdout, "%s%10d%s\n", "           ",
+		client_stats[totals].num_access_io_files,
+		" Files accessed for I/O operations");
+    (void) fprintf(stdout, "%s%10d%s\n", "           ",
+		client_stats[totals].num_non_io_files,
+		" Files for non-I/O operations");
+    (void) fprintf(stdout, "%s%10d%s\n", "           ",
+		client_stats[totals].num_symlinks,
+		" Symlinks");
+    (void) fprintf(stdout, "%s%10d%s\n", "           ",
+		client_stats[totals].num_dirs,
+		" Directories");
+    (void) fprintf(stdout, "%s%s\n", "           ",
+		"           Additional non-I/O files created as necessary\n");
+
+
+    (void) fprintf(stdout,"SFS Aggregate Results for %d Client(s), %s\n",
+		    Num_clients, lad_timestamp());
+    (void) fprintf(stderr, "SPEC SFS Benchmark Version %s, Creation - %s\n",
+                                SFS_VERSION_NUM, SFS_VERSION_DATE);
+    (void) fprintf(stdout, "NFS Protocol Version %d\n", nfs_version);
+
+    /* print column headers for per operation statistics */
+    (void) fprintf(stdout,
+"------------------------------------------------------------------------------");
+(void) fprintf(stdout, "\n");
+(void) fprintf(stdout,"%s\n%s\n%s\n%s\n%s\n",
+"NFS         Target Actual     NFS    NFS    Mean    Std Dev  Std Error   Pcnt ",
+"Op           NFS    NFS       Op     Op    Response Response of Mean,95%  of  ",
+"Type         Mix    Mix     Success Error   Time     Time    Confidence  Total",
+"             Pcnt   Pcnt     Count  Count  Msec/Op  Msec/Op  +- Msec/Op  Time ",
+"------------------------------------------------------------------------------");
+    (void) fflush(stdout);
+
+    /* print per operation statistics */
+    for (k = 0; k < NOPS; k++) {
+	tot_got = 0;
+	tot_secs = 0;
+	tot_msec_calls = 0;
+	tot_res_time =  0;
+	tot_want = 0;
+	tot_calls = 0;
+	tot_errors = 0;
+	tot_sum2_msec = 0;
+	tot_squared_time_msec = 0;
+
+	/* total the results from each client */
+	for (i = 0; i < Num_clients; i++) {
+
+	    tot_want += client_stats[i].op_stats[k].want;
+	    tot_got += client_stats[i].op_stats[k].got;
+	    tot_calls += client_stats[i].op_stats[k].calls;
+	    tot_errors += client_stats[i].op_stats[k].errors;
+	    tot_secs += client_stats[i].op_stats[k].secs;
+	    tot_msec_calls += client_stats[i].op_stats[k].msec_calls;
+	    tot_res_time += client_stats[i].op_stats[k].res_time;
+	    tot_squared_time_msec +=
+			client_stats[i].op_stats[k].squared_time_msec;
+	    tot_sum2_msec += client_stats[i].op_stats[k].sum2_msec;
+
+	} /* end for each client */
+
+	/*
+	 * If the total wanted is zero and no operations succeeded or
+	 * errored don't print out the
+	 * summary.  However leave it in the individual client logs
+	 * in case there is some interesting error.
+	 */
+	if (tot_want == 0 && tot_calls == 0 && tot_errors == 0)
+	    continue;
+
+	/* compute the standard deviation for the mean response time */
+	if (tot_calls <= 1) {
+	    stdev_msec = 0;
+	    var_msec = 0;
+	} else {
+	    /* variance = 1/(n-1) * (sum(x^2) - 1/n * (sum(x))^2)  */
+	    var_msec = (tot_squared_time_msec - (tot_sum2_msec / tot_calls)) /
+			(tot_calls-1);
+
+	    if(var_msec == 0.0) {
+		stdev_msec = 0.0;
+	    } else
+		stdev_msec = sqrt(var_msec);
+	}
+
+	/* compute the confidence interval */
+	if (tot_calls > 0) {
+	    sq_conf_interval_msec = DEFAULT_CHI_SQR_CI *
+				    (stdev_msec / tot_calls);
+	    if (sq_conf_interval_msec == 0.0) {
+    		if (DEBUG_PARENT_GENERAL) {
+		    (void) fprintf(stderr,
+			"Error computing confidence interval for mean\n");
+		    (void) fflush(stderr);
+		}
+		conf_interval_msec = 0.0;
+	    } else
+		conf_interval_msec = sqrt(sq_conf_interval_msec);
+	} else {
+	    conf_interval_msec = 0.0;
+	}
+
+	/* print the per op statistics */
+	(void) fprintf(stdout,
+	    "%-12s%3d%%  %5.1f%%   %7d %5d %8.2f %8.2f  %8.2f    %5.1f%%\n",
+	    Ops_name[k],					/* op name */
+	    tot_want / Num_clients,				/* target mix */
+	    tot_got / Num_clients,				/* actual mix */
+	    tot_calls,						/* successes */
+	    tot_errors,						/* errors */
+	    tot_msec_calls / Num_clients,			/* mean */
+	    stdev_msec, 					/* std dev */
+	    conf_interval_msec,					/* conf int */
+	    tot_res_time / Num_clients);			/* % of time */
+
+    } /* end for each op */
+
+    (void) fprintf(stdout,
+"------------------------------------------------------------------------------\n");
+
+    /* check and report client INVALID RUN */
+    for (i = 0; i < Num_clients; i++) {
+	if (client_stats[i].client_invalid_flag != 0) {
+	    invalid++;
+	    (void) fprintf(stdout,"INVALID RUN reported for Client %d (%s).\n",
+		   i+1, Client_names[i]);
+	    if (client_stats[i].client_invalid_flag >= INVALID_GOODCALLS) {
+	        (void) fprintf(stdout,"INVALID RUN, %s\n",
+			invalid_str[client_stats[i].client_invalid_flag]);
+	    } else {
+		(void) fprintf(stdout,
+                        "INVALID RUN, ILLEGAL PARAMETER: Non-standard %s\n",
+			invalid_str[client_stats[i].client_invalid_flag]);
+	    }
+	}
+    }
+
+    (void) fprintf(stdout, "\n");
+    (void) fprintf(stdout,
+	"        --------------------------------------------------------\n");
+    (void) fprintf(stdout,
+	"        | SPEC SFS VERSION %6s AGGREGATE RESULTS SUMMARY    |\n",
+							SFS_VERSION_NUM);
+    (void) fprintf(stdout,
+	"        --------------------------------------------------------\n");
+    (void) fprintf(stdout, "NFS V%d THROUGHPUT: ", nfs_version);
+    (void) fprintf(stdout,"%7.0f Ops/Sec   AVG. RESPONSE TIME: %7.1f Msec/Op\n",
+	client_stats[totals].sum_calls_sec,
+	client_stats[totals].sum_msec_calls / Num_clients);
+
+    (void) fprintf(stdout, "%s PROTOCOL\n", P_tcp ? "TCP" : "UDP");
+    (void) fprintf(stdout, "NFS MIXFILE:");
+    if (P_mix_file)
+	(void) fprintf(stdout,"%s\n", P_mix_file);
+    else (void)
+	(void) fprintf(stdout," [ SFS default ]\n");
+
+    (void) fprintf(stdout, "AGGREGATE REQUESTED LOAD: %d Ops/Sec \n",
+		    (Num_clients * P_total_load));
+
+    (void) fprintf(stdout,"TOTAL NFS OPERATIONS: %8d      TEST TIME: %d Sec \n",
+		    client_stats[totals].sum_calls,
+		    client_stats[totals].sum_secs / Num_clients);
+    (void) fprintf(stdout,"NUMBER OF SFS CLIENTS: %d\n", Num_clients);
+    (void) fprintf(stdout,
+		"TOTAL FILE SET SIZE CREATED: %6.1f MB\n" ,
+		client_stats[totals].total_fss_bytes/1024.0);
+    (void) fprintf(stdout,
+		"TOTAL FILE SET SIZE ACCESSED: %6.1f - %6.1f MB  (%lu%% to %lu%% of Base)\n",
+		client_stats[totals].least_fss_bytes/1024.0,
+		client_stats[totals].most_fss_bytes/1024.0,
+		(100 * client_stats[totals].least_fss_bytes) /
+			client_stats[totals].base_fss_bytes,
+		(100 * client_stats[totals].most_fss_bytes) /
+			client_stats[totals].base_fss_bytes);
+    (void) fprintf(stdout, "\n");
+
+    (void) fprintf(stdout,
+    "------------------------------------------------------------------------");
+    (void) fprintf(stdout,"\n\n");
+    (void) fflush(stdout);
+
+    /*
+     * Summary results file format:
+     *                 response total   elps                  prcs biod  vers
+     *  load   thruput time     ops     time V P fileset_sz clnt   rd wr
+     * DDDDDDD FFFFFFF FFFFFFF DDDDDDDD DDDD D C DDDDDDDDDD DDD DD DD DD SSSS
+     */
+    (void) fprintf(sum_result_fp,
+"%7s %7d %7.0f %7.1f %8d %4d %1d %c %10lu %3d %2d %2d %2d %s\n",
+			invalid ? "INVALID" : "",
+			Num_clients * P_total_load,
+			client_stats[totals].sum_calls_sec,
+			client_stats[totals].sum_msec_calls / Num_clients,
+			client_stats[totals].sum_calls,
+			client_stats[totals].sum_secs / Num_clients,
+			nfs_version,
+			P_tcp ? 'T' : 'U',
+			(unsigned long)client_stats[totals].total_fss_bytes,
+			Num_clients,
+			P_children,
+			P_biod_max_outstanding_reads,
+			P_biod_max_outstanding_writes,
+			SFS_VERSION_NUM);
+    (void) fflush(sum_result_fp);
+
+    (void) free(client_stats);
+} /* print_multi_results */
+
+static void
+prog_usage(void)
+{
+   (void) fprintf(stderr,
+      "Usage: %s [-a access_pcnt] [-A append_pcnt] [-b blocksz_file] [-B block_size]\n",
+	sfs_Myname);
+    (void) fprintf(stderr,
+      "\t[-C summary_file] [-d debug_level] [-f file_set_delta]\n");
+    (void) fprintf(stderr,
+      "\t[-k script_name] [-K script_args] [-l load] [-m mix_file]\n");
+    (void) fprintf(stderr,
+      "\t[-p procs] [-Q] [-R biod_reads] [-s sleeptime]\n");
+    (void) fprintf(stderr,
+      "\t[-t time] [-T op_num] [-w warmup] [-x timeout]\n");
+    (void) fprintf(stderr,
+      "\t[-W biod_writes] [-z] <hostname1> [<hostname2>...]\n");
+
+
+    (void) fflush(stderr);
+    (int) signal_sfs_clients("PRIME_STOP");
+    exit(64);
+    /* NOTREACHED */
+} /* prog_usage */
+
+/* sfs_m_prm.c */
diff --git a/TBBT/trace_play/sfs_m_snc.c b/TBBT/trace_play/sfs_m_snc.c
new file mode 100644
index 0000000..8a8f2e2
--- /dev/null
+++ b/TBBT/trace_play/sfs_m_snc.c
@@ -0,0 +1,456 @@
+#ifndef lint
+static char sccsid[] = "@(#)sfs_m_snc.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ *.Exported_routines
+ *     None.
+ *
+ *.Local_routines
+ *     void sfs_syncprog_1(struct svc_req *, SVCXPRT *)
+ *     int * signal_sync_sfs_1(struct sync_string *)
+ *     void lad_syncd_cleanup(int)
+ *
+ *.Revision_history
+ *      04-Dec-91	Keith	Include sfs_def.h for SYSV/SVR4 mem*
+ *				functions. Include string.h for SYSV/SVR4.
+ *	28-Nov-91	Teeluckingh	Fixed 'multiple signals to sfs'
+ *				problem.  Uses a 'transaction id' field in
+ *				the sync rpc xdr structure to compare
+ *				previous rpc, if the current transaction id
+ *				matches the previous one then sfs_syncd
+ *				just return 'success' to the client. If the
+ *				transaction ids do not match, the actions
+ *				are performed and the transaction id value
+ *				is saved.
+ *	17-Jun-91 	Teelucksingh	Creation - multi-client
+ *				synchronization server sfs_syncd.
+ *				Processes the sfs sync rpcs between systems.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+ 
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include <sys/signal.h>
+#include <sys/file.h>
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+
+/*
+ * -----------------------  External Definitions  -----------------------
+ */
+
+/* forward definitions for local routines */
+static void sfs_syncprog_1(struct svc_req *, SVCXPRT *);
+static int * signal_sync_sfs_1(struct sync_string *);
+static void lad_syncd_cleanup(int);
+
+/*
+ * -----------------------  Static Definitions  -----------------------
+ */
+
+int Debug_level = 0;            /* flag indicates prime client debug mode */
+char *sfs_Myname;                   /* program name */
+
+static char previous_transaction[MAX_STR1_LEN];	/* to hold transaction id */
+
+
+/*
+ * -------------------  Multi-client Synchronization  -------------------
+ */
+
+
+/*ARGSUSED*/
+int
+main(
+    int		argc,
+    char *	argv[])
+{
+    char 	*nameptr;
+    SVCXPRT *	transp;
+    FILE	*pid_fp;
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    struct sigaction sig_act, old_sig_act;
+#endif /* USE_POSIX_SIGNALS */
+
+    /* 
+     * Place pid in pid log file 
+     */   
+    if ((pid_fp = fopen(SFS_SYNCD_PID, "a+")) == NULL) { 
+        perror(SFS_SYNCD_PID);  
+        (void) unlink(SFS_SYNCD_PID); 
+        exit(1); 
+    } 
+    (void) fprintf(pid_fp, "%d\n", getpid()); 
+    (void) fclose(pid_fp);
+
+    sfs_Myname = argv[0];
+
+    if ((nameptr = strrchr(argv[0], '/')) != NULL)
+        sfs_Myname = ++nameptr;
+
+#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
+    /* use XOPEN signal handling */
+    sig_act.sa_handler = generic_catcher;
+    (void)sigemptyset(&sig_act.sa_mask);
+    sig_act.sa_flags = 0;
+
+    /* signals handlers for signals used by sfs_prime */
+    sig_act.sa_handler = lad_syncd_cleanup;
+    if (sigaction(SIGINT,&sig_act,&old_sig_act) != 0) {
+		perror("sigaction failed: SIGINT");
+        	(void) unlink(SFS_SYNCD_PID); 
+		exit(4);
+    }
+#else
+    /* set up SIGINT signal handler */
+    (void) signal(SIGINT, lad_syncd_cleanup);
+#endif /* USE_POSIX_SIGNALS */
+
+    (void) fprintf(stderr,"--------------------\n");
+    (void) fprintf(stderr,"Start of sfs run.\n");
+
+    (void) pmap_unset(SFS_SYNCPROG, SFS_SYNCVERS);
+
+    transp = svcudp_create(RPC_ANYSOCK);
+    if (transp == ((SVCXPRT *) NULL)) {
+	(void) fprintf(stderr, "%s: cannot create udp service.\n", sfs_Myname);
+       	(void) unlink(SFS_SYNCD_PID); 
+	exit(5);
+    }
+    if (!svc_register(transp, SFS_SYNCPROG, SFS_SYNCVERS,
+		     sfs_syncprog_1, IPPROTO_UDP)) {
+	(void) fprintf(stderr,
+	    "%s: unable to register (SFS_SYNCPROG,SFS_SYNCVERS, udp).\n",
+	    sfs_Myname);
+       	(void) unlink(SFS_SYNCD_PID); 
+	exit(6);
+    }
+
+    transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+    if (transp == ((SVCXPRT *) NULL)) {
+	(void) fprintf(stderr, "%s: cannot create tcp service.\n", sfs_Myname);
+       	(void) unlink(SFS_SYNCD_PID); 
+	exit(6);
+    }
+    if (!svc_register(transp, SFS_SYNCPROG, SFS_SYNCVERS,
+		      sfs_syncprog_1, IPPROTO_TCP)) {
+	(void) fprintf(stderr,
+	    "%s: unable to register (SFS_SYNCPROG, SFS_SYNCVERS, tcp).\n",
+	    sfs_Myname);
+       	(void) unlink(SFS_SYNCD_PID); 
+	exit(7);
+    }
+
+    svc_run();
+    (void) fprintf(stderr, "%s: svc_run returned\n", sfs_Myname);
+    return(1);
+
+} /* main */
+
+
+static void
+sfs_syncprog_1(
+    struct svc_req *	rqstp,
+    SVCXPRT *		transp)
+{
+    union {
+	sync_string	signal_sync_sfs_1_arg;
+    } argument;
+    char *		result;
+    bool_t 		(*xdr_argument)(), (*xdr_result)();
+    char *		(*local)();
+
+    switch (rqstp->rq_proc) {
+	case SIGNAL_NULLPROC:
+	    (void) svc_sendreply(transp, xdr_void, (char *)NULL);
+	    return;
+
+	case SIGNAL_SFS:
+	    xdr_argument = xdr_sync_string;
+	    xdr_result = xdr_int;
+	    local = (char * (*)()) signal_sync_sfs_1;
+	    break;
+
+	default:
+	    svcerr_noproc(transp);
+	    return;
+    }
+    (void) memset((char *) &argument, '\0', sizeof(argument));
+    if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
+	svcerr_decode(transp);
+	return;
+    }
+    result = (*local)(&argument);
+    if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+	svcerr_systemerr(transp);
+    }
+    if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
+	(void) fprintf(stderr, "%s: unable to free arguments\n", sfs_Myname);
+       	(void) unlink(SFS_SYNCD_PID); 
+	exit(8);
+    }
+
+} /* sfs_syncprog_1 */
+
+
+/*
+ * signal_sync_sfs_1 - multi-client synch RPC
+ * Provides interface between sfs program running
+ * on multiple clients and the controlling sfs_prime program.
+ */
+static int *
+signal_sync_sfs_1(
+    struct sync_string *	sfs_signal)
+{
+    static int			result = 0 ;	/* return status - failure */
+    FILE *			fp;
+    int				sfs_pid;	/* sfs parent process pid */
+    char			datafile[SFS_MAXPATHLEN]; /* results file */
+    char			CL_Logname[SFS_MAXPATHLEN];
+
+    result = 0;
+    /* if a duplicate transactions then just return success to calling client */
+    if (strcmp(sfs_signal->clnt_transaction, previous_transaction) == 0) {
+	(void) fprintf(stderr,"%s: Got a duplicate signal - %s\n",
+			sfs_Myname, sfs_signal->clnt_transaction);
+	result = 1;
+	return(&result);
+    }
+
+    if (strcmp(sfs_signal->clnt_type,"CLIENT_SIGNAL") == 0) {
+
+	/*
+	 * message from parent sfs process on client to Prime-client
+	 * (sfs_prime).
+	 *
+	 * Append client id to Prime client sync logfile
+	 */
+	fp = fopen(SFS_PRIME_SYNC_LOG, "a");
+	if (fp == NULL) {
+	    (void) fprintf(stderr,"%s: Cannot open %s\n",
+		sfs_Myname, SFS_PRIME_SYNC_LOG);
+	    return (&result);
+	}
+	(void) fwrite((char *)&sfs_signal->clnt_id,
+			sizeof(sfs_signal->clnt_id), 1, fp);
+	(void) fclose(fp);
+	result = 1;
+	(void) sprintf(previous_transaction, sfs_signal->clnt_transaction);
+	(void) fprintf(stderr,"%s: Got Client_SIGNAL - %s\n",
+			sfs_Myname, sfs_signal->clnt_transaction);
+	return (&result); /* success */
+
+    } else if (strcmp(sfs_signal->clnt_type,"CLIENT_DATA") == 0) {
+
+	/*
+	 * message from parent sfs process on client to Prime-client
+	 * completed run, here are my results. Write it to file and let
+	 * Prime client know about it.
+	 */
+	(void) sprintf(datafile,"%s%d",
+			PRIME_RESULTS_LOG, sfs_signal->clnt_id);
+	fp = fopen(datafile, "w");
+	if (fp == NULL) {
+	    (void) fprintf(stderr,"%s: Cannot open %s\n",
+		sfs_Myname, datafile);
+	    return (&result);
+	}
+	(void) fprintf(fp,"%s",sfs_signal->clnt_data);
+	(void) fclose(fp);
+
+	/* after writing data write client id to sync log */
+	fp = fopen(SFS_PRIME_SYNC_LOG, "a");
+	if (fp == NULL) {
+	    (void) fprintf(stderr,"%s: Cannot open %s\n",
+		sfs_Myname, SFS_PRIME_SYNC_LOG);
+	    return (&result);
+	}
+	(void) fwrite((char *)&sfs_signal->clnt_id,
+				sizeof(sfs_signal->clnt_id), 1, fp);
+	(void) fclose(fp);
+
+	/* let the remote process know success */
+	result = 1;
+	(void) sprintf(previous_transaction, sfs_signal->clnt_transaction);
+	(void) fprintf(stderr,"%s: Got Client_DATA - %s\n",
+			sfs_Myname, sfs_signal->clnt_transaction);
+	return (&result);
+
+    } else if (strcmp(sfs_signal->clnt_type,"CLIENT_STOP") == 0) {
+
+	/*
+	 * message from parent sfs process on client to Prime-client
+	 * (sfs_prime) to stop due to error.
+	 */
+	fp = fopen(SFS_PRIME_SYNC_LOG, "a");
+	if (fp == NULL) {
+	    (void) fprintf(stderr,"%s: Cannot open %s\n",
+		sfs_Myname, SFS_PRIME_SYNC_LOG);
+	    return (&result);
+	}
+	/*
+	 * Write out client id 1000 times to fool prime into thinking
+	 * all clients have responded and will get an error when it
+	 * tries to communicate to it.
+	 */
+	for (result = 0; result < 1000; result++)
+		(void) fwrite((char *)&sfs_signal->clnt_id,
+			sizeof(sfs_signal->clnt_id), 1, fp);
+	(void) fclose(fp);
+	result = 1;
+	(void) sprintf(previous_transaction, sfs_signal->clnt_transaction);
+	(void) fprintf(stderr,"%s: Got Client_STOP - %s\n",
+			sfs_Myname, sfs_signal->clnt_transaction);
+	return (&result); /* success */
+
+    } else if (strcmp(sfs_signal->clnt_type,"PRIME_SIGNAL") == 0) {
+
+	/*
+	 * message from the Prime client (sfs_prime)
+	 * send SIGUSR1 signal to parent sfs process on
+	 * client - signals it to proceed
+	 */
+	(void) sprintf(CL_Logname,"%s%d",
+			SFS_CLIENT_SYNC_LOG, sfs_signal->clnt_id);
+	fp = fopen(CL_Logname, "r");
+	if (fp == NULL) {
+	    (void) fprintf(stderr,"%s: Cannot open %s\n",
+		sfs_Myname, CL_Logname);
+	    return(&result);
+	}
+	if (fscanf(fp,"%d",&sfs_pid) != 1)
+	    return (&result);
+	if ((int) generic_kill(sfs_pid, SIGUSR1) == 0) {
+	    result = 1;
+	    (void) sprintf(previous_transaction,
+			   sfs_signal->clnt_transaction);
+	    (void) fprintf(stderr,"%s: Got PRIME_SIGNAL(SIGUSR1) - %s\n",
+			    sfs_Myname, sfs_signal->clnt_transaction);
+	    (void) fprintf(stderr,"   Sent SIGUSR1\n");
+	    return (&result); /* success */
+	} else
+	    return (&result);
+
+    } else if (strcmp(sfs_signal->clnt_type,"PRIME_ALARM") == 0) {
+
+	/*
+	 * message from the Prime client (sfs_prime)
+	 * send SIGALRM signal to parent sfs process on
+	 * client - tell it to wake up and finish execution at this time
+	 */
+
+	(void) sprintf(CL_Logname,"%s%d",
+			SFS_CLIENT_SYNC_LOG, sfs_signal->clnt_id);
+	fp = fopen(CL_Logname, "r");
+	if (fp == NULL) {
+	    (void) fprintf(stderr,"%s: Cannot open %s\n",
+		sfs_Myname, CL_Logname);
+	    return (&result);
+	}
+	if (fscanf(fp,"%d",&sfs_pid) != 1)
+	    return (&result);
+	if ((int) generic_kill(sfs_pid, SIGALRM) == 0) {
+	    result = 1;
+	    (void) sprintf(previous_transaction,
+			   sfs_signal->clnt_transaction);
+	    (void) fprintf(stderr,"%s: Got PRIME_ALARM(SIGALRM) - %s\n",
+				sfs_Myname, sfs_signal->clnt_transaction);
+	    (void) fprintf(stderr,"   Sent SIGALRM\n");
+	    return (&result); /* success */
+	} else
+	    return (&result);
+
+    } else if (strcmp(sfs_signal->clnt_type,"PRIME_STOP") == 0) {
+
+	/*
+	 * message from Prime-client
+	 * sent SIGINT signal to sfs parent process
+	 * to tell it to terminate experiment now
+	 */
+	(void) sprintf(CL_Logname,"%s%d",
+			SFS_CLIENT_SYNC_LOG, sfs_signal->clnt_id);
+	fp = fopen(CL_Logname, "r");
+	if (fp == NULL) {
+	    (void) fprintf(stderr,"%s: Cannot open %s\n",
+		sfs_Myname, CL_Logname);
+	    return (&result);
+	}
+	if (fscanf(fp,"%d",&sfs_pid) != 1)
+	    return (&result);
+	if ((int) generic_kill(sfs_pid, SIGINT) == 0) {
+	    result = 1;
+	    (void) sprintf(previous_transaction,
+			   sfs_signal->clnt_transaction);
+	    (void) fprintf(stderr,"%s: Got PRIME_STOP(SIGSTOP) - %s\n",
+				sfs_Myname, sfs_signal->clnt_transaction);
+	    (void) fprintf(stderr,"   Sent SIGINT\n");
+	    return (&result); /* success */
+	} else
+	    return (&result);
+
+    } else
+	return (&result); /* failure */
+
+} /* signal_sync_sfs_1 */
+
+/* ARGSUSED */
+static void
+lad_syncd_cleanup(
+    int         sig_id)
+{
+    (void) pmap_unset(SFS_SYNCPROG, SFS_SYNCVERS);
+    (void) fprintf(stderr, "Unregistered sfs_syncd.\n");
+    (void) unlink(SFS_SYNCD_PID); 
+    exit(0);
+
+} /* lad_syncd_cleanup */
+
+/* sfs_m_snc.c */
diff --git a/TBBT/trace_play/sfs_m_xdr.c b/TBBT/trace_play/sfs_m_xdr.c
new file mode 100644
index 0000000..b2cf930
--- /dev/null
+++ b/TBBT/trace_play/sfs_m_xdr.c
@@ -0,0 +1,103 @@
+#ifndef lint
+static char sfs_m_xdrSid[] = "@(#)sfs_m_xdr.c	2.1	97/10/23";
+#endif
+
+/*
+ *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+ *	All rights reserved.
+ *		Standard Performance Evaluation Corporation (SPEC)
+ *		6585 Merchant Place, Suite 100
+ *		Warrenton, VA 20187
+ *
+ *	This product contains benchmarks acquired from several sources who
+ *	understand and agree with SPEC's goal of creating fair and objective
+ *	benchmarks to measure computer performance.
+ *
+ *	This copyright notice is placed here only to protect SPEC in the
+ *	event the source is misused in any manner that is contrary to the
+ *	spirit, the goals and the intent of SPEC.
+ *
+ *	The source code is provided to the user or company under the license
+ *	agreement for the SPEC Benchmark Suite for this product.
+ */
+
+/*****************************************************************
+ *                                                               *
+ *	Copyright 1991,1992  Legato Systems, Inc.                *
+ *	Copyright 1991,1992  Auspex Systems, Inc.                *
+ *	Copyright 1991,1992  Data General Corporation            *
+ *	Copyright 1991,1992  Digital Equipment Corporation       *
+ *	Copyright 1991,1992  Interphase Corporation              *
+ *	Copyright 1991,1992  Sun Microsystems, Inc.              *
+ *                                                               *
+ *****************************************************************/
+
+/*
+ *.Exported_routines
+ *	bool_t xdr_sync_string(XDR *, sync_string *)
+ *
+ *.Revision_history
+ *	28-Nov-91	0.0.13	Teelucksingh
+ *				added 'transaction id' field to xdr data
+ *				structure and ANSI C features.
+ *	17-Jun-91       0.0.7	Teelucksingh - Creation
+ *				Multi-client synchronization rpc xdr
+ *				functions.
+ */
+
+
+/*
+ * -------------------------  Include Files  -------------------------
+ */
+
+/*
+ * ANSI C headers
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h> 
+
+#include "sfs_c_def.h"
+#include "sfs_m_def.h"
+
+/*
+ * ---------------  Multi-client Message XDR Routines  ---------------
+ */
+
+bool_t
+xdr_sync_string(
+    XDR *		xdrs,
+    sync_string *	objp)
+{
+    if (!xdr_int(xdrs, (int *) &objp->clnt_id)) {
+	(void) fprintf(stderr, "%s: can't encode client id %d",
+			sfs_Myname, objp->clnt_id);
+	return (FALSE);
+    }
+    if (!xdr_string(xdrs, (char **) &objp->clnt_type,
+					(unsigned int) MAX_STR1_LEN)) {
+	(void) fprintf(stderr, "%s: can't encode client type %s",
+			sfs_Myname, objp->clnt_type);
+	return (FALSE);
+    }
+    if (!xdr_string(xdrs, (char **) &objp->clnt_transaction,
+					(unsigned int) MAX_STR1_LEN)) {
+	(void) fprintf(stderr, "%s: can't encode client transaction %s",
+			sfs_Myname, objp->clnt_transaction);
+	return (FALSE);
+    }
+    if (!xdr_string(xdrs, (char **) &objp->clnt_data,
+					(unsigned int) MAX_STR2_LEN)) {
+	(void) fprintf(stderr, "%s: can't encode client data %s",
+			sfs_Myname, objp->clnt_data);
+	return (FALSE);
+    }
+    return (TRUE);
+}
+
+
+/* sfs_m_xdr.c */
diff --git a/TBBT/trace_play/sfs_mcr b/TBBT/trace_play/sfs_mcr
new file mode 100755
index 0000000..c24fb3e
--- /dev/null
+++ b/TBBT/trace_play/sfs_mcr
@@ -0,0 +1,170 @@
+#! /bin/sh
+#	@(#)sfs_mcr	2.1	97/10/23
+#
+#
+#    Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+#	All rights reserved.
+#		Standard Performance Evaluation Corporation (SPEC)
+#		6585 Merchant Place, Suite 100
+#		Warrenton, VA 20187
+#	This product contains benchmarks acquired from several sources who
+#	understand and agree with SPEC's goal of creating fair and objective
+#	benchmarks to measure computer performance.
+#
+#	This copyright notice is placed here only to protect SPEC in the
+#	event the source is misused in any manner that is contrary to the
+#	spirit, the goals and the intent of SPEC.
+#
+#	The source code is provided to the user or company under the license
+#	agreement for the SPEC Benchmark Suite for this product.
+#
+# *****************************************************************
+# *                                                               *
+# *	Copyright 1991,1992  Legato Systems, Inc.                 *
+# *	Copyright 1991,1992  Auspex Systems, Inc.                 *
+# *	Copyright 1991,1992  Data General Corporation             *
+# *	Copyright 1991,1992  Digital Equipment Corporation        *
+# *	Copyright 1991,1992  Interphase Corporation               *
+# *	Copyright 1991,1992  Sun Microsystems, Inc.               *
+# *                                                               *
+# *****************************************************************
+#
+# Usage sfs_mcr <sfs parameter string>
+#
+# Teelucksingh - Creation (6/17/91)
+#
+# This script is remotely started from the Prime-client
+# by sfs_mgr .
+#
+
+#
+# Client pid files
+#
+SFS_PNT_PID="/tmp/sfs_pnt_pid"
+SFS_SYNCD_PID="/tmp/sfs_syncd_pid"
+
+# SFS client log files
+CLIENT_LOG_FILES="/tmp/sfs_CL$CLIENT_NUM \
+		/tmp/sfs_sig$CLIENT_NUM \
+		/tmp/sfs_x$CLIENT_NUM"
+
+if [ "$1" = "cleanup" ]; then
+    #
+    # do cleanup
+    #
+    rm -f $CLIENT_LOG_FILES
+
+    #
+    # clean up any 'old' sfs processes
+    #
+    if [ -f $SFS_PNT_PID ]; then
+        kill -2 `cat $SFS_PNT_PID` > /dev/null 2>&1
+        rm -f $SFS_PNT_PID
+    fi
+    if [ -f $SFS_SYNCD_PID ]; then
+        kill -2 `cat $SFS_SYNCD_PID` > /dev/null 2>&1
+        rm -f $SFS_SYNCD_PID
+    fi
+
+    exit
+fi
+
+# read command line arguments
+SFS_PROG=$1
+shift
+SFS_DIR=$1
+shift
+S_LOGFILE=$1
+shift
+C_LOGFILE=$1
+shift
+CLIENT_NUM=$1
+shift
+
+# print start message
+echo "========================================================================" >> $C_LOGFILE
+echo "" >> $C_LOGFILE
+
+#
+# decide whether to use BSD (which one) or SYSV variant of commands
+#
+# do test to see whether to use hostname or uname
+sh -c "hostname > /dev/null 2>&1" > /dev/null 2>&1
+if [ $? -eq 0 ]; then
+	HOSTNAME_CMD="hostname"
+else
+	sh -c "uname -n  > /dev/null 2>&1" > /dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		HOSTNAME_CMD="uname -n"
+	else
+	 echo "sfs_mcr: can't use hostname(1) or uname(1), exiting." >> $C_LOGFILE
+		exit 1
+	fi
+fi
+
+#
+# trap for signals used by sfs
+#
+# Try to find cpp in the common places, if not there then let PATH find it
+if [ "$CPP" = "" ]
+then
+    if [ -f /lib/cpp ]
+    then
+        CPP=/lib/cpp
+    elif [ -f /usr/ccs/lib/cpp ]
+    then
+        CPP=/usr/ccs/lib/cpp
+    else
+        CPP=cpp
+    fi
+fi
+
+#
+# Allow trap numbers to be defined externally for broken systems
+#
+if [ "$TRAP_NUMS" = "" ]
+then
+    echo "#include <signal.h>" > /tmp/sfs_sig$CLIENT_NUM
+    echo "myprint SIGINT SIGALRM SIGTERM SIGUSR1 SIGUSR2" >> \
+         /tmp/sfs_sig$CLIENT_NUM
+    cat /tmp/sfs_sig$CLIENT_NUM | $CPP | grep myprint | \
+        awk '{print $2 " " $3 " " $4 " " $5 " " $6}'  > /tmp/sfs_x$CLIENT_NUM
+    TRAP_NUMS=`cat /tmp/sfs_x$CLIENT_NUM`
+fi
+trap "" $TRAP_NUMS
+
+#
+# start the sync daemon on the client
+#
+# Let's truncate the syncd log file at the start of each invocation
+# of sfs_mcr. Else it grows unbounded.
+#
+trap "" $TRAP_NUMS
+$SFS_DIR/sfs_syncd > $S_LOGFILE 2>&1 &
+echo "Started: sfs_syncd on client (`$HOSTNAME_CMD`). " >> $C_LOGFILE
+
+#
+# start SFS
+trap "" $TRAP_NUMS
+echo "Starting: $SFS_DIR/$SFS_PROG -N $CLIENT_NUM $*" >> $C_LOGFILE
+
+$SFS_DIR/$SFS_PROG -N $CLIENT_NUM $*  >> $C_LOGFILE 2>&1
+
+if [ $? -ne 0 ]; then     # error condition
+   # clean up
+   echo "sfs_mcr: sfs benchmark terminated with error status" >>$C_LOGFILE
+fi
+
+#
+# clean up any 'old' sfs processes
+#
+if [ -f $SFS_PNT_PID ]; then
+    kill -2 `cat $SFS_PNT_PID` > /dev/null 2>&1
+    rm -f $SFS_PNT_PID
+fi
+if [ -f $SFS_SYNCD_PID ]; then
+    kill -2 `cat $SFS_SYNCD_PID` > /dev/null 2>&1
+    rm -f $SFS_SYNCD_PID
+fi
+
+trap $TRAP_NUMS
diff --git a/TBBT/trace_play/sfs_mgr b/TBBT/trace_play/sfs_mgr
new file mode 100755
index 0000000..c1203a4
--- /dev/null
+++ b/TBBT/trace_play/sfs_mgr
@@ -0,0 +1,1093 @@
+#! /bin/sh
+#       @(#)sfs_mgr  2.1     97/10/23
+#
+#    Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+#	All rights reserved.
+#		Standard Performance Evaluation Corporation (SPEC)
+#		6585 Merchant Palce, Suite 100
+#		Warrenton, VA 20187
+#	This product contains benchmarks acquired from several sources who
+#	understand and agree with SPEC's goal of creating fair and objective
+#	benchmarks to measure computer performance.
+#
+#	This copyright notice is placed here only to protect SPEC in the
+#	event the source is misused in any manner that is contrary to the
+#	spirit, the goals and the intent of SPEC.
+#
+#	The source code is provided to the user or company under the license
+#	agreement for the SPEC Benchmark Suite for this product.
+#
+# *****************************************************************
+# *                                                               *
+# *	Copyright 1991,1992  Legato Systems, Inc.                 *
+# *	Copyright 1991,1992  Auspex Systems, Inc.                 *
+# *	Copyright 1991,1992  Data General Corporation             *
+# *	Copyright 1991,1992  Digital Equipment Corporation        *
+# *	Copyright 1991,1992  Interphase Corporation               *
+# *	Copyright 1991,1992  Sun Microsystems, Inc.               *
+# *                                                               *
+# *****************************************************************
+#
+# Usage sfs_mgr [-r <rc file>] [-s <suffix>] [-v <level>]
+#
+# Teelucksingh - Creation (6/17/91)
+#
+# Starts SFS (sfs_mcr) on clients with parameters
+# specified in sfs_rc .
+# Starts Prime-client program (sfs_prime)
+# Can have multiple runs with incrementing load
+# Summarized result(s) placed in sfsres.<suffix>
+# Log of multi-client run placed in sfslog.<suffix>
+# Individual client result(s) placed in sfs<cnnn>.<suffix>
+#
+#
+
+# --------------- defined constants and strings --------------
+#
+
+STARline='************************************************************************'
+RHOSTSCKMSG1="Ensure permissions in .rhosts or hosts.equiv allows remote operation."
+RHOSTSCKMSG2="Or check target directory/file existence or permissions."
+USAGE="usage: $0 [-r <rc file>] [-s <suffix>] [-v <level>]"
+
+# ----------------- variable initialization ------------------
+#
+
+error=FALSE
+
+# --------------- program initialization phase ---------------
+#
+# get the command line arguments
+#
+# init with default
+#
+SUFFIX=out
+RC_FILE=./sfs_rc
+VALIDATE=0
+#
+if [ $# -gt 6 ]
+then
+    echo $USAGE
+    exit 1
+fi
+while [ $# -gt 0 ]
+do
+    if [ "$#" -lt 2 ]
+    then
+        echo $USAGE
+	exit 1
+    fi
+    case $1 in
+    -r)
+	    RC_FILE=$2
+	    ;;
+    -s)
+	    SUFFIX=$2
+	    ;;
+    -v)
+	    VALID_LEVEL=$2
+	    VALIDATE=1
+	    ;;
+    *)	    echo $USAGE
+	    exit 1
+    esac
+    shift; shift
+done
+
+#
+# pass in environment variables from sfs_rc
+#
+if [ ! -r "$RC_FILE" ]; then
+    echo "sfs_mgr: missing or protected rc file $RC_FILE"
+    exit 1
+fi
+. "$RC_FILE"
+
+#
+# Make sure WORK_DIR is defined
+#
+if [ "$WORK_DIR" = "" ]
+then
+    echo "sfs_mgr: WORK_DIR not defined, check sfs_rc file, exiting."
+    exit 1
+fi
+
+#
+# Prime client output files
+#
+P_OUTFILE=$WORK_DIR/sfsres.$SUFFIX
+P_SUMFILE=$WORK_DIR/sfssum.$SUFFIX
+P_LOGFILE=$WORK_DIR/sfslog.$SUFFIX
+P_VALFILE=$WORK_DIR/sfsval.$SUFFIX
+
+#
+# Client pid files
+#
+SFS_PNT_PID="/tmp/sfs_pnt_pid"
+SFS_PRM_PID="/tmp/sfs_prm_pid"
+SFS_SYNCD_PID="/tmp/sfs_syncd_pid"
+
+#
+# --------------------
+# Setup machine/OS dependant parameters
+#
+# decide whether to use BSD (which one) or SYSV variant of commands
+#
+# do echo test to get no end-of-line character
+#
+op=`echo "\c"`
+if [ "$op" = "\c" ]; then
+    ECHO_NONL="echo -n"
+    NONL=
+else
+    ECHO_NONL="echo"
+    NONL="\c"
+fi
+
+#
+# do test to see whether to use hostname or uname
+#
+if sh -c "hostname > /dev/null 2>&1"  > /dev/null 2>&1
+then
+    HOSTNAME_VAL=`hostname`
+elif sh -c "uname -n  > /dev/null 2>&1" > /dev/null 2>&1
+then
+    HOSTNAME_VAL=`uname -n`
+else
+    echo "sfs_mgr: can't use hostname(1) or uname(1), exiting."
+    echo "sfs_mgr: can't use hostname(1) or uname(1), exiting." \
+		 >> $P_LOGFILE
+    exit 1
+fi
+
+#
+# Make sure RSH is defined, if not set reasonable default
+# RSH_CMD overrides RSH if set
+#
+if [ "$RSH_CMD" != "" ]
+then
+    RSH=$RSH_CMD
+fi
+    
+if [ "$RSH" = "" ]
+then
+    RSH="rsh"
+fi
+
+#
+# If CPP is not already defined then
+# try to find cpp in the common places, if not there then let PATH find it
+#
+if [ "$CPP" = "" ]; then
+    if [ -f /lib/cpp ]
+    then
+        CPP=/lib/cpp
+    elif [ -f /usr/ccs/lib/cpp ]
+    then
+        CPP=/usr/ccs/lib/cpp
+    else
+        CPP=cpp
+    fi
+fi
+
+#
+# trap for signals used by sfs programs
+#
+if [ "$TRAP_NUMS" = "" ]
+then
+    echo "#include <signal.h>" > /tmp/sfs_tmp1
+    echo "myprint SIGINT SIGALRM SIGTERM SIGUSR1 SIGUSR2" >> /tmp/sfs_tmp1
+    cat /tmp/sfs_tmp1 | $CPP | grep myprint | \
+        awk '{print $2 " " $3 " " $4 " " $5 " " $6}' > /tmp/sfs_tmp2
+    TRAP_NUMS=`cat /tmp/sfs_tmp2`
+fi
+rm -f /tmp/sfs_tmp1 /tmp/sfs_tmp2
+#
+# --------------------
+
+#
+# Get NFS version number
+#
+SFS_PROG="sfs"
+if [ "$NFS_VERSION" != "" ]
+then
+    if [ "$NFS_VERSION" = "3" ]
+    then
+	SFS_PROG="sfs3"
+    elif [ "$NFS_VERSION" != "2" ]
+    then
+	echo "sfs_mgr: Illegal NFS version number: $NFS_VERSION" \
+			>> $P_LOGFILE 2>&1
+	echo "sfs_mgr: Illegal NFS version number: $NFS_VERSION"
+	exit 1
+    fi
+fi
+
+#
+# print logfile header information
+#
+echo '========================================================================'\
+	>>$P_LOGFILE
+echo " " >>$P_LOGFILE
+echo "SFS NFS Benchmark Prime Client Logfile." >>$P_LOGFILE
+echo "        Creation Date: `date`" >>$P_LOGFILE
+echo "        Prime Client hostname: $HOSTNAME_VAL" >>$P_LOGFILE
+
+#
+# check for mixfile and block-size file
+# if specified
+#
+# check for mixfile
+#
+if [ "$MIXFILE" != "" -a ! -r "$WORK_DIR/$MIXFILE" ]
+then
+    echo "sfs_mgr: error missing or protected mixfile $WORK_DIR/$MIXFILE" \
+		>> $P_LOGFILE 2>&1
+    echo "sfs_mgr: error missing or protected mixfile $WORK_DIR/$MIXFILE"
+    exit 1
+fi
+
+#
+# check for block size file
+#
+if [ "$BLOCK_FILE" != "" -a ! -r "$WORK_DIR/$BLOCK_FILE" ]
+then
+    echo "sfs_mgr: error missing or protected block size file \
+	    $WORK_DIR/$BLOCK_FILE" >> $P_LOGFILE 2>&1
+    echo "sfs_mgr: error missing or protected block size file \
+	    $WORK_DIR/$BLOCK_FILE"
+    exit 1
+fi
+
+#
+#
+NUM_CLIENTS=0
+PRIME_CLIENT_NUM=0
+for i in $CLIENTS; do
+    NUM_CLIENTS=`expr $NUM_CLIENTS + 1`
+    #
+    # hack: First try a simple remote "echo" to
+    # /dev/null. If the $RSH fails, then we don't have
+    # permission to execute the remote command sfs_mcr.
+    # The initial probe is necessary because we must
+    # background the sfs_mcr rsh because we're looping
+    # on all clients, and spawn a bunch, and the rsh won't
+    # detach from the command. So, the probe.
+    #
+    $RSH $i -l $SFS_USER "echo >/dev/null" >/dev/null 2>&1 </dev/null
+    if [ $? -ne 0 ]; then
+	echo "sfs_mgr: test rsh to $i failed"
+	echo "            $RHOSTSCKMSG1"
+	echo "sfs_mgr: test rsh to $i failed" >> $P_LOGFILE
+	echo "            $RHOSTSCKMSG1" >> $P_LOGFILE
+	exit 1
+    fi
+
+    # Get canonical hostname of client $i and see if it is the prime client.
+    client_name=`$RSH $i -l $SFS_USER 'hostname || uname -n' 2>/dev/null </dev/null`
+    if [ "$client_name" = $HOSTNAME_VAL ]
+    then
+	PRIME_CLIENT_NUM=$NUM_CLIENTS
+	continue
+    fi
+    #
+    # Also check to make sure the work directory exists
+    #
+    exists=`$RSH $i -l $SFS_USER sh -c \"if [ -d $WORK_DIR ]\; then echo 0 \; else echo 1 \; fi\" </dev/null`
+    if [ "$exists" != 0 ]; then
+	echo "sfs_mgr: $WORK_DIR on $i does not exist"
+	echo "sfs_mgr: $WORK_DIR on $i does not exist" >> $P_LOGFILE
+	exit 1
+    fi
+    #
+    # propagate the mixfile to remote clients
+    #
+    if [ "$MIXFILE" != "" ]; then
+	rcp "$WORK_DIR/$MIXFILE" \
+	   "$SFS_USER"@"$i":"$WORK_DIR/$MIXFILE" >> $P_LOGFILE 2>&1
+	if [ $? -ne 0 ]; then
+	    echo \
+	    "sfs_mgr: can't rcp mix file $WORK_DIR/$MIXFILE to client $i."
+	    echo "            $RHOSTSCKMSG1"
+	    echo "            $RHOSTSCKMSG2"
+	    echo \
+	    "sfs_mgr: can't rcp mix file $WORK_DIR/$MIXFILE to client $i." \
+			>> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG1" >> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG2" >> $P_LOGFILE
+	    exit 1
+	fi
+    fi
+    #
+    # propagate block size file to remote clients
+    #
+    if [ "$BLOCK_FILE" != "" ]; then
+	rcp "$WORK_DIR/$BLOCK_FILE" \
+		"$SFS_USER"@"$i":"$WORK_DIR/$BLOCK_FILE" >> $P_LOGFILE 2>&1
+	if [ $? -ne 0 ]; then
+	    echo \
+    "sfs_mgr: can't rcp block size file $WORK_DIR/$BLOCK_FILE to client $i."
+	    echo "            $RHOSTSCKMSG1"
+	    echo "            $RHOSTSCKMSG2"
+	    echo \
+    "sfs_mgr: can't rcp block size file $WORK_DIR/$BLOCK_FILE to client $i." \
+			>> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG1"	>> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG2"	>> $P_LOGFILE
+	    exit 1
+	fi
+    fi
+done
+
+if [ "$NUM_CLIENTS" -eq 0 ]; then
+    echo "Cannot run SFS with no clients."
+    echo "Assign value to CLIENT variable in sfs_rc."
+    echo "Cannot run SFS with no clients."	>> $P_LOGFILE
+    echo "Assign value to CLIENT variable in sfs_rc."	>> $P_LOGFILE
+    exit 1
+fi
+
+
+echo "        Number of Clients: $NUM_CLIENTS" >>$P_LOGFILE
+echo "        Client hostname(s): $CLIENTS" >>$P_LOGFILE
+echo " " >>$P_LOGFILE
+
+#
+# Loop invariant setup
+# -------------------
+#
+# check for program that starts external monitoring
+#
+if [ "$PRIME_MON_SCRIPT" != "" -a ! -x "$WORK_DIR/$PRIME_MON_SCRIPT" ]
+then
+    echo "sfs_mgr: error missing or not executeable program \
+	$WORK_DIR/$PRIME_MON_SCRIPT" >> $P_LOGFILE 2>&1
+    echo "sfs_mgr: error missing or not executeable program \
+	    $WORK_DIR/$PRIME_MON_SCRIPT"
+    exit 1
+fi
+
+#
+# Set default number of procs if missing
+#
+PRCS=$PROCS
+if [ "$PRCS" = "" ]; then
+    PRCS=4
+fi
+
+if [ "$MNT_POINTS" = "" ]; then
+    echo "sfs_mgr: MNT_POINTS not specified" >> $P_LOGFILE 2>&1
+    echo "sfs_mgr: MNT_POINTS not specified"
+    exit 1
+fi
+
+set `echo $MNT_POINTS`
+NUM_MNTS=$#
+MPC=`expr $NUM_CLIENTS \* $PRCS`
+if [ $NUM_MNTS -ne 1 -a $NUM_MNTS -ne $PRCS -a  $NUM_MNTS -ne $MPC ]; then
+    ESTR=""
+    if [ $PROCS -ne $MPC ]; then
+	ESTR="or $MPC"
+    fi
+    echo "sfs_mgr: incorrect number of MNT_POINTS ($NUM_MNTS) must be $PROCS $ESTR" >> $P_LOGFILE 2>&1
+    echo "sfs_mgr: incorrect number of MNT_POINTS ($NUM_MNTS) must be $PROCS $ESTR"
+    exit 1
+fi
+
+#
+# -----------------
+#
+trap "" $TRAP_NUMS
+
+#
+# clean up any 'old' sfs processes
+#
+if [ -f $SFS_PRM_PID ]; then
+    kill -2 `cat $SFS_PRM_PID` > /dev/null 2>&1
+    rm -f $SFS_PRM_PID
+fi
+if [ -f $SFS_PNT_PID ]; then
+    kill -2 `cat $SFS_PNT_PID` > /dev/null 2>&1
+    rm -f $SFS_PNT_PID
+fi
+if [ -f $SFS_SYNCD_PID ]; then
+    kill -2 `cat $SFS_SYNCD_PID` > /dev/null 2>&1
+    rm -f $SFS_SYNCD_PID
+fi
+
+#
+# Prime Client sfs_syncd logfile
+#
+S_LOGFILE=$WORK_DIR/syncd_$PRIME_CLIENT_NUM.log
+
+#
+# Determine the number of test runs (TOTAL_RUNS)
+# from user supplied values in sfs_rc
+#
+NUM_LOADS=0
+LOAD_ARRAY=""
+DEFAULT_LOAD=60
+#
+# get the number of LOAD elements (NUM_LOADS)
+#
+for i in $LOAD; do
+    NUM_LOADS=`expr $NUM_LOADS + 1`
+done
+#
+# if NUM_LOADS > 1 then the number of test runs (TOTAL_RUNS) = NUM_LOADS and
+# Report conflict if user specifies multiple LOAD elements as well as
+# NUM_RUNS > 1.
+#
+# if NUM_LOADS <= 1 then the number of test runs (TOTAL_RUNS) = NUM_RUNS
+#
+if [ "$NUM_LOADS" -gt 1 ]; then
+    TOTAL_RUNS=$NUM_LOADS
+    LOAD_ARRAY=$LOAD
+    if [ "$NUM_RUNS" -gt 1 ]; then
+	echo "Cannot specify an array of LOAD values as well as NUM_RUNS >1."
+	echo "Cannot specify an array of LOAD values as well as NUM_RUNS >1." \
+		>> $P_LOGFILE 2>&1
+	exit 1
+    fi
+else
+    TOTAL_RUNS=$NUM_RUNS
+    if [ "$NUM_LOADS" -eq 0 ]; then
+	LOAD=$DEFAULT_LOAD
+    fi
+    LOAD_ARRAY=$LOAD
+    i=1
+    while [ "$i" -lt "$NUM_RUNS" ]; do
+	LOAD_ARRAY="$LOAD_ARRAY `expr $LOAD + $i \* $INCR_LOAD`"
+	i=`expr $i + 1`
+    done
+fi
+
+#
+# Loop invariant parameters
+# create parameter strings here ... from sfs_rc values.
+# - SFS_PARAM : sfs parameters
+# - SFS_VPARAM : sfs validation parameters
+# - SFS_PRIME_PARAM : sfs_prime parameters
+SFS_PARAM=
+SFS_VPARAM=
+SFS_PRIME_PARAM=
+#
+# get runtime
+#
+if [ "$RUNTIME" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -t $RUNTIME"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -t $RUNTIME"
+fi
+
+#
+# get mixfile filename, if specified
+#
+if [ "$MIXFILE" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -m $WORK_DIR/$MIXFILE"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -m $WORK_DIR/$MIXFILE"
+fi
+
+#
+# get sfs DEBUG level
+#
+if [ "$DEBUG" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -d $DEBUG"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -d $DEBUG"
+fi
+
+#
+# get access percentage
+#
+if [ "$ACCESS_PCNT" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -a $ACCESS_PCNT"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -a $ACCESS_PCNT"
+fi
+
+#
+# get append percentage
+#
+if [ "$APPEND_PCNT" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -A $APPEND_PCNT"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -A $APPEND_PCNT"
+fi
+
+#
+# get block size
+#
+if [ "$BLOCK_SIZE" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -B $BLOCK_SIZE"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -B $BLOCK_SIZE"
+fi
+
+#
+# get block size filename, if specified
+#
+if [ "$BLOCK_FILE" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -b $WORK_DIR/$BLOCK_FILE"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -b $WORK_DIR/$BLOCK_FILE"
+fi
+
+#
+# get maximum number of outstanding biod reads
+#
+if [ "$BIOD_MAX_READS" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -R $BIOD_MAX_READS"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -R $BIOD_MAX_READS"
+fi
+
+#
+# get maximum number of outstanding biod writes
+#
+if [ "$BIOD_MAX_WRITES" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -W $BIOD_MAX_WRITES"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -W $BIOD_MAX_WRITES"
+fi
+
+#
+# get directory count
+#
+if [ "$DIR_COUNT" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -D $DIR_COUNT"
+fi
+
+#
+# get file count
+#
+if [ -n "$FILE_COUNT" ]; then
+  if [ "$FILE_COUNT" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -F $FILE_COUNT"
+  fi
+fi
+
+#
+# get symbolic link count
+#
+if [ "$SYMLINK_COUNT" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -S $SYMLINK_COUNT"
+fi
+
+#
+# set flag for raw data dump if option set
+#
+if [ "$DUMP" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -z"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -z"
+fi
+
+#
+# set flag for NFS/TCP if variable is "1" or "on"
+#
+if [ "$TCP" != "" ]
+then
+    if [ "$TCP" = "1" -o "$TCP" = "on" ]; then
+	SFS_PARAM="$SFS_PARAM -Q"
+	SFS_VPARAM="$SFS_VPARAM -Q"
+	SFS_PRIME_PARAM="$SFS_PRIME_PARAM -Q"
+    fi
+fi
+
+#
+# get number of processes
+#
+if [ "$PROCS" -ne 0 ]; then
+    SFS_PARAM="$SFS_PARAM -p $PROCS"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -p $PROCS"
+fi
+
+#
+# get warm-up value (allow 0 warmup)
+#
+if [ "$WARMUP_TIME" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -w $WARMUP_TIME"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -w $WARMUP_TIME"
+fi
+
+#
+# get sfs_prime sleep value
+#
+if [ "${PRIME_SLEEP:-0}" -gt 0 ]; then
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -s $PRIME_SLEEP"
+fi
+
+#
+# get file set percentage delta
+#
+if [ "$FILESET_DELTA" != "" ]; then
+    SFS_PARAM="$SFS_PARAM -f $FILESET_DELTA"
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -f $FILESET_DELTA"
+fi
+
+#
+# get sfs_prime timeout value
+#
+if [ "${PRIME_TIMEOUT:-0}" -gt 0 ]; then
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -x $PRIME_TIMEOUT"
+fi
+
+#
+# get populate only flag
+# 
+if [ "$POPULATE" != "" ]; then 
+    SFS_PARAM="$SFS_PARAM -P" 
+fi
+
+#
+# check for program that starts external monitoring
+#
+if [ "$PRIME_MON_SCRIPT" != "" ]; then
+    SFS_PRIME_PARAM="$SFS_PRIME_PARAM -k $WORK_DIR/$PRIME_MON_SCRIPT"
+    # check for parameters to the monitor program; use a different method
+    # to test for nonempty because the arguments may start with a hyphen,
+    # which would confuse the "test" command.
+    if [ "x$PRIME_MON_ARGS" != "x" ]; then
+	SFS_PRIME_PARAM="$SFS_PRIME_PARAM -K '$PRIME_MON_ARGS'"
+    fi
+
+    echo "" >> $P_LOGFILE
+fi
+
+#
+# Add clients to prime
+#
+SFS_PRIME_PARAM="$SFS_PRIME_PARAM $CLIENTS"
+
+#
+# get prime client hostname
+#
+SFS_PARAM="$SFS_PARAM -M $HOSTNAME_VAL"
+
+#### End client loop invariant section
+#
+# VALIDATE stuff
+#
+if [ "$VALIDATE" -gt 0 ]; then
+    echo "Executing SFS NFS Validation ..."
+    #
+    # if validate option used then take the first client
+    # from the CLIENT array and run the SFS validation
+    # suite using the first element on the MOUNT_PNTS list.
+
+    set `echo $CLIENTS`
+    VALID_CLIENT=$1
+
+    set `echo $MNT_POINTS`
+    VALID_MOUNT_PNT=$1
+
+    if [ $NUM_MNTS -eq 1 -a -f "$WORK_DIR/$VALID_MOUNT_PNT" ]
+    then
+	#
+	# If the mount point and is actually a file
+	# name then we assume that it is a file containing a list
+	# of mount points one line per client, possibly of the format
+	# hostname:path
+	#
+	MNT_PTS=`while read CLNT_LINE MNT_LINE
+	do
+	    if [ $VALID_CLIENT = $CLNT_LINE ]
+	    then
+		echo $MNT_LINE
+		break
+	    fi
+	done < $WORK_DIR/$VALID_MOUNT_PNT`
+
+	set `echo $MNT_PTS`
+	VALID_MOUNT_PNT=$1
+    fi
+
+    echo "Starting SFS NFS validation on client ($VALID_CLIENT)"
+    echo "    $SFS_DIR/$SFS_PROG $SFS_VPARAM -V $VALID_LEVEL $VALID_MOUNT_PNT"
+    echo "Starting SFS Validation suite on client ($VALID_CLIENT)" \
+		> $P_VALFILE 2>&1
+    echo "    $SFS_DIR/$SFS_PROG $SFS_VPARAM -V $VALID_LEVEL $VALID_MOUNT_PNT" \
+		>> $P_VALFILE 2>&1
+
+    # Get canonical hostname of $VALID_CLIENT and see if it is the prime client.
+    client_name=`$RSH $VALID_CLIENT -l $SFS_USER 'hostname || uname -n' 2>/dev/null </dev/null`
+    if [ "$client_name" = $HOSTNAME_VAL ]; then
+	$SFS_DIR/$SFS_PROG $SFS_VPARAM -V $VALID_LEVEL $VALID_MOUNT_PNT \
+		>> $P_VALFILE 2>&1
+	# if error then clean-up and exit
+	if [ $? -ne 0 ]; then
+	    echo "SFS NFS validation failed."
+	    echo "See $P_VALFILE for results."
+	    exit 1
+	else
+	    echo "SFS NFS validation completed successfully."
+	    echo "See $P_VALFILE for results."
+	    exit 0
+	fi
+    else
+	$RSH $VALID_CLIENT -l $SFS_USER \
+	    "( cd $WORK_DIR; \
+	    $SFS_DIR/$SFS_PROG $SFS_VPARAM -V $VALID_LEVEL $VALID_MOUNT_PNT )" \
+	    >> $P_VALFILE 2>&1
+	if [ $? -ne 0 ]; then
+	    echo \
+	    "sfs_mgr: can't run validation pass of sfs on client $VALID_CLIENT."
+	    echo "            $RHOSTSCKMSG1"
+	    echo \
+	    "sfs_mgr: can't run validation pass of sfs on client $VALID_CLIENT." \
+				>> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG1"	>> $P_LOGFILE
+	    exit 1
+	fi
+	# if error then clean-up and exit
+	tail -1 $P_VALFILE | grep -s 'validation completed successfully'
+	if [ $? -ne 0 ]; then
+	    echo "SFS NFS validation failed."
+	    echo "See $P_VALFILE for results."
+	    echo "SFS NFS validation failed." >> $P_LOGFILE
+	    echo "See $P_VALFILE for results." >> $P_LOGFILE
+	    exit 1
+	else
+	    echo "SFS NFS validation completed successfully."
+	    echo "See $P_VALFILE for results."
+	    echo "SFS NFS validation completed successfully." >> $P_LOGFILE
+	    echo "See $P_VALFILE for results." >> $P_LOGFILE
+	    exit 0
+	fi
+    fi
+fi
+
+
+#
+# Prime client /tmp logfiles - used for clean up
+#
+PRIME_LOG_FILES="/tmp/sfs_PC_sync \
+		/tmp/sfs_x$PRIME_CLIENT_NUM \
+		/tmp/sfs_CL$PRIME_CLIENT_NUM \
+		/tmp/sfs_mpr$PRIME_CLIENT_NUM \
+		/tmp/sfs_res*"
+
+#
+# start test
+# MAIN CLIENT LOOP
+#
+RUN=1
+for LOAD_INDEX in $LOAD_ARRAY; do
+    LOAD_VALUE=`expr $LOAD_INDEX / $NUM_CLIENTS`
+
+    export LOAD_VALUE LOAD_INDEX SUFFIX WORK_DIR
+
+    echo " ">>$P_LOGFILE
+    echo "$STARline" >> $P_LOGFILE
+    echo "$STARline" >> $P_OUTFILE
+
+    #
+    # clean up /tmp files
+    #
+    for i in $PRIME_LOG_FILES; do
+	if [ -f $i ]; then
+	    if [ -w $i ]; then
+		rm $i
+	    else
+		echo "sfs_mgr: error could not remove file - $i"
+		echo "sfs_mgr: error could not remove file - $i" >> $P_LOGFILE
+		exit 1
+	    fi
+	fi
+    done
+    #
+    # restart the sfs_syncd process
+    #
+    if [ -f $SFS_SYNCD_PID ]; then
+	kill -2 `cat $SFS_SYNCD_PID` > /dev/null 2>&1
+	rm -f $SFS_SYNCD_PID
+    fi
+
+    trap "" $TRAP_NUMS
+
+    echo "Test Run $RUN of $TOTAL_RUNS" >>$P_LOGFILE
+    echo " " >>$P_LOGFILE
+    echo "    `date`"
+    $ECHO_NONL "     Executing run $RUN of $TOTAL_RUNS ... $NONL"
+    sh -c "$SFS_DIR/sfs_syncd >> $S_LOGFILE 2>&1 &"
+    sleep 15
+    echo "Started: sfs_syncd on Prime-Client ($HOSTNAME_VAL)" \
+	>> $P_LOGFILE
+
+    #
+    # start sfs on all the clients
+    #
+    CLIENTS_NUM=1
+    for i in $CLIENTS; do
+	#
+	# compose client's logfile name
+	#
+	if [ "$CLIENTS_NUM" -lt 10 ]; then
+	    C_LOGFILE="$WORK_DIR"/sfsc00"$CLIENTS_NUM"."$SUFFIX"
+	elif [ "$CLIENTS_NUM" -lt 100 ]; then
+	    C_LOGFILE="$WORK_DIR"/sfsc0"$CLIENTS_NUM"."$SUFFIX"
+	else
+	    C_LOGFILE="$WORK_DIR"/sfsc"$CLIENTS_NUM"."$SUFFIX"
+	fi
+
+	#
+	# compose client's sfs_syncd logfile name
+	#
+	S_LOGFILE=$WORK_DIR/syncd_$CLIENTS_NUM.log
+
+	if [ $NUM_MNTS -eq 1 -a -f "$WORK_DIR/$MNT_POINTS" ]
+	then
+	    #
+	    # If there is only one mount point and it is actually a file
+	    # name then we assume that it is a file containing a list
+	    # of mount points one line per client, possibly of the format
+	    # hostname:path
+	    #
+	    MNT_PTS=`while read CLNT_LINE MNT_LINE
+	    do
+		if [ $i = $CLNT_LINE ]
+		then
+		    echo $MNT_LINE
+		    break
+		fi
+	    done < $WORK_DIR/$MNT_POINTS`
+	else
+	    #
+	    # construct MNT_PTS for this particular CLIENTS_NUM (client)
+	    # from MNT_POINTS, using total number of CLIENTS
+	    # and PRCS [number of processes per client]
+	    #
+	    # PRCS must be a multiple of NUM_MNTS,
+	    # no need to resequence the list of mount points
+	    #
+	    MNT_PTS="$MNT_POINTS"
+	fi
+
+	#
+	# if prime client in $CLIENT then start sfs locally
+	#
+        client_name=`$RSH $i -l $SFS_USER 'hostname || uname -n' 2>/dev/null </dev/null`
+	if [ "$client_name" = $HOSTNAME_VAL ]; then
+	    echo "`date` $i start:" >>$P_LOGFILE
+	    echo "        $SFS_PROG -N $CLIENTS_NUM -l $LOAD_VALUE $SFS_PARAM $MNT_PTS" \
+				    >> $P_LOGFILE
+
+	    trap "" $TRAP_NUMS
+	    $SFS_DIR/$SFS_PROG -N $CLIENTS_NUM -l $LOAD_VALUE $SFS_PARAM $MNT_PTS \
+			>> $C_LOGFILE 2>&1 &
+	else
+	    #
+	    # Cause remote client to cleanup
+	    #
+	    $RSH $i -l $SFS_USER "( cd $WORK_DIR; \
+		$SFS_DIR/sfs_mcr cleanup )" >>/dev/null 2>&1 </dev/null
+
+	    #
+	    # remotely start sfs_mcr script on clients
+	    #
+	    echo "`date` $i start:" >>$P_LOGFILE
+	    echo "        $SFS_PROG -N $CLIENTS_NUM -l $LOAD_VALUE $SFS_PARAM $MNT_PTS" \
+		>> $P_LOGFILE
+
+	    $RSH $i -l $SFS_USER "( cd $WORK_DIR; \
+		$SFS_DIR/sfs_mcr $SFS_PROG $SFS_DIR \
+		$S_LOGFILE $C_LOGFILE $CLIENTS_NUM \
+		-l $LOAD_VALUE $SFS_PARAM $MNT_PTS ) &"\
+		>>/dev/null 2>&1 </dev/null &
+	fi
+
+	#
+	# increment client num
+	#
+	CLIENTS_NUM=`expr $CLIENTS_NUM + 1`
+    done
+
+    #
+    # start the Prime client program, sfs_prime,
+    # and wait for completion
+    #
+    trap "" $TRAP_NUMS
+    $SFS_DIR/sfs_prime -l $LOAD_VALUE -C $P_SUMFILE $SFS_PRIME_PARAM \
+	> /tmp/sfs_mpr$PRIME_CLIENT_NUM 2>> $P_LOGFILE
+
+    #
+    # if error then clean-up set error flag, and break out
+    #
+    if [ $? -ne 0 ]; then
+	echo "sfs_mgr: sfs_prime returned an error, exiting"
+	echo "sfs_mgr: sfs_prime returned an error, exiting" \
+		>> $P_LOGFILE 2>&1
+	if [ -f $SFS_PNT_PID ]; then
+	    kill -2 `cat $SFS_PNT_PID` > /dev/null 2>&1
+	    rm -f $SFS_PNT_PID
+	fi
+	if [ -f $SFS_SYNCD_PID ]; then
+	    kill -2 `cat $SFS_SYNCD_PID` > /dev/null 2>&1
+	    rm -f $SFS_SYNCD_PID
+	fi
+	error=TRUE
+	break	# break out of for loop
+    fi
+
+    #
+    # record results
+    #
+    cat /tmp/sfs_mpr$PRIME_CLIENT_NUM >> $P_LOGFILE
+    cat /tmp/sfs_mpr$PRIME_CLIENT_NUM >> $P_OUTFILE
+    rm /tmp/sfs_mpr$PRIME_CLIENT_NUM >> $P_LOGFILE 2>&1
+
+    #
+    # increment RUN value and reset SFS_PARAM
+    #
+    RUN=`expr $RUN + 1`
+    echo " done"
+    #
+    echo "" >> $P_LOGFILE
+    echo "$STARline" >> $P_LOGFILE
+    echo "$STARline" >> $P_OUTFILE
+
+    #
+    # test run(s) completed
+    #
+done   # END OF MAIN CLIENT LOOP: 'for LOAD_INDEX in $LOAD_ARRAY'
+
+#
+# copy log files from clients
+#
+CLIENTS_NUM=1
+for i in $CLIENTS; do
+    #
+    # compose client's logfile name
+    #
+    if [ "$CLIENTS_NUM" -lt 10 ]; then
+	C_LOGFILE="$WORK_DIR"/sfsc00"$CLIENTS_NUM"."$SUFFIX"
+    elif [ "$CLIENTS_NUM" -lt 100 ]; then
+	C_LOGFILE="$WORK_DIR"/sfsc0"$CLIENTS_NUM"."$SUFFIX"
+    else
+	C_LOGFILE="$WORK_DIR"/sfsc"$CLIENTS_NUM"."$SUFFIX"
+    fi
+    #
+    # Copy over the logfiles. We copy the files to a temporary
+    # file on the chance that either the prime client is also
+    # a load generating client and we might rcp a file over
+    # itself, or the $WORK_DIR is NFS mounted by all clients,
+    # in which case we don't want to really remove the remote
+    # file since it is the same as the 'local' file on the
+    # prime. While not necessarily efficient, this is correct.
+    #
+    client_name=`$RSH $i -l $SFS_USER 'hostname || uname -n' 2>/dev/null </dev/null`
+    if [ $client_name != $HOSTNAME_VAL ]; then
+	#
+	# copy to temporary file: of different name than target
+	# in off chance /tmp is our $WORK_DIR
+	#
+	rcp "$SFS_USER"@"$i":"$C_LOGFILE" \
+		/tmp/sfs"$CLIENTS_NUM"."$SUFFIX"
+	if [ $? -ne 0 ]; then
+	    echo "sfs_mgr: can't rcp $C_LOGFILE from client $i."
+	    echo "            $RHOSTSCKMSG1"
+	    echo "            $RHOSTSCKMSG2"
+	    echo "sfs_mgr: can't rcp $C_LOGFILE from client $i." >> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG1" >> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG2" >> $P_LOGFILE
+	    exit 1
+	fi
+	$RSH $i -l $SFS_USER "/bin/rm $C_LOGFILE"
+	if [ $? -ne 0 ]; then
+	    echo "sfs_mgr: can't remove $C_LOGFILE on client $i."
+	    echo "            $RHOSTSCKMSG1"
+	    echo "sfs_mgr: can't remove $C_LOGFILE on client $i." >> $P_LOGFILE
+	    echo "            $RHOSTSCKMSG1" >> $P_LOGFILE
+	    exit 1
+	fi
+	mv /tmp/sfs"$CLIENTS_NUM"."$SUFFIX" "$C_LOGFILE"
+    fi
+    CLIENTS_NUM=`expr $CLIENTS_NUM + 1`
+done
+
+#
+# if we got an error, terminate sfs_mgr
+#
+if [ "$error" = TRUE ]; then
+    exit 1
+fi
+
+#
+# copy 'raw data dump' files from clients
+# only do this for one point, the final one--it dosn't make
+# sense to concatenate dumps from different loads
+#
+if [ "$DUMP" != "" ]; then
+    CLIENTS_NUM=1
+    for i in $CLIENTS; do
+	#
+	# compose client's raw dump logfile name
+	#
+	if [ "$CLIENTS_NUM" -lt 10 ]; then
+	    CLNTNUM=00"$CLIENTS_NUM"
+	elif [ "$CLIENTS_NUM" -lt 100 ]; then
+	    CLNTNUM=0"$CLIENTS_NUM"
+	else
+	    CLNTNUM="$CLIENTS_NUM"
+	fi
+	PRC=$PROCS
+	if [ "$PRC" = "" ]; then
+	    PRC=4
+	fi
+	PRCJ=0
+	while [ $PRCJ -lt $PRC ]; do
+	    if [ "$PRCJ" -lt 10 ]; then
+		PROCNUM=00"$PRCJ"
+	    elif [ "$PRCJ" -lt 100 ]; then
+		PROCNUM=0"$PRCJ"
+	    else
+		PROCNUM="$PRCJ"
+	    fi
+	    RAWFILE=c${CLNTNUM}-p${PROCNUM}
+	    #
+	    # copy over the logfiles
+	    # clean out (remove) originals
+	    #
+    	    client_name=`$RSH $i -l $SFS_USER 'hostname || uname -n' 2>/dev/null </dev/null`
+	    if [ $client_name != $HOSTNAME_VAL ]; then
+		$RSH $i -l $SFS_USER \
+		    cat /tmp/"$RAWFILE" \
+		    >> "$WORK_DIR"/"$RAWFILE"."$SUFFIX"
+		$RSH $i -l $SFS_USER \
+		    /bin/rm /tmp/"$RAWFILE"
+	    else
+		cat /tmp/"$RAWFILE" \
+		    >> "$WORK_DIR"/"$RAWFILE"."$SUFFIX"
+		/bin/rm /tmp/"$RAWFILE"
+	    fi
+	    PRCJ=`expr $PRCJ + 1`
+	done
+	CLIENTS_NUM=`expr $CLIENTS_NUM + 1`
+    done
+fi
+
+#
+# cleanup processes before ending
+#
+if [ -f $SFS_PRM_PID ]; then
+    kill -2 `cat $SFS_PRM_PID` > /dev/null 2>&1
+    rm -f $SFS_PRM_PID
+fi
+if [ -f $SFS_PNT_PID ]; then
+    kill -2 `cat $SFS_PNT_PID` > /dev/null 2>&1
+    rm -f $SFS_PNT_PID
+fi
+if [ -f $SFS_SYNCD_PID ]; then
+    kill -2 `cat $SFS_SYNCD_PID` > /dev/null 2>&1
+    rm -f $SFS_SYNCD_PID
+fi
+
+#
+# cleanup temporary files
+#
+for i in $PRIME_LOG_FILES; do
+    if [ -f $i ]; then
+	if [ -w $i ]; then
+	    rm $i
+	else
+	    echo "sfs_mgr: error could not remove file - $i"
+	    echo "sfs_mgr: error could not remove file - $i" >> $P_LOGFILE
+	    exit 1
+	fi
+    fi
+done
+
+echo '========================================================================'\        >>$P_LOGFILE
+exit 0
diff --git a/TBBT/trace_play/sfs_rc b/TBBT/trace_play/sfs_rc
new file mode 100755
index 0000000..fcf8cfd
--- /dev/null
+++ b/TBBT/trace_play/sfs_rc
@@ -0,0 +1,149 @@
+##############################################################################
+#
+#	@(#)sfs_rc	2.1	97/10/23
+#
+# Specify SFS parameters for sfs runs in this file.
+#
+# The following parameters are configurable within the SFS run and
+# reporting rules.
+#
+# See below for details.
+#
+# Example shows a run of 100 to 1000 ops/sec
+#
+LOAD="100"
+INCR_LOAD=100
+NUM_RUNS=10
+PROCS=4
+CLIENTS="client1 client2"
+MNT_POINTS="srvr:/a srvr:/b srvr:/c srvr:/d srvr:/e srvr:/f srvr:/g srvr:/h"
+BIOD_MAX_WRITES=2
+BIOD_MAX_READS=2
+TCP="on"
+NFS_VERSION="3"
+SFS_USER="`id | tr '()' '  ' | awk '{print $2}' `"
+SFS_DIR="`pwd`/bin"
+WORK_DIR="`pwd`/result"
+PRIME_MON_SCRIPT=""
+PRIME_MON_ARGS=""
+RSH="rsh"
+#
+# The following parameters are strictly defined within the SFS
+# run and reporting rules and may not be changed.
+#
+RUNTIME=300
+WARMUP_TIME=300
+MIXFILE=""
+ACCESS_PCNT=10
+APPEND_PCNT=70
+BLOCK_SIZE=8
+BLOCK_FILE=""
+DIR_COUNT=30
+FILE_COUNT=
+SYMLINK_COUNT=20
+#
+# The following parameters are useful for debugging or general system
+# tuning.  They may not be used during during a reportable SFS run.
+#
+DEBUG=
+DUMP=
+POPULATE=
+PRIME_SLEEP=0
+PRIME_TIMEOUT=0
+#
+# The default SFS options are implied if no values are assigned to
+# the variables. The variables and their meaning are as follows.
+#
+# The following parameters are configurable within the SFS run and
+# reporting rules.
+#
+#  LOAD		- array of numbers specifying the NFS loads
+#		  (NFS calls per second) to be generated by all clients
+#		  combined. The number of consecutive runs equals the size
+#		  of the array and the peak load equals the largest value
+#		  in the array.
+#  PROCS	- number of SFS sub-processes to generate NFS
+#		  calls (DEFAULT PROCS = 4).
+#  MNT_POINTS	- string containing the mount points of NFS-mounted
+#		  filesystems on the client which will be used in the test.
+#  BIOD_MAX_WRITES - maximum number of outstanding async (biod) writes
+#		  (DEFAULT BIOD_MAX_WRITES = 2).
+#  BIOD_MAX_READS - maximum number of outstanding async (biod) reads
+#		  (DEFAULT BIOD_MAX_READS = 2).
+#  TCP		- If set ("on") then use NFS/TCP behaviour rather
+#  NFS_VERSION	- Set the version of the NFS protocol to use
+#		  (DEFAULT [or unset] NFS_VERSION = 2)
+#  NUM_RUNS	- number indicating the number of multi-client runs. NUM_RUNS
+#		  should only be used if the size of the LOAD array <= 1;
+#  INCR_LOAD	- number indicating the load increment factor in NFS call/sec.
+#		  The first run generates LOAD calls/sec,
+#		  subsequent runs are made with LOAD + (N * INCR_LOAD)
+#		  calls/sec; where initial N = 0. INCR_LOAD should
+#		  only be used if the size of the LOAD array <= 1.
+#  CLIENTS	- string containing client's host names; include the Prime-
+#		  Client's host name if you will be using the Prime-Client to
+#		  generate NFS loads.
+#  SFS_USER	- string containing the user account name that has appropriate
+#		  permission to execute SFS on each of the clients. The
+#		  user account name used on the Prime-Client should be added
+#		  to the SFS_USER's .rhosts file on each of the clients.
+#  SFS_DIR	- string containing the directory path where the SFS
+#		  executables are stored; should be the same for all systems
+#  WORK_DIR	- string containing directory path where the SFS output
+#		  files are stored, this should be the same for all systems.
+#  RSH		- OS dependent version of remote shell executable ON THE
+#		  PRIME CLIENT
+#  PRIME_MON_SCRIPT - string containing the name of a shell script used to
+#		  control the start and stop of any external SFS
+#		  processes like external performance monitors. The sample
+#		  The sample shell script 'sfs_ext_mon' shows the
+#		  expected semantics of the program.
+#  PRIME_MON_ARGS - string containing optional arguments that are passed
+#		  to the PRIME_MON_SCRIPT.
+#
+# The following parameters are strictly defined within the SFS
+# run and reporting rules and may not be changed.
+#
+#  RUNTIME	- number of seconds to generate load
+#		  (DEFAULT RUNTIME = 300).
+#  WARMUP_TIME	- number of seconds to warmup
+#		  (DEFAULT WARMUP_TIME = 300).
+#  MIXFILE	- string containing the NFS call distribution filename;
+#		  a copy of $MIXFILE must be placed in the $WORK_DIR
+#		  directory on the Prime_Client. The Prime-Client will
+#		  propagate a copy to all the other clients in the test.
+#  ACCESS_PCNT	- percent of total file set available for use by i/o
+#		  operations that will be accessed.
+#		  (DEFAULT ACCESS_PCNT = 10).
+#  APPEND_PCNT	- percent of writes that append rather than overwrite
+#		  (DEFAULT APPEND_PCNT = 70).
+#  BLOCK_SIZE	- number of KB in a block, up to 8 KB
+#		  (DEFAULT BLOCK_SIZE = 8 ).
+#  BLOCK_FILE	- string containing the block transfer sizes filename.
+#		  A copy of $BLOCK_FILE must be placed in the $WORK_DIR
+#		  directory on the Prime_Client. The Prime-Client will
+#		  propagate a copy to all the other clients in the test.
+#  DIR_COUNT	- number of files per directory to use for directory
+#		  operations (DEFAULT DIR_COUNT = 30).
+#  FILE_COUNT	- number of files to use for read and write
+#		  operations. By default, number of files is
+#		  calculated from the specified LOAD and ACCESS_PCNT.
+#  SYMLINK_COUNT - number of symbolic links to use for symlink
+#		  operations (DEFAULT SYMLINK_COUNT = 20).
+#
+# The following parameters are useful for debugging or general system
+# tuning.  They may not be used during during a reportable SFS run.
+#
+#  DUMP		- If set, dump raw data points at end of run
+#  POPULATE	- If set ("on") the only populate the file set and do
+#		  run test.
+#
+#  PRIME_SLEEP	- number of seconds Prime-Client should sleep after starting
+#		  and stopping the SFS external monitoring facility and
+#		  before sending synchronization message to clients. This is a
+#		  provision to allow sufficient time for starting and stopping
+#		  other performance monitoring utilities that could be used
+#		  during SFS execution.
+#  PRIME_TIMEOUT - number of seconds Prime-Client should wait for a
+#		  response from all the clients.  Zero indicates the
+#		  default should be used.
diff --git a/TBBT/trace_play/sfs_suchown b/TBBT/trace_play/sfs_suchown
new file mode 100755
index 0000000..49ac031
--- /dev/null
+++ b/TBBT/trace_play/sfs_suchown
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# @(#)sfs_suchown	2.1	97/10/23
+#
+#  Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
+#	All rights reserved.
+#		Standard Performance Evaluation Corporation (SPEC)
+#		6585 Merchant Place, Suite 100
+#		Warrenton, VA 20187
+#	This product contains benchmarks acquired from several sources who
+#	understand and agree with SPEC's goal of creating fair and objective
+#	benchmarks to measure computer performance.
+#
+#	This copyright notice is placed here only to protect SPEC in the
+#	event the source is misused in any manner that is contrary to the
+#	spirit, the goals and the intent of SPEC.
+#
+#	The source code is provided to the user or company under the license
+#	agreement for the SPEC Benchmark Suite for this product.
+
+#
+SPEC=${SPEC-0}
+
+if [ "$SPEC" != 0 ] ; then
+	rm -f $BENCH/bin/sfs
+	rm -f $BENCH/bin/sfs3
+	rm -f $BENCH/bin/sfs_syncd
+	rm -f $BENCH/bin/sfs_prime
+	rm -f $BENCH/bin/sfs_mgr
+	rm -f $BENCH/bin/sfs_mcr
+	rm -f $BENCH/bin/sfs_ext_mon
+fi
+
+#
+# If first argument is clobber, just remove executeables
+#
+if [ "$1" = "clobber" ]
+then
+	exit 0
+fi
+
+#
+# if first argument == -DRESVPORT then we must make executeable
+# setuid to root.
+#
+if [ "$1" = "-DRESVPORT" ]
+then
+	shift
+	echo "Setting root ownership on sfs setuid executable in order to"
+	echo "perform binding to privileged port. You may be asked to enter"
+	echo "the root password."
+	#
+	su $ROOTUSER <<EOF
+	chown root $*
+	chmod 04755 $*
+EOF
+fi
+
+#
+# if the SPEC tools are configured then move binaries to RESULTSDIR
+#
+if [ "$SPEC" != 0 ] ; then
+	mv sfs $BENCH/bin
+	mv sfs3 $BENCH/bin
+	mv sfs_syncd $BENCH/bin
+	mv sfs_prime $BENCH/bin
+	cp sfs_mgr $BENCH/bin
+	cp sfs_mcr $BENCH/bin
+	cp sfs_ext_mon $BENCH/bin
+fi
+exit 0
diff --git a/TBBT/trace_play/sfs_sync.x b/TBBT/trace_play/sfs_sync.x
new file mode 100755
index 0000000..2a7066e
--- /dev/null
+++ b/TBBT/trace_play/sfs_sync.x
@@ -0,0 +1,25 @@
+/*
+ * SFS sync daemon rpcgen configuration file
+ *	@(#)sfs_sync.x	2.1	97/10/23
+ *
+ * XXX Not currently used to generate source code
+ */
+
+const MAX_STR1_LEN = 31;
+const MAX_STR2_LEN = 2560;
+
+struct sync_string {
+	int	clnt_id;			/* client number */
+	string	clnt_type<MAX_STR1_LEN>;	/* message type, hard coded */
+	string	clnt_transaction<MAX_STR1_LEN>;	/* transaction id */
+	string	clnt_data<MAX_STR2_LEN>;	/* results strings */
+};
+
+program SFS {
+	version SFS {
+		int
+		SIGNAL_NULLPROC (void) = 0;
+		int
+		SIGNAL_SFS (sync_string) = 1;
+	} = 1;
+} = 100500;
diff --git a/TBBT/trace_play/t b/TBBT/trace_play/t
new file mode 100755
index 0000000000000000000000000000000000000000..9686a681a22296fbe1d13ccd3f8077f0af398055
GIT binary patch
literal 11546
zcmd^FdvsjId7r)a?t1O3$I235iXzr8Y8PuIOTyT$1K6@GE69=~$zY&xvoA>tt6g~?
zegH|JvLNPBOraqyZUf~s<Uk9dZBk0o)YODP>FMFn<Q&?P1MM*fQyfYYm%6nZ_4oVc
z-qqFOoCXSib@t4i?=|1|&CEBmcV_Mvd-}Ho0s-YELz#-$-e0%ET_~GBr8!+HszPdo
zTB6QJsT6r#w?GE@Fkt2&vW09SpI`=$xe+ikdDLC82A)EWfWgfADx&#9yB|DcR<Mw1
zmwW?7Gvu4WV}1cRGx@Z^9EN=ORx8XL1<vg8+OnBMTQ=32&E(2^W5s-|L-U|oeCr+9
z0Z7}SE&9badF_L0!BJEa<<68AgSZoYc?#u1WE*)L_&OIS&Dw8;>05)UQ=KTi6eR#(
zlk{<onk-~;rBUVd4LZeADwA`{#dJzJ4kbW|7fQ}VJd*=uY$Bg?DURyx@7vVvbi~@B
z%)pP{vz`1&cM2ZKWNOLZB$!e)zh#9(aLPhC4}xKqXylFqZ%!Q#AB#im*mwB23CtId
zsF{mSV<cvlE67pB%yQNoC;0XoGf2y+VVu0TUk1AR$JZVBr>UdwZ66sLziSGdU&G_G
zSB$SfaqKT4aN^)W*c#q`j4H0V^~ex<>dvVqAk&9S#>~riUVHk*BO(KTZuxYCcFQXt
zUIZ`hj7+~$I_JRqQ-`fbh|j!IA(!8IK1k8Pi$@N;uiNtQ35Y=Fxlhv)fXLMGnsE}3
zy?*nl|Co9%GHVA8i`2^JzTb12-FJ7->1U$`JeVn;9uH$2k2S*g**aGYAN%W{&CEQ_
zFmC1J*^|cVe_VH@SbyO8gELLPOH%i`pB7GBbKQ$aq`h-Qrw`w~bEa&wt#7Y^xdZRJ
zbq@T)<<qZ}fAY?otTXiRQK*?ZIrD9nrJAXCEcA~FLixnbYqZ`WuOAmQV9=h2Ptt)B
z#{rD{^3(!0zmndACN_|{2Du$EivUqaF+Pmd6_{6?4-cW_yxWeF8v2nL<D5%pAv1CA
zoP<8k5z;w`@Isw~9ED!Oi%@bdFhICgu!NKOlhBJE&C`$fP#y;k@IxikpJ4^BB+PY#
zCDV1VokJF+x4V0NbOn}xmC?>vN30{-(ca$K-qFz!T``nSMYqOF(SEKQn%jEON~Qjv
zSCMXO##66>j1K+(u}mQSScSq+(fN9%)p5i)U|cc24xwDCMdiu5hI*wU|6hnZ##;~M
zv>h$HSmgHOc?jdTAGvCMq}VOUu5*kd`E#SeSgftMub4_t7TYqNYuB`;v!iXYkj92p
zTe(<hD;AP%iE<{JYU}7+-L-CAtB7sd(bvDZZH((~Yex)G(ke01xw^A0Su88WPITjN
zv?I2<Gq$ch)*f5ERt0YP3S2WJ^sPW1KF~gM8$9|QILAM{fUyCbuyMEfw<wLfi5ch>
zi?eDNIY=O&LJ3SMYu-HkA1Esro(9n}2j(9jH4z}XU<m5W{sh52Ae-Cn0_at=4gqEs
zeWnWiA>csBcmYM&95gS1KV}~d!n*kbl;*(If?3Ki;c!i`#co1r+(FFzD;NtlzpUl$
zzr#40gO9M*PXPu$^|o6z)JX?}#(LC=1ee;^fNR`IOlw%YkSbwOsx8sg!YUL)wQ#WJ
zHgK)b1-1K8P1Q0A0=4hMvQfK@7Hi)kzcvnfu=cBfL$wUBd9~wshHJkAnfa>bK~b`{
zc8c9y+l-~lP<8dFvjIk$LYwTpAcc04VtyJjq3a(-4LD_=f`ZVsji8yQAsf2kurMt9
zL1JkNo43<!_V0xeHt(RSiMPNume!bO5z7ri%vc&x_10N15gEoKz>aPp)R2N~11mJV
z&Bv(<6hO6xT0HFQq1^i6G^#+yRj5?QO78*K5W3X-Z<L|(HDW}WKLIDSJ1&@Ieiv0j
zd-bS>&8z9ojalK<m@m=sn=}@&2guu60MBGdgg*Z`)EY~hY=dH#KTbxP-SLIzgt5rp
zNU?$E$)Nk8FaAgv&Gri*g$7?Eqk~#+d0!Y&bClSA?aeatJ=UMr*b1|TDsI!*Dzl6l
zq1!dqZr(%e4vlr`F1|~5@mh4q^{81#v=;6y3tfg_hWLH+V4s2Y=fv*Um}Ndi>?>MT
z*gS`d4{5B%e2acRq_K#30o(oi?~0Zt3D3|YIy@Jd8`zLX^|(gWLaW~TSLkg#LFJF2
zS%Gl9#nG&{Xt&-Xqu%O;wR-DZP$G;R9Rsr?FT+py20kF!jiQN00umpfFp|&uCLV!$
zYX=zh))=0RoYwU+!RxKPAVfG?)gg9<z-nMy<$>x?u_8w^kPs@IZJ^&^{S8?h&sm+I
z{xb+o?4N)HGAQhxx(hK1QvkxDKQdoK8G3^4=16q2N1tTS8%r%cjNhQNu{5l#^#C}M
zXLGqzh68j}u**D!I>C+;utE)-UBOO@u}=64B6QIL5o)8*g71MB?4mMdzeP(+*ao{x
zjNT7&=pfb4vmbzBW7#z22FYCh6q(mT*qUeG1lU+{gp@ykL?C2uhGk====ui1UwMPf
zW_l8|zrf-`YPT<@_Eqdx`v+9pI!&+}ETe;~p8Z4G?QCHH?L@WkJbMe})(P_<6|E=J
zzJTDAfO&%ZMbYb2G%X<i-HhAlwY`hobGyhsN$^V|@O8=_5O5V`?-H+e61;mky)r5A
z8(hupK32O&lwHdf928}5(ARrK1K;nA-xS%W2;L{uB&*#o)K*fzEGGV#dLIz#>$E1*
z&3=p22Ss3-)ZY^@O%o4`?9~LnCg6S4`>1ruJ*@Vac=iyfkBet(DEov^FDLk<P@4(<
zspx%_gY-@Qx!6y$+P4nQV<azU*WOFspK;-{caryv)VP?2{$d)<n12(fR!=}&*#&a2
zg-fEn3)+H97f|Q<poZc{Md!cZ8R46xo*i6z8;Hu<4Vw!9*IOjpFJmM_sq=)e7|+NW
zJajce4HSYb*980XuoHT!S7aI5_7Hf%i#RdtHwj+M5ahV1;96<HgJ@T9orK{bu!8HS
z!8_+w)D4{bWf}^a+;%onSUrJks6{Yh1=!Ia?cGOSl;jOb@2vSU)RruiGM~WPl=gUq
zczpb0_c-?ncpPX@kx)ZmVZaQZ7hWE2#GqiY3`9Z;@ignst6N^zhygSj1A#`{UT^;@
z5VKa9bp-nw*J5*J;h?6muMwlUSoJlwK_IjY0=9h#z<B_}8VsM~(=q>Sts}^a3uYA}
zTwD&c<Bbl=D|TyFpiVQC*3lbU(EildD_f)^XMz69HLTbWgfBSTAPav#7YNp*`S^os
zgr*HOSjy=#BCtz)11*=<7~C*Qzs%_q^pg+&ti)y;B?G7G7T_tTRe>|SyDR0rydxse
zO9l_I%vhkkW%c?c=P$nE%9iu5y3)Y;R^V(=%Dw1ZrAmEYIM057<1;sw&ZP?(Yz#7`
zq5^$SvN(|_>Pf?srLklZ6Cfd5iq=9pH6Aay6GAqWZJAs$TTZ1})!TiH<;p}e$$W0N
zQkh()6idPdRoXY1F2=_3%CGh$$KwTnST1q;lS+>Q#?s*QI;b?783T&RJw^=x8C`mg
zq(9J<k8gG><xX$6zj-)db_7~hwX|H>V$4V9Vi35)Gnat4-Uw+5w>_rqiltJkR<*8g
zF>o*y;2y<LpSZ`I-mb^oR+<X~u#e*~ddvN#IX~dySe4-t&kex7Ib35|UqVInId)#1
z9Zm^nZKcdaT7cf}!GSBBzJcz+ZQJ{MMtT5l-!TG-R6La`h{$X$87FATl$_Bd)IcLg
zPNWLi%*2{5zs~;tp5Bf9&gP!s?xDWzBZEUc;}iKzZZxlo<M~1<TFw<SV>ujAa93DC
z7&VZ_Q6c10MbVnfmvf~w$zt2t9nS*Bvz$hmE0(Y!b{n~RjntTk?{#wNbSj;4Mhp1~
zNNMwlQhra;)si0_71?4jbEEDN%tom4!Wq_zqnT_nSJGnIN`>gQIFY@<lK|+c>UBmZ
z^F>!go0h&W#B)U_or72GM5oMgLFo>K+il)B=z7_FoXyB5u1`yyQr^kMC)n^ZD!V2!
zDe+P3>Djh@<f_VOCVAwV$>n_l1A`oTA@9y7<E0EvUuXMx(p6S=WSk%-Je0f2ac!sU
zWb?T(P)3V$EN|J--|r0W7}0U$8-!9G!i+o}SJKg=<?KiN<L04-ZoV7SH>CGT^U97J
zKDz4|7!WLuV|8=J<GECp-8O-fXg4<CmX1X|45>5&noWz!LsQ-1lc7t+OL3^kmrIHA
zs86yIzPd`;?G>zn3D;8z%spVcj#m28uYNW%MzirT#I$P(bim2{L?VL;1JGY-c2fH0
zr!$dHxnWWg&oP@y>AiaP^1!G27d<V+xQPNCv7GDD0yGVNpgof%cTDF@Sp=Mfru+*?
z1vkcro&Jr(BdDq;jvK$D#W^UP*E4cgWhugRs<gY(P1QFGa3@{J#j{*KAgxUf3~t^8
zB$>@8ZxByrg9A&QjHkalca_tHeeV1$qDnTMlUmU2I_s(3*0T+Iv5dHM-{PX@zgKUq
zuLA}zM;))Zr1#1^b^|$wD<17+aSwXLSFdkiq-SUVi)zo%kgTWp3+HkrB4cj6NgG{Q
zxUl7Kn?DG!a3UTc;0{dhz~E4i);<hsrH}RSgTm!Tw?wPd0m0?fTabJ+YtE|c4<NV4
zlitAU=DW*w)?1TdN=PbJ+&58*Cs39Ox*Yc)8SF_F%jHYy*v3tLt)=*wijBvM<0_Wg
zmqSHemI^9{_m$Z0bfJiqZVuvrS4d|muYt*INyRv$RE*O_#YTaEl^4Hb>2ds@aP^I8
z9QEQ8nWTy(OZfs`u2Q<VK1rK-R8JH^#l)RRW1)|w(uwkz6UTfSOH*3V$#Q}-wSvoE
zq$iq46w<prNdyNiOD)e0LC_`m+y8~rd64A$1YXVbohM4X>sFGyYXDn{jQyd=$=xIv
zQQ%(UhL34AGGE}RkM}Ix=Bxnh@mVtSd;#y=BFFoe?U36JoOJ<;4BuZaMaHY5$nn1B
zAu#1+1vDngGW8<kRVPooyl3IYim&LNUDBCHka;&lnD;X$Ar}Sgw+mG96?Q%{<#@ld
z2mrR86@Ao8Jd5nf@jfUDIr>dL+vmxZ0n=A(ZROse9df)w@{;H0BnY0|R_NObxpq$o
zCFPiJLiXgiRoDx;ED3J%^xX>FljAGyQFJE9+)JL^?I2JNYH$^SZ9f>;`c#r9cMm9@
zTn*%E!0>n!_Tb-k<v4b{DC8Bvne=@XeD(?D<W3xNF97CvFi{`-`RmBEOF7;Y9tDGR
zFHw%^Nn}s%IOLB19Jz1#<al4olL=1;^?2~NeR8}9JPF1k3b=`K%!iTbkF*z;v=KDG
z(*be?{vKfZ=OxN@_y``zOB4^L>{fKrUat~LukAkq?3X(Xx#d1NkN4v$xi=xVpA*DQ
zp4@)|_h7OzxZqstBX}V1)jgPU590##W(gi*v%JPCxhO7Hd9~psuaBaxoEPg|kb4F`
zdWp7};g0mNM}HT=d?6Wb@<5h8cT{!>#t8ZrgU&U8b~#TucR6NWTD4NCcYOp;pU3x?
z{62)Z{^|r{g7rk>+A`NajcbKm=QOTc&Gk&<2m&PUei)Zpf^&T$V9Ls?*CCAyS?-@T
z&Q|DkMdNy4xqfJzE0MlB)VQ9BTn{wP+i@h$dn6Ozaxigzvouvb3z^3(P3gJWduUTe
zMbAsk=WRIJgZZLy{g1+Vrg0qsoKG6px9##B1PG?$8OLlg=d6_E`)45Wb7zGCnd+CS
zaQ})&esdMy{ZPoInyRIWe|{Ant-=@2nG2Tsw;9Hkmx%l0i1_C`CQ9NrRN**EsiZUU
ztMymcueMh$U(Nqq#oC$ud8vy3N)^7$r;z^cuEMM3eQas}hxM;o->p!{vl+T&;GgDR
zp8@)F2sr;Y$PeIarpJJL@fpAy&(pxYcn=`nd8z2dYXB?OtHAj^j;<e3uK|~jaYWzQ
z>KO3DKKnlde%gmu`?CN`#IcILg^D+L{BA|-Z&b^G`~B$v?)Qh++=t!y%l3`{_Y&Lt
zzl}$=Jlw4$*8i~MQLXQ5RsK8%-1}~&0qez|kdO6+D<Qufdj>e)6X-+)_Fn?t<l+rR
zM7;`}-&%EnzYy&`2ArpJlwXK9y?250JxJp<>feF;^@Xtn^E0h>xBepF-g-lO%YgIy
ztqzyJ68KK&J0-YMTPW}I?@AvYg~$A=!T)Vs3AneuE>yMZM#}R$FC^N#6}Y$lHQ;Nb
z2Y@&E_=hO(v-c!$%hzAuox_i)mw<aI3gGoBTy5aa1Lq!5?i?=ph^H+dye9F^Z#R%t
zYR%*>QSn5kRW@QD^+S{oTES%uwPII?^I>kuaK!xa9R>g2E_%-BEzY=k_Dxs0YlOSW
zcsA?%xRIyN#Zq~66fDQ-#<{4|-#0wsIKVc~!FskjTZT4n>v1;q^!5#iz-PKE(v$c$
z5+ggAO_$QC*lN^H<(;u?K7o@D*?~Io@?Ir7L?>0AnAqo8>lxTQYs^EmArGS&51!R3
z+gs84@s0pbwmGiO=BoxaZtLq-I5&01_rPEFAa=@y_&y#*u!+U|>=_<EWpZ!~C}K*^
zy_EidbZ%7~f)sehQIY510LQl66?eZt6#<c!Z&EM2Z1yWuo^s*Xd)60j{oUI76W2M?
za$w-3^*Kjx|KKK^*$i&kGTbxbjBMQ0--E%{4f1Jq-K;*&@)>eIv)dU;k7aPAS?JEj
Pi$$Cl;B3eL-R%DWqfDn`

literal 0
HcmV?d00001

diff --git a/TBBT/trace_play/t.c b/TBBT/trace_play/t.c
new file mode 100644
index 0000000..45baab2
--- /dev/null
+++ b/TBBT/trace_play/t.c
@@ -0,0 +1,6 @@
+main()
+{
+	int i = 1;
+	i <<= 2;
+	printf("%d\n", i);
+}
-- 
2.20.1