mirror of
https://gitlab.com/qemu-project/qemu
synced 2025-04-29 09:22:36 +08:00
Block layer patches
- Discard alignment fixes - Remove unused callback .bdrv_aio_pdiscard() - qemu-img bench: Input validation fix -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmgLy7QRHGt3b2xmQHJl ZGhhdC5jb20ACgkQfwmycsiPL9YB4A//Zsbb+tVsyLBKeffwPpHF/cAzHVH7Q2dV GC2JJvfrwq0gykfjj+u4akVQnPh49QiQM623PX7O15IikwdLy45ddQcYL1qflYCs ZGmBOuz/deI74qjl67bZVqIm8WeRhwHkdutfXOL7GRe2IHbceLbwwGUcbCgOVavt LHu3E2MIbvkLJoHEgg8UbJhZZY9DTLGDaMt00Yhy3UvNHU8UDeIr8o4dxMVv3gOf +8kIjGQkYNqpWp7aCxy8vofdSFjbBp4lSCK4G83xikUw49qkwWcgZ6jyTzXALg0G V+nMjH+DnfIRqhi1skFTHQNmFc6upxr7FIOgC+G5amkKLHCPnX9j5/2pBwrk63R7 kXqzIPfRmfOTnJX+m7a9K/pE6RU9aPfr8mQdokEcQtlJkEjc6QN9HKfy/CLnJ5Id Le8jQODSZ1zRsP6Z8jyG4unj0AuOucUoXjAKQ5EWK5RoRoLMirxqDEDd9tBjcPYB JQmB/j7aTrF3aDWBs5ragCQYdcoXJbAbqLAwhaofyVRmVyjYJmWEIkPGGo946GPd /BFgaUaea4qW5+iIpWFTD9TCQEY/A7RRpT4teu7anZ/hDzLUyXLJU28xYC6LxiDZ Yoy5M/U6MLvgkBVTNuss4T3CIutBrUI7a/DLuGB+cSM6KkigQvNwLuBqPzTDfEQP sQJOP4UsX6k= =8amc -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging Block layer patches - Discard alignment fixes - Remove unused callback .bdrv_aio_pdiscard() - qemu-img bench: Input validation fix # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmgLy7QRHGt3b2xmQHJl # ZGhhdC5jb20ACgkQfwmycsiPL9YB4A//Zsbb+tVsyLBKeffwPpHF/cAzHVH7Q2dV # GC2JJvfrwq0gykfjj+u4akVQnPh49QiQM623PX7O15IikwdLy45ddQcYL1qflYCs # ZGmBOuz/deI74qjl67bZVqIm8WeRhwHkdutfXOL7GRe2IHbceLbwwGUcbCgOVavt # LHu3E2MIbvkLJoHEgg8UbJhZZY9DTLGDaMt00Yhy3UvNHU8UDeIr8o4dxMVv3gOf # +8kIjGQkYNqpWp7aCxy8vofdSFjbBp4lSCK4G83xikUw49qkwWcgZ6jyTzXALg0G # V+nMjH+DnfIRqhi1skFTHQNmFc6upxr7FIOgC+G5amkKLHCPnX9j5/2pBwrk63R7 # kXqzIPfRmfOTnJX+m7a9K/pE6RU9aPfr8mQdokEcQtlJkEjc6QN9HKfy/CLnJ5Id # Le8jQODSZ1zRsP6Z8jyG4unj0AuOucUoXjAKQ5EWK5RoRoLMirxqDEDd9tBjcPYB # JQmB/j7aTrF3aDWBs5ragCQYdcoXJbAbqLAwhaofyVRmVyjYJmWEIkPGGo946GPd # /BFgaUaea4qW5+iIpWFTD9TCQEY/A7RRpT4teu7anZ/hDzLUyXLJU28xYC6LxiDZ # Yoy5M/U6MLvgkBVTNuss4T3CIutBrUI7a/DLuGB+cSM6KkigQvNwLuBqPzTDfEQP # sQJOP4UsX6k= # =8amc # -----END PGP SIGNATURE----- # gpg: Signature made Fri 25 Apr 2025 13:51:48 EDT # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * tag 'for-upstream' of https://repo.or.cz/qemu/kevin: qemu-img: improve queue depth validation in img_bench block: Remove unused callback function *bdrv_aio_pdiscard block/io: skip head/tail requests on EINVAL file-posix: probe discard alignment on Linux block devices Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
73d29ea241
@ -1276,10 +1276,10 @@ static int get_sysfs_zoned_model(struct stat *st, BlockZoneModel *zoned)
|
||||
}
|
||||
#endif /* defined(CONFIG_BLKZONED) */
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
/*
|
||||
* Get a sysfs attribute value as a long integer.
|
||||
*/
|
||||
#ifdef CONFIG_LINUX
|
||||
static long get_sysfs_long_val(struct stat *st, const char *attribute)
|
||||
{
|
||||
g_autofree char *str = NULL;
|
||||
@ -1299,6 +1299,30 @@ static long get_sysfs_long_val(struct stat *st, const char *attribute)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a sysfs attribute value as a uint32_t.
|
||||
*/
|
||||
static int get_sysfs_u32_val(struct stat *st, const char *attribute,
|
||||
uint32_t *u32)
|
||||
{
|
||||
g_autofree char *str = NULL;
|
||||
const char *end;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = get_sysfs_str_val(st, attribute, &str);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The file is ended with '\n', pass 'end' to accept that. */
|
||||
ret = qemu_strtoui(str, &end, 10, &val);
|
||||
if (ret == 0 && end && *end == '\0') {
|
||||
*u32 = val;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int hdev_get_max_segments(int fd, struct stat *st)
|
||||
@ -1318,6 +1342,23 @@ static int hdev_get_max_segments(int fd, struct stat *st)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills in *dalign with the discard alignment and returns 0 on success,
|
||||
* -errno otherwise.
|
||||
*/
|
||||
static int hdev_get_pdiscard_alignment(struct stat *st, uint32_t *dalign)
|
||||
{
|
||||
#ifdef CONFIG_LINUX
|
||||
/*
|
||||
* Note that Linux "discard_granularity" is QEMU "discard_alignment". Linux
|
||||
* "discard_alignment" is something else.
|
||||
*/
|
||||
return get_sysfs_u32_val(st, "discard_granularity", dalign);
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLKZONED)
|
||||
/*
|
||||
* If the reset_all flag is true, then the wps of zone whose state is
|
||||
@ -1527,6 +1568,30 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
if (S_ISBLK(st.st_mode)) {
|
||||
uint32_t dalign = 0;
|
||||
int ret;
|
||||
|
||||
ret = hdev_get_pdiscard_alignment(&st, &dalign);
|
||||
if (ret == 0) {
|
||||
uint32_t ralign = bs->bl.request_alignment;
|
||||
|
||||
/* Probably never happens, but handle it just in case */
|
||||
if (dalign < ralign && (ralign % dalign == 0)) {
|
||||
dalign = ralign;
|
||||
}
|
||||
|
||||
/* The block layer requires a multiple of request_alignment */
|
||||
if (dalign % ralign != 0) {
|
||||
error_setg(errp, "Invalid pdiscard_alignment limit %u is not a "
|
||||
"multiple of request_alignment %u", dalign, ralign);
|
||||
return;
|
||||
}
|
||||
|
||||
bs->bl.pdiscard_alignment = dalign;
|
||||
}
|
||||
}
|
||||
|
||||
raw_refresh_zoned_limits(bs, &st, errp);
|
||||
}
|
||||
|
||||
|
35
block/io.c
35
block/io.c
@ -3102,18 +3102,19 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bs->drv->bdrv_co_pdiscard && !bs->drv->bdrv_aio_pdiscard) {
|
||||
if (!bs->drv->bdrv_co_pdiscard) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Invalidate the cached block-status data range if this discard overlaps */
|
||||
bdrv_bsc_invalidate_range(bs, offset, bytes);
|
||||
|
||||
/* Discard is advisory, but some devices track and coalesce
|
||||
/*
|
||||
* 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. */
|
||||
* round here. Still, most devices reject unaligned requests with
|
||||
* -EINVAL or -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;
|
||||
@ -3161,26 +3162,14 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
||||
ret = -ENOMEDIUM;
|
||||
goto out;
|
||||
}
|
||||
if (bs->drv->bdrv_co_pdiscard) {
|
||||
ret = bs->drv->bdrv_co_pdiscard(bs, offset, num);
|
||||
} else {
|
||||
BlockAIOCB *acb;
|
||||
CoroutineIOCompletion co = {
|
||||
.coroutine = qemu_coroutine_self(),
|
||||
};
|
||||
|
||||
acb = bs->drv->bdrv_aio_pdiscard(bs, offset, num,
|
||||
bdrv_co_io_em_complete, &co);
|
||||
if (acb == NULL) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
} else {
|
||||
qemu_coroutine_yield();
|
||||
ret = co.ret;
|
||||
}
|
||||
}
|
||||
ret = bs->drv->bdrv_co_pdiscard(bs, offset, num);
|
||||
if (ret && ret != -ENOTSUP) {
|
||||
goto out;
|
||||
if (ret == -EINVAL && (offset % align != 0 || num % align != 0)) {
|
||||
/* Silently skip rejected unaligned head/tail requests */
|
||||
} else {
|
||||
goto out; /* bail out */
|
||||
}
|
||||
}
|
||||
|
||||
offset += num;
|
||||
|
@ -506,10 +506,6 @@ struct BlockDriver {
|
||||
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
|
||||
BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
|
||||
|
||||
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pdiscard)(
|
||||
BlockDriverState *bs, int64_t offset, int bytes,
|
||||
BlockCompletionFunc *cb, void *opaque);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_readv)(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
|
||||
|
||||
|
@ -4571,7 +4571,7 @@ static int img_bench(int argc, char **argv)
|
||||
{
|
||||
unsigned long res;
|
||||
|
||||
if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
|
||||
if (qemu_strtoul(optarg, NULL, 0, &res) <= 0 || res > INT_MAX) {
|
||||
error_report("Invalid queue depth specified");
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user