/* Maximum size of a single RPC message that we will accept (8 MB). */
#define MAX_RPC_MSGSIZE (8 << 20)
+int threads;
+int completed = 0;
+
struct rpc_reply {
uint32_t xid;
uint32_t type;
GHashTable *xid_table;
} NFSConnection;
+
+typedef void (*NFSFunc)(NFSConnection *nfs,
+ gpointer user_data, const char *reply, size_t len);
+
typedef struct {
- GFunc callback;
+ NFSFunc callback;
gpointer user_data;
int64_t start, end;
} CallInfo;
}
static void send_rpc(NFSConnection *nfs, int proc, GString *msg,
- GFunc completion_handler, gpointer user_data)
+ NFSFunc completion_handler, gpointer user_data)
{
static int xid_count = 0;
struct rpc_call_header header;
}
info->end = now_hires();
- g_print("Call(XID = %d) duration: %"PRIi64" ns\n",
- xid, info->end - info->start);
+ printf("XID %d: Time = %"PRIi64"\n", xid, info->end - info->start);
if (info->callback != NULL)
- info->callback(nfs, info->user_data);
+ info->callback(nfs, info->user_data,
+ msg->str + sizeof(*reply), msg->len - sizeof(*reply));
g_hash_table_remove(nfs->xid_table, key);
g_free(info);
+
+ completed++;
+ if (completed == 5 * threads) {
+ g_main_loop_quit(main_loop);
+ }
}
static gboolean read_handler(GIOChannel *channel,
/* We were reading in the fragment body. */
nfs->frag_len -= bytes_read;
- if (nfs->frag_len = 0x80000000) {
+ if (nfs->frag_len == 0x80000000) {
process_reply(nfs, nfs->msgbuf);
nfs->frag_len = 0;
g_string_set_size(nfs->msgbuf, 0);
return TRUE;
}
+static void send_read_requests(NFSConnection *nfs, const struct nfs_fh3 *fh)
+{
+ int i;
+
+ g_print("Sending read requests...\n");
+ for (i = 0; i < 4; i++) {
+ char buf[64];
+ struct read3args read;
+ memcpy(&read.file, fh, sizeof(struct nfs_fh3));
+ read.offset = (1 << 20) * i;
+ read.count = (1 << 20);
+
+ GString *str = g_string_new("");
+ XDR xdr;
+ xdr_string_create(&xdr, str, XDR_ENCODE);
+ xdr_read3args(&xdr, &read);
+ send_rpc(nfs, NFSPROC3_READ, str, NULL, NULL);
+ g_string_free(str, TRUE);
+ }
+}
+
+static void store_fh(NFSConnection *nfs, gpointer user_data,
+ const char *reply, size_t len)
+{
+ struct lookup3res res;
+ XDR xdr;
+ memset(&res, 0, sizeof(res));
+ xdrmem_create(&xdr, (char *)reply, len, XDR_DECODE);
+ if (!xdr_lookup3res(&xdr, &res)) {
+ g_print("Decode error for lookup3res!\n");
+ return;
+ }
+ if (res.status != NFS3_OK) {
+ g_print("Response not NFS3_OK\n");
+ return;
+ }
+
+ struct nfs_fh3 *fh = g_new0(struct nfs_fh3, 1);
+ fh->data.data_len = res.lookup3res_u.resok.object.data.data_len;
+ fh->data.data_val = g_memdup(res.lookup3res_u.resok.object.data.data_val,
+ fh->data.data_len);
+
+ xdr.x_op = XDR_FREE;
+ xdr_lookup3res(&xdr, &res);
+
+ send_read_requests(nfs, fh);
+}
+
static gboolean idle_handler(gpointer data)
{
NFSConnection *nfs = (NFSConnection *)data;
int i;
g_print("Sending requests...\n");
- for (i = 0; i < 64; i++) {
+ for (i = 0; i < threads; i++) {
char buf[64];
struct diropargs3 lookup;
uint64_t rootfh = GUINT64_TO_BE(1);
XDR xdr;
xdr_string_create(&xdr, str, XDR_ENCODE);
xdr_diropargs3(&xdr, &lookup);
- send_rpc(nfs, NFSPROC3_LOOKUP, str, NULL, NULL);
+ send_rpc(nfs, NFSPROC3_LOOKUP, str, store_fh, NULL);
g_string_free(str, TRUE);
}
g_set_prgname("synclient");
g_print("Launching synthetic NFS RPC client...\n");
+ threads = 8;
+ if (argc > 1)
+ threads = atoi(argv[1]);
+
main_loop = g_main_loop_new(NULL, FALSE);
nfs_connect("niniel.sysnet.ucsd.edu");