17.05.2021 15:07, Vladimir Sementsov-Ogievskiy wrote:
3.1 and make it possible to modify the bitmap externally, so that consumer of
fleecing can say to backup-top filter: I've already copied these blocks, don't
bother with copying them to temp image". This is to solve [2].
Still, how consumer of fleecing will reset shared bitmap after copying blocks? I have the
following idea: we make a "discard-bitmap-filter" filter driver, that own some
bitmap and on discard request unset corresponding bits. Also, on read, if read from the
region with unset bits the EINVAL returned immediately. This way both consumers (backup
job and NBD client) are able to use this interface:
Backup job can simply call discard on source, we can add an option for this.
External backup tool will send TRIM request after reading some region. This way
disk space will be freed and no extra copy-before-write operations will be
done. I also have a side idea that we can implement READ_ONCE flag, so that
READ and TRIM can be done in one NBD command. But this works only for clients
that don't want to implement any kind of retrying.
So, finally, how will it look (here I call backup-top with a new name, and "file" child is used
instead of "backing", as this change I propose in "[PATCH 00/21] block: publish backup-top
filter"):
Pull backup:
┌────────────────────────────────────┐
│ NBD export │
└────────────────────────────────────┘
│
│
┌────────────────────────────────────┐ file
┌───────────────────────────────────────┐ backing ┌─────────────┐
│ discard-bitmap filter (bitmap=bm0) │ ──────▶ │ temp qcow2 img
│ ─────────▶ │ active disk │
└────────────────────────────────────┘
└───────────────────────────────────────┘ └─────────────┘
▲
▲
│ target
│
│
│
┌────────────────────────────────────┐
┌───────────────────────────────────────┐ file │
│ guest blk │ ──────▶ │ copy-before-write filter
(bitmap=bm0) │ ─────────────┘
└────────────────────────────────────┘
└───────────────────────────────────────┘
Now I think that discard-bitmap is not really good idea:
1. If it is separate of internal BlockCopyState::copy_bitmap, than we'll have
to consider both bitmaps inside block-copy code, it's not a small complication.
2. Using BlockCopyState::copy_bitmap directly seems possible:
User creates copy_bitmap by hand, and pass to copy-before-write filter as an
option, block-copy will use this bitmap directly
Same bitmap is passed to discard-bitmap filter, so that it can clear bits on
discards.
Pros:
- we don't make block-copy code more complicated
Note then, that BlockCopyState::copy_bitmap is used in block-copy process as
follows:
- copy tasks are created to copy dirty areas
- when task is created, corresponding dirty area is cleared (so that creating
tasks on same area can't happen)
- if task failed, corresponding area becomes dirty again (so that it can be
retried)
So, we have
Cons:
- if discard comes when task is in-flight, bits are already clean. Then if
task failed bits become dirty again. That's wrong. Not very bad, and not worth
doing coplications of [1]. But still, keep it in mind [*]
- we have to use separate bitmap in discard-filter to fail reads from
non-dirty areas (because BlockCopyState::copy_bitmap is cleared by block-copy
process, not only by discards). That is worse.. It just means that
discard-filter is strange thing and we don't have good understanding of what
should it do. Good documentation will help of course, but...
...this all leads me to new idea:
Let's go without discard-bitmap filter with the simple logic:
If discard is done on block-copy target, let's inform block-copy about it. So,
block-copy can:
- clear corresponding area in its internal bitmap
- [not really improtant, but it addresses [*]]: cancel in-flight tasks in
discarded area.
Pros: avoid extra filter
--
Best regards,
Vladimir