]> xenbits.xensource.com Git - xen.git/commitdiff
[QEMU] Enhance raw io reliability
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 11 Sep 2007 16:02:03 +0000 (17:02 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 11 Sep 2007 16:02:03 +0000 (17:02 +0100)
For raw block device only :
log any I/O error and perform automatic read retry for CDrom
(improves MediaCheck with old installers).

Signed-off-by: Ben Guthro <bguthro@virtualiron.com>
Signed-off-by: Josh Nicholas <jnicholas@virtualiron.com>
tools/ioemu/block-raw.c

index 9b01211bbfd42cf76d2887577702f7c41a6c431a..f2ce456fc49425e3ef23e4af55c23d906ff2a17c 100644 (file)
 
 //#define DEBUG_FLOPPY
 
+#define DEBUG_BLOCK
+#ifdef  DEBUG_BLOCK
+#define DEBUG_BLOCK_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, ##args ); fflush( logfile )
+#else
+#define DEBUG_BLOCK_PRINT( formatCstr, args... )
+#endif
+
 #define FTYPE_FILE   0
 #define FTYPE_CD     1
 #define FTYPE_FD     2
@@ -70,6 +77,7 @@
 typedef struct BDRVRawState {
     int fd;
     int type;
+    unsigned int lseek_err_cnt;
 #if defined(__linux__)
     /* linux floppy specific */
     int fd_open_flags;
@@ -87,6 +95,8 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
     BDRVRawState *s = bs->opaque;
     int fd, open_flags, ret;
 
+    s->lseek_err_cnt = 0;
+
     open_flags = O_BINARY;
     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
         open_flags |= O_RDWR;
@@ -137,8 +147,58 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
     if (ret < 0)
         return ret;
 
-    lseek(s->fd, offset, SEEK_SET);
+    if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+        ++(s->lseek_err_cnt);
+        if(s->lseek_err_cnt <= 10) {
+                DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %ld, %p, %d) [%ld] lseek failed : %d = %s\n", 
+                        s->fd, 
+                        bs->filename, 
+                        offset, 
+                        buf, 
+                        count, 
+                        bs->total_sectors, errno, strerror(errno) );
+       }
+       return -1;
+    }
+    s->lseek_err_cnt=0;
+
     ret = read(s->fd, buf, count);
+    if (ret == count) 
+        goto label__raw_read__success;
+    
+    DEBUG_BLOCK_PRINT("raw_read(%d:%s, %ld, %p, %d) [%ld] read failed %d : %d = %s\n", 
+        s->fd, 
+        bs->filename, 
+        offset, 
+        buf, 
+        count, 
+        bs->total_sectors, 
+        ret, errno, strerror(errno) );
+    
+    if (bs->type == BDRV_TYPE_CDROM) {  // Try harder for CDrom
+        lseek(s->fd, offset, SEEK_SET);
+        ret = read(s->fd, buf, count);
+        if (ret == count) 
+            goto label__raw_read__success;
+        lseek(s->fd, offset, SEEK_SET);
+        ret = read(s->fd, buf, count);
+        if (ret == count)
+            goto label__raw_read__success;
+        
+        DEBUG_BLOCK_PRINT("raw_read(%d:%s, %ld, %p, %d) [%ld] retry read failed %d : %d = %s\n", 
+            s->fd, 
+            bs->filename, 
+            offset, 
+            buf, 
+            count, 
+            bs->total_sectors, 
+            ret, errno, strerror(errno) );
+    }
+    
+    return -1;
+    
+label__raw_read__success:
+
     return ret;
 }
 
@@ -152,8 +212,38 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
     if (ret < 0)
         return ret;
 
-    lseek(s->fd, offset, SEEK_SET);
+    if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+        ++(s->lseek_err_cnt);
+        if(s->lseek_err_cnt) {
+                DEBUG_BLOCK_PRINT("raw_write(%d:%s, %ld, %p, %d) [%ld] lseek failed : %d = %s\n", 
+                        s->fd, 
+                        bs->filename, 
+                        offset, 
+                        buf, 
+                        count, 
+                        bs->total_sectors, errno, strerror(errno) );
+        }
+        return -1;
+    }
+    s->lseek_err_cnt = 0;
+
     ret = write(s->fd, buf, count);
+    if (ret == count) 
+        goto label__raw_write__success;
+    
+    DEBUG_BLOCK_PRINT("raw_write(%d:%s, %ld, %p, %d) [%ld] write failed %d : %d = %s\n", 
+        s->fd, 
+        bs->filename, 
+        offset, 
+        buf, 
+        count, 
+        bs->total_sectors, 
+        ret, errno, strerror(errno) );
+    
+    return -1;
+    
+label__raw_write__success:
+
     return ret;
 }