From patchwork Mon Feb 14 17:28:58 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Thomas X-Patchwork-Id: 556371 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p1EI92Mh005512 for ; Mon, 14 Feb 2011 18:09:03 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752462Ab1BNSID (ORCPT ); Mon, 14 Feb 2011 13:08:03 -0500 Received: from egg.sh.bytemark.co.uk ([212.110.161.171]:52550 "EHLO egg.sh.bytemark.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752973Ab1BNSIB (ORCPT ); Mon, 14 Feb 2011 13:08:01 -0500 X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 14 Feb 2011 18:09:13 +0000 (UTC) X-Greylist: delayed 2339 seconds by postgrey-1.27 at vger.kernel.org; Mon, 14 Feb 2011 13:08:01 EST Received: from bytemail.bytemark.co.uk ([212.110.161.227]) by egg.sh.bytemark.co.uk with esmtp (Exim 4.69) (envelope-from ) id 1Pp2EO-00011w-3L for kvm@vger.kernel.org; Mon, 14 Feb 2011 17:29:00 +0000 Received: from desk4.office.bytemark.co.uk ([89.16.168.152]) by bytemail.bytemark.co.uk with esmtp (Exim 4.69) (envelope-from ) id 1Pp2EN-0005e9-KS for kvm@vger.kernel.org; Mon, 14 Feb 2011 17:29:00 +0000 Subject: nbd block device backend - 'improvements' From: Nicholas Thomas To: kvm@vger.kernel.org Organization: Bytemark Date: Mon, 14 Feb 2011 17:28:58 +0000 Message-ID: <1297704538.9421.75.camel@desk4.office.bytemark.co.uk> Mime-Version: 1.0 X-Mailer: Evolution 2.28.3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/block/nbd.c b/block/nbd.c index c8dc763..87da07e 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -39,9 +39,11 @@ typedef struct BDRVNBDState { int sock; off_t size; size_t blocksize; + char *filename; } BDRVNBDState; -static int nbd_open(BlockDriverState *bs, const char* filename, int flags) + +static int nbd_open(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; uint32_t nbdflags; @@ -56,7 +58,7 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags) int ret; int err = -EINVAL; - file = qemu_strdup(filename); + file = qemu_strdup(s->filename); name = strstr(file, EN_OPTSTR); if (name) { @@ -121,32 +123,62 @@ out: return err; } +// Puts the filename into the driver state and calls nbd_open - hanging until +// it is successful. +static int nbd_setup(BlockDriverState *bs, const char* filename, int flags) +{ + BDRVNBDState *s = bs->opaque; + int err = 1; + + s->filename = qemu_strdup(filename); + while (err != 0) + { + err = nbd_open(bs); + // Avoid tight loops + if (err != 0) + sleep(1); + } + + return err; +} + static int nbd_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { BDRVNBDState *s = bs->opaque; struct nbd_request request; struct nbd_reply reply; + bool success = false; request.type = NBD_CMD_READ; request.handle = (uint64_t)(intptr_t)bs; - request.from = sector_num * 512;; + request.from = sector_num * 512; request.len = nb_sectors * 512; - if (nbd_send_request(s->sock, &request) == -1) - return -errno; + while (success == false) + { + if ( (nbd_send_request(s->sock, &request) == -1) || + (nbd_receive_reply(s->sock, &reply) == -1) ) + { + // We hang here until the TCP session is established + close(s->sock); + while(nbd_open(bs) != 0) + sleep(1); + continue; + } - if (nbd_receive_reply(s->sock, &reply) == -1) - return -errno; + if (reply.error !=0) + return -reply.error; - if (reply.error !=0) - return -reply.error; + if (reply.handle != request.handle) + return -EIO; - if (reply.handle != request.handle) - return -EIO; + // If reading the actual data fails, we retry the whole request + if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len) + continue; - if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len) - return -EIO; + success = true; + } return 0; } @@ -157,26 +189,39 @@ static int nbd_write(BlockDriverState *bs, int64_t sector_num, BDRVNBDState *s = bs->opaque; struct nbd_request request; struct nbd_reply reply; + bool success = false; request.type = NBD_CMD_WRITE; request.handle = (uint64_t)(intptr_t)bs; request.from = sector_num * 512;; request.len = nb_sectors * 512; - if (nbd_send_request(s->sock, &request) == -1) - return -errno; + while (success == false) + { + if ( (nbd_send_request(s->sock, &request) == -1) || + (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len) ) + { + // We hang here until the TCP session is established + close(s->sock); + while(nbd_open(bs) != 0) + sleep(1); + continue; + } + + // We didn't get a reply from the write, so try again + if (nbd_receive_reply(s->sock, &reply) == -1) + continue; - if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len) - return -EIO; + // Problem with the response itself + if (reply.error !=0) + return -reply.error; - if (nbd_receive_reply(s->sock, &reply) == -1) - return -errno; + if (reply.handle != request.handle) + return -EIO; - if (reply.error !=0) - return -reply.error; + success = true; + } - if (reply.handle != request.handle) - return -EIO; return 0; } @@ -191,6 +236,7 @@ static void nbd_close(BlockDriverState *bs) request.from = 0; request.len = 0; nbd_send_request(s->sock, &request); + qemu_free(s->filename); close(s->sock); } @@ -205,7 +251,7 @@ static int64_t nbd_getlength(BlockDriverState *bs) static BlockDriver bdrv_nbd = { .format_name = "nbd", .instance_size = sizeof(BDRVNBDState), - .bdrv_file_open = nbd_open, + .bdrv_file_open = nbd_setup, .bdrv_read = nbd_read, .bdrv_write = nbd_write, .bdrv_close = nbd_close,