X-Git-Url: http://git.alex.org.uk diff --git a/nbd-server.c b/nbd-server.c index 820458c..51b725c 100644 --- a/nbd-server.c +++ b/nbd-server.c @@ -150,7 +150,7 @@ gboolean do_oldstyle=FALSE; #define OFFT_MAX ~((off_t)1<<(sizeof(off_t)*8-1)) #define LINELEN 256 /**< Size of static buffer used to read the authorization file (yuck) */ -#define BUFSIZE (1024*1024) /**< Size of buffer that can hold requests */ +#define BUFSIZE ((1024*1024)+sizeof(struct nbd_reply)) /**< Size of buffer that can hold requests */ #define DIFFPAGESIZE 4096 /**< diff file uses those chunks */ #define F_READONLY 1 /**< flag to tell us a file is readonly */ #define F_MULTIFILE 2 /**< flag to tell us a file is exported using -m */ @@ -1364,7 +1364,10 @@ int mainloop(CLIENT *client) { reply.error = 0; while (go_on) { char buf[BUFSIZE]; + char* p; size_t len; + size_t currlen; + size_t writelen; #ifdef DODBG i++; printf("%d: ", i); @@ -1389,8 +1392,12 @@ int mainloop(CLIENT *client) { if (request.magic != htonl(NBD_REQUEST_MAGIC)) err("Not enough magic."); - if (len > BUFSIZE + sizeof(struct nbd_reply)) - err("Request too big!"); + if (len > BUFSIZE - sizeof(struct nbd_reply)) { + currlen = BUFSIZE - sizeof(struct nbd_reply); + msg("INFO: oversized request (this is not a problem)"); + } else { + currlen = len; + } #ifdef DODBG printf("%s from %llu (%llu) len %d, ", request.type ? "WRITE" : "READ", (unsigned long long)request.from, @@ -1411,35 +1418,47 @@ int mainloop(CLIENT *client) { if (request.type==NBD_CMD_WRITE) { DEBUG("wr: net->buf, "); - readit(client->net, buf, len); - DEBUG("buf->exp, "); - if ((client->server->flags & F_READONLY) || - (client->server->flags & F_AUTOREADONLY)) { - DEBUG("[WRITE to READONLY!]"); - ERROR(client, reply, EPERM); - continue; - } - if (expwrite(request.from, buf, len, client)) { - DEBUG("Write failed: %m" ); - ERROR(client, reply, errno); - continue; + while(len > 0) { + readit(client->net, buf, currlen); + DEBUG("buf->exp, "); + if ((client->server->flags & F_READONLY) || + (client->server->flags & F_AUTOREADONLY)) { + DEBUG("[WRITE to READONLY!]"); + ERROR(client, reply, EPERM); + continue; + } + if (expwrite(request.from, buf, len, client)) { + DEBUG("Write failed: %m" ); + ERROR(client, reply, errno); + continue; + } + SEND(client->net, reply); + DEBUG("OK!\n"); + len -= currlen; + currlen = (len < BUFSIZE) ? len : BUFSIZE; } - SEND(client->net, reply); - DEBUG("OK!\n"); continue; } /* READ */ DEBUG("exp->buf, "); - if (expread(request.from, buf + sizeof(struct nbd_reply), len, client)) { - DEBUG("Read failed: %m"); - ERROR(client, reply, errno); - continue; - } - - DEBUG("buf->net, "); memcpy(buf, &reply, sizeof(struct nbd_reply)); - writeit(client->net, buf, len + sizeof(struct nbd_reply)); + p = buf + sizeof(struct nbd_reply); + writelen = currlen + sizeof(struct nbd_reply); + while(len > 0) { + if (expread(request.from, p, currlen, client)) { + DEBUG("Read failed: %m"); + ERROR(client, reply, errno); + continue; + } + + DEBUG("buf->net, "); + writeit(client->net, buf, writelen); + len -= currlen; + currlen = (len < BUFSIZE) ? len : BUFSIZE; + p = buf; + writelen = currlen; + } DEBUG("OK!\n"); } return 0;