[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [Qemu-devel] QEMU interfaces for image streaming and post-copy block migration

 On 09/12/2010 05:23 PM, Anthony Liguori wrote:
On 09/12/2010 08:40 AM, Avi Kivity wrote:
Why would it serialize all I/O operations? It's just like another vcpu issuing reads.

Because the block layer isn't re-entrant.

A threaded block layer is reentrant. Of course pushing the thing into a thread requires that.

What you basically do is:


stream_step_two(offset, length):
   bdrv_aio_readv(offset, length, buffer, stream_step_three)


Isn't there a write() missing somewhere?

Streaming relies on copy-on-read to do the writing.

Ah. You can avoid the copy-on-read implementation in the block format driver and do it completely in generic code.

And that's exactly what the current code looks like. The only change to the patch that this does is make some of qed's internals be block layer interfaces.

Why do you need find_free_cluster()? That's a physical offset thing. Just write to the same logical offset.


        bdrv_aio_read(offset, stream_2)

It's an optimization. If you've got a fully missing L1 entry, then you're going to memset() 2GB worth of zeros. That's just wasted work. With a 1TB image with a 1GB allocation, it's a huge amount of wasted work.

Ok. And it's a logical offset, not physical as I thought, which confused me.

        if all zeros:
            increment offset
            if more:
       bdrv_aio_write(offset, stream_3)

        bdrv_aio_write(offset, stream_4)

I don't understand why stream_3() is needed.

This implementation doesn't rely on copy-on-read code in the block format driver. It is generic and uses existing block layer interfaces. It would need copy-on-read support in the generic block layer as well.

        increment offset
        if more:

Of course, need to serialize wrt guest writes, which adds a bit more complexity. I'll leave it to you to code the state machine for that.


Clever - it pushes all the synchronization into the copy-on-read implementation. But the serialization there hardly jumps out of the code.

Do I understand correctly that you can only have one allocating read or write running?

Parts of it are: commit.  Of course, that's horribly synchronous.

If you've got AIO internally, making commit work is pretty easy. Doing asynchronous commit at a generic layer is not easy though unless you expose lots of details.

I don't see why. Commit is a simple loop that copies all clusters. All it needs to know is if a cluster is allocated or not.

When commit is running you need additional serialization against guest writes, and to direct guest writes and reads to the committed region to the backing file instead of the temporary image. But the block layer already knows of all guest writes.

Generally, I think the block layer makes more sense if the interface to the formats are high level and code sharing is achieved not by mandating a world view but rather but making libraries of common functionality. This is more akin to how the FS layer works in Linux.

So IMHO, we ought to add a bdrv_aio_commit function, turn the current code into a generic_aio_commit, implement a qed_aio_commit, then somehow do qcow2_aio_commit, and look at what we can refactor into common code.

What Linux does if have an equivalent of bdrv_generic_aio_commit() which most implementations call (or default to), and only do something if they want something special. Something like commit (or copy-on-read, or copy-on-write, or streaming) can be implement 100% in terms of the generic functions (and indeed qcow2 backing files can be any format).

error compiling committee.c: too many arguments to function

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]