Commit 8c05dbf9b68cc8444573116063582e01a0442b0b

Authored by ths
1 parent c3e88d8c

Enhance raw io reliability, by Ben Guthro.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3166 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 70 additions and 2 deletions
block-raw.c
... ... @@ -59,6 +59,13 @@
59 59  
60 60 //#define DEBUG_FLOPPY
61 61  
  62 +#define DEBUG_BLOCK
  63 +#if defined(DEBUG_BLOCK) && !defined(QEMU_TOOL)
  64 +#define DEBUG_BLOCK_PRINT(formatCstr, args...) fprintf(logfile, formatCstr, ##args); fflush(logfile)
  65 +#else
  66 +#define DEBUG_BLOCK_PRINT(formatCstr, args...)
  67 +#endif
  68 +
62 69 #define FTYPE_FILE 0
63 70 #define FTYPE_CD 1
64 71 #define FTYPE_FD 2
... ... @@ -70,6 +77,7 @@
70 77 typedef struct BDRVRawState {
71 78 int fd;
72 79 int type;
  80 + unsigned int lseek_err_cnt;
73 81 #if defined(__linux__)
74 82 /* linux floppy specific */
75 83 int fd_open_flags;
... ... @@ -87,6 +95,8 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
87 95 BDRVRawState *s = bs->opaque;
88 96 int fd, open_flags, ret;
89 97  
  98 + s->lseek_err_cnt = 0;
  99 +
90 100 open_flags = O_BINARY;
91 101 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
92 102 open_flags |= O_RDWR;
... ... @@ -137,8 +147,45 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
137 147 if (ret < 0)
138 148 return ret;
139 149  
140   - lseek(s->fd, offset, SEEK_SET);
  150 + if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
  151 + ++(s->lseek_err_cnt);
  152 + if(s->lseek_err_cnt <= 10) {
  153 + DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
  154 + s->fd, bs->filename, offset, buf, count,
  155 + bs->total_sectors, errno, strerror(errno));
  156 + }
  157 + return -1;
  158 + }
  159 + s->lseek_err_cnt=0;
  160 +
141 161 ret = read(s->fd, buf, count);
  162 + if (ret == count)
  163 + goto label__raw_read__success;
  164 +
  165 + DEBUG_BLOCK_PRINT("raw_read(%d:%s, %lld, %p, %d) [%lld] read failed %d : %d = %s\n",
  166 + s->fd, bs->filename, offset, buf, count,
  167 + bs->total_sectors, ret, errno, strerror(errno));
  168 +
  169 + /* Try harder for CDrom. */
  170 + if (bs->type == BDRV_TYPE_CDROM) {
  171 + lseek(s->fd, offset, SEEK_SET);
  172 + ret = read(s->fd, buf, count);
  173 + if (ret == count)
  174 + goto label__raw_read__success;
  175 + lseek(s->fd, offset, SEEK_SET);
  176 + ret = read(s->fd, buf, count);
  177 + if (ret == count)
  178 + goto label__raw_read__success;
  179 +
  180 + DEBUG_BLOCK_PRINT("raw_read(%d:%s, %lld, %p, %d) [%lld] retry read failed %d : %d = %s\n",
  181 + s->fd, bs->filename, offset, buf, count,
  182 + bs->total_sectors, ret, errno, strerror(errno));
  183 + }
  184 +
  185 + return -1;
  186 +
  187 +label__raw_read__success:
  188 +
142 189 return ret;
143 190 }
144 191  
... ... @@ -152,8 +199,29 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
152 199 if (ret < 0)
153 200 return ret;
154 201  
155   - lseek(s->fd, offset, SEEK_SET);
  202 + if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
  203 + ++(s->lseek_err_cnt);
  204 + if(s->lseek_err_cnt) {
  205 + DEBUG_BLOCK_PRINT("raw_write(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
  206 + s->fd, bs->filename, offset, buf, count,
  207 + bs->total_sectors, errno, strerror(errno));
  208 + }
  209 + return -1;
  210 + }
  211 + s->lseek_err_cnt = 0;
  212 +
156 213 ret = write(s->fd, buf, count);
  214 + if (ret == count)
  215 + goto label__raw_write__success;
  216 +
  217 + DEBUG_BLOCK_PRINT("raw_write(%d:%s, %lld, %p, %d) [%lld] write failed %d : %d = %s\n",
  218 + s->fd, bs->filename, offset, buf, count,
  219 + bs->total_sectors, ret, errno, strerror(errno));
  220 +
  221 + return -1;
  222 +
  223 +label__raw_write__success:
  224 +
157 225 return ret;
158 226 }
159 227  
... ...