X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=nfs3%2Fsynclient.c;h=4246f420bb5cd14421c4ae22b65021e33ec91a78;hb=8ff0fd08d6e1cc97cdb7e94b7cd97dc28c29e674;hp=d96ae13a8dfdbed89e2dd598db9a28ea1c162ff5;hpb=aa3638792c059633e2b84d42c2d41bdf17555381;p=bluesky.git diff --git a/nfs3/synclient.c b/nfs3/synclient.c index d96ae13..4246f42 100644 --- a/nfs3/synclient.c +++ b/nfs3/synclient.c @@ -3,7 +3,29 @@ * Copyright (C) 2009 The Regents of the University of California * Written by Michael Vrable * - * TODO: Licensing + * 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 REGENTS 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 REGENTS 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. */ /* Synthetic client for benchmarking: a tool for directly generating NFS @@ -35,6 +57,9 @@ /* 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; @@ -85,8 +110,12 @@ typedef struct { 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; @@ -125,7 +154,7 @@ static void do_write(NFSConnection *conn, const char *buf, size_t len) } 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; @@ -173,13 +202,18 @@ static void process_reply(NFSConnection *nfs, GString *msg) } 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, @@ -250,7 +284,7 @@ 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); @@ -260,13 +294,61 @@ static gboolean read_handler(GIOChannel *channel, 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 < 8; i++) { + for (i = 0; i < threads; i++) { char buf[64]; struct diropargs3 lookup; uint64_t rootfh = GUINT64_TO_BE(1); @@ -280,7 +362,7 @@ static gboolean idle_handler(gpointer data) 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); } @@ -336,6 +418,10 @@ int main(int argc, char *argv[]) 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");