Il 23/10/2012 18:09, Avi Kivity ha scritto: >> But our interfaces had better support asynchronicity, and indeed they >> do: after you write to the "eject" register, the "up" will show the >> device as present until after destroy is done. This can be changed to >> show the device as present only until after step 4 is done. > > Let's say we want to eject the hotplug hardware itself (just as an > example). With refcounts, the callback that updates "up" will hold on > to to it via refcounts. With stop_machine(), you need to cancel that > callback, or wait for it somehow, or it can arrive after the > stop_machine() and bite you.
The callback that updates "up" is for the parent of the hotplug hardware. There is nothing that has to be updated in the hotplug hardware itself. Updating the "up" register is the final part of isolate(), and runs before the stop_machine(). The steps above can be further refined like this: 4a. close all backends (also cancel or complete all pending I/O) 4b. notify parent that we're done 4ba. parent removes device from its bus 4bb. parent notifies guest 4bc. parent schedules stop_machine(qdev_free(child)) 5. a bottom half calls stop_machine(qdev_free(child)) If unplugging a whole sub-tree, the parent can notify its own parent at the end of 4b. Because the only purpose of stop_machine is to quiesce subsystems not affected by step 4 (timer+memory, typically), destructions can be done in any order and even intermixed with executions of 4b for the parent. In the beginning the only asynchronous step would be 5. If the need arises we can use continuation-passing to make all the preceding steps asynchronous too. >>> We may also want notification after step 4 (or 5); if the device holds >>> some host resource someone may want to know that it is ready for reuse. >> >> I think guest notification should be after (4), while management >> notification should be after (5). > Yes. After (2) we can return from the eject mmio. Agreed. Paolo