summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2016-11-17 14:13:57 -0600
committerMichael Roth <mdroth@linux.vnet.ibm.com>2016-12-12 17:48:43 -0600
commit5e4eb851ddc5c7c23c0c5705fbf917b7b3a20586 (patch)
treed41404273b53b28c47e06c03ac127ec49d39ac96
parentdd11d33deb8350fd2599220bf3bb79eef8547a24 (diff)
downloadqemu-5e4eb851ddc5c7c23c0c5705fbf917b7b3a20586.tar.gz
block: Return -ENOTSUP rather than assert on unaligned discards
Right now, the block layer rounds discard requests, so that individual drivers are able to assert that discard requests will never be unaligned. But there are some ISCSI devices that track and coalesce multiple unaligned requests, turning it into an actual discard if the requests eventually cover an entire page, which implies that it is better to always pass discard requests as low down the stack as possible. In isolation, this patch has no semantic effect, since the block layer currently never passes an unaligned request through. But the block layer already has code that silently ignores drivers that return -ENOTSUP for a discard request that cannot be honored (as well as drivers that return 0 even when nothing was done). But the next patch will update the block layer to fragment discard requests, so that clients are guaranteed that they are either dealing with an unaligned head or tail, or an aligned core, making it similar to the block layer semantics of write zero fragmentation. CC: qemu-stable@nongnu.org Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> (cherry picked from commit 49228d1e95e1be879c57f5dbccb44405670e343d) Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
-rw-r--r--block/iscsi.c4
-rw-r--r--block/qcow2.c5
-rw-r--r--block/sheepdog.c5
3 files changed, 11 insertions, 3 deletions
diff --git a/block/iscsi.c b/block/iscsi.c
index b2b4e5d2a9..8bc5f7e305 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1048,7 +1048,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 */
diff --git a/block/qcow2.c b/block/qcow2.c
index 497df0f639..3a80be0411 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2486,6 +2486,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);
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 66e1cb2b2d..314b470cba 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2820,8 +2820,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;