summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2011-11-07 10:57:27 -0600
committerAnthony Liguori <aliguori@us.ibm.com>2011-11-07 10:57:27 -0600
commit2963e65a4e195737256d849166981ea24a337b2e (patch)
tree9de12b20f50f9d8226c6399ee42b71267bf2a9a6
parentca062aaed0b88060914ffb58442e12fde08db26d (diff)
parent273e4e03b3413fd489601cd9d8ba407ccb3b4130 (diff)
downloadqemu-2963e65a4e195737256d849166981ea24a337b2e.tar.gz
Merge remote-tracking branch 'kwolf/for-anthony' into staging
-rw-r--r--block/cloop.c119
-rw-r--r--block/vvfat.c60
-rw-r--r--hw/dma.c10
-rw-r--r--qemu-io.c37
4 files changed, 138 insertions, 88 deletions
diff --git a/block/cloop.c b/block/cloop.c
index 775f8a98e1..7570eb8e74 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -30,7 +30,7 @@ typedef struct BDRVCloopState {
CoMutex lock;
uint32_t block_size;
uint32_t n_blocks;
- uint64_t* offsets;
+ uint64_t *offsets;
uint32_t sectors_per_block;
uint32_t current_block;
uint8_t *compressed_block;
@@ -40,21 +40,23 @@ typedef struct BDRVCloopState {
static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
{
- const char* magic_version_2_0="#!/bin/sh\n"
- "#V2.0 Format\n"
- "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
- int length=strlen(magic_version_2_0);
- if(length>buf_size)
- length=buf_size;
- if(!memcmp(magic_version_2_0,buf,length))
- return 2;
+ const char *magic_version_2_0 = "#!/bin/sh\n"
+ "#V2.0 Format\n"
+ "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
+ int length = strlen(magic_version_2_0);
+ if (length > buf_size) {
+ length = buf_size;
+ }
+ if (!memcmp(magic_version_2_0, buf, length)) {
+ return 2;
+ }
return 0;
}
static int cloop_open(BlockDriverState *bs, int flags)
{
BDRVCloopState *s = bs->opaque;
- uint32_t offsets_size,max_compressed_block_size=1,i;
+ uint32_t offsets_size, max_compressed_block_size = 1, i;
bs->read_only = 1;
@@ -74,26 +76,28 @@ static int cloop_open(BlockDriverState *bs, int flags)
s->offsets = g_malloc(offsets_size);
if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
offsets_size) {
- goto cloop_close;
+ goto cloop_close;
}
for(i=0;i<s->n_blocks;i++) {
- s->offsets[i]=be64_to_cpu(s->offsets[i]);
- if(i>0) {
- uint32_t size=s->offsets[i]-s->offsets[i-1];
- if(size>max_compressed_block_size)
- max_compressed_block_size=size;
- }
+ s->offsets[i] = be64_to_cpu(s->offsets[i]);
+ if (i > 0) {
+ uint32_t size = s->offsets[i] - s->offsets[i - 1];
+ if (size > max_compressed_block_size) {
+ max_compressed_block_size = size;
+ }
+ }
}
/* initialize zlib engine */
- s->compressed_block = g_malloc(max_compressed_block_size+1);
+ s->compressed_block = g_malloc(max_compressed_block_size + 1);
s->uncompressed_block = g_malloc(s->block_size);
- if(inflateInit(&s->zstream) != Z_OK)
- goto cloop_close;
- s->current_block=s->n_blocks;
+ if (inflateInit(&s->zstream) != Z_OK) {
+ goto cloop_close;
+ }
+ s->current_block = s->n_blocks;
s->sectors_per_block = s->block_size/512;
- bs->total_sectors = s->n_blocks*s->sectors_per_block;
+ bs->total_sectors = s->n_blocks * s->sectors_per_block;
qemu_co_mutex_init(&s->lock);
return 0;
@@ -105,27 +109,30 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
{
BDRVCloopState *s = bs->opaque;
- if(s->current_block != block_num) {
- int ret;
- uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
+ if (s->current_block != block_num) {
+ int ret;
+ uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
bytes);
- if (ret != bytes)
+ if (ret != bytes) {
return -1;
+ }
+
+ s->zstream.next_in = s->compressed_block;
+ s->zstream.avail_in = bytes;
+ s->zstream.next_out = s->uncompressed_block;
+ s->zstream.avail_out = s->block_size;
+ ret = inflateReset(&s->zstream);
+ if (ret != Z_OK) {
+ return -1;
+ }
+ ret = inflate(&s->zstream, Z_FINISH);
+ if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) {
+ return -1;
+ }
- s->zstream.next_in = s->compressed_block;
- s->zstream.avail_in = bytes;
- s->zstream.next_out = s->uncompressed_block;
- s->zstream.avail_out = s->block_size;
- ret = inflateReset(&s->zstream);
- if(ret != Z_OK)
- return -1;
- ret = inflate(&s->zstream, Z_FINISH);
- if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
- return -1;
-
- s->current_block = block_num;
+ s->current_block = block_num;
}
return 0;
}
@@ -136,12 +143,15 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
BDRVCloopState *s = bs->opaque;
int i;
- for(i=0;i<nb_sectors;i++) {
- uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
- block_num=(sector_num+i)/s->sectors_per_block;
- if(cloop_read_block(bs, block_num) != 0)
- return -1;
- memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
+ for (i = 0; i < nb_sectors; i++) {
+ uint32_t sector_offset_in_block =
+ ((sector_num + i) % s->sectors_per_block),
+ block_num = (sector_num + i) / s->sectors_per_block;
+ if (cloop_read_block(bs, block_num) != 0) {
+ return -1;
+ }
+ memcpy(buf + i * 512,
+ s->uncompressed_block + sector_offset_in_block * 512, 512);
}
return 0;
}
@@ -160,20 +170,21 @@ static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
static void cloop_close(BlockDriverState *bs)
{
BDRVCloopState *s = bs->opaque;
- if(s->n_blocks>0)
- free(s->offsets);
- free(s->compressed_block);
- free(s->uncompressed_block);
+ if (s->n_blocks > 0) {
+ g_free(s->offsets);
+ }
+ g_free(s->compressed_block);
+ g_free(s->uncompressed_block);
inflateEnd(&s->zstream);
}
static BlockDriver bdrv_cloop = {
- .format_name = "cloop",
- .instance_size = sizeof(BDRVCloopState),
- .bdrv_probe = cloop_probe,
- .bdrv_open = cloop_open,
- .bdrv_read = cloop_co_read,
- .bdrv_close = cloop_close,
+ .format_name = "cloop",
+ .instance_size = sizeof(BDRVCloopState),
+ .bdrv_probe = cloop_probe,
+ .bdrv_open = cloop_open,
+ .bdrv_read = cloop_co_read,
+ .bdrv_close = cloop_close,
};
static void bdrv_cloop_init(void)
diff --git a/block/vvfat.c b/block/vvfat.c
index e1fcdbc45b..8511fe523c 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -799,6 +799,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
/* root directory */
int cur = s->directory.next;
array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
+ s->directory.next = ROOT_ENTRIES;
memset(array_get(&(s->directory), cur), 0,
(ROOT_ENTRIES - cur) * sizeof(direntry_t));
}
@@ -915,11 +916,8 @@ static int init_directories(BDRVVVFATState* s,
cluster = mapping->end;
if(cluster > s->cluster_count) {
- fprintf(stderr,"Directory does not fit in FAT%d (capacity %s)\n",
- s->fat_type,
- s->fat_type == 12 ? s->sector_count == 2880 ? "1.44 MB"
- : "2.88 MB"
- : "504MB");
+ fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
+ s->fat_type, s->sector_count / 2000.0);
return -EINVAL;
}
@@ -953,7 +951,7 @@ static int init_directories(BDRVVVFATState* s,
bootsector->number_of_fats=0x2; /* number of FATs */
bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
- bootsector->media_type=(s->fat_type!=12?0xf8:s->sector_count==5760?0xf9:0xf8); /* media descriptor */
+ bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
s->fat.pointer[0] = bootsector->media_type;
bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
@@ -962,7 +960,7 @@ static int init_directories(BDRVVVFATState* s,
bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
/* LATER TODO: if FAT32, this is wrong */
- bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */
+ bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
bootsector->u.fat16.current_head=0;
bootsector->u.fat16.signature=0x29;
bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
@@ -984,7 +982,6 @@ static int is_consistent(BDRVVVFATState *s);
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
{
BDRVVVFATState *s = bs->opaque;
- int floppy = 0;
int i;
#ifdef DEBUG
@@ -998,11 +995,8 @@ DLOG(if (stderr == NULL) {
s->bs = bs;
- s->fat_type=16;
/* LATER TODO: if FAT32, adjust */
s->sectors_per_cluster=0x10;
- /* 504MB disk*/
- bs->cyls=1024; bs->heads=16; bs->secs=63;
s->current_cluster=0xffffffff;
@@ -1017,16 +1011,6 @@ DLOG(if (stderr == NULL) {
if (!strstart(dirname, "fat:", NULL))
return -1;
- if (strstr(dirname, ":floppy:")) {
- floppy = 1;
- s->fat_type = 12;
- s->first_sectors_number = 1;
- s->sectors_per_cluster=2;
- bs->cyls = 80; bs->heads = 2; bs->secs = 36;
- }
-
- s->sector_count=bs->cyls*bs->heads*bs->secs;
-
if (strstr(dirname, ":32:")) {
fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
s->fat_type = 32;
@@ -1034,9 +1018,31 @@ DLOG(if (stderr == NULL) {
s->fat_type = 16;
} else if (strstr(dirname, ":12:")) {
s->fat_type = 12;
- s->sector_count=2880;
}
+ if (strstr(dirname, ":floppy:")) {
+ /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
+ if (!s->fat_type) {
+ s->fat_type = 12;
+ bs->secs = 36;
+ s->sectors_per_cluster=2;
+ } else {
+ bs->secs=(s->fat_type == 12 ? 18 : 36);
+ s->sectors_per_cluster=1;
+ }
+ s->first_sectors_number = 1;
+ bs->cyls=80; bs->heads=2;
+ } else {
+ /* 32MB or 504MB disk*/
+ if (!s->fat_type) {
+ s->fat_type = 16;
+ }
+ bs->cyls=(s->fat_type == 12 ? 64 : 1024);
+ bs->heads=16; bs->secs=63;
+ }
+
+ s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
+
if (strstr(dirname, ":rw:")) {
if (enable_write_target(s))
return -1;
@@ -1060,10 +1066,10 @@ DLOG(if (stderr == NULL) {
if(s->first_sectors_number==0x40)
init_mbr(s);
-
- /* for some reason or other, MS-DOS does not like to know about CHS... */
- if (floppy)
+ else {
+ /* MS-DOS does not like to know about CHS (?). */
bs->heads = bs->cyls = bs->secs = 0;
+ }
// assert(is_consistent(s));
qemu_co_mutex_init(&s->lock);
@@ -1244,7 +1250,7 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
int i;
for(i=0;i<nb_sectors;i++,sector_num++) {
- if (sector_num >= s->sector_count)
+ if (sector_num >= bs->total_sectors)
return -1;
if (s->qcow) {
int n;
@@ -1270,7 +1276,7 @@ DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
uint32_t sector=sector_num-s->faked_sectors,
sector_offset_in_cluster=(sector%s->sectors_per_cluster),
cluster_num=sector/s->sectors_per_cluster;
- if(read_cluster(s, cluster_num) != 0) {
+ if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
/* LATER TODO: strict: return -1; */
memset(buf+i*0x200,0,0x200);
continue;
diff --git a/hw/dma.c b/hw/dma.c
index 8a7302a42f..0a9322daa3 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -358,6 +358,14 @@ static void DMA_run (void)
struct dma_cont *d;
int icont, ichan;
int rearm = 0;
+ static int running = 0;
+
+ if (running) {
+ rearm = 1;
+ goto out;
+ } else {
+ running = 1;
+ }
d = dma_controllers;
@@ -374,6 +382,8 @@ static void DMA_run (void)
}
}
+ running = 0;
+out:
if (rearm)
qemu_bh_schedule_idle(dma_bh);
}
diff --git a/qemu-io.c b/qemu-io.c
index 5af887e057..de26422fcf 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -596,6 +596,9 @@ static int readv_f(int argc, char **argv)
nr_iov = argc - optind;
buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
+ if (buf == NULL) {
+ return 0;
+ }
gettimeofday(&t1, NULL);
cnt = do_aio_readv(&qiov, offset, &total);
@@ -850,6 +853,9 @@ static int writev_f(int argc, char **argv)
nr_iov = argc - optind;
buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
+ if (buf == NULL) {
+ return 0;
+ }
gettimeofday(&t1, NULL);
cnt = do_aio_writev(&qiov, offset, &total);
@@ -950,25 +956,25 @@ static int multiwrite_f(int argc, char **argv)
}
}
- reqs = g_malloc(nr_reqs * sizeof(*reqs));
- buf = g_malloc(nr_reqs * sizeof(*buf));
+ reqs = g_malloc0(nr_reqs * sizeof(*reqs));
+ buf = g_malloc0(nr_reqs * sizeof(*buf));
qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
- for (i = 0; i < nr_reqs; i++) {
+ for (i = 0; i < nr_reqs && optind < argc; i++) {
int j;
/* Read the offset of the request */
offset = cvtnum(argv[optind]);
if (offset < 0) {
printf("non-numeric offset argument -- %s\n", argv[optind]);
- return 0;
+ goto out;
}
optind++;
if (offset & 0x1ff) {
printf("offset %lld is not sector aligned\n",
(long long)offset);
- return 0;
+ goto out;
}
if (i == 0) {
@@ -985,8 +991,12 @@ static int multiwrite_f(int argc, char **argv)
nr_iov = j - optind;
/* Build request */
+ buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
+ if (buf[i] == NULL) {
+ goto out;
+ }
+
reqs[i].qiov = &qiovs[i];
- buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
reqs[i].sector = offset >> 9;
reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
@@ -995,6 +1005,9 @@ static int multiwrite_f(int argc, char **argv)
pattern++;
}
+ /* If there were empty requests at the end, ignore them */
+ nr_reqs = i;
+
gettimeofday(&t1, NULL);
cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
gettimeofday(&t2, NULL);
@@ -1014,7 +1027,9 @@ static int multiwrite_f(int argc, char **argv)
out:
for (i = 0; i < nr_reqs; i++) {
qemu_io_free(buf[i]);
- qemu_iovec_destroy(&qiovs[i]);
+ if (reqs[i].qiov != NULL) {
+ qemu_iovec_destroy(&qiovs[i]);
+ }
}
g_free(buf);
g_free(reqs);
@@ -1185,6 +1200,10 @@ static int aio_read_f(int argc, char **argv)
nr_iov = argc - optind;
ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
+ if (ctx->buf == NULL) {
+ free(ctx);
+ return 0;
+ }
gettimeofday(&ctx->t1, NULL);
acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
@@ -1280,6 +1299,10 @@ static int aio_write_f(int argc, char **argv)
nr_iov = argc - optind;
ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
+ if (ctx->buf == NULL) {
+ free(ctx);
+ return 0;
+ }
gettimeofday(&ctx->t1, NULL);
acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,