On Thu, Jan 30, 2025 at 11:08:40AM +0100, Maciej S. Szmigiero wrote:
> +static int multifd_device_state_save_thread(void *opaque)
> +{
> + struct MultiFDDSSaveThreadData *data = opaque;
> + int ret;
> +
> + ret = data->hdlr(data->idstr, data->instance_id, &send_threads_abort,
> + data->handler_opaque);
I thought we discussed somewhere and the plan was we could use Error** here
to report errors. Would that still make sense, or maybe I lost some
context?
Meanwhile, I still feel uneasy on having these globals (send_threads_abort,
send_threads_ret). Can we make MultiFDDSSaveThreadData the only interface
between migration and the threads impl? So I wonder if it can be:
ret = data->hdlr(data);
With extended struct like this (I added thread_error and thread_quit):
struct MultiFDDSSaveThreadData {
SaveLiveCompletePrecopyThreadHandler hdlr;
char *idstr;
uint32_t instance_id;
void *handler_opaque;
/*
* Should be NULL when struct passed over to thread, the thread should
* set this if the handler would return false. It must be kept NULL if
* the handler returned true / success.
*/
Error *thread_error;
/*
* Migration core would set this when it wants to notify thread to
* quit, for example, when error occured in other threads, or migration is
* cancelled by the user.
*/
bool thread_quit;
};
Then if any multifd_device_state_save_thread() failed, for example, it
should notify all threads to quit by setting thread_quit, instead of
relying on yet another global variable to show migration needs to quit.
Thanks,
> + if (ret && !qatomic_read(&send_threads_ret)) {
> + /*
> + * Racy with the above read but that's okay - which thread error
> + * return we report is purely arbitrary anyway.
> + */
> + qatomic_set(&send_threads_ret, ret);
> + }
> +
> + return 0;
> +}
--
Peter Xu