Message ID | 20240930084325.187606-4-vsementsov@yandex-team.ru |
---|---|
State | New |
Headers | show |
Series | [PULL,1/5] copy-before-write: allow specifying minimum cluster size | expand |
30.09.2024 11:43, Vladimir Sementsov-Ogievskiy wrote: > From: Fiona Ebner <f.ebner@proxmox.com> > > Allow overlapping request by removing the assert that made it > impossible. There are only two callers: > > 1. block_copy_task_create() > > It already asserts the very same condition before calling > reqlist_init_req(). > > 2. cbw_snapshot_read_lock() > > There is no need to have read requests be non-overlapping in > copy-before-write when used for snapshot-access. In fact, there was no > protection against two callers of cbw_snapshot_read_lock() calling > reqlist_init_req() with overlapping ranges and this could lead to an > assertion failure [1]. > > In particular, with the reproducer script below [0], two > cbw_co_snapshot_block_status() callers could race, with the second > calling reqlist_init_req() before the first one finishes and removes > its conflicting request. Hm. This one applies to 7.2 too (current oldest stable series), with the description above matching what the code is doing. I picked it up for up to 7.2. Please let me know if this shouldn't be done :) Thanks, /mjt
On 01.10.24 19:28, Michael Tokarev wrote: > 30.09.2024 11:43, Vladimir Sementsov-Ogievskiy wrote: >> From: Fiona Ebner <f.ebner@proxmox.com> >> >> Allow overlapping request by removing the assert that made it >> impossible. There are only two callers: >> >> 1. block_copy_task_create() >> >> It already asserts the very same condition before calling >> reqlist_init_req(). >> >> 2. cbw_snapshot_read_lock() >> >> There is no need to have read requests be non-overlapping in >> copy-before-write when used for snapshot-access. In fact, there was no >> protection against two callers of cbw_snapshot_read_lock() calling >> reqlist_init_req() with overlapping ranges and this could lead to an >> assertion failure [1]. >> >> In particular, with the reproducer script below [0], two >> cbw_co_snapshot_block_status() callers could race, with the second >> calling reqlist_init_req() before the first one finishes and removes >> its conflicting request. > > Hm. This one applies to 7.2 too (current oldest stable series), with > the description above matching what the code is doing. > > I picked it up for up to 7.2. Please let me know if this shouldn't be > done :) > I don't see any problems) Still, that's not a guarantee that we don't have them. At least, we definitely lack a test for this case.
diff --git a/block/copy-before-write.c b/block/copy-before-write.c index e835987e52..81afeff1c7 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -66,7 +66,8 @@ typedef struct BDRVCopyBeforeWriteState { /* * @frozen_read_reqs: current read requests for fleecing user in bs->file - * node. These areas must not be rewritten by guest. + * node. These areas must not be rewritten by guest. There can be multiple + * overlapping read requests. */ BlockReqList frozen_read_reqs; diff --git a/block/reqlist.c b/block/reqlist.c index 08cb57cfa4..098e807378 100644 --- a/block/reqlist.c +++ b/block/reqlist.c @@ -20,8 +20,6 @@ void reqlist_init_req(BlockReqList *reqs, BlockReq *req, int64_t offset, int64_t bytes) { - assert(!reqlist_find_conflict(reqs, offset, bytes)); - *req = (BlockReq) { .offset = offset, .bytes = bytes,