Outputs are a little bit trickier than filters, because if user wants to change the set of outputs that is currently defined for a different set that may contain outputs that do already exist in the current set, opening a file descriptor for that output would only work for files, but not for syslog or journald, because that would overwrite the existing ones which might (and probably will be in use by workers). So, we need a mechanism to find out, if such an output is already defined and only copy its data. For files, the data also include the already opened file descriptor. For journald, the file descriptor is global, so nothing to copy there. Syslog is the most trickiest one, since it keeps the open file descriptor to system daemon private and cannot be reopened (to change the message prefix) until the very last moment when the whole output set is ready to be swapped with the defined one. This method is also used when deallocating a list of outputs (either the new copy that is just being prepared or the global active set of outputs). According to the paragraph above, the problem of changing data when it is being used has been solved. It still needs to be ensured that when deallocating the global active set of outputs after it was swap with the user-provided copy does not close all file descriptors, since that would cause invalid references in the copy that we just swapped. By issuing virLogOutputExist during deallocation, the described scenario can be safely prevented. --- src/libvirt_private.syms | 1 + src/util/virlog.c | 36 ++++++++++++++++++++++++++++++++++++ src/util/virlog.h | 1 + 3 files changed, 38 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 319ef18..cc40b46 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1752,6 +1752,7 @@ virLogGetNbOutputs; virLogGetOutputs; virLogLock; virLogMessage; +virLogOutputExists; virLogOutputFree; virLogOutputListFree; virLogOutputNew; diff --git a/src/util/virlog.c b/src/util/virlog.c index 9fe47fb..204372f 100644 --- a/src/util/virlog.c +++ b/src/util/virlog.c @@ -186,6 +186,42 @@ VIR_ONCE_GLOBAL_INIT(virLog) /** + * virLogOutputExists: + * @dest: destination type + * @opaque: opaque data to the method + * + * Looks for an output of destination type @dest. If such output exists, + * a reference to the output is returned, unless the destination is of type + * file in which case a comparison of the output's data with @opaque needs to + * be done first. + * + * Returns a reference to an output if one was found or NULL if such output + * does not exist. + */ +virLogOutputPtr +virLogOutputExists(virLogDestination dest, const void *opaque) +{ + size_t i; + const char *name = opaque; + + for (i = 0; i < virLogNbOutputs; i++) { + if (!virLogOutputs[i]) + continue; + + if (dest == virLogOutputs[i]->dest) { + if (dest != VIR_LOG_TO_FILE) + return virLogOutputs[i]; + + if (STREQ(virLogOutputs[i]->name, name)) + return virLogOutputs[i]; + } + } + + return NULL; +} + + +/** * virLogReset: * * Reset the logging module to its default initial state diff --git a/src/util/virlog.h b/src/util/virlog.h index 0102489..1c55a48 100644 --- a/src/util/virlog.h +++ b/src/util/virlog.h @@ -229,5 +229,6 @@ extern void virLogVMessage(virLogSourcePtr source, bool virLogProbablyLogMessage(const char *str); int virLogDefineOutputs(virLogOutputPtr *outputs, size_t noutputs); int virLogDefineFilters(virLogFilterPtr *filters, size_t nfilters); +virLogOutputPtr virLogOutputExists(virLogDestination dest, const void *opaque); #endif -- 2.4.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list