-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJWeQ9nAAoJEJykq7OBq3PIn74IALimi9+E0Ng9fjDYSbfV/T9e xRWIOMxicWO+UfB+sVNdNUj9PUFBBWb5k163f2wvbhHQ8rm+/j/cG5X4fZ4bdyHR KZE0FHiqhEKE4Az1z8d01ojwXDeSq+feTZX2BlEvUqIfWJYUI7gH6XI92BMk4wen p/ISslPX33Le2nsd0vWuwtRcZ95CFVTcilYp4p+u5+o71z4+e7k46B0udw+awB6F 1aAxWqe0tq+utLEOSF3RZfB2Md2o6yKLhWNCviIELqOc9ECkVUOJUyWZZHBj1k0p X9p3dL2hgqEok+fa8NRb5eIJ2b5jstq6Qs1phlEJ4j2LssmuU6FUzCcaLgYFUgU= =Fys+ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging # gpg: Signature made Tue 22 Dec 2015 08:52:55 GMT using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: sdhci: add optional quirk property to disable card insertion/removal interrupts sdhci: don't raise a command index error for an unexpected response sd: sdhci: Delete over-zealous power check scripts/gdb: Fix a python exception in mtree.py parallels: add format spec block/mirror: replace IOV_MAX with blk_get_max_iov() block: replace IOV_MAX with BlockLimits.max_iov block-backend: add blk_get_max_iov() block: add BlockLimits.max_iov field virtio-blk: trivial code optimization Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5dc42c186d
@ -1490,6 +1490,7 @@ M: Denis V. Lunev <den@openvz.org>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: block/parallels.c
|
||||
F: docs/specs/parallels.txt
|
||||
|
||||
qed
|
||||
M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
|
@ -1023,6 +1023,11 @@ int blk_get_max_transfer_length(BlockBackend *blk)
|
||||
}
|
||||
}
|
||||
|
||||
int blk_get_max_iov(BlockBackend *blk)
|
||||
{
|
||||
return blk->bs->bl.max_iov;
|
||||
}
|
||||
|
||||
void blk_set_guest_block_size(BlockBackend *blk, int align)
|
||||
{
|
||||
blk->guest_block_size = align;
|
||||
|
10
block/io.c
10
block/io.c
@ -166,9 +166,13 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
bs->bl.max_transfer_length = bs->file->bs->bl.max_transfer_length;
|
||||
bs->bl.min_mem_alignment = bs->file->bs->bl.min_mem_alignment;
|
||||
bs->bl.opt_mem_alignment = bs->file->bs->bl.opt_mem_alignment;
|
||||
bs->bl.max_iov = bs->file->bs->bl.max_iov;
|
||||
} else {
|
||||
bs->bl.min_mem_alignment = 512;
|
||||
bs->bl.opt_mem_alignment = getpagesize();
|
||||
|
||||
/* Safe default since most protocols use readv()/writev()/etc */
|
||||
bs->bl.max_iov = IOV_MAX;
|
||||
}
|
||||
|
||||
if (bs->backing) {
|
||||
@ -189,6 +193,9 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
bs->bl.min_mem_alignment =
|
||||
MAX(bs->bl.min_mem_alignment,
|
||||
bs->backing->bs->bl.min_mem_alignment);
|
||||
bs->bl.max_iov =
|
||||
MIN(bs->bl.max_iov,
|
||||
bs->backing->bs->bl.max_iov);
|
||||
}
|
||||
|
||||
/* Then let the driver override it */
|
||||
@ -1882,7 +1889,8 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
|
||||
merge = 1;
|
||||
}
|
||||
|
||||
if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
|
||||
if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 >
|
||||
bs->bl.max_iov) {
|
||||
merge = 0;
|
||||
}
|
||||
|
||||
|
@ -161,13 +161,15 @@ static void mirror_read_complete(void *opaque, int ret)
|
||||
static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
{
|
||||
BlockDriverState *source = s->common.bs;
|
||||
int nb_sectors, sectors_per_chunk, nb_chunks;
|
||||
int nb_sectors, sectors_per_chunk, nb_chunks, max_iov;
|
||||
int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector;
|
||||
uint64_t delay_ns = 0;
|
||||
MirrorOp *op;
|
||||
int pnum;
|
||||
int64_t ret;
|
||||
|
||||
max_iov = MIN(source->bl.max_iov, s->target->bl.max_iov);
|
||||
|
||||
s->sector_num = hbitmap_iter_next(&s->hbi);
|
||||
if (s->sector_num < 0) {
|
||||
bdrv_dirty_iter_init(s->dirty_bitmap, &s->hbi);
|
||||
@ -248,7 +250,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight);
|
||||
break;
|
||||
}
|
||||
if (IOV_MAX < nb_chunks + added_chunks) {
|
||||
if (max_iov < nb_chunks + added_chunks) {
|
||||
trace_mirror_break_iov_max(s, nb_chunks, added_chunks);
|
||||
break;
|
||||
}
|
||||
|
228
docs/specs/parallels.txt
Normal file
228
docs/specs/parallels.txt
Normal file
@ -0,0 +1,228 @@
|
||||
= License =
|
||||
|
||||
Copyright (c) 2015 Denis Lunev
|
||||
Copyright (c) 2015 Vladimir Sementsov-Ogievskiy
|
||||
|
||||
This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
See the COPYING file in the top-level directory.
|
||||
|
||||
= Parallels Expandable Image File Format =
|
||||
|
||||
A Parallels expandable image file consists of three consecutive parts:
|
||||
* header
|
||||
* BAT
|
||||
* data area
|
||||
|
||||
All numbers in a Parallels expandable image are stored in little-endian byte
|
||||
order.
|
||||
|
||||
|
||||
== Definitions ==
|
||||
|
||||
Sector A 512-byte data chunk.
|
||||
|
||||
Cluster A data chunk of the size specified in the image header.
|
||||
Currently, the default size is 1MiB (2048 sectors). In previous
|
||||
versions, cluster sizes of 63 sectors, 256 and 252 kilobytes were
|
||||
used.
|
||||
|
||||
BAT Block Allocation Table, an entity that contains information for
|
||||
guest-to-host I/O data address translation.
|
||||
|
||||
|
||||
== Header ==
|
||||
|
||||
The header is placed at the start of an image and contains the following
|
||||
fields:
|
||||
|
||||
Bytes:
|
||||
0 - 15: magic
|
||||
Must contain "WithoutFreeSpace" or "WithouFreSpacExt".
|
||||
|
||||
16 - 19: version
|
||||
Must be 2.
|
||||
|
||||
20 - 23: heads
|
||||
Disk geometry parameter for guest.
|
||||
|
||||
24 - 27: cylinders
|
||||
Disk geometry parameter for guest.
|
||||
|
||||
28 - 31: tracks
|
||||
Cluster size, in sectors.
|
||||
|
||||
32 - 35: nb_bat_entries
|
||||
Disk size, in clusters (BAT size).
|
||||
|
||||
36 - 43: nb_sectors
|
||||
Disk size, in sectors.
|
||||
|
||||
For "WithoutFreeSpace" images:
|
||||
Only the lowest 4 bytes are used. The highest 4 bytes must be
|
||||
cleared in this case.
|
||||
|
||||
For "WithouFreSpacExt" images, there are no such
|
||||
restrictions.
|
||||
|
||||
44 - 47: in_use
|
||||
Set to 0x746F6E59 when the image is opened by software in R/W
|
||||
mode; set to 0x312e3276 when the image is closed.
|
||||
|
||||
A zero in this field means that the image was opened by an old
|
||||
version of the software that doesn't support Format Extension
|
||||
(see below).
|
||||
|
||||
Other values are not allowed.
|
||||
|
||||
48 - 51: data_off
|
||||
An offset, in sectors, from the start of the file to the start of
|
||||
the data area.
|
||||
|
||||
For "WithoutFreeSpace" images:
|
||||
- If data_off is zero, the offset is calculated as the end of BAT
|
||||
table plus some padding to ensure sector size alignment.
|
||||
- If data_off is non-zero, the offset should be aligned to sector
|
||||
size. However it is recommended to align it to cluster size for
|
||||
newly created images.
|
||||
|
||||
For "WithouFreSpacExt" images:
|
||||
data_off must be non-zero and aligned to cluster size.
|
||||
|
||||
52 - 55: flags
|
||||
Miscellaneous flags.
|
||||
|
||||
Bit 0: Empty Image bit. If set, the image should be
|
||||
considered clear.
|
||||
|
||||
Bits 2-31: Unused.
|
||||
|
||||
56 - 63: ext_off
|
||||
Format Extension offset, an offset, in sectors, from the start of
|
||||
the file to the start of the Format Extension Cluster.
|
||||
|
||||
ext_off must meet the same requirements as cluster offsets
|
||||
defined by BAT entries (see below).
|
||||
|
||||
|
||||
== BAT ==
|
||||
|
||||
BAT is placed immediately after the image header. In the file, BAT is a
|
||||
contiguous array of 32-bit unsigned little-endian integers with
|
||||
(bat_entries * 4) bytes size.
|
||||
|
||||
Each BAT entry contains an offset from the start of the file to the
|
||||
corresponding cluster. The offset set in clusters for "WithouFreSpacExt" images
|
||||
and in sectors for "WithoutFreeSpace" images.
|
||||
|
||||
If a BAT entry is zero, the corresponding cluster is not allocated and should
|
||||
be considered as filled with zeroes.
|
||||
|
||||
Cluster offsets specified by BAT entries must meet the following requirements:
|
||||
- the value must not be lower than data offset (provided by header.data_off
|
||||
or calculated as specified above),
|
||||
- the value must be lower than the desired file size,
|
||||
- the value must be unique among all BAT entries,
|
||||
- the result of (cluster offset - data offset) must be aligned to cluster
|
||||
size.
|
||||
|
||||
|
||||
== Data Area ==
|
||||
|
||||
The data area is an area from the data offset (provided by header.data_off or
|
||||
calculated as specified above) to the end of the file. It represents a
|
||||
contiguous array of clusters. Most of them are allocated by the BAT, some may
|
||||
be allocated by the ext_off field in the header while other may be allocated by
|
||||
extensions. All clusters allocated by ext_off and extensions should meet the
|
||||
same requirements as clusters specified by BAT entries.
|
||||
|
||||
|
||||
== Format Extension ==
|
||||
|
||||
The Format Extension is an area 1 cluster in size that provides additional
|
||||
format features. This cluster is addressed by the ext_off field in the header.
|
||||
The format of the Format Extension area is the following:
|
||||
|
||||
0 - 7: magic
|
||||
Must be 0xAB234CEF23DCEA87
|
||||
|
||||
8 - 23: m_CheckSum
|
||||
The MD5 checksum of the entire Header Extension cluster except
|
||||
the first 24 bytes.
|
||||
|
||||
The above are followed by feature sections or "extensions". The last
|
||||
extension must be "End of features" (see below).
|
||||
|
||||
Each feature section has the following format:
|
||||
|
||||
0 - 7: magic
|
||||
The identifier of the feature:
|
||||
0x0000000000000000 - End of features
|
||||
0x20385FAE252CB34A - Dirty bitmap
|
||||
|
||||
8 - 15: flags
|
||||
External flags for extension:
|
||||
|
||||
Bit 0: NECESSARY
|
||||
If the software cannot load the extension (due to an
|
||||
unknown magic number or error), the file should not be
|
||||
changed. If this flag is unset and there is an error on
|
||||
loading the extension, said extension should be dropped.
|
||||
|
||||
Bit 1: TRANSIT
|
||||
If there is an unknown extension with this flag set,
|
||||
said extension should be left as is.
|
||||
|
||||
If neither NECESSARY nor TRANSIT are set, the extension should be
|
||||
dropped.
|
||||
|
||||
16 - 19: data_size
|
||||
The size of the following feature data, in bytes.
|
||||
|
||||
20 - 23: unused32
|
||||
Align header to 8 bytes boundary.
|
||||
|
||||
variable: data (data_size bytes)
|
||||
|
||||
The above is followed by padding to the next 8 bytes boundary, then the
|
||||
next extension starts.
|
||||
|
||||
The last extension must be "End of features" with all the fields set to 0.
|
||||
|
||||
|
||||
=== Dirty bitmaps feature ===
|
||||
|
||||
This feature provides a way of storing dirty bitmaps in the image. The fields
|
||||
of its data area are:
|
||||
|
||||
0 - 7: size
|
||||
The bitmap size, should be equal to disk size in sectors.
|
||||
|
||||
8 - 23: id
|
||||
An identifier for backup consistency checking.
|
||||
|
||||
24 - 27: granularity
|
||||
Bitmap granularity, in sectors. I.e., the number of sectors
|
||||
corresponding to one bit of the bitmap. Granularity must be
|
||||
a power of 2.
|
||||
|
||||
28 - 31: l1_size
|
||||
The number of entries in the L1 table of the bitmap.
|
||||
|
||||
variable: l1 (64 * l1_size bytes)
|
||||
L1 offset table (in bytes)
|
||||
|
||||
A dirty bitmap is stored using a one-level structure for the mapping to host
|
||||
clusters - an L1 table.
|
||||
|
||||
Given an offset in bytes into the bitmap data, the offset in bytes into the
|
||||
image file can be obtained as follows:
|
||||
|
||||
offset = l1_table[offset / cluster_size] + (offset % cluster_size)
|
||||
|
||||
If an L1 table entry is 0, the corresponding cluster of the bitmap is assumed
|
||||
to be zero.
|
||||
|
||||
If an L1 table entry is 1, the corresponding cluster of the bitmap is assumed
|
||||
to have all bits set.
|
||||
|
||||
If an L1 table entry is not 0 or 1, it allocates a cluster from the data area.
|
@ -407,24 +407,16 @@ void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
|
||||
for (i = 0; i < mrb->num_reqs; i++) {
|
||||
VirtIOBlockReq *req = mrb->reqs[i];
|
||||
if (num_reqs > 0) {
|
||||
bool merge = true;
|
||||
|
||||
/* merge would exceed maximum number of IOVs */
|
||||
if (niov + req->qiov.niov > IOV_MAX) {
|
||||
merge = false;
|
||||
}
|
||||
|
||||
/* merge would exceed maximum transfer length of backend device */
|
||||
if (req->qiov.size / BDRV_SECTOR_SIZE + nb_sectors > max_xfer_len) {
|
||||
merge = false;
|
||||
}
|
||||
|
||||
/* requests are not sequential */
|
||||
if (sector_num + nb_sectors != req->sector_num) {
|
||||
merge = false;
|
||||
}
|
||||
|
||||
if (!merge) {
|
||||
/*
|
||||
* NOTE: We cannot merge the requests in below situations:
|
||||
* 1. requests are not sequential
|
||||
* 2. merge would exceed maximum number of IOVs
|
||||
* 3. merge would exceed maximum transfer length of backend device
|
||||
*/
|
||||
if (sector_num + nb_sectors != req->sector_num ||
|
||||
niov > blk_get_max_iov(blk) - req->qiov.niov ||
|
||||
req->qiov.size / BDRV_SECTOR_SIZE > max_xfer_len ||
|
||||
nb_sectors > max_xfer_len - req->qiov.size / BDRV_SECTOR_SIZE) {
|
||||
submit_requests(blk, mrb, start, num_reqs, niov);
|
||||
num_reqs = 0;
|
||||
}
|
||||
|
@ -193,7 +193,9 @@ static void sdhci_reset(SDHCIState *s)
|
||||
* initialization */
|
||||
memset(&s->sdmasysad, 0, (uintptr_t)&s->capareg - (uintptr_t)&s->sdmasysad);
|
||||
|
||||
sd_set_cb(s->card, s->ro_cb, s->eject_cb);
|
||||
if (!s->noeject_quirk) {
|
||||
sd_set_cb(s->card, s->ro_cb, s->eject_cb);
|
||||
}
|
||||
s->data_count = 0;
|
||||
s->stopped_state = sdhc_not_stopped;
|
||||
}
|
||||
@ -243,9 +245,6 @@ static void sdhci_send_command(SDHCIState *s)
|
||||
(s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
|
||||
s->norintsts |= SDHC_NIS_TRSCMP;
|
||||
}
|
||||
} else if (rlen != 0 && (s->errintstsen & SDHC_EISEN_CMDIDX)) {
|
||||
s->errintsts |= SDHC_EIS_CMDIDX;
|
||||
s->norintsts |= SDHC_NIS_ERR;
|
||||
}
|
||||
|
||||
if (s->norintstsen & SDHC_NISEN_CMDCMP) {
|
||||
@ -831,7 +830,7 @@ static void sdhci_data_transfer(void *opaque)
|
||||
|
||||
static bool sdhci_can_issue_command(SDHCIState *s)
|
||||
{
|
||||
if (!SDHC_CLOCK_IS_ON(s->clkcon) || !(s->pwrcon & SDHC_POWER_ON) ||
|
||||
if (!SDHC_CLOCK_IS_ON(s->clkcon) ||
|
||||
(((s->prnsts & SDHC_DATA_INHIBIT) || s->stopped_state) &&
|
||||
((s->cmdreg & SDHC_CMD_DATA_PRESENT) ||
|
||||
((s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY &&
|
||||
@ -1279,6 +1278,7 @@ static Property sdhci_sysbus_properties[] = {
|
||||
DEFINE_PROP_UINT32("capareg", SDHCIState, capareg,
|
||||
SDHC_CAPAB_REG_DEFAULT),
|
||||
DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0),
|
||||
DEFINE_PROP_BOOL("noeject-quirk", SDHCIState, noeject_quirk, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -330,6 +330,9 @@ typedef struct BlockLimits {
|
||||
|
||||
/* memory alignment for bounce buffer */
|
||||
size_t opt_mem_alignment;
|
||||
|
||||
/* maximum number of iovec elements */
|
||||
int max_iov;
|
||||
} BlockLimits;
|
||||
|
||||
typedef struct BdrvOpBlocker BdrvOpBlocker;
|
||||
|
@ -77,6 +77,7 @@ typedef struct SDHCIState {
|
||||
uint32_t buf_maxsz;
|
||||
uint16_t data_count; /* current element in FIFO buffer */
|
||||
uint8_t stopped_state;/* Current SDHC state */
|
||||
bool noeject_quirk;/* Quirk to disable card insert/remove interrupts */
|
||||
/* Buffer Data Port Register - virtual access point to R and W buffers */
|
||||
/* Software Reset Register - always reads as 0 */
|
||||
/* Force Event Auto CMD12 Error Interrupt Reg - write only */
|
||||
|
@ -146,6 +146,7 @@ void blk_lock_medium(BlockBackend *blk, bool locked);
|
||||
void blk_eject(BlockBackend *blk, bool eject_flag);
|
||||
int blk_get_flags(BlockBackend *blk);
|
||||
int blk_get_max_transfer_length(BlockBackend *blk);
|
||||
int blk_get_max_iov(BlockBackend *blk);
|
||||
void blk_set_guest_block_size(BlockBackend *blk, int align);
|
||||
void *blk_blockalign(BlockBackend *blk, size_t size);
|
||||
bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp);
|
||||
|
@ -21,7 +21,7 @@ def isnull(ptr):
|
||||
return ptr == gdb.Value(0).cast(ptr.type)
|
||||
|
||||
def int128(p):
|
||||
return long(p['lo']) + (long(p['hi']) << 64)
|
||||
return int(p['lo']) + (int(p['hi']) << 64)
|
||||
|
||||
class MtreeCommand(gdb.Command):
|
||||
'''Display the memory tree hierarchy'''
|
||||
@ -40,11 +40,11 @@ class MtreeCommand(gdb.Command):
|
||||
def process_queue(self):
|
||||
while self.queue:
|
||||
ptr = self.queue.pop(0)
|
||||
if long(ptr) in self.seen:
|
||||
if int(ptr) in self.seen:
|
||||
continue
|
||||
self.print_item(ptr)
|
||||
def print_item(self, ptr, offset = gdb.Value(0), level = 0):
|
||||
self.seen.add(long(ptr))
|
||||
self.seen.add(int(ptr))
|
||||
addr = ptr['addr']
|
||||
addr += offset
|
||||
size = int128(ptr['size'])
|
||||
@ -58,8 +58,8 @@ class MtreeCommand(gdb.Command):
|
||||
klass = ' (RAM)'
|
||||
gdb.write('%s%016x-%016x %s%s (@ %s)\n'
|
||||
% (' ' * level,
|
||||
long(addr),
|
||||
long(addr + (size - 1)),
|
||||
int(addr),
|
||||
int(addr + (size - 1)),
|
||||
ptr['name'].string(),
|
||||
klass,
|
||||
ptr,
|
||||
|
Loading…
Reference in New Issue
Block a user