Am 12.04.2018 um 22:44 hat Paolo Bonzini geschrieben: > On 12/04/2018 16:25, Kevin Wolf wrote: > > This is already the order we have there. What is probably different from > > what you envision is that after the parents have concluded, we still > > check that they are still quiescent in every iteration. > > Yes, and that's the quadratic part. > > > What we could do easily is introducing a bool bs->quiesce_concluded or > > something that bdrv_drain_poll() sets to true the first time that it > > returns false. It also gets a shortcut so that it returns false > > immediately if bs->quiesce_concluded is true. The field is reset in > > bdrv_do_drained_end() when bs->quiesce_counter reaches 0. > > Or bs->quiescent, for the sake of bikeshedding.
Yes, that sounds better. The only problem with the proposal as I made it is that it's wrong. We can't keep bs->quiescent until bdrv_do_drained_end() because the caller can issue new requests and then have a nested drained section that needs to wait for all requests again instead of deciding that everything is already quiescent. Maybe where we should really reset it is in the initial recursion of bdrv_do_drained_begin(), specifically in bdrv_do_drained_begin_quiesce() which is called by both the parent and the child recursion. There don't seem to be completely obviously correct solutions (can't an I/O thread be draining a specific node while the main loop runs drain_all?), but this would probably be the most obvious one. Hm... Or actually, reset bs->quiescent in bdrv_inc_in_flight()? Would this be enough? Kevin