raw-posix: Use pread/pwrite instead of lseek+read/write

This patch combines the lseek+read/write calls to use pread/pwrite
instead.  This will result in fewer system calls and is already used by
AIO.

Thanks to Jan Kiszka <jan.kiszka@siemens.com> for identifying excessive
lseek and Christoph Hellwig <hch@lst.de> for confirming that this
approach should work.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2010-04-19 13:34:11 +01:00 committed by Kevin Wolf
parent 508e089368
commit 4899d10d14

View File

@ -105,7 +105,6 @@
typedef struct BDRVRawState { typedef struct BDRVRawState {
int fd; int fd;
int type; int type;
unsigned int lseek_err_cnt;
int open_flags; int open_flags;
#if defined(__linux__) #if defined(__linux__)
/* linux floppy specific */ /* linux floppy specific */
@ -134,8 +133,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int fd, ret; int fd, ret;
s->lseek_err_cnt = 0;
s->open_flags = open_flags | O_BINARY; s->open_flags = open_flags | O_BINARY;
s->open_flags &= ~O_ACCMODE; s->open_flags &= ~O_ACCMODE;
if (bdrv_flags & BDRV_O_RDWR) { if (bdrv_flags & BDRV_O_RDWR) {
@ -243,19 +240,7 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { ret = pread(s->fd, buf, count, offset);
++(s->lseek_err_cnt);
if(s->lseek_err_cnt <= 10) {
DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
"] 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) if (ret == count)
goto label__raw_read__success; goto label__raw_read__success;
@ -276,12 +261,10 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
/* Try harder for CDrom. */ /* Try harder for CDrom. */
if (bs->type == BDRV_TYPE_CDROM) { if (bs->type == BDRV_TYPE_CDROM) {
lseek(s->fd, offset, SEEK_SET); ret = pread(s->fd, buf, count, offset);
ret = read(s->fd, buf, count);
if (ret == count) if (ret == count)
goto label__raw_read__success; goto label__raw_read__success;
lseek(s->fd, offset, SEEK_SET); ret = pread(s->fd, buf, count, offset);
ret = read(s->fd, buf, count);
if (ret == count) if (ret == count)
goto label__raw_read__success; goto label__raw_read__success;
@ -313,19 +296,7 @@ static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
if (ret < 0) if (ret < 0)
return -errno; return -errno;
if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { ret = pwrite(s->fd, buf, count, offset);
++(s->lseek_err_cnt);
if(s->lseek_err_cnt) {
DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
PRId64 "] lseek failed : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, errno, strerror(errno));
}
return -EIO;
}
s->lseek_err_cnt = 0;
ret = write(s->fd, buf, count);
if (ret == count) if (ret == count)
goto label__raw_write__success; goto label__raw_write__success;