[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3/3] piix4acpi, xen, hotplug: Fix race with ACPI AML code and hotplug.
On Mon, May 13, 2013 at 06:17:50PM +0100, Stefano Stabellini wrote: > On Mon, 13 May 2013, Konrad Rzeszutek Wilk wrote: > > This is a race so the amount varies but on a 4PCPU box > > I seem to get only ~14 out of 16 vCPUs I want to online. > > > > The issue at hand is that QEMU xenstore.c hotplug code changes > > the vCPU array and triggers an ACPI SCI for each vCPU > > online/offline change. That means we modify the array of vCPUs > > as the guests ACPI AML code is reading it - resulting in > > the guest reading the data only once and not changing the > > CPU states appropiately. > > > > The fix is to seperate the vCPU array changes from the ACPI SCI > > notification. The code now will enumerate all of the vCPUs > > and change the vCPU array if there is a need for a change. > > If a change did occur then only _one_ ACPI SCI pulse is sent > > to the guest. The vCPU array at that point has the online/offline > > modified to what the user wanted to have. > > > > Specifically, if a user provided this command: > > xl vcpu-set latest 16 > > > > (guest config has vcpus=1, maxvcpus=32) QEMU and the guest > > (in this case Linux) would do: > > > > QEMU: Guest OS: > > -xenstore_process_vcpu_set_event > > -> Gets an XenBus notification for CPU1 > > -> Updates the gpe_state.cpus_state bitfield. > > -> Pulses the ACPI SCI > > - ACPI SCI kicks in > > > > -> Gets an XenBus notification for CPU2 > > -> Updates the gpe_state.cpus_state bitfield. > > -> Pulses the ACPI SCI > > > > -> Gets an XenBus notification for CPU3 > > -> Updates the gpe_state.cpus_state bitfield. > > -> Pulses the ACPI SCI > > ... > > - Method(PRST) invoked > > > > -> Gets an XenBus notification for CPU12 > > -> Updates the gpe_state.cpus_state bitfield. > > -> Pulses the ACPI SCI > > - reads AF00 for CPU state > > [gets 0xff] > > - reads AF02 [gets 0x7f] > > > > -> Gets an XenBus notification for CPU13 > > -> Updates the gpe_state.cpus_state bitfield. > > -> Pulses the ACPI SCI > > > > .. until VCPU 16 > > - Method PRST updates > > PR01 through 13 FLG > > entry. > > - PR01->PR13 _MAD > > invoked. > > > > - Brings up 13 CPUs. > > > > While QEMU updates the rest of the cpus_state bitfields the ACPI AML > > only does the CPU hotplug on those it had read. > > > > Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> > > --- > > xenstore.c | 68 > > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ > > 1 file changed, 62 insertions(+), 6 deletions(-) > > > > diff --git a/xenstore.c b/xenstore.c > > index c861d36..31dbbe5 100644 > > --- a/xenstore.c > > +++ b/xenstore.c > > @@ -999,25 +999,24 @@ void xenstore_record_dm_state(const char *state) > > { > > xenstore_record_dm("state", state); > > } > > - > > -static void xenstore_process_vcpu_set_event(char **vec) > > +static int xenstore_process_one_vcpu_set_event(char *node) > > { > > char *act = NULL; > > - char *vcpustr, *node = vec[XS_WATCH_PATH]; > > + char *vcpustr; > > unsigned int vcpu, len; > > int changed = -EINVAL; > > > > vcpustr = strstr(node, "cpu/"); > > if (!vcpustr) { > > fprintf(stderr, "vcpu-set: watch node error.\n"); > > - return; > > + return changed; > > } > > sscanf(vcpustr, "cpu/%u", &vcpu); > > > > act = xs_read(xsh, XBT_NULL, node, &len); > > if (!act) { > > fprintf(stderr, "vcpu-set: no command yet.\n"); > > - return; > > + return changed; > > } > > > > if (!strncmp(act, "online", len)) > > @@ -1028,8 +1027,65 @@ static void xenstore_process_vcpu_set_event(char > > **vec) > > fprintf(stderr, "vcpu-set: command error.\n"); > > > > free(act); > > - if (changed > 0) > > + return changed; > > +} > > +static void xenstore_process_vcpu_set_event(char **vec) > > +{ > > + int changed = 0, rc, i, num = 0; > > + char *vcpu, **dir; > > + char *path = vec[XS_WATCH_PATH]; > > + > > + /* > > + * Process the event right away in case the loop below fails > > + * to enumerate the correct vCPU. > > + */ > > + rc = xenstore_process_one_vcpu_set_event(path); > > + if (rc > 0) > > + changed = 1; > > I am not sure I follow you here: why the loop below would fail? If there is an error (for example the xs_read fails), then the loop below would stop as rc == -EINVAL. > > > + /* > > + * We get: /local/domain/<domid>/cpu/<vcpu>/availability or > > + * (at init) /local/domain/<domid>/cpu [ignore it] and need to > > + * iterate over /local/domain/<domid>/cpu/ directory. > > + */ > > + vcpu = strstr(path, "cpu/"); > > + if (!vcpu) { > > + fprintf(stderr,"[%s]: %s has no CPU!\n", __func__, path); > > + return; > > + } > > + /* Eliminate '/availability' */ > > + vcpu[3] = '\0'; > > + dir = xs_directory(xsh, XBT_NULL, path, &num); > > + > > + if (!dir) { > > + fprintf(stderr, "[%s]: directory %s has no dirs!\n", __func__, > > path); > > + return; > > + } > > + if (num != vcpus) > > + fprintf(stderr, "[%s]: %d (number of vcpu entries) != %d > > (maxvcpus)! "\ > > + "Continuing on..\n", __func__, num, vcpus); > > + > > + for (i = 0; i < num; i++) { > > + char *attr; > > + ssize_t len = strlen(path) + strlen(dir[i]) + > > strlen("availability") + > > + 3 /* account for two '/' and '\0'*/; > > + attr = malloc(len); > > just use XEN_BUFSIZE and put in on the stack OK. > > > > + > > + /* Construct "/local/domain/<domid>/cpu" (path) with <vcpu> (attr), > > + * and "availability" with '/' sprinkled around. */ > > + snprintf(attr, len, "%s/%s/%s", path, dir[i], "availability"); > > + rc = xenstore_process_one_vcpu_set_event(attr); > > + > > + free(attr); > > + if (rc > 0) > > + changed = 1; > > + if (rc < 0) > > + break; > > Given that the user could provide a mask of vcpus to enable/disable, > shouldn't we just process them all anyway? rc < 0 is if an error occurs. 0 is if there are no changes. And xenstore_process_one_vcpu_set_event could fail (say xs_read). The top of the function would process the vCPU for which the event occured. Please keep in mind that this function is called for _each_ vCPU that has changed. > > + free (dir); > > + if (changed > 0) { > > + fprintf(stderr, "Notifying OS about CPU hotplug changes.\n"); > > qemu_cpu_notify(); > > + } > > return; > > } > > > > -- > > 1.8.1.4 > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |