added some tools from ronnie sahlberg
authorAndrew Tridgell <tridge@samba.org>
Fri, 5 Oct 2007 01:38:34 +0000 (11:38 +1000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 5 Oct 2007 01:38:34 +0000 (11:38 +1000)
13 files changed:
ronnie/nfsclient/Makefile [new file with mode: 0644]
ronnie/nfsclient/mount.h [new file with mode: 0644]
ronnie/nfsclient/mount.x [new file with mode: 0644]
ronnie/nfsclient/mount_client.c [new file with mode: 0644]
ronnie/nfsclient/mount_xdr.c [new file with mode: 0644]
ronnie/nfsclient/nfs.h [new file with mode: 0644]
ronnie/nfsclient/nfs.x [new file with mode: 0644]
ronnie/nfsclient/nfs_client.c [new file with mode: 0644]
ronnie/nfsclient/nfs_xdr.c [new file with mode: 0644]
ronnie/nfsclient/nfsclient.c [new file with mode: 0644]
ronnie/nfsclient/nfsio.c [new file with mode: 0644]
ronnie/nfsclient/threadio.c [new file with mode: 0644]
ronnie/scsi_readdisk/scsi_readdisk.c [new file with mode: 0644]

diff --git a/ronnie/nfsclient/Makefile b/ronnie/nfsclient/Makefile
new file mode 100644 (file)
index 0000000..ec48740
--- /dev/null
@@ -0,0 +1,56 @@
+
+all: nfsclient nfsio
+
+clean:
+       rm -f *.o
+       rm -f nfsclient
+
+nfsio: nfsio.o mount_xdr.o mount_client.o nfs_xdr.o nfs_client.o
+       gcc -o $@ nfsio.o mount_client.o mount_xdr.o nfs_client.o nfs_xdr.o -lpthread
+
+nfsclient: nfsclient.o mount_xdr.o mount_client.o nfs_xdr.o nfs_client.o
+       gcc -o $@ nfsclient.o mount_client.o mount_xdr.o nfs_client.o nfs_xdr.o 
+
+nfsio.o: nfsio.c
+       gcc -g -c nfsio.c -o $@
+
+nfsclient.o: nfsclient.c
+       gcc -g -c nfsclient.c -o $@
+
+mount_xdr.o:  mount_xdr.c
+       gcc -g -c mount_xdr.c -o $@
+
+mount_client.o:  mount_client.c
+       gcc -g -c mount_client.c -o $@
+
+mount.h:  mount.x
+       @echo Generating $@
+       rpcgen -h mount.x > mount.h
+
+mount_xdr.c:  mount.x mount.h
+       @echo Generating $@
+       rpcgen -c mount.x > mount_xdr.c
+
+mount_client.c:  mount.x mount.h
+       @echo Generating $@
+       rpcgen -l mount.x > mount_client.c
+
+nfs_xdr.o:  nfs_xdr.c
+       gcc -g -c nfs_xdr.c -o $@
+
+nfs_client.o:  nfs_client.c
+       gcc -g -c nfs_client.c -o $@
+
+nfs.h:  nfs.x
+       @echo Generating $@
+       rpcgen -h nfs.x > nfs.h
+
+nfs_xdr.c:  nfs.x nfs.h
+       @echo Generating $@
+       rpcgen -c nfs.x > nfs_xdr.c
+
+nfs_client.c:  nfs.x nfs.h
+       @echo Generating $@
+       rpcgen -l nfs.x > nfs_client.c
+
+
diff --git a/ronnie/nfsclient/mount.h b/ronnie/nfsclient/mount.h
new file mode 100644 (file)
index 0000000..9ca9790
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _MOUNT_H_RPCGEN
+#define _MOUNT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNTPATHLEN 1024
+#define MNTNAMLEN 255
+#define FHSIZE3 64
+
+typedef struct {
+       u_int fhandle3_len;
+       char *fhandle3_val;
+} fhandle3;
+
+typedef char *dirpath;
+
+typedef char *name;
+
+enum mountstat3 {
+       MNT3_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 mountstat3 mountstat3;
+
+typedef struct mountbody *mountlist;
+
+struct mountbody {
+       name ml_hostname;
+       dirpath ml_directory;
+       mountlist ml_next;
+};
+typedef struct mountbody mountbody;
+
+typedef struct groupnode *groups;
+
+struct groupnode {
+       name gr_name;
+       groups gr_next;
+};
+typedef struct groupnode groupnode;
+
+typedef struct exportnode *exports;
+
+struct exportnode {
+       dirpath ex_dir;
+       groups ex_groups;
+       exports ex_next;
+};
+typedef struct exportnode exportnode;
+
+struct mountres3_ok {
+       fhandle3 fhandle;
+       struct {
+               u_int auth_flavors_len;
+               int *auth_flavors_val;
+       } auth_flavors;
+};
+typedef struct mountres3_ok mountres3_ok;
+
+struct mountres3 {
+       mountstat3 fhs_status;
+       union {
+               mountres3_ok mountinfo;
+       } mountres3_u;
+};
+typedef struct mountres3 mountres3;
+
+#define MOUNT_PROGRAM 100005
+#define MOUNT_V3 3
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define MOUNTPROC3_NULL 0
+extern  void * mountproc3_null_3(void *, CLIENT *);
+extern  void * mountproc3_null_3_svc(void *, struct svc_req *);
+#define MOUNTPROC3_MNT 1
+extern  mountres3 * mountproc3_mnt_3(dirpath *, CLIENT *);
+extern  mountres3 * mountproc3_mnt_3_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC3_DUMP 2
+extern  mountlist * mountproc3_dump_3(void *, CLIENT *);
+extern  mountlist * mountproc3_dump_3_svc(void *, struct svc_req *);
+#define MOUNTPROC3_UMNT 3
+extern  void * mountproc3_umnt_3(dirpath *, CLIENT *);
+extern  void * mountproc3_umnt_3_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC3_UMNTALL 4
+extern  void * mountproc3_umntall_3(void *, CLIENT *);
+extern  void * mountproc3_umntall_3_svc(void *, struct svc_req *);
+#define MOUNTPROC3_EXPORT 5
+extern  exports * mountproc3_export_3(void *, CLIENT *);
+extern  exports * mountproc3_export_3_svc(void *, struct svc_req *);
+extern int mount_program_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+#else /* K&R C */
+#define MOUNTPROC3_NULL 0
+extern  void * mountproc3_null_3();
+extern  void * mountproc3_null_3_svc();
+#define MOUNTPROC3_MNT 1
+extern  mountres3 * mountproc3_mnt_3();
+extern  mountres3 * mountproc3_mnt_3_svc();
+#define MOUNTPROC3_DUMP 2
+extern  mountlist * mountproc3_dump_3();
+extern  mountlist * mountproc3_dump_3_svc();
+#define MOUNTPROC3_UMNT 3
+extern  void * mountproc3_umnt_3();
+extern  void * mountproc3_umnt_3_svc();
+#define MOUNTPROC3_UMNTALL 4
+extern  void * mountproc3_umntall_3();
+extern  void * mountproc3_umntall_3_svc();
+#define MOUNTPROC3_EXPORT 5
+extern  exports * mountproc3_export_3();
+extern  exports * mountproc3_export_3_svc();
+extern int mount_program_3_freeresult ();
+#endif /* K&R C */
+
+/* the xdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern  bool_t xdr_fhandle3 (XDR *, fhandle3*);
+extern  bool_t xdr_dirpath (XDR *, dirpath*);
+extern  bool_t xdr_name (XDR *, name*);
+extern  bool_t xdr_mountstat3 (XDR *, mountstat3*);
+extern  bool_t xdr_mountlist (XDR *, mountlist*);
+extern  bool_t xdr_mountbody (XDR *, mountbody*);
+extern  bool_t xdr_groups (XDR *, groups*);
+extern  bool_t xdr_groupnode (XDR *, groupnode*);
+extern  bool_t xdr_exports (XDR *, exports*);
+extern  bool_t xdr_exportnode (XDR *, exportnode*);
+extern  bool_t xdr_mountres3_ok (XDR *, mountres3_ok*);
+extern  bool_t xdr_mountres3 (XDR *, mountres3*);
+
+#else /* K&R C */
+extern bool_t xdr_fhandle3 ();
+extern bool_t xdr_dirpath ();
+extern bool_t xdr_name ();
+extern bool_t xdr_mountstat3 ();
+extern bool_t xdr_mountlist ();
+extern bool_t xdr_mountbody ();
+extern bool_t xdr_groups ();
+extern bool_t xdr_groupnode ();
+extern bool_t xdr_exports ();
+extern bool_t xdr_exportnode ();
+extern bool_t xdr_mountres3_ok ();
+extern bool_t xdr_mountres3 ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_MOUNT_H_RPCGEN */
diff --git a/ronnie/nfsclient/mount.x b/ronnie/nfsclient/mount.x
new file mode 100644 (file)
index 0000000..2bb7fe9
--- /dev/null
@@ -0,0 +1,71 @@
+/* copied from RFC1813 */
+
+const MNTPATHLEN = 1024;  /* Maximum bytes in a path name */
+const MNTNAMLEN  = 255;   /* Maximum bytes in a name */
+const FHSIZE3    = 64;    /* Maximum bytes in a V3 file handle */
+
+
+typedef opaque fhandle3<FHSIZE3>;
+typedef string dirpath<MNTPATHLEN>;
+typedef string name<MNTNAMLEN>;
+
+enum mountstat3 {
+       MNT3_OK = 0,                 /* no error */
+       MNT3ERR_PERM = 1,            /* Not owner */
+       MNT3ERR_NOENT = 2,           /* No such file or directory */
+       MNT3ERR_IO = 5,              /* I/O error */
+       MNT3ERR_ACCES = 13,          /* Permission denied */
+       MNT3ERR_NOTDIR = 20,         /* Not a directory */
+       MNT3ERR_INVAL = 22,          /* Invalid argument */
+       MNT3ERR_NAMETOOLONG = 63,    /* Filename too long */
+       MNT3ERR_NOTSUPP = 10004,     /* Operation not supported */
+       MNT3ERR_SERVERFAULT = 10006  /* A failure on the server */
+};
+
+
+typedef struct mountbody *mountlist;
+
+struct mountbody {
+       name       ml_hostname;
+       dirpath    ml_directory;
+       mountlist  ml_next;
+};
+
+typedef struct groupnode *groups;
+
+struct groupnode {
+       name     gr_name;
+       groups   gr_next;
+};
+
+
+typedef struct exportnode *exports;
+
+struct exportnode {
+       dirpath  ex_dir;
+       groups   ex_groups;
+       exports  ex_next;
+};
+
+struct mountres3_ok {
+       fhandle3   fhandle;
+       int        auth_flavors<>;
+};
+
+union mountres3 switch (mountstat3 fhs_status) {
+       case MNT3_OK:
+               mountres3_ok  mountinfo;
+       default:
+               void;
+};
+
+program MOUNT_PROGRAM {
+       version MOUNT_V3 {
+       void      MOUNTPROC3_NULL(void)    = 0;
+       mountres3 MOUNTPROC3_MNT(dirpath)  = 1;
+       mountlist MOUNTPROC3_DUMP(void)    = 2;
+       void      MOUNTPROC3_UMNT(dirpath) = 3;
+       void      MOUNTPROC3_UMNTALL(void) = 4;
+       exports   MOUNTPROC3_EXPORT(void)  = 5;
+       } = 3;
+} = 100005;
diff --git a/ronnie/nfsclient/mount_client.c b/ronnie/nfsclient/mount_client.c
new file mode 100644 (file)
index 0000000..7aef955
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include <memory.h> /* for memset */
+#include "mount.h"
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+void *
+mountproc3_null_3(void *argp, CLIENT *clnt)
+{
+       static char clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, MOUNTPROC3_NULL,
+               (xdrproc_t) xdr_void, (caddr_t) argp,
+               (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return ((void *)&clnt_res);
+}
+
+mountres3 *
+mountproc3_mnt_3(dirpath *argp, CLIENT *clnt)
+{
+       static mountres3 clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, MOUNTPROC3_MNT,
+               (xdrproc_t) xdr_dirpath, (caddr_t) argp,
+               (xdrproc_t) xdr_mountres3, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return (&clnt_res);
+}
+
+mountlist *
+mountproc3_dump_3(void *argp, CLIENT *clnt)
+{
+       static mountlist clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, MOUNTPROC3_DUMP,
+               (xdrproc_t) xdr_void, (caddr_t) argp,
+               (xdrproc_t) xdr_mountlist, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return (&clnt_res);
+}
+
+void *
+mountproc3_umnt_3(dirpath *argp, CLIENT *clnt)
+{
+       static char clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, MOUNTPROC3_UMNT,
+               (xdrproc_t) xdr_dirpath, (caddr_t) argp,
+               (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return ((void *)&clnt_res);
+}
+
+void *
+mountproc3_umntall_3(void *argp, CLIENT *clnt)
+{
+       static char clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, MOUNTPROC3_UMNTALL,
+               (xdrproc_t) xdr_void, (caddr_t) argp,
+               (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return ((void *)&clnt_res);
+}
+
+exports *
+mountproc3_export_3(void *argp, CLIENT *clnt)
+{
+       static exports clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, MOUNTPROC3_EXPORT,
+               (xdrproc_t) xdr_void, (caddr_t) argp,
+               (xdrproc_t) xdr_exports, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return (&clnt_res);
+}
diff --git a/ronnie/nfsclient/mount_xdr.c b/ronnie/nfsclient/mount_xdr.c
new file mode 100644 (file)
index 0000000..48d2afd
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "mount.h"
+
+bool_t
+xdr_fhandle3 (XDR *xdrs, fhandle3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_dirpath (XDR *xdrs, dirpath *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, objp, MNTPATHLEN))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_name (XDR *xdrs, name *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, objp, MNTNAMLEN))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_mountstat3 (XDR *xdrs, mountstat3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_enum (xdrs, (enum_t *) objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_mountlist (XDR *xdrs, mountlist *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct mountbody), (xdrproc_t) xdr_mountbody))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_mountbody (XDR *xdrs, mountbody *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_name (xdrs, &objp->ml_hostname))
+                return FALSE;
+        if (!xdr_dirpath (xdrs, &objp->ml_directory))
+                return FALSE;
+        if (!xdr_mountlist (xdrs, &objp->ml_next))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_groups (XDR *xdrs, groups *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct groupnode), (xdrproc_t) xdr_groupnode))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_groupnode (XDR *xdrs, groupnode *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_name (xdrs, &objp->gr_name))
+                return FALSE;
+        if (!xdr_groups (xdrs, &objp->gr_next))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_exports (XDR *xdrs, exports *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct exportnode), (xdrproc_t) xdr_exportnode))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_exportnode (XDR *xdrs, exportnode *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_dirpath (xdrs, &objp->ex_dir))
+                return FALSE;
+        if (!xdr_groups (xdrs, &objp->ex_groups))
+                return FALSE;
+        if (!xdr_exports (xdrs, &objp->ex_next))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_fhandle3 (xdrs, &objp->fhandle))
+                return FALSE;
+        if (!xdr_array (xdrs, (char **)&objp->auth_flavors.auth_flavors_val, (u_int *) &objp->auth_flavors.auth_flavors_len, ~0,
+               sizeof (int), (xdrproc_t) xdr_int))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_mountres3 (XDR *xdrs, mountres3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_mountstat3 (xdrs, &objp->fhs_status))
+                return FALSE;
+       switch (objp->fhs_status) {
+       case MNT3_OK:
+                if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo))
+                        return FALSE;
+               break;
+       default:
+               break;
+       }
+       return TRUE;
+}
diff --git a/ronnie/nfsclient/nfs.h b/ronnie/nfsclient/nfs.h
new file mode 100644 (file)
index 0000000..6485400
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _NFS_H_RPCGEN
+#define _NFS_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NFS3_FHSIZE 64
+#define NFS3_WRITEVERFSIZE 8
+
+struct nfs_fh3 {
+       struct {
+               u_int data_len;
+               char *data_val;
+       } data;
+};
+typedef struct nfs_fh3 nfs_fh3;
+
+typedef char *filename3;
+
+struct diropargs3 {
+       nfs_fh3 dir;
+       filename3 name;
+};
+typedef struct diropargs3 diropargs3;
+
+enum ftype3 {
+       NF3REG = 1,
+       NF3DIR = 2,
+       NF3BLK = 3,
+       NF3CHR = 4,
+       NF3LNK = 5,
+       NF3SOCK = 6,
+       NF3FIFO = 7,
+};
+typedef enum ftype3 ftype3;
+
+typedef u_long uint32;
+
+typedef long int32;
+
+typedef uint32 mode3;
+
+typedef uint32 uid3;
+
+typedef uint32 gid3;
+
+typedef u_quad_t uint64;
+
+typedef uint64 size3;
+
+typedef uint64 fileid3;
+
+struct specdata3 {
+       uint32 specdata1;
+       uint32 specdata2;
+};
+typedef struct specdata3 specdata3;
+
+struct nfstime3 {
+       uint32 seconds;
+       uint32 nseconds;
+};
+typedef struct nfstime3 nfstime3;
+
+struct fattr3 {
+       ftype3 type;
+       mode3 mode;
+       uint32 nlink;
+       uid3 uid;
+       gid3 gid;
+       size3 size;
+       size3 used;
+       specdata3 rdev;
+       uint64 fsid;
+       fileid3 fileid;
+       nfstime3 atime;
+       nfstime3 mtime;
+       nfstime3 ctime;
+};
+typedef struct fattr3 fattr3;
+
+struct post_op_attr {
+       bool_t attributes_follow;
+       union {
+               fattr3 attributes;
+       } post_op_attr_u;
+};
+typedef struct post_op_attr post_op_attr;
+
+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,
+};
+typedef enum nfsstat3 nfsstat3;
+
+enum stable_how {
+       UNSTABLE = 0,
+       DATA_SYNC = 1,
+       FILE_SYNC = 2,
+};
+typedef enum stable_how stable_how;
+
+typedef uint64 offset3;
+
+typedef uint32 count3;
+
+struct wcc_attr {
+       size3 size;
+       nfstime3 mtime;
+       nfstime3 ctime;
+};
+typedef struct wcc_attr wcc_attr;
+
+struct pre_op_attr {
+       bool_t attributes_follow;
+       union {
+               wcc_attr attributes;
+       } pre_op_attr_u;
+};
+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 WRITE3args {
+       nfs_fh3 file;
+       offset3 offset;
+       count3 count;
+       stable_how stable;
+       struct {
+               u_int data_len;
+               char *data_val;
+       } data;
+};
+typedef struct WRITE3args WRITE3args;
+
+typedef char writeverf3[NFS3_WRITEVERFSIZE];
+
+struct WRITE3resok {
+       wcc_data file_wcc;
+       count3 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 resok;
+               WRITE3resfail resfail;
+       } WRITE3res_u;
+};
+typedef struct WRITE3res WRITE3res;
+
+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 resok;
+               LOOKUP3resfail resfail;
+       } LOOKUP3res_u;
+};
+typedef struct LOOKUP3res LOOKUP3res;
+
+struct COMMIT3args {
+       nfs_fh3 file;
+       offset3 offset;
+       count3 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 resok;
+               COMMIT3resfail resfail;
+       } COMMIT3res_u;
+};
+typedef struct COMMIT3res COMMIT3res;
+
+#define NFS_PROGRAM 100003
+#define NFS_V3 3
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define NFSPROC3_NULL 0
+extern  void * nfsproc3_null_3(void *, CLIENT *);
+extern  void * nfsproc3_null_3_svc(void *, struct svc_req *);
+#define NFSPROC3_LOOKUP 3
+extern  LOOKUP3res * nfsproc3_lookup_3(LOOKUP3args *, CLIENT *);
+extern  LOOKUP3res * nfsproc3_lookup_3_svc(LOOKUP3args *, struct svc_req *);
+#define NFSPROC3_WRITE 7
+extern  WRITE3res * nfsproc3_write_3(WRITE3args *, CLIENT *);
+extern  WRITE3res * nfsproc3_write_3_svc(WRITE3args *, struct svc_req *);
+#define NFSPROC3_COMMIT 21
+extern  COMMIT3res * nfsproc3_commit_3(COMMIT3args *, CLIENT *);
+extern  COMMIT3res * nfsproc3_commit_3_svc(COMMIT3args *, struct svc_req *);
+extern int nfs_program_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+#else /* K&R C */
+#define NFSPROC3_NULL 0
+extern  void * nfsproc3_null_3();
+extern  void * nfsproc3_null_3_svc();
+#define NFSPROC3_LOOKUP 3
+extern  LOOKUP3res * nfsproc3_lookup_3();
+extern  LOOKUP3res * nfsproc3_lookup_3_svc();
+#define NFSPROC3_WRITE 7
+extern  WRITE3res * nfsproc3_write_3();
+extern  WRITE3res * nfsproc3_write_3_svc();
+#define NFSPROC3_COMMIT 21
+extern  COMMIT3res * nfsproc3_commit_3();
+extern  COMMIT3res * nfsproc3_commit_3_svc();
+extern int nfs_program_3_freeresult ();
+#endif /* K&R C */
+
+/* the xdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern  bool_t xdr_nfs_fh3 (XDR *, nfs_fh3*);
+extern  bool_t xdr_filename3 (XDR *, filename3*);
+extern  bool_t xdr_diropargs3 (XDR *, diropargs3*);
+extern  bool_t xdr_ftype3 (XDR *, ftype3*);
+extern  bool_t xdr_uint32 (XDR *, uint32*);
+extern  bool_t xdr_int32 (XDR *, int32*);
+extern  bool_t xdr_mode3 (XDR *, mode3*);
+extern  bool_t xdr_uid3 (XDR *, uid3*);
+extern  bool_t xdr_gid3 (XDR *, gid3*);
+extern  bool_t xdr_uint64 (XDR *, uint64*);
+extern  bool_t xdr_size3 (XDR *, size3*);
+extern  bool_t xdr_fileid3 (XDR *, fileid3*);
+extern  bool_t xdr_specdata3 (XDR *, specdata3*);
+extern  bool_t xdr_nfstime3 (XDR *, nfstime3*);
+extern  bool_t xdr_fattr3 (XDR *, fattr3*);
+extern  bool_t xdr_post_op_attr (XDR *, post_op_attr*);
+extern  bool_t xdr_nfsstat3 (XDR *, nfsstat3*);
+extern  bool_t xdr_stable_how (XDR *, stable_how*);
+extern  bool_t xdr_offset3 (XDR *, offset3*);
+extern  bool_t xdr_count3 (XDR *, count3*);
+extern  bool_t xdr_wcc_attr (XDR *, wcc_attr*);
+extern  bool_t xdr_pre_op_attr (XDR *, pre_op_attr*);
+extern  bool_t xdr_wcc_data (XDR *, wcc_data*);
+extern  bool_t xdr_WRITE3args (XDR *, WRITE3args*);
+extern  bool_t xdr_writeverf3 (XDR *, writeverf3);
+extern  bool_t xdr_WRITE3resok (XDR *, WRITE3resok*);
+extern  bool_t xdr_WRITE3resfail (XDR *, WRITE3resfail*);
+extern  bool_t xdr_WRITE3res (XDR *, WRITE3res*);
+extern  bool_t xdr_LOOKUP3args (XDR *, LOOKUP3args*);
+extern  bool_t xdr_LOOKUP3resok (XDR *, LOOKUP3resok*);
+extern  bool_t xdr_LOOKUP3resfail (XDR *, LOOKUP3resfail*);
+extern  bool_t xdr_LOOKUP3res (XDR *, LOOKUP3res*);
+extern  bool_t xdr_COMMIT3args (XDR *, COMMIT3args*);
+extern  bool_t xdr_COMMIT3resok (XDR *, COMMIT3resok*);
+extern  bool_t xdr_COMMIT3resfail (XDR *, COMMIT3resfail*);
+extern  bool_t xdr_COMMIT3res (XDR *, COMMIT3res*);
+
+#else /* K&R C */
+extern bool_t xdr_nfs_fh3 ();
+extern bool_t xdr_filename3 ();
+extern bool_t xdr_diropargs3 ();
+extern bool_t xdr_ftype3 ();
+extern bool_t xdr_uint32 ();
+extern bool_t xdr_int32 ();
+extern bool_t xdr_mode3 ();
+extern bool_t xdr_uid3 ();
+extern bool_t xdr_gid3 ();
+extern bool_t xdr_uint64 ();
+extern bool_t xdr_size3 ();
+extern bool_t xdr_fileid3 ();
+extern bool_t xdr_specdata3 ();
+extern bool_t xdr_nfstime3 ();
+extern bool_t xdr_fattr3 ();
+extern bool_t xdr_post_op_attr ();
+extern bool_t xdr_nfsstat3 ();
+extern bool_t xdr_stable_how ();
+extern bool_t xdr_offset3 ();
+extern bool_t xdr_count3 ();
+extern bool_t xdr_wcc_attr ();
+extern bool_t xdr_pre_op_attr ();
+extern bool_t xdr_wcc_data ();
+extern bool_t xdr_WRITE3args ();
+extern bool_t xdr_writeverf3 ();
+extern bool_t xdr_WRITE3resok ();
+extern bool_t xdr_WRITE3resfail ();
+extern bool_t xdr_WRITE3res ();
+extern bool_t xdr_LOOKUP3args ();
+extern bool_t xdr_LOOKUP3resok ();
+extern bool_t xdr_LOOKUP3resfail ();
+extern bool_t xdr_LOOKUP3res ();
+extern bool_t xdr_COMMIT3args ();
+extern bool_t xdr_COMMIT3resok ();
+extern bool_t xdr_COMMIT3resfail ();
+extern bool_t xdr_COMMIT3res ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_NFS_H_RPCGEN */
diff --git a/ronnie/nfsclient/nfs.x b/ronnie/nfsclient/nfs.x
new file mode 100644 (file)
index 0000000..6c66c51
--- /dev/null
@@ -0,0 +1,236 @@
+/* from rfc 1813 */
+
+const NFS3_FHSIZE    = 64;    /* Maximum bytes in a V3 file handle */
+const NFS3_WRITEVERFSIZE = 8;
+
+struct nfs_fh3 {
+       opaque       data<NFS3_FHSIZE>;
+};
+
+typedef string filename3<>;
+
+struct diropargs3 {
+       nfs_fh3     dir;
+       filename3   name;
+};
+
+enum ftype3 {
+       NF3REG    = 1,
+       NF3DIR    = 2,
+       NF3BLK    = 3,
+       NF3CHR    = 4,
+       NF3LNK    = 5,
+       NF3SOCK   = 6,
+       NF3FIFO   = 7
+};
+
+typedef unsigned long uint32;
+
+typedef long int32;
+
+typedef uint32 mode3;
+
+typedef uint32 uid3;
+
+typedef uint32 gid3;
+
+typedef unsigned hyper uint64;
+
+typedef uint64 size3;
+
+typedef uint64 fileid3;
+
+struct specdata3 {
+       uint32     specdata1;
+       uint32     specdata2;
+};
+
+struct nfstime3 {
+       uint32   seconds;
+       uint32   nseconds;
+};
+
+struct fattr3 {
+       ftype3     type;
+       mode3      mode;
+       uint32     nlink;
+       uid3       uid;
+       gid3       gid;
+       size3      size;
+       size3      used;
+       specdata3  rdev;
+       uint64     fsid;
+       fileid3    fileid;
+       nfstime3   atime;
+       nfstime3   mtime;
+       nfstime3   ctime;
+};
+
+union post_op_attr switch (bool attributes_follow) {
+       case TRUE:
+               fattr3   attributes;
+       case FALSE:
+               void;
+};
+
+
+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
+};     
+
+enum stable_how {
+       UNSTABLE  = 0,
+       DATA_SYNC = 1,
+       FILE_SYNC = 2
+};
+
+typedef uint64 offset3;
+
+typedef uint32 count3;
+
+struct wcc_attr {
+       size3       size;
+       nfstime3    mtime;
+       nfstime3    ctime;
+};
+
+union pre_op_attr switch (bool attributes_follow) {
+       case TRUE:
+               wcc_attr  attributes;
+       case FALSE:
+               void;
+};
+
+struct wcc_data {
+       pre_op_attr    before;
+       post_op_attr   after;
+};
+
+struct WRITE3args {
+       nfs_fh3     file;
+       offset3     offset;
+       count3      count;
+       stable_how  stable;
+       opaque      data<>;
+};
+
+typedef opaque writeverf3[NFS3_WRITEVERFSIZE];
+
+struct WRITE3resok {
+       wcc_data    file_wcc;
+       count3      count;
+       stable_how  committed;
+       writeverf3  verf;
+};
+
+struct WRITE3resfail {
+       wcc_data    file_wcc;
+};
+
+union WRITE3res switch (nfsstat3 status) {
+       case NFS3_OK:
+               WRITE3resok    resok;
+       default:
+               WRITE3resfail  resfail;
+};
+
+struct LOOKUP3args {
+       diropargs3  what;
+};
+
+struct LOOKUP3resok {
+       nfs_fh3      object;
+       post_op_attr obj_attributes;
+       post_op_attr dir_attributes;
+};
+
+struct LOOKUP3resfail {
+       post_op_attr dir_attributes;
+};
+
+
+
+union LOOKUP3res switch (nfsstat3 status) {
+       case NFS3_OK:
+               LOOKUP3resok    resok;
+       default:
+               LOOKUP3resfail  resfail;
+};
+
+struct COMMIT3args {
+       nfs_fh3    file;
+       offset3    offset;
+       count3     count;
+};
+
+struct COMMIT3resok {
+       wcc_data   file_wcc;
+       writeverf3 verf;
+};
+
+struct COMMIT3resfail {
+       wcc_data   file_wcc;
+};
+
+union COMMIT3res switch (nfsstat3 status) {
+       case NFS3_OK:
+               COMMIT3resok   resok;
+       default:
+               COMMIT3resfail resfail;
+};
+
+
+program NFS_PROGRAM {
+       version NFS_V3 {
+               void NFSPROC3_NULL(void)                    = 0;
+/*             GETATTR3res NFSPROC3_GETATTR(GETATTR3args)         = 1;*/
+/*             SETATTR3res NFSPROC3_SETATTR(SETATTR3args)         = 2;*/
+               LOOKUP3res NFSPROC3_LOOKUP(LOOKUP3args)           = 3;
+/*             ACCESS3res NFSPROC3_ACCESS(ACCESS3args)           = 4;*/
+/*             READLINK3res NFSPROC3_READLINK(READLINK3args)       = 5;*/
+/*             READ3res NFSPROC3_READ(READ3args)               = 6;*/
+               WRITE3res NFSPROC3_WRITE(WRITE3args)             = 7;
+/*             CREATE3res NFSPROC3_CREATE(CREATE3args)           = 8;*/
+/*             MKDIR3res NFSPROC3_MKDIR(MKDIR3args)             = 9;*/
+/*             SYMLINK3res NFSPROC3_SYMLINK(SYMLINK3args)         = 10;*/
+/*             MKNOD3res NFSPROC3_MKNOD(MKNOD3args)             = 11;*/
+/*             REMOVE3res NFSPROC3_REMOVE(REMOVE3args)           = 12;*/
+/*             RMDIR3res NFSPROC3_RMDIR(RMDIR3args)             = 13;*/
+/*             RENAME3res NFSPROC3_RENAME(RENAME3args)           = 14;*/
+/*             LINK3res NFSPROC3_LINK(LINK3args)               = 15;*/
+/*             READDIR3res NFSPROC3_READDIR(READDIR3args)         = 16;*/
+/*             READDIRPLUS3res NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17;*/
+/*             FSSTAT3res NFSPROC3_FSSTAT(FSSTAT3args)           = 18;*/
+/*             FSINFO3res NFSPROC3_FSINFO(FSINFO3args)           = 19;*/
+/*             PATHCONF3res NFSPROC3_PATHCONF(PATHCONF3args)       = 20;*/
+               COMMIT3res NFSPROC3_COMMIT(COMMIT3args)           = 21;
+       } = 3;
+} = 100003;
diff --git a/ronnie/nfsclient/nfs_client.c b/ronnie/nfsclient/nfs_client.c
new file mode 100644 (file)
index 0000000..fcc8fd9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include <memory.h> /* for memset */
+#include "nfs.h"
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+void *
+nfsproc3_null_3(void *argp, CLIENT *clnt)
+{
+       static char clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, NFSPROC3_NULL,
+               (xdrproc_t) xdr_void, (caddr_t) argp,
+               (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return ((void *)&clnt_res);
+}
+
+LOOKUP3res *
+nfsproc3_lookup_3(LOOKUP3args *argp, CLIENT *clnt)
+{
+       static LOOKUP3res clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, NFSPROC3_LOOKUP,
+               (xdrproc_t) xdr_LOOKUP3args, (caddr_t) argp,
+               (xdrproc_t) xdr_LOOKUP3res, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return (&clnt_res);
+}
+
+WRITE3res *
+nfsproc3_write_3(WRITE3args *argp, CLIENT *clnt)
+{
+       static WRITE3res clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, NFSPROC3_WRITE,
+               (xdrproc_t) xdr_WRITE3args, (caddr_t) argp,
+               (xdrproc_t) xdr_WRITE3res, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return (&clnt_res);
+}
+
+COMMIT3res *
+nfsproc3_commit_3(COMMIT3args *argp, CLIENT *clnt)
+{
+       static COMMIT3res clnt_res;
+
+       memset((char *)&clnt_res, 0, sizeof(clnt_res));
+       if (clnt_call (clnt, NFSPROC3_COMMIT,
+               (xdrproc_t) xdr_COMMIT3args, (caddr_t) argp,
+               (xdrproc_t) xdr_COMMIT3res, (caddr_t) &clnt_res,
+               TIMEOUT) != RPC_SUCCESS) {
+               return (NULL);
+       }
+       return (&clnt_res);
+}
diff --git a/ronnie/nfsclient/nfs_xdr.c b/ronnie/nfsclient/nfs_xdr.c
new file mode 100644 (file)
index 0000000..e8bfe8c
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "nfs.h"
+
+bool_t
+xdr_nfs_fh3 (XDR *xdrs, nfs_fh3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS3_FHSIZE))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_filename3 (XDR *xdrs, filename3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, objp, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_diropargs3 (XDR *xdrs, diropargs3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_nfs_fh3 (xdrs, &objp->dir))
+                return FALSE;
+        if (!xdr_filename3 (xdrs, &objp->name))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_ftype3 (XDR *xdrs, ftype3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_enum (xdrs, (enum_t *) objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_uint32 (XDR *xdrs, uint32 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_u_long (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_int32 (XDR *xdrs, int32 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_long (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_mode3 (XDR *xdrs, mode3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint32 (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_uid3 (XDR *xdrs, uid3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint32 (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_gid3 (XDR *xdrs, gid3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint32 (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_uint64 (XDR *xdrs, uint64 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_u_quad_t (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_size3 (XDR *xdrs, size3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint64 (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_fileid3 (XDR *xdrs, fileid3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint64 (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_specdata3 (XDR *xdrs, specdata3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint32 (xdrs, &objp->specdata1))
+                return FALSE;
+        if (!xdr_uint32 (xdrs, &objp->specdata2))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_nfstime3 (XDR *xdrs, nfstime3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint32 (xdrs, &objp->seconds))
+                return FALSE;
+        if (!xdr_uint32 (xdrs, &objp->nseconds))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_fattr3 (XDR *xdrs, fattr3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_ftype3 (xdrs, &objp->type))
+                return FALSE;
+        if (!xdr_mode3 (xdrs, &objp->mode))
+                return FALSE;
+        if (!xdr_uint32 (xdrs, &objp->nlink))
+                return FALSE;
+        if (!xdr_uid3 (xdrs, &objp->uid))
+                return FALSE;
+        if (!xdr_gid3 (xdrs, &objp->gid))
+                return FALSE;
+        if (!xdr_size3 (xdrs, &objp->size))
+                return FALSE;
+        if (!xdr_size3 (xdrs, &objp->used))
+                return FALSE;
+        if (!xdr_specdata3 (xdrs, &objp->rdev))
+                return FALSE;
+        if (!xdr_uint64 (xdrs, &objp->fsid))
+                return FALSE;
+        if (!xdr_fileid3 (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;
+}
+
+bool_t
+xdr_post_op_attr (XDR *xdrs, post_op_attr *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_bool (xdrs, &objp->attributes_follow))
+                return FALSE;
+       switch (objp->attributes_follow) {
+       case TRUE:
+                if (!xdr_fattr3 (xdrs, &objp->post_op_attr_u.attributes))
+                        return FALSE;
+               break;
+       case FALSE:
+               break;
+       default:
+               return FALSE;
+       }
+       return TRUE;
+}
+
+bool_t
+xdr_nfsstat3 (XDR *xdrs, nfsstat3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_enum (xdrs, (enum_t *) objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_stable_how (XDR *xdrs, stable_how *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_enum (xdrs, (enum_t *) objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_offset3 (XDR *xdrs, offset3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint64 (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_count3 (XDR *xdrs, count3 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_uint32 (xdrs, objp))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_wcc_attr (XDR *xdrs, wcc_attr *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_size3 (xdrs, &objp->size))
+                return FALSE;
+        if (!xdr_nfstime3 (xdrs, &objp->mtime))
+                return FALSE;
+        if (!xdr_nfstime3 (xdrs, &objp->ctime))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_pre_op_attr (XDR *xdrs, pre_op_attr *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_bool (xdrs, &objp->attributes_follow))
+                return FALSE;
+       switch (objp->attributes_follow) {
+       case TRUE:
+                if (!xdr_wcc_attr (xdrs, &objp->pre_op_attr_u.attributes))
+                        return FALSE;
+               break;
+       case FALSE:
+               break;
+       default:
+               return FALSE;
+       }
+       return TRUE;
+}
+
+bool_t
+xdr_wcc_data (XDR *xdrs, wcc_data *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_pre_op_attr (xdrs, &objp->before))
+                return FALSE;
+        if (!xdr_post_op_attr (xdrs, &objp->after))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_WRITE3args (XDR *xdrs, WRITE3args *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_nfs_fh3 (xdrs, &objp->file))
+                return FALSE;
+        if (!xdr_offset3 (xdrs, &objp->offset))
+                return FALSE;
+        if (!xdr_count3 (xdrs, &objp->count))
+                return FALSE;
+        if (!xdr_stable_how (xdrs, &objp->stable))
+                return FALSE;
+        if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_writeverf3 (XDR *xdrs, writeverf3 objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_opaque (xdrs, objp, NFS3_WRITEVERFSIZE))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_WRITE3resok (XDR *xdrs, WRITE3resok *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_wcc_data (xdrs, &objp->file_wcc))
+                return FALSE;
+        if (!xdr_count3 (xdrs, &objp->count))
+                return FALSE;
+        if (!xdr_stable_how (xdrs, &objp->committed))
+                return FALSE;
+        if (!xdr_writeverf3 (xdrs, objp->verf))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_WRITE3resfail (XDR *xdrs, WRITE3resfail *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_wcc_data (xdrs, &objp->file_wcc))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_WRITE3res (XDR *xdrs, WRITE3res *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_nfsstat3 (xdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!xdr_WRITE3resok (xdrs, &objp->WRITE3res_u.resok))
+                        return FALSE;
+               break;
+       default:
+                if (!xdr_WRITE3resfail (xdrs, &objp->WRITE3res_u.resfail))
+                        return FALSE;
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+xdr_LOOKUP3args (XDR *xdrs, LOOKUP3args *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_diropargs3 (xdrs, &objp->what))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_LOOKUP3resok (XDR *xdrs, LOOKUP3resok *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_nfs_fh3 (xdrs, &objp->object))
+                return FALSE;
+        if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
+                return FALSE;
+        if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_LOOKUP3resfail (XDR *xdrs, LOOKUP3resfail *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_LOOKUP3res (XDR *xdrs, LOOKUP3res *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_nfsstat3 (xdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!xdr_LOOKUP3resok (xdrs, &objp->LOOKUP3res_u.resok))
+                        return FALSE;
+               break;
+       default:
+                if (!xdr_LOOKUP3resfail (xdrs, &objp->LOOKUP3res_u.resfail))
+                        return FALSE;
+               break;
+       }
+       return TRUE;
+}
+
+bool_t
+xdr_COMMIT3args (XDR *xdrs, COMMIT3args *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_nfs_fh3 (xdrs, &objp->file))
+                return FALSE;
+        if (!xdr_offset3 (xdrs, &objp->offset))
+                return FALSE;
+        if (!xdr_count3 (xdrs, &objp->count))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_COMMIT3resok (XDR *xdrs, COMMIT3resok *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_wcc_data (xdrs, &objp->file_wcc))
+                return FALSE;
+        if (!xdr_writeverf3 (xdrs, objp->verf))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_COMMIT3resfail (XDR *xdrs, COMMIT3resfail *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_wcc_data (xdrs, &objp->file_wcc))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_COMMIT3res (XDR *xdrs, COMMIT3res *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_nfsstat3 (xdrs, &objp->status))
+                return FALSE;
+       switch (objp->status) {
+       case NFS3_OK:
+                if (!xdr_COMMIT3resok (xdrs, &objp->COMMIT3res_u.resok))
+                        return FALSE;
+               break;
+       default:
+                if (!xdr_COMMIT3resfail (xdrs, &objp->COMMIT3res_u.resfail))
+                        return FALSE;
+               break;
+       }
+       return TRUE;
+}
diff --git a/ronnie/nfsclient/nfsclient.c b/ronnie/nfsclient/nfsclient.c
new file mode 100644 (file)
index 0000000..158155e
--- /dev/null
@@ -0,0 +1,171 @@
+/* 
+   simple nfsclient
+
+   Copyright (C) Ronnie Sahlberg 2007
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include "mount.h"
+#include "nfs.h"
+
+static fhandle3 *
+get_mount_fh(const char *client, char *mntdir)
+{
+       CLIENT *clnt;
+       dirpath mountdir=mntdir;
+       mountres3 *mountres;
+       fhandle3 *mfh;
+       int i;
+
+       clnt = clnt_create(client, MOUNT_PROGRAM, MOUNT_V3, "tcp");
+       if (clnt == NULL) {
+               printf("ERROR: failed to connect to MOUNT daemon on %s\n", client);
+               exit(10);
+       }
+
+       mountres=mountproc3_mnt_3(&mountdir, clnt);
+       if (mountres == NULL) {
+               printf("ERROR: failed to call the MNT procedure\n");
+               exit(10);
+       }
+       if (mountres->fhs_status != MNT3_OK) {
+               printf("ERROR: Server returned error %d when trying to MNT\n",mountres->fhs_status);
+               exit(10);
+       }
+
+       mfh = malloc(sizeof(fhandle3));
+       mfh->fhandle3_len = mountres->mountres3_u.mountinfo.fhandle.fhandle3_len;
+       mfh->fhandle3_val = malloc(mountres->mountres3_u.mountinfo.fhandle.fhandle3_len);
+       memcpy(mfh->fhandle3_val, 
+               mountres->mountres3_u.mountinfo.fhandle.fhandle3_val,
+               mountres->mountres3_u.mountinfo.fhandle.fhandle3_len);
+
+       clnt_destroy(clnt);
+
+       printf("mount filehandle : %d ", mfh->fhandle3_len);
+       for (i=0;i<mfh->fhandle3_len;i++) {
+               printf("%02x", mfh->fhandle3_val[i]);
+       }
+       printf("\n");
+
+       return mfh;
+}
+
+
+static nfs_fh3 *
+lookup_fh(CLIENT *clnt, nfs_fh3 *dir, char *name)
+{
+       nfs_fh3 *fh;
+       LOOKUP3args l3args;
+       LOOKUP3res *l3res;
+       int i;
+
+       l3args.what.dir.data.data_len = dir->data.data_len;
+       l3args.what.dir.data.data_val = dir->data.data_val;
+       l3args.what.name = name;
+       l3res = nfsproc3_lookup_3(&l3args, clnt);               
+       if (l3res == NULL) {
+               printf("Failed to lookup file %s\n", "x.dat");
+               exit(10);
+       }
+       if (l3res->status != NFS3_OK) {
+               printf("lookup returned error %d\n", l3res->status);
+               exit(10);
+       }
+
+       fh = malloc(sizeof(nfs_fh3));
+       fh->data.data_len = l3res->LOOKUP3res_u.resok.object.data.data_len;
+       fh->data.data_val = malloc(fh->data.data_len);
+       memcpy(fh->data.data_val, 
+               l3res->LOOKUP3res_u.resok.object.data.data_val,
+               fh->data.data_len);
+
+       printf("file filehandle : %d ", fh->data.data_len);
+       for (i=0;i<fh->data.data_len;i++) {
+               printf("%02x", fh->data.data_val[i]);
+       }
+       printf("\n");
+
+       return fh;
+}
+
+/* return number of bytes weitten    or -1 if there was an error */
+static int
+write_data(CLIENT *clnt, nfs_fh3 *fh, offset3 offset, char *buffer, 
+               count3 count, enum stable_how stable)
+{
+       WRITE3args w3args;
+       WRITE3res *w3res;
+
+       w3args.file = *fh;
+       w3args.offset = offset;
+       w3args.count  = count;
+       w3args.stable = stable;
+       w3args.data.data_len = count;
+       w3args.data.data_val = buffer;
+       w3res = nfsproc3_write_3(&w3args, clnt);
+       if (w3res == NULL) {
+               return -1;
+       }
+       if (w3res->status != NFS3_OK) {
+               return -1;
+       }
+       return w3res->WRITE3res_u.resok.count;
+}
+
+
+static void
+commit_data(CLIENT *clnt, nfs_fh3 *fh)
+{
+       COMMIT3args c3args;
+       COMMIT3res *c3res;
+
+       c3args.file   = *fh;
+       c3args.offset = 0;
+       c3args.count  = 0;
+
+       c3res = nfsproc3_commit_3(&c3args, clnt);
+}
+
+int main(int argc, const char *argv[])
+{
+       CLIENT *clnt;
+       fhandle3 *mfh;
+       nfs_fh3 *fh;
+       char buffer[512];
+
+       /* get the filehandle for the mountpoint */
+       mfh = get_mount_fh("9.155.61.98", "/gpfs1/data");
+
+       /* connect to NFS */
+       clnt = clnt_create("9.155.61.98", NFS_PROGRAM, NFS_V3, "tcp");
+       if (clnt == NULL) {
+               printf("ERROR: failed to connect to NFS daemon on %s\n", "9.155.61.98");
+               exit(10);
+       }
+
+
+       /* get the file filehandle */
+       fh = lookup_fh(clnt, (nfs_fh3 *)mfh, "x.dat");
+
+       
+       if (write_data(clnt, fh, 1024, buffer, sizeof(buffer), UNSTABLE) == -1) {
+               printf("failed to write data\n");
+               exit(10);
+       }
+       commit_data(clnt, fh);
+
+       return 0;
+}
diff --git a/ronnie/nfsclient/nfsio.c b/ronnie/nfsclient/nfsio.c
new file mode 100644 (file)
index 0000000..b7cf570
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+  simulate IO and thread pattern in ntap sio test
+
+  Copyright (C) Andrew Tridgell <tridge@samba.org> 2007
+
+  Released under the GNU GPL version 2 or later
+*/
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE64_SOURCE
+#define _LARGE_FILES
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <getopt.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include "mount.h"
+#include "nfs.h"
+
+static size_t block_size = 8192;
+static off_t file_size = 1024*1024*(1024LL);
+static unsigned num_threads = 1;
+static const char *fname;
+static volatile unsigned *io_count;
+static volatile int run_finished;
+static unsigned runtime = 20;
+static bool sync_io;
+static int flush_blocks;
+
+/* filehandle for the mount */
+static fhandle3 *mfh;
+
+
+static fhandle3 *
+get_mount_fh(const char *client, char *mntdir)
+{
+       CLIENT *clnt;
+       dirpath mountdir=mntdir;
+       mountres3 *mountres;
+       fhandle3 *mfh;
+       int i;
+
+       clnt = clnt_create(client, MOUNT_PROGRAM, MOUNT_V3, "tcp");
+       if (clnt == NULL) {
+               printf("ERROR: failed to connect to MOUNT daemon on %s\n", client);
+               exit(10);
+       }
+
+       mountres=mountproc3_mnt_3(&mountdir, clnt);
+       if (mountres == NULL) {
+               printf("ERROR: failed to call the MNT procedure\n");
+               exit(10);
+       }
+       if (mountres->fhs_status != MNT3_OK) {
+               printf("ERROR: Server returned error %d when trying to MNT\n",mountres->fhs_status);
+               exit(10);
+       }
+
+       mfh = malloc(sizeof(fhandle3));
+       mfh->fhandle3_len = mountres->mountres3_u.mountinfo.fhandle.fhandle3_len;
+       mfh->fhandle3_val = malloc(mountres->mountres3_u.mountinfo.fhandle.fhandle3_len);
+       memcpy(mfh->fhandle3_val, 
+               mountres->mountres3_u.mountinfo.fhandle.fhandle3_val,
+               mountres->mountres3_u.mountinfo.fhandle.fhandle3_len);
+
+       clnt_destroy(clnt);
+
+       printf("mount filehandle : %d ", mfh->fhandle3_len);
+       for (i=0;i<mfh->fhandle3_len;i++) {
+               printf("%02x", mfh->fhandle3_val[i]);
+       }
+       printf("\n");
+
+       return mfh;
+}
+
+static nfs_fh3 *
+lookup_fh(CLIENT *clnt, nfs_fh3 *dir, char *name)
+{
+       nfs_fh3 *fh;
+       LOOKUP3args l3args;
+       LOOKUP3res *l3res;
+       int i;
+
+       l3args.what.dir.data.data_len = dir->data.data_len;
+       l3args.what.dir.data.data_val = dir->data.data_val;
+       l3args.what.name = name;
+       l3res = nfsproc3_lookup_3(&l3args, clnt);               
+       if (l3res == NULL) {
+               printf("Failed to lookup file %s\n", name);
+               exit(10);
+       }
+       if (l3res->status != NFS3_OK) {
+               printf("lookup returned error %d\n", l3res->status);
+               exit(10);
+       }
+
+       fh = malloc(sizeof(nfs_fh3));
+       fh->data.data_len = l3res->LOOKUP3res_u.resok.object.data.data_len;
+       fh->data.data_val = malloc(fh->data.data_len);
+       memcpy(fh->data.data_val, 
+               l3res->LOOKUP3res_u.resok.object.data.data_val,
+               fh->data.data_len);
+
+       printf("file filehandle : %d ", fh->data.data_len);
+       for (i=0;i<fh->data.data_len;i++) {
+               printf("%02x", fh->data.data_val[i]);
+       }
+       printf("\n");
+
+       return fh;
+}
+
+/* return number of bytes written    or -1 if there was an error */
+static int
+write_data(CLIENT *clnt, nfs_fh3 *fh, offset3 offset, char *buffer, 
+               count3 count, enum stable_how stable)
+{
+       WRITE3args w3args;
+       WRITE3res *w3res;
+
+       w3args.file = *fh;
+       w3args.offset = offset;
+       w3args.count  = count;
+       w3args.stable = stable;
+       w3args.data.data_len = count;
+       w3args.data.data_val = buffer;
+       w3res = nfsproc3_write_3(&w3args, clnt);
+       if (w3res == NULL) {
+               return -1;
+       }
+       if (w3res->status != NFS3_OK) {
+               return -1;
+       }
+       return w3res->WRITE3res_u.resok.count;
+}
+
+static void
+commit_data(CLIENT *clnt, nfs_fh3 *fh)
+{
+       COMMIT3args c3args;
+       COMMIT3res *c3res;
+
+       c3args.file   = *fh;
+       c3args.offset = 0;
+       c3args.count  = 0;
+
+       c3res = nfsproc3_commit_3(&c3args, clnt);
+}
+
+static void run_child(int id)
+{
+       unsigned num_blocks = file_size / block_size;
+       char *buf;
+       CLIENT *clnt;
+       nfs_fh3 *fh;
+       enum stable_how stable = UNSTABLE;
+
+       if (sync_io) {
+               stable = FILE_SYNC;
+       }
+
+       /* connect to NFS */
+       clnt = clnt_create("9.155.61.98", NFS_PROGRAM, NFS_V3, "tcp");
+       if (clnt == NULL) {
+               printf("ERROR: failed to connect to NFS daemon on %s\n", "9.155.61.98");
+               exit(10);
+       }
+
+
+       /* get the file filehandle */
+       fh = lookup_fh(clnt, (nfs_fh3 *)mfh, fname);
+
+       buf = malloc(block_size);
+       memset(buf, 1, block_size);
+       
+       srandom(id ^ random());
+
+       while (!run_finished) {
+               unsigned offset = random() % num_blocks;
+               if (write_data(clnt, fh, offset*(off_t)block_size, buf, block_size, stable) != block_size) {
+                       printf("write_data failed!\n");
+                       exit(1);
+               }
+               io_count[id]++;
+               if (flush_blocks && io_count[id] % flush_blocks == 0) {
+                       commit_data(clnt, fh);
+               }
+       }
+
+       return;
+}
+
+/*
+  create a thread with initial function fn(private)
+*/
+static pthread_t thread_start(void (*fn)(int), int id)
+{
+       pthread_t thread_id;
+       pthread_attr_t thread_attr;
+       int rc;
+       typedef void *(*thread_fn_t)(void *);
+       pthread_attr_init(&thread_attr);
+       pthread_attr_setdetachstate(&thread_attr, 0);
+       rc = pthread_create(&thread_id, &thread_attr, (thread_fn_t)fn, (void *)id);
+       pthread_attr_destroy(&thread_attr);
+
+       if (rc != 0) {
+               fprintf(stderr,"Thread create failed for id %d\n", id);
+               exit(1);
+       }
+
+       return thread_id;
+}
+
+/* wait for a thread to exit */
+static int thread_join(pthread_t id)
+{
+       return pthread_join(id, NULL);
+}
+
+static void run_test(void)
+{
+       int i;
+       pthread_t *tids;
+       time_t started = 0;
+       unsigned warmup_count=0;
+       unsigned total;
+
+       /* get the filehandle for the mountpoint */
+       mfh = get_mount_fh("9.155.61.98", "/gpfs1/data");
+
+       tids = calloc(num_threads, sizeof(pthread_t));
+       io_count = calloc(num_threads, sizeof(unsigned));
+
+
+       for (i=0;i<num_threads;i++) {
+               tids[i] = thread_start(run_child, i);
+       }
+       
+       while (1) {
+               int in_warmup=0;
+               time_t t = time(NULL);
+               total = 0;
+
+               sleep(1);
+               if (started == 0) {
+                       in_warmup = 1;
+                       started = t;
+               }
+               for (i=0;i<num_threads;i++) {
+                       unsigned count = io_count[i];
+                       printf("%6u ", count);
+                       if (count == 0) {
+                               started = 0;
+                       }
+                       total += count;
+               }
+               printf("    total: %6u ", total);
+               if (started != 0 && started != t) {
+                       printf(" %3u seconds  %.0f kbytes/s\n", 
+                              (unsigned)(t - started),
+                              block_size*(total-warmup_count)/(1024.0*(t-started)));
+               } else {
+                       printf("warmup\n");
+               }
+               if (started != 0) {
+                       if (in_warmup) {
+                               printf("Starting run\n");
+                               warmup_count = total;
+                       }
+                       if (time(NULL) - started >= runtime) {
+                               break;
+                       }
+               }
+       }
+
+       run_finished = 1;
+       printf("Run finished - cleaning up\n");
+       for (i=0;i<num_threads;i++) {
+               thread_join(tids[i]);
+               printf("finished thread %d\n", i);
+       }
+
+       printf("Throughput %.0f kbytes/s\n", 
+              block_size*(total-warmup_count)/(1024.0*runtime));
+}
+
+static void usage(void)
+{
+       printf("Usage: threadio <options> <filename>\n");
+       printf("Options:\n");
+       printf(" -b <size>     block size\n");
+       printf(" -f <size>     file size\n");
+       printf(" -n <number>   number of threads\n");   
+       printf(" -t <time>     runtime in seconds\n");
+       printf(" -F <numios>   fsync every numios blocks per thread\n");
+       printf(" -S            use FILE_SYNC for writes\n");
+}
+
+
+int main(int argc, char * const argv[])
+{
+       int opt;
+
+       setlinebuf(stdout);
+       
+       while ((opt = getopt(argc, argv, "b:f:n:t:1F:SD")) != -1) {
+               switch (opt) {
+               case 'b':
+                       block_size = strtoul(optarg, NULL, 0);
+                       break;
+               case 'f':
+                       file_size = strtoull(optarg, NULL, 0);
+                       break;
+               case 'n':
+                       num_threads = strtoul(optarg, NULL, 0);
+                       break;
+               case 't':
+                       runtime = strtoul(optarg, NULL, 0);
+                       break;
+               case 'S':
+                       sync_io = true;
+                       break;
+               case 'F':
+                       flush_blocks = strtoul(optarg, NULL, 0);
+                       break;
+               default:
+                       printf("Invalid option '%c'\n", opt);
+                       usage();
+                       exit(1);
+               }
+       }
+
+       argv += optind;
+       argc -= optind;
+
+       if (argc < 1) {
+               usage();
+               exit(1);
+       }
+
+       fname = argv[0];
+
+       srandom(time(NULL));
+
+       run_test();
+       return 0;
+}
diff --git a/ronnie/nfsclient/threadio.c b/ronnie/nfsclient/threadio.c
new file mode 100644 (file)
index 0000000..3b903be
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+  simulate IO and thread pattern in ntap sio test
+
+  Copyright (C) Andrew Tridgell <tridge@samba.org> 2007
+
+  Released under the GNU GPL version 2 or later
+*/
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE64_SOURCE
+#define _LARGE_FILES
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <getopt.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <stdbool.h>
+
+static size_t block_size = 8192;
+static off_t file_size = 1024*1024*(1024LL);
+static unsigned num_threads = 1;
+static const char *fname;
+static volatile unsigned *io_count;
+static volatile int run_finished;
+static unsigned runtime = 20;
+static bool sync_io;
+static bool direct_io;
+static int flush_blocks;
+static bool one_fd;
+
+static int shared_fd;
+
+static int open_file(void) 
+{
+       unsigned flags = O_RDWR|O_CREAT|O_LARGEFILE;
+       int fd;
+
+       if (sync_io) flags |= O_SYNC;
+       if (direct_io) flags |= O_DIRECT;
+       fd = open(fname, flags, 0644);
+       if (fd == -1) {
+               perror(fname);
+               exit(1);
+       }
+       return fd;
+}
+
+static void run_child(int id)
+{
+       unsigned num_blocks = file_size / block_size;
+       char *buf;
+       int fd;
+
+       if (!one_fd) {
+               fd = open_file();
+       } else {
+               fd = shared_fd;
+       }
+
+       buf = malloc(block_size);
+       memset(buf, 1, block_size);
+       
+       srandom(id ^ random());
+
+       while (!run_finished) {
+               unsigned offset = random() % num_blocks;
+               if (pwrite(fd, buf, block_size, offset*(off_t)block_size) != block_size) {
+                       perror("pwrite");
+                       printf("pwrite failed!\n");
+                       exit(1);
+               }
+               io_count[id]++;
+               if (flush_blocks && io_count[id] % flush_blocks == 0) {
+                       fsync(fd);
+               }
+       }
+
+       close(fd);
+       return;
+}
+
+/*
+  create a thread with initial function fn(private)
+*/
+static pthread_t thread_start(void (*fn)(int), int id)
+{
+       pthread_t thread_id;
+       pthread_attr_t thread_attr;
+       int rc;
+       typedef void *(*thread_fn_t)(void *);
+       pthread_attr_init(&thread_attr);
+       pthread_attr_setdetachstate(&thread_attr, 0);
+       rc = pthread_create(&thread_id, &thread_attr, (thread_fn_t)fn, (void *)id);
+       pthread_attr_destroy(&thread_attr);
+
+       if (rc != 0) {
+               fprintf(stderr,"Thread create failed for id %d\n", id);
+               exit(1);
+       }
+
+       return thread_id;
+}
+
+/* wait for a thread to exit */
+static int thread_join(pthread_t id)
+{
+       return pthread_join(id, NULL);
+}
+
+
+static void run_test(void)
+{
+       int i;
+       pthread_t *tids;
+       time_t started = 0;
+       unsigned warmup_count=0;
+       unsigned total;
+
+       tids = calloc(num_threads, sizeof(pthread_t));
+       io_count = calloc(num_threads, sizeof(unsigned));
+
+       if (one_fd) {
+               shared_fd = open_file();
+       }
+
+
+       for (i=0;i<num_threads;i++) {
+               tids[i] = thread_start(run_child, i);
+       }
+       
+       while (1) {
+               int in_warmup=0;
+               time_t t = time(NULL);
+               total = 0;
+
+               sleep(1);
+               if (started == 0) {
+                       in_warmup = 1;
+                       started = t;
+               }
+               for (i=0;i<num_threads;i++) {
+                       unsigned count = io_count[i];
+                       printf("%6u ", count);
+                       if (count == 0) {
+                               started = 0;
+                       }
+                       total += count;
+               }
+               printf("    total: %6u ", total);
+               if (started != 0 && started != t) {
+                       printf(" %3u seconds  %.0f kbytes/s\n", 
+                              (unsigned)(t - started),
+                              block_size*(total-warmup_count)/(1024.0*(t-started)));
+               } else {
+                       printf("warmup\n");
+               }
+               if (started != 0) {
+                       if (in_warmup) {
+                               printf("Starting run\n");
+                               warmup_count = total;
+                       }
+                       if (time(NULL) - started >= runtime) {
+                               break;
+                       }
+               }
+       }
+
+       run_finished = 1;
+       printf("Run finished - cleaning up\n");
+       for (i=0;i<num_threads;i++) {
+               thread_join(tids[i]);
+               printf("finished thread %d\n", i);
+       }
+
+       printf("Throughput %.0f kbytes/s\n", 
+              block_size*(total-warmup_count)/(1024.0*runtime));
+}
+
+static void usage(void)
+{
+       printf("Usage: threadio <options> <filename>\n");
+       printf("Options:\n");
+       printf(" -b <size>     block size\n");
+       printf(" -f <size>     file size\n");
+       printf(" -n <number>   number of threads\n");   
+       printf(" -t <time>     runtime in seconds\n");
+       printf(" -F <numios>   fsync every numios blocks per thread\n");
+       printf(" -S            use O_SYNC on open\n");
+       printf(" -D            use O_DIRECT on open\n");
+       printf(" -1            use one file descriptor for all threads\n");
+}
+
+
+int main(int argc, char * const argv[])
+{
+       int opt;
+
+       setlinebuf(stdout);
+       
+       while ((opt = getopt(argc, argv, "b:f:n:t:1F:SD")) != -1) {
+               switch (opt) {
+               case 'b':
+                       block_size = strtoul(optarg, NULL, 0);
+                       break;
+               case 'f':
+                       file_size = strtoull(optarg, NULL, 0);
+                       break;
+               case 'n':
+                       num_threads = strtoul(optarg, NULL, 0);
+                       break;
+               case 't':
+                       runtime = strtoul(optarg, NULL, 0);
+                       break;
+               case 'S':
+                       sync_io = true;
+                       break;
+               case 'D':
+                       direct_io = true;
+                       break;
+               case 'F':
+                       flush_blocks = strtoul(optarg, NULL, 0);
+                       break;
+               case '1':
+                       one_fd = true;
+                       break;
+               default:
+                       printf("Invalid option '%c'\n", opt);
+                       usage();
+                       exit(1);
+               }
+       }
+
+       argv += optind;
+       argc -= optind;
+
+       if (argc < 1) {
+               usage();
+               exit(1);
+       }
+
+       fname = argv[0];
+
+       srandom(time(NULL));
+
+       run_test();
+       return 0;
+}
diff --git a/ronnie/scsi_readdisk/scsi_readdisk.c b/ronnie/scsi_readdisk/scsi_readdisk.c
new file mode 100644 (file)
index 0000000..da41d80
--- /dev/null
@@ -0,0 +1,428 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <scsi/sg.h>
+
+#define SCSI_TIMEOUT 5000 /* ms */
+
+
+static struct timeval tp1,tp2;
+static size_t num_blocks = 1;
+static int do_sync = 0;
+static int do_random = 0;
+
+static void start_timer()
+{
+       gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+       gettimeofday(&tp2,NULL);
+       return((tp2.tv_sec - tp1.tv_sec) + 
+              (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+}
+
+const char *sensetable[16]={
+       "no sense",
+       "recovered error",
+       "not ready",
+       "medium error",
+       "hardware error",
+       "illegal request",
+       "unit attention",
+       "data protect",
+       "blank check",
+       "vendor specific",
+       "copy aborted",
+       "aboreted command",
+       "unknown",
+       "unknown",
+       "unknown",
+       "unknown"
+};
+
+void print_sense_data(unsigned char *sense, int sense_len)
+{
+       int i;
+       unsigned char asc, ascq;
+
+       printf("Device returned sense information\n");
+       if(sense[0]==0x70){
+               printf("filemark:%d eom:%d ili:%d  sense-key:0x%02x (%s)\n",
+                       !!(sense[2]&0x80),
+                       !!(sense[2]&0x40),
+                       !!(sense[2]&0x20),
+                       sense[2]&0x0f,
+                       sensetable[sense[2]&0x0f]);
+               printf("command specific info: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+                       sense[8],sense[9],sense[10],sense[11]);
+
+               asc=sense[12];
+               printf("additional sense code:0x%02x\n", asc);
+
+               ascq=sense[13];
+               printf("additional sense code qualifier:0x%02x\n", ascq);
+
+               printf("field replacable unit code:0x%02x\n", sense[14]);
+
+               if((asc==0x20)&&(ascq==0x00))
+                       printf("INVALID COMMAND OPERATION CODE\n");
+       }
+
+       printf("Sense data:\n");
+       for(i=0;i<sense_len;i++){
+               printf("0x%02x ", sense[i]);
+               if((i%8)==7)printf("\n");
+       }
+       printf("\n");
+}
+
+int open_scsi_device(const char *dev)
+{
+       int fd, vers;
+
+       if((fd=open(dev, O_RDWR))<0){
+               printf("ERROR could not open device %s\n", dev);
+               return -1;
+       }
+       if ((ioctl(fd, SG_GET_VERSION_NUM, &vers) < 0) || (vers < 30000)) {
+               printf("/dev is not an sg device, or old sg driver\n");
+               close(fd);
+               return -1;
+       }
+
+       return fd;
+}
+
+int scsi_io(int fd, unsigned char *cdb, unsigned char cdb_size, int xfer_dir, unsigned char *data, unsigned int *data_size, unsigned char *sense, unsigned int *sense_len)
+{
+       sg_io_hdr_t io_hdr;
+
+       memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+       io_hdr.interface_id = 'S';
+
+       /* CDB */
+       io_hdr.cmdp = cdb;
+       io_hdr.cmd_len = cdb_size;
+
+       /* Where to store the sense_data, if there was an error */
+       io_hdr.sbp = sense;
+       io_hdr.mx_sb_len = *sense_len;
+       *sense_len=0;
+
+       /* Transfer direction, either in or out. Linux does not yet
+          support bidirectional SCSI transfers ?
+        */
+       io_hdr.dxfer_direction = xfer_dir;
+
+       /* Where to store the DATA IN/OUT from the device and how big the
+          buffer is
+        */
+       io_hdr.dxferp = data;
+       io_hdr.dxfer_len = *data_size;
+
+       /* SCSI timeout in ms */
+       io_hdr.timeout = SCSI_TIMEOUT;
+
+
+       if(ioctl(fd, SG_IO, &io_hdr) < 0){
+               perror("SG_IO ioctl failed");
+               return -1;
+       }
+
+       /* now for the error processing */
+       if((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK){
+               if(io_hdr.sb_len_wr > 0){
+                       *sense_len=io_hdr.sb_len_wr;
+                       return 0;
+               }
+       }
+       if(io_hdr.masked_status){
+               printf("status=0x%x\n", io_hdr.status);
+               printf("masked_status=0x%x\n", io_hdr.masked_status);
+               return -2;
+       }
+       if(io_hdr.host_status){
+               printf("host_status=0x%x\n", io_hdr.host_status);
+               return -3;
+       }
+       if(io_hdr.driver_status){
+               printf("driver_status=0x%x\n", io_hdr.driver_status);
+               return -4;
+       }
+
+       return 0;
+}
+
+unsigned long read_uint32(unsigned char *data)
+{
+       unsigned long val;
+
+       val = data[0];
+       val <<= 8;
+       val |= data[1];
+       val <<= 8;
+       val |= data[2];
+       val <<= 8;
+       val |= data[3];
+
+       return val;
+}
+
+struct scsi_inquiry_data {
+       int peripheral_qualifier;
+#define SCSI_DEV_TYPE_SBC      0x00
+       int peripheral_device_type;
+       int removable;
+};
+
+struct scsi_inquiry_data *scsi_inquiry(int fd)
+{
+       unsigned char cdb[]={0x12,0,0,0,0,0};
+
+       unsigned int data_size=96;
+       unsigned char data[data_size];
+
+       unsigned int sense_len=32;
+       unsigned char sense[sense_len];
+
+       int res, alen, i;
+
+       static struct scsi_inquiry_data inq;
+
+       cdb[3]=(data_size>>8)&0xff;
+       cdb[4]=data_size&0xff;
+
+
+       res=scsi_io(fd, cdb, sizeof(cdb), SG_DXFER_FROM_DEV, data, &data_size, sense, &sense_len);
+       if(res){
+               printf("SCSI_IO failed\n");
+               return NULL;
+       }
+       if(sense_len){
+               print_sense_data(sense, sense_len);
+               return NULL;
+       }
+
+       /* Peripheral Qualifier */
+       inq.peripheral_qualifier = data[0]&0xe0;
+
+       /* Peripheral Device Type */
+       inq.peripheral_device_type = data[0]&0x1f;
+
+
+       /* RMB */
+       inq.removable = data[1]&0x80;
+
+       return &inq;
+}
+
+
+struct scsi_capacity_data {
+       unsigned long blocks;
+       unsigned long blocksize;
+};
+
+struct scsi_capacity_data *scsi_read_capacity10(int fd)
+{
+       unsigned char cdb[]={0x25,0,0,0,0,0,0,0,0,0};
+
+       unsigned int data_size=96;
+       unsigned char data[data_size];
+
+       unsigned int sense_len=32;
+       unsigned char sense[sense_len];
+
+       int res, alen, i;
+       static struct scsi_capacity_data capacity;
+
+       res=scsi_io(fd, cdb, sizeof(cdb), SG_DXFER_FROM_DEV, data, &data_size, sense, &sense_len);
+       if(res){
+               printf("SCSI_IO failed\n");
+               return NULL;
+       }
+       if(sense_len){
+               print_sense_data(sense, sense_len);
+               return NULL;
+       }
+
+       capacity.blocks    = read_uint32(&data[0]);
+       capacity.blocksize = read_uint32(&data[4]);
+
+       return &capacity;
+}
+
+#define READ_FUA    0x04
+#define REAF_FUA_NV 0x02
+/* If READ_FUA is not set   the device may return data from cache
+   if it is set  the device must read the data from medium
+*/
+unsigned char *scsi_read10(int fd, unsigned long lba, unsigned short len, unsigned char fua)
+{
+       unsigned char cdb[]={0x28,0,0,0,0,0,0,0,0,0};
+
+       unsigned int data_size=len*512;
+
+       unsigned int sense_len=32;
+       unsigned char sense[sense_len];
+       int res, alen, i;
+       char *buf;
+
+       buf = malloc(len * 512);
+       if (!buf) {
+               printf("Malloc of %d failed\n", len * 512);
+               exit(1);
+       }
+       /* allow device to return data from cache or force a read from the medium ?*/
+       cdb[1] = fua;
+
+
+       /* lba */
+       cdb[2] = (lba>>24)&0xff;
+       cdb[3] = (lba>>16)&0xff;
+       cdb[4] = (lba>> 8)&0xff;
+       cdb[5] = (lba    )&0xff;
+
+       /* number of blocks */
+       cdb[7] = (len>>8)&0xff;
+       cdb[8] = (len   )&0xff;
+
+       res=scsi_io(fd, cdb, sizeof(cdb), SG_DXFER_FROM_DEV, buf, &data_size, sense, &sense_len);
+       if(res){
+               printf("SCSI_IO failed\n");
+               return NULL;
+       }
+       if(sense_len){
+               print_sense_data(sense, sense_len);
+               return NULL;
+       }
+
+       return buf;
+}
+
+static void read_disk(int fd, struct scsi_capacity_data *capacity)
+{
+       static double total, thisrun;
+       unsigned char *buf;
+       unsigned long offset = 0;
+
+       total = 0;
+       while (1) {
+               if (do_random) {
+                       offset = random() % (capacity->blocks - num_blocks);
+               } else {
+                       offset += num_blocks;
+               }
+               buf = scsi_read10(fd, offset, num_blocks, do_sync);
+               if (buf == NULL) {
+                       printf("read failure\n");
+                       exit(0);
+               }
+               free(buf);
+
+               total += num_blocks*512;
+               thisrun += num_blocks*512;
+               if (end_timer() >= 1.0) {
+                       printf("%d MB    %g MB/sec\n", 
+                              (int)(total/1.0e6),
+                              (thisrun*1.0e-6)/end_timer());
+                       start_timer();
+                       thisrun = 0;
+               }
+       }
+}
+
+
+static void usage(void)
+{
+       printf("\n" \
+"readfiles - reads from a list of files, showing read throughput\n" \
+"\n" \
+"Usage: readfiles [options] <files>\n" \
+"\n" \
+"Options:\n" \
+"    -B size        number of 512-byte blocks per i/o\n" \
+"    -S             force device to bypass any read cache\n" \
+"    -R             random read\n" \
+"");
+}
+
+int main(int argc, char *argv[])
+{
+       int i;
+       extern char *optarg;
+       extern int optind;
+       int c;
+       int fd;
+       struct scsi_inquiry_data *inq_data;
+       struct scsi_capacity_data *capacity;
+
+
+       while ((c = getopt(argc, argv, "B:h:SR")) != -1) {
+               switch (c) {
+               case 'B':
+                       num_blocks = strtol(optarg, NULL, 0);
+                       break;
+               case 'S':
+                       do_sync = READ_FUA;
+                       break;
+               case 'R':
+                       do_random = 1;
+                       break;
+               case 'h':
+               default:
+                       usage();
+                       exit(1);
+               }
+       }
+
+       argc -= optind;
+       argv += optind;
+
+       if (argc == 0) {
+               usage();
+               exit(1);
+       }
+
+       /* open the scsi device */
+       fd = open_scsi_device(argv[0]);
+       if (fd == -1) {
+               perror(argv[0]);
+               exit(10);
+       }
+
+       /* read inq data and make sure it is a DISK device   so that we will
+          use the correct scsi protocol later
+       */
+       inq_data = scsi_inquiry(fd);
+       if (inq_data == NULL) {
+               printf("Failed to read INQ data from device\n");
+               exit(10);
+       }
+       if (inq_data->peripheral_device_type != SCSI_DEV_TYPE_SBC) {
+               printf("Not a SCSI disk\n");
+               exit(10);
+       }
+
+       /* get size of the device in number of 512 byte blocks */
+       capacity = scsi_read_capacity10(fd);
+       if (capacity == NULL) {
+               printf("Failed to read capacity from device\n");
+               exit(10);
+       }
+
+
+       srandom(time(NULL));
+       start_timer();
+
+       read_disk(fd, capacity);
+
+       return 0;
+}
+