This source file includes following definitions.
- pcmk__clone_assign
- pcmk__clone_create_actions
- pcmk__clone_internal_constraints
- can_interleave
- pcmk__clone_apply_coloc_score
- pcmk__with_clone_colocations
- pcmk__clone_with_colocations
- pcmk__clone_action_flags
- pcmk__clone_apply_location
- call_action_flags
- pcmk__clone_add_actions_to_graph
- rsc_probed_on
- find_probed_instance_on
- probe_anonymous_clone
- pcmk__clone_create_probe
- pcmk__clone_add_graph_meta
- pcmk__clone_add_utilization
- pcmk__clone_shutdown_lock
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <crm/common/xml.h>
  13 #include <pacemaker-internal.h>
  14 
  15 #include "libpacemaker_private.h"
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 pcmk_node_t *
  37 pcmk__clone_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer,
     
  38                    bool stop_if_fail)
  39 {
  40     GList *colocations = NULL;
  41 
  42     pcmk__assert(pcmk__is_clone(rsc));
  43 
  44     if (!pcmk_is_set(rsc->flags, pcmk__rsc_unassigned)) {
  45         return NULL; 
  46     }
  47 
  48     
  49     if (pcmk_is_set(rsc->flags, pcmk__rsc_assigning)) {
  50         pcmk__rsc_debug(rsc, "Breaking assignment loop involving %s", rsc->id);
  51         return NULL;
  52     }
  53     pcmk__set_rsc_flags(rsc, pcmk__rsc_assigning);
  54 
  55     
  56     if (pcmk_is_set(rsc->flags, pcmk__rsc_promotable)) {
  57         pcmk__add_promotion_scores(rsc);
  58     }
  59 
  60     
  61     colocations = pcmk__this_with_colocations(rsc);
  62     for (GList *iter = colocations; iter != NULL; iter = iter->next) {
  63         pcmk__colocation_t *constraint = (pcmk__colocation_t *) iter->data;
  64         pcmk_resource_t *primary = constraint->primary;
  65 
  66         pcmk__rsc_trace(rsc, "%s: Assigning colocation %s primary %s first",
  67                         rsc->id, constraint->id, primary->id);
  68         primary->priv->cmds->assign(primary, prefer, stop_if_fail);
  69     }
  70     g_list_free(colocations);
  71 
  72     
  73     colocations = pcmk__with_this_colocations(rsc);
  74     g_list_foreach(colocations, pcmk__add_dependent_scores, rsc);
  75     g_list_free(colocations);
  76 
  77     pe__show_node_scores(!pcmk_is_set(rsc->priv->scheduler->flags,
  78                                       pcmk__sched_output_scores),
  79                          rsc, __func__, rsc->priv->allowed_nodes,
  80                          rsc->priv->scheduler);
  81 
  82     rsc->priv->children = g_list_sort(rsc->priv->children, pcmk__cmp_instance);
  83     pcmk__assign_instances(rsc, rsc->priv->children, pe__clone_max(rsc),
  84                            pe__clone_node_max(rsc));
  85 
  86     if (pcmk_is_set(rsc->flags, pcmk__rsc_promotable)) {
  87         pcmk__set_instance_roles(rsc);
  88     }
  89 
  90     pcmk__clear_rsc_flags(rsc, pcmk__rsc_unassigned|pcmk__rsc_assigning);
  91     pcmk__rsc_trace(rsc, "Assigned clone %s", rsc->id);
  92     return NULL;
  93 }
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 void
 102 pcmk__clone_create_actions(pcmk_resource_t *rsc)
     
 103 {
 104     pcmk__assert(pcmk__is_clone(rsc));
 105 
 106     pcmk__rsc_trace(rsc, "Creating actions for clone %s", rsc->id);
 107     pcmk__create_instance_actions(rsc, rsc->priv->children);
 108     if (pcmk_is_set(rsc->flags, pcmk__rsc_promotable)) {
 109         pcmk__create_promotable_actions(rsc);
 110     }
 111 }
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 void
 120 pcmk__clone_internal_constraints(pcmk_resource_t *rsc)
     
 121 {
 122     bool ordered = false;
 123 
 124     pcmk__assert(pcmk__is_clone(rsc));
 125 
 126     pcmk__rsc_trace(rsc, "Creating internal constraints for clone %s", rsc->id);
 127 
 128     
 129     pcmk__order_resource_actions(rsc, PCMK_ACTION_STOPPED,
 130                                  rsc, PCMK_ACTION_START,
 131                                  pcmk__ar_ordered);
 132     pcmk__order_resource_actions(rsc, PCMK_ACTION_START,
 133                                  rsc, PCMK_ACTION_RUNNING,
 134                                  pcmk__ar_unrunnable_first_blocks);
 135     pcmk__order_resource_actions(rsc, PCMK_ACTION_STOP,
 136                                  rsc, PCMK_ACTION_STOPPED,
 137                                  pcmk__ar_unrunnable_first_blocks);
 138 
 139     
 140     if (pcmk_is_set(rsc->flags, pcmk__rsc_promotable)) {
 141         pcmk__order_resource_actions(rsc, PCMK_ACTION_DEMOTED,
 142                                      rsc, PCMK_ACTION_STOP,
 143                                      pcmk__ar_ordered);
 144         pcmk__order_resource_actions(rsc, PCMK_ACTION_RUNNING,
 145                                      rsc, PCMK_ACTION_PROMOTE,
 146                                      pcmk__ar_unrunnable_first_blocks);
 147     }
 148 
 149     ordered = pe__clone_is_ordered(rsc);
 150     if (ordered) {
 151         
 152 
 153 
 154 
 155         rsc->priv->children = g_list_sort(rsc->priv->children,
 156                                           pcmk__cmp_instance_number);
 157     }
 158     for (GList *iter = rsc->priv->children;
 159          iter != NULL; iter = iter->next) {
 160 
 161         pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
 162 
 163         instance->priv->cmds->internal_constraints(instance);
 164 
 165         
 166         pcmk__order_starts(rsc, instance, pcmk__ar_unrunnable_first_blocks
 167                                           |pcmk__ar_then_implies_first_graphed);
 168         pcmk__order_resource_actions(instance, PCMK_ACTION_START,
 169                                      rsc, PCMK_ACTION_RUNNING,
 170                                      pcmk__ar_first_implies_then_graphed);
 171 
 172         
 173         pcmk__order_stops(rsc, instance, pcmk__ar_then_implies_first_graphed);
 174         pcmk__order_resource_actions(instance, PCMK_ACTION_STOP,
 175                                      rsc, PCMK_ACTION_STOPPED,
 176                                      pcmk__ar_first_implies_then_graphed);
 177 
 178         
 179 
 180 
 181 
 182         if (ordered) {
 183             for (GList *later = iter->next;
 184                  later != NULL; later = later->next) {
 185                 pcmk__order_starts(instance, (pcmk_resource_t *) later->data,
 186                                    pcmk__ar_ordered);
 187                 pcmk__order_stops((pcmk_resource_t *) later->data, instance,
 188                                   pcmk__ar_ordered);
 189             }
 190         }
 191     }
 192     if (pcmk_is_set(rsc->flags, pcmk__rsc_promotable)) {
 193         pcmk__order_promotable_instances(rsc);
 194     }
 195 }
 196 
 197 
 198 
 199 
 200 
 201 
 202 
 203 
 204 
 205 static bool
 206 can_interleave(const pcmk__colocation_t *colocation)
     
 207 {
 208     const pcmk_resource_t *primary = colocation->primary;
 209     const pcmk_resource_t *dependent = colocation->dependent;
 210 
 211     
 212     if (dependent->priv->variant <= pcmk__rsc_variant_group) {
 213         return false;
 214     }
 215 
 216     
 217     if (!crm_is_true(g_hash_table_lookup(dependent->priv->meta,
 218                                          PCMK_META_INTERLEAVE))) {
 219         return false;
 220     }
 221 
 222     
 223 
 224 
 225     if (dependent->priv->fns->max_per_node(dependent)
 226         != primary->priv->fns->max_per_node(primary)) {
 227         pcmk__config_err("Cannot interleave %s and %s because they do not "
 228                          "support the same number of instances per node",
 229                          dependent->id, primary->id);
 230         return false;
 231     }
 232 
 233     return true;
 234 }
 235 
 236 
 237 
 238 
 239 
 240 
 241 
 242 
 243 
 244 
 245 
 246 
 247 
 248 
 249 
 250 
 251 int
 252 pcmk__clone_apply_coloc_score(pcmk_resource_t *dependent,
     
 253                               const pcmk_resource_t *primary,
 254                               const pcmk__colocation_t *colocation,
 255                               bool for_dependent)
 256 {
 257     const GList *iter = NULL;
 258     int priority_delta = 0;
 259 
 260     
 261 
 262 
 263 
 264     pcmk__assert(!for_dependent && (colocation != NULL)
 265                  && pcmk__is_clone(primary) && pcmk__is_primitive(dependent));
 266 
 267     if (pcmk_is_set(primary->flags, pcmk__rsc_unassigned)) {
 268         pcmk__rsc_trace(primary,
 269                         "Delaying processing colocation %s "
 270                         "because cloned primary %s is still provisional",
 271                         colocation->id, primary->id);
 272         return 0;
 273     }
 274 
 275     pcmk__rsc_trace(primary, "Processing colocation %s (%s with clone %s @%s)",
 276                     colocation->id, dependent->id, primary->id,
 277                     pcmk_readable_score(colocation->score));
 278 
 279     
 280     if (pcmk_is_set(primary->flags, pcmk__rsc_promotable)
 281         && (colocation->primary_role != pcmk_role_unknown)) {
 282 
 283         if (pcmk_is_set(dependent->flags, pcmk__rsc_unassigned)) {
 284             
 285             pcmk__update_dependent_with_promotable(primary, dependent,
 286                                                    colocation);
 287             return 0;
 288         }
 289 
 290         if (colocation->dependent_role == pcmk_role_promoted) {
 291             
 292             return pcmk__update_promotable_dependent_priority(primary,
 293                                                               dependent,
 294                                                               colocation);
 295         }
 296     }
 297 
 298     
 299     if (can_interleave(colocation)) {
 300         const pcmk_resource_t *primary_instance = NULL;
 301 
 302         primary_instance = pcmk__find_compatible_instance(dependent, primary,
 303                                                           pcmk_role_unknown,
 304                                                           false);
 305         if (primary_instance != NULL) {
 306             pcmk__rsc_debug(primary, "Interleaving %s with %s",
 307                             dependent->id, primary_instance->id);
 308 
 309             return dependent->priv->cmds->apply_coloc_score(dependent,
 310                                                             primary_instance,
 311                                                             colocation, true);
 312         }
 313 
 314         if (colocation->score >= PCMK_SCORE_INFINITY) {
 315             crm_notice("%s cannot run because it cannot interleave with "
 316                        "any instance of %s", dependent->id, primary->id);
 317             pcmk__assign_resource(dependent, NULL, true, true);
 318 
 319         } else {
 320             pcmk__rsc_debug(primary,
 321                             "%s will not colocate with %s "
 322                             "because no instance can interleave with it",
 323                             dependent->id, primary->id);
 324         }
 325 
 326         return 0;
 327     }
 328 
 329     
 330     if (colocation->score >= PCMK_SCORE_INFINITY) {
 331         GList *primary_nodes = NULL;
 332 
 333         
 334         for (iter = primary->priv->children;
 335              iter != NULL; iter = iter->next) {
 336 
 337             const pcmk_resource_t *instance = iter->data;
 338             pcmk_node_t *chosen = NULL;
 339 
 340             chosen = instance->priv->fns->location(instance, NULL,
 341                                                    pcmk__rsc_node_assigned);
 342             if ((chosen != NULL)
 343                 && !is_set_recursive(instance, pcmk__rsc_blocked, TRUE)) {
 344                 pcmk__rsc_trace(primary, "Allowing %s: %s %d",
 345                                 colocation->id, pcmk__node_name(chosen),
 346                                 chosen->assign->score);
 347                 primary_nodes = g_list_prepend(primary_nodes, chosen);
 348             }
 349         }
 350         pcmk__colocation_intersect_nodes(dependent, primary, colocation,
 351                                          primary_nodes, false);
 352         g_list_free(primary_nodes);
 353         return 0;
 354     }
 355 
 356     
 357     for (iter = primary->priv->children; iter != NULL; iter = iter->next) {
 358         const pcmk_resource_t *instance = iter->data;
 359         int instance_delta = instance->priv->cmds->apply_coloc_score(dependent,
 360                                                                      instance,
 361                                                                      colocation,
 362                                                                      false);
 363 
 364         priority_delta = pcmk__add_scores(priority_delta, instance_delta);
 365     }
 366     return priority_delta;
 367 }
 368 
 369 
 370 void
 371 pcmk__with_clone_colocations(const pcmk_resource_t *rsc,
     
 372                              const pcmk_resource_t *orig_rsc, GList **list)
 373 {
 374     const pcmk_resource_t *parent = NULL;
 375 
 376     CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
 377     parent = rsc->priv->parent;
 378 
 379     pcmk__add_with_this_list(list, rsc->priv->with_this_colocations,
 380                              orig_rsc);
 381 
 382     if (parent != NULL) {
 383         parent->priv->cmds->with_this_colocations(parent, orig_rsc, list);
 384     }
 385 }
 386 
 387 
 388 void
 389 pcmk__clone_with_colocations(const pcmk_resource_t *rsc,
     
 390                              const pcmk_resource_t *orig_rsc, GList **list)
 391 {
 392     const pcmk_resource_t *parent = NULL;
 393 
 394     CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
 395     parent = rsc->priv->parent;
 396 
 397     pcmk__add_this_with_list(list, rsc->priv->this_with_colocations,
 398                              orig_rsc);
 399 
 400     if (parent != NULL) {
 401         parent->priv->cmds->this_with_colocations(parent, orig_rsc, list);
 402     }
 403 }
 404 
 405 
 406 
 407 
 408 
 409 
 410 
 411 
 412 
 413 
 414 uint32_t
 415 pcmk__clone_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
     
 416 {
 417     pcmk__assert((action != NULL) && pcmk__is_clone(action->rsc));
 418 
 419     return pcmk__collective_action_flags(action, action->rsc->priv->children,
 420                                          node);
 421 }
 422 
 423 
 424 
 425 
 426 
 427 
 428 
 429 
 430 void
 431 pcmk__clone_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
     
 432 {
 433     CRM_CHECK((location != NULL) && pcmk__is_clone(rsc), return);
 434 
 435     pcmk__apply_location(rsc, location);
 436 
 437     for (GList *iter = rsc->priv->children;
 438          iter != NULL; iter = iter->next) {
 439 
 440         pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
 441 
 442         instance->priv->cmds->apply_location(instance, location);
 443     }
 444 }
 445 
 446 
 447 static void
 448 call_action_flags(gpointer data, gpointer user_data)
     
 449 {
 450     pcmk_resource_t *rsc = user_data;
 451 
 452     rsc->priv->cmds->action_flags((pcmk_action_t *) data, NULL);
 453 }
 454 
 455 
 456 
 457 
 458 
 459 
 460 
 461 void
 462 pcmk__clone_add_actions_to_graph(pcmk_resource_t *rsc)
     
 463 {
 464     pcmk__assert(pcmk__is_clone(rsc));
 465 
 466     g_list_foreach(rsc->priv->actions, call_action_flags, rsc);
 467     pe__create_clone_notifications(rsc);
 468 
 469     for (GList *iter = rsc->priv->children;
 470          iter != NULL; iter = iter->next) {
 471 
 472         pcmk_resource_t *child_rsc = (pcmk_resource_t *) iter->data;
 473 
 474         child_rsc->priv->cmds->add_actions_to_graph(child_rsc);
 475     }
 476 
 477     pcmk__add_rsc_actions_to_graph(rsc);
 478     pe__free_clone_notification_data(rsc);
 479 }
 480 
 481 
 482 
 483 
 484 
 485 
 486 
 487 
 488 
 489 
 490 
 491 static bool
 492 rsc_probed_on(const pcmk_resource_t *rsc, const pcmk_node_t *node)
     
 493 {
 494     if (rsc->priv->children != NULL) {
 495         for (GList *child_iter = rsc->priv->children;
 496              child_iter != NULL; child_iter = child_iter->next) {
 497 
 498             pcmk_resource_t *child = (pcmk_resource_t *) child_iter->data;
 499 
 500             if (rsc_probed_on(child, node)) {
 501                 return true;
 502             }
 503         }
 504         return false;
 505     }
 506 
 507     if (rsc->priv->probed_nodes != NULL) {
 508         GHashTableIter iter;
 509         pcmk_node_t *known_node = NULL;
 510 
 511         g_hash_table_iter_init(&iter, rsc->priv->probed_nodes);
 512         while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
 513             if (pcmk__same_node(node, known_node)) {
 514                 return true;
 515             }
 516         }
 517     }
 518     return false;
 519 }
 520 
 521 
 522 
 523 
 524 
 525 
 526 
 527 
 528 
 529 
 530 
 531 static pcmk_resource_t *
 532 find_probed_instance_on(const pcmk_resource_t *clone, const pcmk_node_t *node)
     
 533 {
 534     for (GList *iter = clone->priv->children;
 535          iter != NULL; iter = iter->next) {
 536 
 537         pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
 538 
 539         if (rsc_probed_on(instance, node)) {
 540             return instance;
 541         }
 542     }
 543     return NULL;
 544 }
 545 
 546 
 547 
 548 
 549 
 550 
 551 
 552 
 553 static bool
 554 probe_anonymous_clone(pcmk_resource_t *clone, pcmk_node_t *node)
     
 555 {
 556     
 557     pcmk_resource_t *child = find_probed_instance_on(clone, node);
 558 
 559     
 560     for (GList *iter = clone->priv->children;
 561          (iter != NULL) && (child == NULL); iter = iter->next) {
 562 
 563         pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
 564         const pcmk_node_t *instance_node = NULL;
 565 
 566         instance_node = instance->priv->fns->location(instance, NULL,
 567                                                       pcmk__rsc_node_assigned);
 568         if (pcmk__same_node(instance_node, node)) {
 569             child = instance;
 570         }
 571     }
 572 
 573     
 574     if (child == NULL) {
 575         child = clone->priv->children->data;
 576     }
 577 
 578     
 579     return child->priv->cmds->create_probe(child, node);
 580 }
 581 
 582 
 583 
 584 
 585 
 586 
 587 
 588 
 589 
 590 
 591 bool
 592 pcmk__clone_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
     
 593 {
 594     pcmk__assert((node != NULL) && pcmk__is_clone(rsc));
 595 
 596     if (pcmk_is_set(rsc->flags, pcmk__rsc_exclusive_probes)) {
 597         
 598 
 599 
 600 
 601 
 602 
 603 
 604 
 605 
 606         pcmk_node_t *allowed = g_hash_table_lookup(rsc->priv->allowed_nodes,
 607                                                    node->priv->id);
 608 
 609         if ((allowed == NULL)
 610             || (allowed->assign->probe_mode != pcmk__probe_exclusive)) {
 611             
 612 
 613 
 614 
 615             pcmk__rsc_trace(rsc,
 616                             "Skipping probe for %s on %s because resource has "
 617                             "exclusive discovery but is not allowed on node",
 618                             rsc->id, pcmk__node_name(node));
 619             g_hash_table_remove(rsc->priv->allowed_nodes, node->priv->id);
 620             return false;
 621         }
 622     }
 623 
 624     rsc->priv->children = g_list_sort(rsc->priv->children,
 625                                       pcmk__cmp_instance_number);
 626     if (pcmk_is_set(rsc->flags, pcmk__rsc_unique)) {
 627         return pcmk__probe_resource_list(rsc->priv->children, node);
 628     } else {
 629         return probe_anonymous_clone(rsc, node);
 630     }
 631 }
 632 
 633 
 634 
 635 
 636 
 637 
 638 
 639 
 640 
 641 
 642 void
 643 pcmk__clone_add_graph_meta(const pcmk_resource_t *rsc, xmlNode *xml)
     
 644 {
 645     char *name = NULL;
 646 
 647     pcmk__assert(pcmk__is_clone(rsc) && (xml != NULL));
 648 
 649     name = crm_meta_name(PCMK_META_GLOBALLY_UNIQUE);
 650     crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk__rsc_unique));
 651     free(name);
 652 
 653     name = crm_meta_name(PCMK_META_NOTIFY);
 654     crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk__rsc_notify));
 655     free(name);
 656 
 657     name = crm_meta_name(PCMK_META_CLONE_MAX);
 658     crm_xml_add_int(xml, name, pe__clone_max(rsc));
 659     free(name);
 660 
 661     name = crm_meta_name(PCMK_META_CLONE_NODE_MAX);
 662     crm_xml_add_int(xml, name, pe__clone_node_max(rsc));
 663     free(name);
 664 
 665     if (pcmk_is_set(rsc->flags, pcmk__rsc_promotable)) {
 666         int promoted_max = pe__clone_promoted_max(rsc);
 667         int promoted_node_max = pe__clone_promoted_node_max(rsc);
 668 
 669         name = crm_meta_name(PCMK_META_PROMOTED_MAX);
 670         crm_xml_add_int(xml, name, promoted_max);
 671         free(name);
 672 
 673         name = crm_meta_name(PCMK_META_PROMOTED_NODE_MAX);
 674         crm_xml_add_int(xml, name, promoted_node_max);
 675         free(name);
 676 
 677         
 678 
 679 
 680         name = crm_meta_name(PCMK__META_PROMOTED_MAX_LEGACY);
 681         crm_xml_add_int(xml, name, promoted_max);
 682         free(name);
 683 
 684         name = crm_meta_name(PCMK__META_PROMOTED_NODE_MAX_LEGACY);
 685         crm_xml_add_int(xml, name, promoted_node_max);
 686         free(name);
 687     }
 688 }
 689 
 690 
 691 void
 692 pcmk__clone_add_utilization(const pcmk_resource_t *rsc,
     
 693                             const pcmk_resource_t *orig_rsc, GList *all_rscs,
 694                             GHashTable *utilization)
 695 {
 696     bool existing = false;
 697     pcmk_resource_t *child = NULL;
 698 
 699     pcmk__assert(pcmk__is_clone(rsc) && (orig_rsc != NULL)
 700                  && (utilization != NULL));
 701 
 702     if (!pcmk_is_set(rsc->flags, pcmk__rsc_unassigned)) {
 703         return;
 704     }
 705 
 706     
 707     for (GList *iter = rsc->priv->children;
 708          iter != NULL; iter = iter->next) {
 709 
 710         child = (pcmk_resource_t *) iter->data;
 711         if (g_list_find(all_rscs, child)) {
 712             existing = true; 
 713         } else {
 714             
 715             for (GList *member_iter = child->priv->children;
 716                  member_iter != NULL; member_iter = member_iter->next) {
 717 
 718                 pcmk_resource_t *member = (pcmk_resource_t *) member_iter->data;
 719 
 720                 if (g_list_find(all_rscs, member) != NULL) {
 721                     
 722                     child->priv->cmds->add_utilization(child, orig_rsc,
 723                                                        all_rscs, utilization);
 724                     existing = true;
 725                     break;
 726                 }
 727             }
 728         }
 729     }
 730 
 731     if (!existing && (rsc->priv->children != NULL)) {
 732         
 733         child = (pcmk_resource_t *) rsc->priv->children->data;
 734 
 735         child->priv->cmds->add_utilization(child, orig_rsc, all_rscs,
 736                                            utilization);
 737     }
 738 }
 739 
 740 
 741 void
 742 pcmk__clone_shutdown_lock(pcmk_resource_t *rsc)
     
 743 {
 744     pcmk__assert(pcmk__is_clone(rsc));
 745     return; 
 746 }