diff mbox

nbd block device backend - 'improvements'

Message ID 1297704538.9421.75.camel@desk4.office.bytemark.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Nicholas Thomas Feb. 14, 2011, 5:28 p.m. UTC
None
diff mbox

Patch

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,