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:
Stefan Hajnoczi 2016-11-22 19:30:03 +00:00
commit 76989f4ffa
4 changed files with 52 additions and 21 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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;