[libvirt] [PATCHv7 14/18] util: Add function for checking if monitor is running
Wang, Huaqiang
huaqiang.wang at intel.com
Mon Nov 12 12:03:16 UTC 2018
This patch is added previously because I though the vcpupid would be
changed during
libvirt re-connection, and if vcpupid is changed and libvirt is not
aware of this change
it will make monitor working on an stale *tasks file and monitor will
get wrong
cache information.
But the vcpuid will not change in process of libvirt re-connection, the
*tasks file is always
tacking on right PIDs. So this patch is not necessary now, will be
removed in next update
of patch series.
Thanks for review.
Huaqiang
On 11/6/2018 3:07 AM, John Ferlan wrote:
> On 10/22/18 4:01 AM, Wang Huaqiang wrote:
>> Check whether monitor is running by checking the monitor's PIDs status.
>>
>> Monitor is looked as running normally if the vcpu PID list matches with
>> the content of monitor's 'tasks' file.
>>
>> Signed-off-by: Wang Huaqiang<huaqiang.wang at intel.com>
>> ---
>> src/libvirt_private.syms | 1 +
>> src/util/virresctrl.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++-
>> src/util/virresctrl.h | 3 ++
>> 3 files changed, 105 insertions(+), 1 deletion(-)
>>
>> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
>> index d59ac86..91801ed 100644
>> --- a/src/libvirt_private.syms
>> +++ b/src/libvirt_private.syms
>> @@ -2684,6 +2684,7 @@ virResctrlMonitorAddPID;
>> virResctrlMonitorCreate;
>> virResctrlMonitorDeterminePath;
>> virResctrlMonitorGetID;
>> +virResctrlMonitorIsRunning;
>> virResctrlMonitorNew;
>> virResctrlMonitorRemove;
>> virResctrlMonitorSetAlloc;
>> diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
>> index b0205bc..fa3e6e9 100644
>> --- a/src/util/virresctrl.c
>> +++ b/src/util/virresctrl.c
>> @@ -359,6 +359,9 @@ struct _virResctrlMonitor {
>> /* libvirt-generated path in /sys/fs/resctrl for this particular
>> * monitor */
>> char *path;
>> + /* Tracking the tasks' PID associated with this monitor */
>> + pid_t *pids;
>> + size_t npids;
>> };
>>
>>
>> @@ -418,6 +421,7 @@ virResctrlMonitorDispose(void *obj)
>> virObjectUnref(monitor->alloc);
>> VIR_FREE(monitor->id);
>> VIR_FREE(monitor->path);
>> + VIR_FREE(monitor->pids);
>> }
>>
>>
>> @@ -2540,7 +2544,20 @@ int
>> virResctrlMonitorAddPID(virResctrlMonitorPtr monitor,
>> pid_t pid)
>> {
>> - return virResctrlAddPID(monitor->path, pid);
>> + size_t i = 0;
>> +
>> + if (virResctrlAddPID(monitor->path, pid) < 0)
>> + return -1;
>> +
>> + for (i = 0; i < monitor->npids; i++) {
>> + if (pid == monitor->pids[i])
>> + return 0;
>> + }
>> +
>> + if (VIR_APPEND_ELEMENT(monitor->pids, monitor->npids, pid) < 0)
>> + return -1;
>> +
>> + return 0;
> could just be a return VIR_APPEND_ELEMENT()
>
> So we theoretically have our @pid in the task file (ResctrlAddPID) and
> this internal list of pids which makes me wonder why other than
> "quicker" lookup than opening the tasks file and looking for our pid, right?
>
> But based on the next hunk for virResctrlMonitorIsRunning, I'm not so
> sure. In fact I wonder why are we doing this?
>
>> }
>>
>>
>> @@ -2613,3 +2630,86 @@ virResctrlMonitorRemove(virResctrlMonitorPtr monitor)
>>
>> return ret;
>> }
>> +
>> +
>> +static int
>> +virResctrlPIDSorter(const void *pida, const void *pidb)
>> +{
>> + return *(pid_t*)pida - *(pid_t*)pidb;
>> +}
>> +
>> +
>> +bool
>> +virResctrlMonitorIsRunning(virResctrlMonitorPtr monitor)
>> +{
>> + char *pidstr = NULL;
>> + char **spids = NULL;
>> + size_t nspids = 0;
>> + pid_t *pids = NULL;
>> + size_t npids = 0;
>> + size_t i = 0;
>> + int rv = -1;
>> + bool ret = false;
>> +
> So this is a heavyweight type method and seems to me to do far more than
> just determine if a monitor is running. In fact, it seems it's
> validating that the internal list of monitor->pids matches whatever is
> in the *tasks file. There's multiple failure scenarios that may or may
> not "mean" a monitor is or isn't running.
>
>> + /* path is not determined yet, monitor is not running*/
>> + if (!monitor->path)
>> + return false;
>> +
>> + /* No vcpu PID filled, regard monitor as not running */
>> + if (monitor->npids == 0)
>> + return false;
>> +
>> + /* If no 'tasks' file found, underlying resctrl directory is not
>> + * ready, regard monitor as not running */
>> + rv = virFileReadValueString(&pidstr, "%s/tasks", monitor->path);
>> + if (rv < 0)
>> + goto cleanup;
> So we read the file, but while we're reading someone could have added to
> it... There's some locking concerns here.
>
> The *tasks file can have a pid added by a <cache> and the same pid added
> by a <monitor> it seems at least from my reading of qemuProcessSetupVcpu
> logic where virResctrlAllocAddPID would be called first followed by a
> call to virResctrlMonitorAddPID. Neither checks if the pid exists before
> writing (so yes more questions/concerns about patch 13 logic).
>
>> +
>> + /* no PID in task file, monitor is not running */
>> + if (!*pidstr)
>> + goto cleanup;
>> +
>> + /* The tracking monitor PID list is not identical to the
>> + * list in current resctrl directory. monitor is corrupted,
>> + * report error and un-running state */
>> + spids = virStringSplitCount(pidstr, "\n", 0, &nspids);
>> + if (nspids != monitor->npids) {
>> + VIR_ERROR(_("Monitor %s PID list mismatch in length"), monitor->path);
>> + goto cleanup;
>> + }
> See this doesn't make sense - why have a lookaside list then? Either
> you trust what's in your file or you don't.
>
> Having boolean logic return true/false where false can either be an
> error generated or a truly false value just doesn't seem right.
>
>> +
>> + for (i = 0; i < nspids; i++) {
>> + unsigned int val = 0;
>> + pid_t pid = 0;
>> +
>> + if (virStrToLong_uip(spids[i], NULL, 0, &val) < 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR,
>> + _("Monitor %s failed in parse PID list"),
>> + monitor->path);
>> + goto cleanup;
>> + }
>> +
>> + pid = (pid_t)val;
>> +
>> + if (VIR_APPEND_ELEMENT(pids, npids, pid) < 0)
>> + goto cleanup;
>> + }
> So we're building this list and could have problems doing so.
>
> I'm not sure this is "good" and why we need to do this. Either keep an
> internal list of pids or keep the list of pids in a file.
>
> John
>
>> +
>> + qsort(pids, npids, sizeof(pid_t), virResctrlPIDSorter);
>> + qsort(monitor->pids, monitor->npids, sizeof(pid_t), virResctrlPIDSorter);
>> +
>> + for (i = 0; i < monitor->npids; i++) {
>> + if (monitor->pids[i] != pids[i]) {
>> + VIR_ERROR(_("Monitor %s PID list corrupted"), monitor->path);
>> + goto cleanup;
>> + }
>> + }
>> +
>> + ret = true;
>> + cleanup:
>> + virStringListFree(spids);
>> + VIR_FREE(pids);
>> + VIR_FREE(pidstr);
>> +
>> + return ret;
>> +}
>> diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
>> index 804d6f5..8d8fdc2 100644
>> --- a/src/util/virresctrl.h
>> +++ b/src/util/virresctrl.h
>> @@ -219,4 +219,7 @@ virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor,
>>
>> int
>> virResctrlMonitorRemove(virResctrlMonitorPtr monitor);
>> +
>> +bool
>> +virResctrlMonitorIsRunning(virResctrlMonitorPtr monitor);
>> #endif /* __VIR_RESCTRL_H__ */
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20181112/619ce73e/attachment-0001.htm>
More information about the libvir-list
mailing list