From 9cb49494c7b5ef25ccd9ae5e2e5ddc57e4d0c1cd Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Thu, 2 Jun 2016 09:12:53 +0200 Subject: [PATCH] pdu: drop the rpc->encodebuf the only call thar really needs a big encodebuf is WRITE. So give each PDU its private encodebuf. This avoids the need to memcpy the data from the static rpc->encodebuf to the pdu->outdata.data. Signed-off-by: Peter Lieven --- include/libnfs-private.h | 7 +++---- include/nfsc/libnfs-raw.h | 2 +- lib/init.c | 14 -------------- lib/pdu.c | 25 ++++++++++++++----------- nfs/nfs.c | 4 ++-- 5 files changed, 20 insertions(+), 32 deletions(-) diff --git a/include/libnfs-private.h b/include/libnfs-private.h index 2ec48c2..6af8f46 100644 --- a/include/libnfs-private.h +++ b/include/libnfs-private.h @@ -82,6 +82,8 @@ struct rpc_queue { #define HASHES 1024 #define NFS_RA_TIMEOUT 5 #define NFS_MAX_XFER_SIZE (1024 * 1024) +#define ZDR_ENCODE_OVERHEAD 1024 +#define ZDR_ENCODEBUF_MINSIZE 4096 struct rpc_context { uint32_t magic; @@ -97,10 +99,6 @@ struct rpc_context { struct AUTH *auth; uint32_t xid; - /* buffer used for encoding RPC PDU */ - char *encodebuf; - int encodebuflen; - struct rpc_queue outqueue; struct sockaddr_storage udp_src; struct rpc_queue waitpdu[HASHES]; @@ -156,6 +154,7 @@ void rpc_return_to_queue(struct rpc_queue *q, struct rpc_pdu *pdu); unsigned int rpc_hash_xid(uint32_t xid); struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_bufsize); +struct rpc_pdu *rpc_allocate_pdu2(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_bufsize, size_t alloc_hint); void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu); int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu); uint32_t rpc_get_pdu_size(char *buf); diff --git a/include/nfsc/libnfs-raw.h b/include/nfsc/libnfs-raw.h index ce88dd2..563bced 100644 --- a/include/nfsc/libnfs-raw.h +++ b/include/nfsc/libnfs-raw.h @@ -31,7 +31,7 @@ extern "C" { struct rpc_data { int size; - unsigned char *data; + char *data; }; struct rpc_context; diff --git a/lib/init.c b/lib/init.c index 0bfa87d..5fe7688 100644 --- a/lib/init.c +++ b/lib/init.c @@ -62,17 +62,8 @@ struct rpc_context *rpc_init_context(void) rpc->magic = RPC_CONTEXT_MAGIC; - /* Allow NFS_MAX_XFER_SIZE of data (for writes) and some */ - rpc->encodebuflen = NFS_MAX_XFER_SIZE + 4096; - rpc->encodebuf = malloc(rpc->encodebuflen); - if (rpc->encodebuf == NULL) { - free(rpc); - return NULL; - } - rpc->auth = authunix_create_default(); if (rpc->auth == NULL) { - free(rpc->encodebuf); free(rpc); return NULL; } @@ -316,11 +307,6 @@ void rpc_destroy_context(struct rpc_context *rpc) close(rpc->fd); } - if (rpc->encodebuf != NULL) { - free(rpc->encodebuf); - rpc->encodebuf = NULL; - } - if (rpc->error_string != NULL) { free(rpc->error_string); rpc->error_string = NULL; diff --git a/lib/pdu.c b/lib/pdu.c index 55a6ab2..9fbf83b 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -86,7 +86,7 @@ unsigned int rpc_hash_xid(uint32_t xid) #define PAD_TO_8_BYTES(x) ((x + 0x07) & ~0x07) -struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_decode_bufsize) +struct rpc_pdu *rpc_allocate_pdu2(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_decode_bufsize, size_t alloc_hint) { struct rpc_pdu *pdu; struct rpc_msg msg; @@ -112,7 +112,13 @@ struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int versi pdu->zdr_decode_fn = zdr_decode_fn; pdu->zdr_decode_bufsize = zdr_decode_bufsize; - zdrmem_create(&pdu->zdr, rpc->encodebuf, rpc->encodebuflen, ZDR_ENCODE); + pdu->outdata.data = malloc(ZDR_ENCODEBUF_MINSIZE + alloc_hint); + if (pdu->outdata.data == NULL) { + rpc_set_error(rpc, "Out of memory: Failed to allocate encode buffer"); + return NULL; + } + + zdrmem_create(&pdu->zdr, pdu->outdata.data, ZDR_ENCODEBUF_MINSIZE + alloc_hint, ZDR_ENCODE); if (rpc->is_udp == 0) { zdr_setpos(&pdu->zdr, 4); /* skip past the record marker */ } @@ -138,6 +144,11 @@ struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int versi return pdu; } +struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_decode_bufsize) +{ + return rpc_allocate_pdu2(rpc, program, version, procedure, cb, private_data, zdr_decode_fn, zdr_decode_bufsize, 0); +} + void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) { assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -175,7 +186,7 @@ int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) unsigned int hash; // XXX add a rpc->udp_dest_sock_size and get rid of sys/socket.h and netinet/in.h - if (sendto(rpc->fd, rpc->encodebuf, size, MSG_DONTWAIT, rpc->udp_dest, sizeof(struct sockaddr_in)) < 0) { + if (sendto(rpc->fd, pdu->zdr.buf, size, MSG_DONTWAIT, rpc->udp_dest, sizeof(struct sockaddr_in)) < 0) { rpc_set_error(rpc, "Sendto failed with errno %s", strerror(errno)); rpc_free_pdu(rpc, pdu); return -1; @@ -192,14 +203,6 @@ int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) zdr_int(&pdu->zdr, &recordmarker); pdu->outdata.size = size; - pdu->outdata.data = malloc(pdu->outdata.size); - if (pdu->outdata.data == NULL) { - rpc_set_error(rpc, "Out of memory. Failed to allocate buffer for pdu\n"); - rpc_free_pdu(rpc, pdu); - return -1; - } - - memcpy(pdu->outdata.data, rpc->encodebuf, pdu->outdata.size); rpc_enqueue(&rpc->outqueue, pdu); return 0; diff --git a/nfs/nfs.c b/nfs/nfs.c index 335c67b..8b54d65 100644 --- a/nfs/nfs.c +++ b/nfs/nfs.c @@ -318,7 +318,7 @@ int rpc_nfs3_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE3args * { struct rpc_pdu *pdu; - pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE3res, sizeof(WRITE3res)); + pdu = rpc_allocate_pdu2(rpc, NFS_PROGRAM, NFS_V3, NFS3_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE3res, sizeof(WRITE3res), args->count); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/WRITE call"); return -1; @@ -1064,7 +1064,7 @@ int rpc_nfs2_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE2args * { struct rpc_pdu *pdu; - pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE2res, sizeof(WRITE2res)); + pdu = rpc_allocate_pdu2(rpc, NFS_PROGRAM, NFS_V2, NFS2_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE2res, sizeof(WRITE2res), args->totalcount); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/WRITE call"); return -1;