mirror of https://github.com/xemu-project/xemu.git
Block layer patches for 2.8.0-rc1
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJYNGp6AAoJEH8JsnLIjy/WAgYP/isOOb1NF6OWQKkVHc6cipMd RElj5HQlFYP7FmdP4Z2QdNI82K12G/wnctGtREAqmUQqivpJoejsLHXo70Oik6EZ KIafgD/xD1zXw+DBTsJBZI5iE/VWRXcQ7l49OqtRTqYEF0V4chzJmlo8m4+TLHbq 119b48GmjYy94a4xbgPBL3Yhude1tvkXR3VNfEQU7EzxpwTGZnH+egqdNvpMpvmY Ty400of4oq/eH25XtJ5pUESeLvUv13WTMsLMCmGBpliJx2R9nqN7ScgJW8z7/fkS z3RC49jroL1O1TIMXIY/EGzFoiGWFAdolVrnLyvzV2sFtynLcbKrM6XHXqUN6ITt rNPpjMX5cij8106kPNgwynpao4/n9abOx8RxtMBZvVVyWvJ/f6HD+gx9QFPseKXC ++l50aOkAu3oLh/KIrXcD/sLe5wCNnJRC5NjNjfi8Bi2Lxcwt8XHHYbGlyierDDW KDL98jshA3tlnC+hso7D5pnwNBt67zN4sOlBiqywZieFTJhwCvhWSUUfEXnIIIrl QV/Fu/y3ohTDiNpzJ4g0Zgb1UbTu+nccQiuaUHaUBIhgKjZR9oyAEsjdky47o67T qvB7wSsfXnURblncn303Q0BuZIGV60JTdxTXEdOp8X3dJy+mkvzH9zRagzWIk10Y FRatMVcTna8MsBJ1pYTy =1Mkm -----END PGP SIGNATURE----- Merge remote-tracking branch 'kwolf/tags/for-upstream' into staging Block layer patches for 2.8.0-rc1 # gpg: Signature made Tue 22 Nov 2016 03:55:38 PM GMT # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * kwolf/tags/for-upstream: block: Pass unaligned discard requests to drivers block: Return -ENOTSUP rather than assert on unaligned discards block: Let write zeroes fallback work even with small max_transfer qcow2: Inform block layer about discard boundaries Message-id: 1479830693-26676-1-git-send-email-kwolf@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
76989f4ffa
58
block/io.c
58
block/io.c
|
@ -1214,6 +1214,8 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
|||
int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT_MAX);
|
||||
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
|
||||
bs->bl.request_alignment);
|
||||
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
|
||||
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
|
||||
|
||||
assert(alignment % bs->bl.request_alignment == 0);
|
||||
head = offset % alignment;
|
||||
|
@ -1229,9 +1231,12 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
|||
* boundaries.
|
||||
*/
|
||||
if (head) {
|
||||
/* Make a small request up to the first aligned sector. */
|
||||
num = MIN(count, alignment - head);
|
||||
head = 0;
|
||||
/* Make a small request up to the first aligned sector. For
|
||||
* convenience, limit this request to max_transfer even if
|
||||
* we don't need to fall back to writes. */
|
||||
num = MIN(MIN(count, max_transfer), alignment - head);
|
||||
head = (head + num) % alignment;
|
||||
assert(num < max_write_zeroes);
|
||||
} else if (tail && num > alignment) {
|
||||
/* Shorten the request to the last aligned sector. */
|
||||
num -= tail;
|
||||
|
@ -1257,8 +1262,6 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
|||
|
||||
if (ret == -ENOTSUP) {
|
||||
/* Fall back to bounce buffer if write zeroes is unsupported */
|
||||
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
|
||||
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
|
||||
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
|
||||
|
||||
if ((flags & BDRV_REQ_FUA) &&
|
||||
|
@ -2421,7 +2424,7 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||
{
|
||||
BdrvTrackedRequest req;
|
||||
int max_pdiscard, ret;
|
||||
int head, align;
|
||||
int head, tail, align;
|
||||
|
||||
if (!bs->drv) {
|
||||
return -ENOMEDIUM;
|
||||
|
@ -2444,19 +2447,15 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Discard is advisory, so ignore any unaligned head or tail */
|
||||
/* Discard is advisory, but some devices track and coalesce
|
||||
* unaligned requests, so we must pass everything down rather than
|
||||
* round here. Still, most devices will just silently ignore
|
||||
* unaligned requests (by returning -ENOTSUP), so we must fragment
|
||||
* the request accordingly. */
|
||||
align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment);
|
||||
assert(align % bs->bl.request_alignment == 0);
|
||||
head = offset % align;
|
||||
if (head) {
|
||||
head = MIN(count, align - head);
|
||||
count -= head;
|
||||
offset += head;
|
||||
}
|
||||
count = QEMU_ALIGN_DOWN(count, align);
|
||||
if (!count) {
|
||||
return 0;
|
||||
}
|
||||
tail = (offset + count) % align;
|
||||
|
||||
bdrv_inc_in_flight(bs);
|
||||
tracked_request_begin(&req, bs, offset, count, BDRV_TRACKED_DISCARD);
|
||||
|
@ -2468,11 +2467,34 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||
|
||||
max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT_MAX),
|
||||
align);
|
||||
assert(max_pdiscard);
|
||||
assert(max_pdiscard >= bs->bl.request_alignment);
|
||||
|
||||
while (count > 0) {
|
||||
int ret;
|
||||
int num = MIN(count, max_pdiscard);
|
||||
int num = count;
|
||||
|
||||
if (head) {
|
||||
/* Make small requests to get to alignment boundaries. */
|
||||
num = MIN(count, align - head);
|
||||
if (!QEMU_IS_ALIGNED(num, bs->bl.request_alignment)) {
|
||||
num %= bs->bl.request_alignment;
|
||||
}
|
||||
head = (head + num) % align;
|
||||
assert(num < max_pdiscard);
|
||||
} else if (tail) {
|
||||
if (num > align) {
|
||||
/* Shorten the request to the last aligned cluster. */
|
||||
num -= tail;
|
||||
} else if (!QEMU_IS_ALIGNED(tail, bs->bl.request_alignment) &&
|
||||
tail > bs->bl.request_alignment) {
|
||||
tail %= bs->bl.request_alignment;
|
||||
num -= tail;
|
||||
}
|
||||
}
|
||||
/* limit request size */
|
||||
if (num > max_pdiscard) {
|
||||
num = max_pdiscard;
|
||||
}
|
||||
|
||||
if (bs->drv->bdrv_co_pdiscard) {
|
||||
ret = bs->drv->bdrv_co_pdiscard(bs, offset, num);
|
||||
|
|
|
@ -1083,7 +1083,9 @@ coroutine_fn iscsi_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
|
|||
struct IscsiTask iTask;
|
||||
struct unmap_list list;
|
||||
|
||||
assert(is_byte_request_lun_aligned(offset, count, iscsilun));
|
||||
if (!is_byte_request_lun_aligned(offset, count, iscsilun)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (!iscsilun->lbp.lbpu) {
|
||||
/* UNMAP is not supported by the target */
|
||||
|
|
|
@ -1206,6 +1206,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
|||
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
|
||||
}
|
||||
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
|
||||
bs->bl.pdiscard_alignment = s->cluster_size;
|
||||
}
|
||||
|
||||
static int qcow2_set_key(BlockDriverState *bs, const char *key)
|
||||
|
@ -2490,6 +2491,11 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
|
|||
int ret;
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
|
||||
if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
|
||||
assert(count < s->cluster_size);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
ret = qcow2_discard_clusters(bs, offset, count >> BDRV_SECTOR_BITS,
|
||||
QCOW2_DISCARD_REQUEST, false);
|
||||
|
|
|
@ -2829,8 +2829,9 @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||
iov.iov_len = sizeof(zero);
|
||||
discard_iov.iov = &iov;
|
||||
discard_iov.niov = 1;
|
||||
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
assert((count & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
if (!QEMU_IS_ALIGNED(offset | count, BDRV_SECTOR_SIZE)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
|
||||
count >> BDRV_SECTOR_BITS);
|
||||
acb->aiocb_type = AIOCB_DISCARD_OBJ;
|
||||
|
|
Loading…
Reference in New Issue