diff --git a/daemons/based/based_notify.c b/daemons/based/based_notify.c
index 71374cf5ff..2fbae8078f 100644
--- a/daemons/based/based_notify.c
+++ b/daemons/based/based_notify.c
@@ -1,279 +1,280 @@
 /*
  * Copyright 2004-2020 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <time.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 
 #include <crm/common/xml.h>
 #include <crm/common/remote_internal.h>
 #include <pacemaker-based.h>
 
 int pending_updates = 0;
 
 struct cib_notification_s {
     xmlNode *msg;
     struct iovec *iov;
     int32_t iov_size;
 };
 
 void attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib);
 
-void do_cib_notify(int options, const char *op, xmlNode * update,
-                   int result, xmlNode * result_data, const char *msg_type);
+static void do_cib_notify(int options, const char *op, xmlNode *update,
+                          int result, xmlNode * result_data,
+                          const char *msg_type);
 
 static gboolean
 cib_notify_send_one(gpointer key, gpointer value, gpointer user_data)
 {
     const char *type = NULL;
     gboolean do_send = FALSE;
 
     pcmk__client_t *client = value;
     struct cib_notification_s *update = user_data;
 
     CRM_CHECK(client != NULL, return TRUE);
     CRM_CHECK(update != NULL, return TRUE);
 
     if (client->ipcs == NULL && client->remote == NULL) {
         crm_warn("Skipping client with NULL channel");
         return FALSE;
     }
 
     type = crm_element_value(update->msg, F_SUBTYPE);
     CRM_LOG_ASSERT(type != NULL);
 
     if (pcmk_is_set(client->flags, cib_notify_diff)
         && pcmk__str_eq(type, T_CIB_DIFF_NOTIFY, pcmk__str_casei)) {
 
         do_send = TRUE;
 
     } else if (pcmk_is_set(client->flags, cib_notify_replace)
                && pcmk__str_eq(type, T_CIB_REPLACE_NOTIFY, pcmk__str_casei)) {
         do_send = TRUE;
 
     } else if (pcmk_is_set(client->flags, cib_notify_confirm)
                && pcmk__str_eq(type, T_CIB_UPDATE_CONFIRM, pcmk__str_casei)) {
         do_send = TRUE;
 
     } else if (pcmk_is_set(client->flags, cib_notify_pre)
                && pcmk__str_eq(type, T_CIB_PRE_NOTIFY, pcmk__str_casei)) {
         do_send = TRUE;
 
     } else if (pcmk_is_set(client->flags, cib_notify_post)
                && pcmk__str_eq(type, T_CIB_POST_NOTIFY, pcmk__str_casei)) {
 
         do_send = TRUE;
     }
 
     if (do_send) {
         switch (PCMK__CLIENT_TYPE(client)) {
             case pcmk__client_ipc:
                 if (pcmk__ipc_send_iov(client, update->iov,
                                        crm_ipc_server_event) != pcmk_rc_ok) {
                     crm_warn("Notification of client %s/%s failed", client->name, client->id);
                 }
                 break;
 #ifdef HAVE_GNUTLS_GNUTLS_H
             case pcmk__client_tls:
 #endif
             case pcmk__client_tcp:
                 crm_debug("Sent %s notification to client %s/%s", type, client->name, client->id);
                 pcmk__remote_send_xml(client->remote, update->msg);
                 break;
             default:
                 crm_err("Unknown transport for %s " CRM_XS " flags=0x%llx",
                         pcmk__client_name(client),
                         (unsigned long long) client->flags);
         }
     }
     return FALSE;
 }
 
 static void
 cib_notify_send(xmlNode * xml)
 {
     struct iovec *iov;
     struct cib_notification_s update;
 
     ssize_t bytes = 0;
     int rc = pcmk__ipc_prepare_iov(0, xml, 0, &iov, &bytes);
 
     crm_trace("Notifying clients");
     if (rc == pcmk_rc_ok) {
         update.msg = xml;
         update.iov = iov;
         update.iov_size = bytes;
         pcmk__foreach_ipc_client_remove(cib_notify_send_one, &update);
 
     } else {
         crm_notice("Could not notify clients: %s " CRM_XS " rc=%d",
                    pcmk_rc_str(rc), rc);
     }
     pcmk_free_ipc_event(iov);
     crm_trace("Notify complete");
 }
 
 void
 cib_diff_notify(int options, const char *client, const char *call_id, const char *op,
                 xmlNode * update, int result, xmlNode * diff)
 {
     int add_updates = 0;
     int add_epoch = 0;
     int add_admin_epoch = 0;
 
     int del_updates = 0;
     int del_epoch = 0;
     int del_admin_epoch = 0;
 
     int log_level = LOG_TRACE;
 
     if (diff == NULL) {
         return;
     }
 
     if (result != pcmk_ok) {
         log_level = LOG_WARNING;
     }
 
     cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
                              &del_admin_epoch, &del_epoch, &del_updates);
 
     if (add_updates != del_updates) {
         do_crm_log(log_level,
                    "Update (client: %s%s%s): %d.%d.%d -> %d.%d.%d (%s)",
                    client, call_id ? ", call:" : "", call_id ? call_id : "",
                    del_admin_epoch, del_epoch, del_updates,
                    add_admin_epoch, add_epoch, add_updates, pcmk_strerror(result));
 
     } else if (diff != NULL) {
         do_crm_log(log_level,
                    "Local-only Change (client:%s%s%s): %d.%d.%d (%s)",
                    client, call_id ? ", call: " : "", call_id ? call_id : "",
                    add_admin_epoch, add_epoch, add_updates, pcmk_strerror(result));
     }
 
     do_cib_notify(options, op, update, result, diff, T_CIB_DIFF_NOTIFY);
 }
 
-void
+static void
 do_cib_notify(int options, const char *op, xmlNode * update,
               int result, xmlNode * result_data, const char *msg_type)
 {
     xmlNode *update_msg = NULL;
     const char *id = NULL;
 
     update_msg = create_xml_node(NULL, "notify");
 
     if (result_data != NULL) {
         id = crm_element_value(result_data, XML_ATTR_ID);
     }
 
     crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
     crm_xml_add(update_msg, F_SUBTYPE, msg_type);
     crm_xml_add(update_msg, F_CIB_OPERATION, op);
     crm_xml_add_int(update_msg, F_CIB_RC, result);
 
     if (id != NULL) {
         crm_xml_add(update_msg, F_CIB_OBJID, id);
     }
 
     if (update != NULL) {
         crm_trace("Setting type to update->name: %s", crm_element_name(update));
         crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(update));
 
     } else if (result_data != NULL) {
         crm_trace("Setting type to new_obj->name: %s", crm_element_name(result_data));
         crm_xml_add(update_msg, F_CIB_OBJTYPE, crm_element_name(result_data));
 
     } else {
         crm_trace("Not Setting type");
     }
 
     attach_cib_generation(update_msg, "cib_generation", the_cib);
     if (update != NULL) {
         add_message_xml(update_msg, F_CIB_UPDATE, update);
     }
     if (result_data != NULL) {
         add_message_xml(update_msg, F_CIB_UPDATE_RESULT, result_data);
     }
 
     cib_notify_send(update_msg);
     free_xml(update_msg);
 }
 
 void
 attach_cib_generation(xmlNode * msg, const char *field, xmlNode * a_cib)
 {
     xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
 
     if (a_cib != NULL) {
         copy_in_properties(generation, a_cib);
     }
     add_message_xml(msg, field, generation);
     free_xml(generation);
 }
 
 void
 cib_replace_notify(const char *origin, xmlNode * update, int result, xmlNode * diff)
 {
     xmlNode *replace_msg = NULL;
 
     int add_updates = 0;
     int add_epoch = 0;
     int add_admin_epoch = 0;
 
     int del_updates = 0;
     int del_epoch = 0;
     int del_admin_epoch = 0;
 
     if (diff == NULL) {
         return;
     }
 
     cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
                              &del_admin_epoch, &del_epoch, &del_updates);
 
     if (del_updates < 0) {
         crm_log_xml_debug(diff, "Bad replace diff");
     }
 
     if (add_updates != del_updates) {
         crm_info("Replaced: %d.%d.%d -> %d.%d.%d from %s",
                  del_admin_epoch, del_epoch, del_updates,
                  add_admin_epoch, add_epoch, add_updates, crm_str(origin));
     } else if (diff != NULL) {
         crm_info("Local-only Replace: %d.%d.%d from %s",
                  add_admin_epoch, add_epoch, add_updates, crm_str(origin));
     }
 
     replace_msg = create_xml_node(NULL, "notify-replace");
     crm_xml_add(replace_msg, F_TYPE, T_CIB_NOTIFY);
     crm_xml_add(replace_msg, F_SUBTYPE, T_CIB_REPLACE_NOTIFY);
     crm_xml_add(replace_msg, F_CIB_OPERATION, CIB_OP_REPLACE);
     crm_xml_add_int(replace_msg, F_CIB_RC, result);
     attach_cib_generation(replace_msg, "cib-replace-generation", update);
 
     crm_log_xml_trace(replace_msg, "CIB Replaced");
 
     cib_notify_send(replace_msg);
     free_xml(replace_msg);
 }
diff --git a/lib/cib/cib_utils.c b/lib/cib/cib_utils.c
index 234f9beb3d..7ee71c0f19 100644
--- a/lib/cib/cib_utils.c
+++ b/lib/cib/cib_utils.c
@@ -1,775 +1,775 @@
 /*
  * Original copyright 2004 International Business Machines
  * Later changes copyright 2008-2020 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 #include <crm_internal.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
 #include <sys/utsname.h>
 
 #include <glib.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/iso8601_internal.h>
 #include <crm/common/xml.h>
 #include <crm/common/xml_internal.h>
 #include <crm/pengine/rules.h>
 
 struct config_root_s {
     const char *name;
     const char *parent;
     const char *path;
 };
 
  /*
   * "//crm_config" will also work in place of "/cib/configuration/crm_config"
   * The / prefix means find starting from the root, whereas the // prefix means
   * find anywhere and risks multiple matches
   */
 /* *INDENT-OFF* */
-struct config_root_s known_paths[] = {
+static struct config_root_s known_paths[] = {
     { NULL,                         NULL,                 "//cib" },
     { XML_TAG_CIB,                  NULL,                 "//cib" },
     { XML_CIB_TAG_STATUS,           "/cib",               "//cib/status" },
     { XML_CIB_TAG_CONFIGURATION,    "/cib",               "//cib/configuration" },
     { XML_CIB_TAG_CRMCONFIG,        "/cib/configuration", "//cib/configuration/crm_config" },
     { XML_CIB_TAG_NODES,            "/cib/configuration", "//cib/configuration/nodes" },
     { XML_CIB_TAG_RESOURCES,        "/cib/configuration", "//cib/configuration/resources" },
     { XML_CIB_TAG_CONSTRAINTS,      "/cib/configuration", "//cib/configuration/constraints" },
     { XML_CIB_TAG_OPCONFIG,         "/cib/configuration", "//cib/configuration/op_defaults" },
     { XML_CIB_TAG_RSCCONFIG,        "/cib/configuration", "//cib/configuration/rsc_defaults" },
     { XML_CIB_TAG_ACLS,             "/cib/configuration", "//cib/configuration/acls" },
     { XML_TAG_FENCING_TOPOLOGY,     "/cib/configuration", "//cib/configuration/fencing-topology" },
     { XML_CIB_TAG_TAGS,             "/cib/configuration", "//cib/configuration/tags" },
     { XML_CIB_TAG_ALERTS,           "/cib/configuration", "//cib/configuration/alerts" },
     { XML_CIB_TAG_SECTION_ALL,      NULL,                 "//cib" },
 };
 /* *INDENT-ON* */
 
 xmlNode *
 cib_get_generation(cib_t * cib)
 {
     xmlNode *the_cib = NULL;
     xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
 
     cib->cmds->query(cib, NULL, &the_cib, cib_scope_local | cib_sync_call);
     if (the_cib != NULL) {
         copy_in_properties(generation, the_cib);
         free_xml(the_cib);
     }
 
     return generation;
 }
 
 gboolean
 cib_version_details(xmlNode * cib, int *admin_epoch, int *epoch, int *updates)
 {
     *epoch = -1;
     *updates = -1;
     *admin_epoch = -1;
 
     if (cib == NULL) {
         return FALSE;
 
     } else {
         crm_element_value_int(cib, XML_ATTR_GENERATION, epoch);
         crm_element_value_int(cib, XML_ATTR_NUMUPDATES, updates);
         crm_element_value_int(cib, XML_ATTR_GENERATION_ADMIN, admin_epoch);
     }
     return TRUE;
 }
 
 gboolean
 cib_diff_version_details(xmlNode * diff, int *admin_epoch, int *epoch, int *updates,
                          int *_admin_epoch, int *_epoch, int *_updates)
 {
     int add[] = { 0, 0, 0 };
     int del[] = { 0, 0, 0 };
 
     xml_patch_versions(diff, add, del);
 
     *admin_epoch = add[0];
     *epoch = add[1];
     *updates = add[2];
 
     *_admin_epoch = del[0];
     *_epoch = del[1];
     *_updates = del[2];
 
     return TRUE;
 }
 
 /*
  * The caller should never free the return value
  */
 
 const char *
 get_object_path(const char *object_type)
 {
     int lpc = 0;
     int max = DIMOF(known_paths);
 
     for (; lpc < max; lpc++) {
         if ((object_type == NULL && known_paths[lpc].name == NULL)
             || pcmk__str_eq(object_type, known_paths[lpc].name, pcmk__str_casei)) {
             return known_paths[lpc].path;
         }
     }
     return NULL;
 }
 
 const char *
 get_object_parent(const char *object_type)
 {
     int lpc = 0;
     int max = DIMOF(known_paths);
 
     for (; lpc < max; lpc++) {
         if (pcmk__str_eq(object_type, known_paths[lpc].name, pcmk__str_casei)) {
             return known_paths[lpc].parent;
         }
     }
     return NULL;
 }
 
 xmlNode *
 get_object_root(const char *object_type, xmlNode * the_root)
 {
     const char *xpath = get_object_path(object_type);
 
     if (xpath == NULL) {
         return the_root;        /* or return NULL? */
     }
 
     return get_xpath_object(xpath, the_root, LOG_TRACE);
 }
 
 /*
  * It is the callers responsibility to free both the new CIB (output)
  *     and the new CIB (input)
  */
 xmlNode *
 createEmptyCib(int admin_epoch)
 {
     xmlNode *cib_root = NULL, *config = NULL;
 
     cib_root = create_xml_node(NULL, XML_TAG_CIB);
     crm_xml_add(cib_root, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
     crm_xml_add(cib_root, XML_ATTR_VALIDATION, xml_latest_schema());
 
     crm_xml_add_int(cib_root, XML_ATTR_GENERATION, admin_epoch);
     crm_xml_add_int(cib_root, XML_ATTR_NUMUPDATES, 0);
     crm_xml_add_int(cib_root, XML_ATTR_GENERATION_ADMIN, 0);
 
     config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION);
     create_xml_node(cib_root, XML_CIB_TAG_STATUS);
 
     create_xml_node(config, XML_CIB_TAG_CRMCONFIG);
     create_xml_node(config, XML_CIB_TAG_NODES);
     create_xml_node(config, XML_CIB_TAG_RESOURCES);
     create_xml_node(config, XML_CIB_TAG_CONSTRAINTS);
 
     return cib_root;
 }
 
 static bool
 cib_acl_enabled(xmlNode *xml, const char *user)
 {
     bool rc = FALSE;
 
 #if ENABLE_ACL
     if(pcmk_acl_required(user)) {
         const char *value = NULL;
         GHashTable *options = crm_str_table_new();
 
         cib_read_config(options, xml);
         value = cib_pref(options, "enable-acl");
         rc = crm_is_true(value);
         g_hash_table_destroy(options);
     }
 
     crm_trace("CIB ACL is %s", rc ? "enabled" : "disabled");
 #endif
     return rc;
 }
 
 int
 cib_perform_op(const char *op, int call_options, cib_op_t * fn, gboolean is_query,
                const char *section, xmlNode * req, xmlNode * input,
                gboolean manage_counters, gboolean * config_changed,
                xmlNode * current_cib, xmlNode ** result_cib, xmlNode ** diff, xmlNode ** output)
 {
     int rc = pcmk_ok;
     gboolean check_schema = TRUE;
     xmlNode *top = NULL;
     xmlNode *scratch = NULL;
     xmlNode *local_diff = NULL;
 
     const char *new_version = NULL;
     static struct qb_log_callsite *diff_cs = NULL;
     const char *user = crm_element_value(req, F_CIB_USER);
     bool with_digest = FALSE;
 
     crm_trace("Begin %s%s%s op",
               (pcmk_is_set(call_options, cib_dryrun)? "dry run of " : ""),
               (is_query? "read-only " : ""), op);
 
     CRM_CHECK(output != NULL, return -ENOMSG);
     CRM_CHECK(result_cib != NULL, return -ENOMSG);
     CRM_CHECK(config_changed != NULL, return -ENOMSG);
 
     if(output) {
         *output = NULL;
     }
 
     *result_cib = NULL;
     *config_changed = FALSE;
 
     if (fn == NULL) {
         return -EINVAL;
     }
 
     if (is_query) {
         xmlNode *cib_ro = current_cib;
         xmlNode *cib_filtered = NULL;
 
         if(cib_acl_enabled(cib_ro, user)) {
             if(xml_acl_filtered_copy(user, current_cib, current_cib, &cib_filtered)) {
                 if (cib_filtered == NULL) {
                     crm_debug("Pre-filtered the entire cib");
                     return -EACCES;
                 }
                 cib_ro = cib_filtered;
                 crm_log_xml_trace(cib_ro, "filtered");
             }
         }
 
         rc = (*fn) (op, call_options, section, req, input, cib_ro, result_cib, output);
 
         if(output == NULL || *output == NULL) {
             /* nothing */
 
         } else if(cib_filtered == *output) {
             cib_filtered = NULL; /* Let them have this copy */
 
         } else if(*output == current_cib) {
             /* They already know not to free it */
 
         } else if(cib_filtered && (*output)->doc == cib_filtered->doc) {
             /* We're about to free the document of which *output is a part */
             *output = copy_xml(*output);
 
         } else if((*output)->doc == current_cib->doc) {
             /* Give them a copy they can free */
             *output = copy_xml(*output);
         }
 
         free_xml(cib_filtered);
         return rc;
     }
 
 
     if (pcmk_is_set(call_options, cib_zero_copy)) {
         /* Conditional on v2 patch style */
 
         scratch = current_cib;
 
         /* Create a shallow copy of current_cib for the version details */
         current_cib = create_xml_node(NULL, (const char *)scratch->name);
         copy_in_properties(current_cib, scratch);
         top = current_cib;
 
         xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
         rc = (*fn) (op, call_options, section, req, input, scratch, &scratch, output);
 
     } else {
         scratch = copy_xml(current_cib);
         xml_track_changes(scratch, user, NULL, cib_acl_enabled(scratch, user));
         rc = (*fn) (op, call_options, section, req, input, current_cib, &scratch, output);
 
         if(scratch && xml_tracking_changes(scratch) == FALSE) {
             crm_trace("Inferring changes after %s op", op);
             xml_track_changes(scratch, user, current_cib, cib_acl_enabled(current_cib, user));
             xml_calculate_changes(current_cib, scratch);
         }
         CRM_CHECK(current_cib != scratch, return -EINVAL);
     }
 
     xml_acl_disable(scratch); /* Allow the system to make any additional changes */
 
     if (rc == pcmk_ok && scratch == NULL) {
         rc = -EINVAL;
         goto done;
 
     } else if(rc == pcmk_ok && xml_acl_denied(scratch)) {
         crm_trace("ACL rejected part or all of the proposed changes");
         rc = -EACCES;
         goto done;
 
     } else if (rc != pcmk_ok) {
         goto done;
     }
 
     if (scratch) {
         new_version = crm_element_value(scratch, XML_ATTR_CRM_VERSION);
 
         if (new_version && compare_version(new_version, CRM_FEATURE_SET) > 0) {
             crm_err("Discarding update with feature set '%s' greater than our own '%s'",
                     new_version, CRM_FEATURE_SET);
             rc = -EPROTONOSUPPORT;
             goto done;
         }
     }
 
     if (current_cib) {
         int old = 0;
         int new = 0;
 
         crm_element_value_int(scratch, XML_ATTR_GENERATION_ADMIN, &new);
         crm_element_value_int(current_cib, XML_ATTR_GENERATION_ADMIN, &old);
 
         if (old > new) {
             crm_err("%s went backwards: %d -> %d (Opts: 0x%x)",
                     XML_ATTR_GENERATION_ADMIN, old, new, call_options);
             crm_log_xml_warn(req, "Bad Op");
             crm_log_xml_warn(input, "Bad Data");
             rc = -pcmk_err_old_data;
 
         } else if (old == new) {
             crm_element_value_int(scratch, XML_ATTR_GENERATION, &new);
             crm_element_value_int(current_cib, XML_ATTR_GENERATION, &old);
             if (old > new) {
                 crm_err("%s went backwards: %d -> %d (Opts: 0x%x)",
                         XML_ATTR_GENERATION, old, new, call_options);
                 crm_log_xml_warn(req, "Bad Op");
                 crm_log_xml_warn(input, "Bad Data");
                 rc = -pcmk_err_old_data;
             }
         }
     }
 
     crm_trace("Massaging CIB contents");
     pcmk__strip_xml_text(scratch);
     fix_plus_plus_recursive(scratch);
 
     if (pcmk_is_set(call_options, cib_zero_copy)) {
         /* At this point, current_cib is just the 'cib' tag and its properties,
          *
          * The v1 format would barf on this, but we know the v2 patch
          * format only needs it for the top-level version fields
          */
         local_diff = xml_create_patchset(2, current_cib, scratch, (bool*)config_changed, manage_counters);
 
     } else {
         static time_t expires = 0;
         time_t tm_now = time(NULL);
 
         if (expires < tm_now) {
             expires = tm_now + 60;  /* Validate clients are correctly applying v2-style diffs at most once a minute */
             with_digest = TRUE;
         }
 
         local_diff = xml_create_patchset(0, current_cib, scratch, (bool*)config_changed, manage_counters);
     }
 
     xml_log_changes(LOG_TRACE, __func__, scratch);
     xml_accept_changes(scratch);
 
     if (diff_cs == NULL) {
         diff_cs = qb_log_callsite_get(__PRETTY_FUNCTION__, __FILE__, "diff-validation", LOG_DEBUG, __LINE__, crm_trace_nonlog);
     }
 
     if(local_diff) {
         patchset_process_digest(local_diff, current_cib, scratch, with_digest);
 
         xml_log_patchset(LOG_INFO, __func__, local_diff);
         crm_log_xml_trace(local_diff, "raw patch");
     }
 
     if (!pcmk_is_set(call_options, cib_zero_copy) // Original to compare against doesn't exist
         && local_diff
         && crm_is_callsite_active(diff_cs, LOG_TRACE, 0)) {
 
         /* Validate the calculated patch set */
         int test_rc, format = 1;
         xmlNode * c = copy_xml(current_cib);
 
         crm_element_value_int(local_diff, "format", &format);
         test_rc = xml_apply_patchset(c, local_diff, manage_counters);
 
         if(test_rc != pcmk_ok) {
             save_xml_to_file(c,           "PatchApply:calculated", NULL);
             save_xml_to_file(current_cib, "PatchApply:input", NULL);
             save_xml_to_file(scratch,     "PatchApply:actual", NULL);
             save_xml_to_file(local_diff,  "PatchApply:diff", NULL);
             crm_err("v%d patchset error, patch failed to apply: %s (%d)", format, pcmk_strerror(test_rc), test_rc);
         }
         free_xml(c);
     }
 
     if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
         /* Throttle the amount of costly validation we perform due to status updates
          * a) we don't really care whats in the status section
          * b) we don't validate any of its contents at the moment anyway
          */
         check_schema = FALSE;
     }
 
     /* === scratch must not be modified after this point ===
      * Exceptions, anything in:
 
      static filter_t filter[] = {
      { 0, XML_ATTR_ORIGIN },
      { 0, XML_CIB_ATTR_WRITTEN },
      { 0, XML_ATTR_UPDATE_ORIG },
      { 0, XML_ATTR_UPDATE_CLIENT },
      { 0, XML_ATTR_UPDATE_USER },
      };
      */
 
     if (*config_changed && !pcmk_is_set(call_options, cib_no_mtime)) {
         const char *schema = crm_element_value(scratch, XML_ATTR_VALIDATION);
 
         pcmk__xe_add_last_written(scratch);
         if (schema) {
             static int minimum_schema = 0;
             int current_schema = get_schema_version(schema);
 
             if (minimum_schema == 0) {
                 minimum_schema = get_schema_version("pacemaker-1.2");
             }
 
             /* Does the CIB support the "update-*" attributes... */
             if (current_schema >= minimum_schema) {
                 const char *origin = crm_element_value(req, F_ORIG);
 
                 CRM_LOG_ASSERT(origin != NULL);
                 crm_xml_replace(scratch, XML_ATTR_UPDATE_ORIG, origin);
                 crm_xml_replace(scratch, XML_ATTR_UPDATE_CLIENT,
                                 crm_element_value(req, F_CIB_CLIENTNAME));
 #if ENABLE_ACL
                 crm_xml_replace(scratch, XML_ATTR_UPDATE_USER, crm_element_value(req, F_CIB_USER));
 #endif
             }
         }
     }
 
     crm_trace("Perform validation: %s", pcmk__btoa(check_schema));
     if ((rc == pcmk_ok) && check_schema && !validate_xml(scratch, NULL, TRUE)) {
         const char *current_schema = crm_element_value(scratch,
                                                        XML_ATTR_VALIDATION);
 
         crm_warn("Updated CIB does not validate against %s schema",
                  crm_str(current_schema));
         rc = -pcmk_err_schema_validation;
     }
 
   done:
 
     *result_cib = scratch;
 #if ENABLE_ACL
     if(rc != pcmk_ok && cib_acl_enabled(current_cib, user)) {
         if(xml_acl_filtered_copy(user, current_cib, scratch, result_cib)) {
             if (*result_cib == NULL) {
                 crm_debug("Pre-filtered the entire cib result");
             }
             free_xml(scratch);
         }
     }
 #endif
 
     if(diff) {
         *diff = local_diff;
     } else {
         free_xml(local_diff);
     }
 
     free_xml(top);
     crm_trace("Done");
     return rc;
 }
 
 xmlNode *
 cib_create_op(int call_id, const char *token, const char *op, const char *host, const char *section,
               xmlNode * data, int call_options, const char *user_name)
 {
     xmlNode *op_msg = create_xml_node(NULL, "cib_command");
 
     CRM_CHECK(op_msg != NULL, return NULL);
     CRM_CHECK(token != NULL, return NULL);
 
     crm_xml_add(op_msg, F_XML_TAGNAME, "cib_command");
 
     crm_xml_add(op_msg, F_TYPE, T_CIB);
     crm_xml_add(op_msg, F_CIB_CALLBACK_TOKEN, token);
     crm_xml_add(op_msg, F_CIB_OPERATION, op);
     crm_xml_add(op_msg, F_CIB_HOST, host);
     crm_xml_add(op_msg, F_CIB_SECTION, section);
     crm_xml_add_int(op_msg, F_CIB_CALLID, call_id);
 #if ENABLE_ACL
     if (user_name) {
         crm_xml_add(op_msg, F_CIB_USER, user_name);
     }
 #endif
     crm_trace("Sending call options: %.8lx, %d", (long)call_options, call_options);
     crm_xml_add_int(op_msg, F_CIB_CALLOPTS, call_options);
 
     if (data != NULL) {
         add_message_xml(op_msg, F_CIB_CALLDATA, data);
     }
 
     if (call_options & cib_inhibit_bcast) {
         CRM_CHECK((call_options & cib_scope_local), return NULL);
     }
     return op_msg;
 }
 
 void
 cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc)
 {
     xmlNode *output = NULL;
     cib_callback_client_t *blob = NULL;
 
     if (msg != NULL) {
         crm_element_value_int(msg, F_CIB_RC, &rc);
         crm_element_value_int(msg, F_CIB_CALLID, &call_id);
         output = get_message_xml(msg, F_CIB_CALLDATA);
     }
 
     blob = g_hash_table_lookup(cib_op_callback_table, GINT_TO_POINTER(call_id));
     if (blob == NULL) {
         crm_trace("No callback found for call %d", call_id);
     }
 
     if (cib == NULL) {
         crm_debug("No cib object supplied");
     }
 
     if (rc == -pcmk_err_diff_resync) {
         /* This is an internal value that clients do not and should not care about */
         rc = pcmk_ok;
     }
 
     if (blob && blob->callback && (rc == pcmk_ok || blob->only_success == FALSE)) {
         crm_trace("Invoking callback %s for call %d", crm_str(blob->id), call_id);
         blob->callback(msg, call_id, rc, output, blob->user_data);
 
     } else if (cib && cib->op_callback == NULL && rc != pcmk_ok) {
         crm_warn("CIB command failed: %s", pcmk_strerror(rc));
         crm_log_xml_debug(msg, "Failed CIB Update");
     }
 
     /* This may free user_data, so do it after the callback */
     if (blob) {
         remove_cib_op_callback(call_id, FALSE);
     }
 
     if (cib && cib->op_callback != NULL) {
         crm_trace("Invoking global callback for call %d", call_id);
         cib->op_callback(msg, call_id, rc, output);
     }
     crm_trace("OP callback activated for %d", call_id);
 }
 
 void
 cib_native_notify(gpointer data, gpointer user_data)
 {
     xmlNode *msg = user_data;
     cib_notify_client_t *entry = data;
     const char *event = NULL;
 
     if (msg == NULL) {
         crm_warn("Skipping callback - NULL message");
         return;
     }
 
     event = crm_element_value(msg, F_SUBTYPE);
 
     if (entry == NULL) {
         crm_warn("Skipping callback - NULL callback client");
         return;
 
     } else if (entry->callback == NULL) {
         crm_warn("Skipping callback - NULL callback");
         return;
 
     } else if (!pcmk__str_eq(entry->event, event, pcmk__str_casei)) {
         crm_trace("Skipping callback - event mismatch %p/%s vs. %s", entry, entry->event, event);
         return;
     }
 
     crm_trace("Invoking callback for %p/%s event...", entry, event);
     entry->callback(event, msg);
     crm_trace("Callback invoked...");
 }
 
 static pcmk__cluster_option_t cib_opts[] = {
     /* name, legacy name, type, allowed values,
      * default value, validator,
      * short description,
      * long description
      */
     {
         "enable-acl", NULL, "boolean", NULL,
         "false", pcmk__valid_boolean,
         "Enable Access Control Lists (ACLs) for the CIB",
         NULL
     },
     {
         "cluster-ipc-limit", NULL, "integer", NULL,
         "500", pcmk__valid_positive_number,
         "Maximum IPC message backlog before disconnecting a cluster daemon",
         "Raise this if log has \"Evicting client\" messages for cluster daemon"
             " PIDs (a good value is the number of resources in the cluster"
             " multiplied by the number of nodes)."
     },
 };
 
 void
 cib_metadata(void)
 {
     pcmk__print_option_metadata("pacemaker-based", "1.0",
                                 "Cluster Information Base manager options",
                                 "Cluster options used by Pacemaker's "
                                     "Cluster Information Base manager",
                                 cib_opts, DIMOF(cib_opts));
 }
 
 void
 verify_cib_options(GHashTable * options)
 {
     pcmk__validate_cluster_options(options, cib_opts, DIMOF(cib_opts));
 }
 
 const char *
 cib_pref(GHashTable * options, const char *name)
 {
     return pcmk__cluster_option(options, cib_opts, DIMOF(cib_opts), name);
 }
 
 gboolean
 cib_read_config(GHashTable * options, xmlNode * current_cib)
 {
     xmlNode *config = NULL;
     crm_time_t *now = NULL;
 
     if (options == NULL || current_cib == NULL) {
         return FALSE;
     }
 
     now = crm_time_new(NULL);
 
     g_hash_table_remove_all(options);
 
     config = get_object_root(XML_CIB_TAG_CRMCONFIG, current_cib);
     if (config) {
         pe_unpack_nvpairs(current_cib, config, XML_CIB_TAG_PROPSET, NULL,
                           options, CIB_OPTIONS_FIRST, TRUE, now, NULL);
     }
 
     verify_cib_options(options);
 
     crm_time_free(now);
 
     return TRUE;
 }
 
 /* v2 and v2 patch formats */
 #define XPATH_CONFIG_CHANGE \
     "//" XML_CIB_TAG_CRMCONFIG " | " \
     "//" XML_DIFF_CHANGE "[contains(@" XML_DIFF_PATH ",'/" XML_CIB_TAG_CRMCONFIG "/')]"
 
 gboolean
 cib_internal_config_changed(xmlNode *diff)
 {
     gboolean changed = FALSE;
 
     if (diff) {
         xmlXPathObject *xpathObj = xpath_search(diff, XPATH_CONFIG_CHANGE);
 
         if (numXpathResults(xpathObj) > 0) {
             changed = TRUE;
         }
         freeXpathObject(xpathObj);
     }
     return changed;
 }
 
 int
 cib_internal_op(cib_t * cib, const char *op, const char *host,
                 const char *section, xmlNode * data,
                 xmlNode ** output_data, int call_options, const char *user_name)
 {
     int (*delegate) (cib_t * cib, const char *op, const char *host,
                      const char *section, xmlNode * data,
                      xmlNode ** output_data, int call_options, const char *user_name) =
         cib->delegate_fn;
 
 #if ENABLE_ACL
     if(user_name == NULL) {
         user_name = getenv("CIB_user");
     }
 #endif
 
     return delegate(cib, op, host, section, data, output_data, call_options, user_name);
 }
 
 // Deprecated functions kept only for backward API compatibility
 int cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output,
                           int level);
 
 /*!
  * \deprecated
  */
 int
 cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output,
                       int level)
 {
     int rc = pcmk_err_generic;
 
     xmlNode *diff = NULL;
 
     CRM_ASSERT(event);
     CRM_ASSERT(input);
     CRM_ASSERT(output);
 
     crm_element_value_int(event, F_CIB_RC, &rc);
     diff = get_message_xml(event, F_CIB_UPDATE_RESULT);
 
     if (rc < pcmk_ok || diff == NULL) {
         return rc;
     }
 
     if (level > LOG_CRIT) {
         xml_log_patchset(level, "Config update", diff);
     }
 
     if (input != NULL) {
         rc = cib_process_diff(NULL, cib_none, NULL, event, diff, input, output,
                               NULL);
 
         if (rc != pcmk_ok) {
             crm_debug("Update didn't apply: %s (%d) %p",
                       pcmk_strerror(rc), rc, *output);
 
             if (rc == -pcmk_err_old_data) {
                 crm_trace("Masking error, we already have the supplied update");
                 return pcmk_ok;
             }
             free_xml(*output);
             *output = NULL;
             return rc;
         }
     }
     return rc;
 }