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 <pl@kamp.de>
libnfs-4.0.0-vitalif
Peter Lieven 2016-06-02 09:12:53 +02:00
parent 21c466254a
commit 9cb49494c7
5 changed files with 20 additions and 32 deletions

View File

@ -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);

View File

@ -31,7 +31,7 @@ extern "C" {
struct rpc_data {
int size;
unsigned char *data;
char *data;
};
struct rpc_context;

View File

@ -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;

View File

@ -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;

View File

@ -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;