Print this page
8225 passing invalid global pattern to coreadm wedges it nicely

@@ -20,10 +20,11 @@
  */
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2017 RackTop Systems.
  */
 
 #include "libscf_impl.h"
 
 #include <assert.h>

@@ -1274,10 +1275,142 @@
 
         scf_simple_prop_free(prop);
         return (ret);
 }
 
+/*
+ * Wait for the given instance to finish transitioning.  This can be gleamed
+ * from looking at the restarter/next_state property, which settles to "none"
+ * when the service has finished.  This is true even in the case of failure.
+ *
+ * Some services take their sweet time so we don't bother with a timeout here.
+ * Instead we let svc.startd deal with timing out the service, after which
+ * restarter/next_state gets set to "none" and we return.
+ */
+static int
+wait_for_transition(const char *instance, const char *state)
+{
+        scf_simple_prop_t               *prop;
+        const char                      *state_str;
+
+        while (1) {
+                if ((prop = scf_simple_prop_get(NULL, instance,
+                    SCF_PG_RESTARTER, SCF_PROPERTY_NEXT_STATE)) == NULL)
+                        return (SCF_FAILED);
+
+                if ((state_str = scf_simple_prop_next_astring(prop)) == NULL) {
+                        scf_simple_prop_free(prop);
+                        return (SCF_FAILED);
+                }
+
+                if (strcmp(state_str, SCF_STATE_STRING_NONE) == 0) {
+                        scf_simple_prop_free(prop);
+                        break;
+                }
+
+                scf_simple_prop_free(prop);
+                (void) sleep(1);
+        }
+
+        if (state != NULL) {
+                if ((prop = scf_simple_prop_get(NULL, instance,
+                    SCF_PG_RESTARTER, SCF_PROPERTY_STATE)) == NULL)
+                        return (SCF_FAILED);
+
+                if ((state_str = scf_simple_prop_next_astring(prop)) == NULL) {
+                        scf_simple_prop_free(prop);
+                        return (SCF_FAILED);
+                }
+
+                if (strcmp(state_str, state) != 0) {
+                        scf_simple_prop_free(prop);
+                        return (SCF_FAILED);
+                }
+
+                scf_simple_prop_free(prop);
+        }
+
+        return (SCF_SUCCESS);
+}
+
+int
+smf_enable_instance_synchronous(const char *instance, int flags)
+{
+        int ret;
+
+        if ((ret = smf_enable_instance(instance, flags)) != SCF_SUCCESS)
+                return (ret);
+
+        return (wait_for_transition(instance, SCF_STATE_STRING_ONLINE));
+}
+
+int
+smf_disable_instance_synchronous(const char *instance, int flags)
+{
+        int ret;
+
+        if ((ret = smf_disable_instance(instance, flags)) != SCF_SUCCESS)
+                return (ret);
+
+        return (wait_for_transition(instance, SCF_STATE_STRING_DISABLED));
+}
+
+int
+smf_refresh_instance_synchronous(const char *instance)
+{
+        int ret;
+
+        if ((ret = smf_refresh_instance(instance)) != SCF_SUCCESS)
+                return (ret);
+
+        return (wait_for_transition(instance, NULL)); /* ignore state */
+}
+
+int
+smf_restart_instance_synchronous(const char *instance)
+{
+        int ret;
+
+        if ((ret = smf_restart_instance(instance)) != SCF_SUCCESS)
+                return (ret);
+
+        return (wait_for_transition(instance, NULL)); /* ignore state */
+}
+
+int
+smf_maintain_instance_synchronous(const char *instance, int flags)
+{
+        int ret;
+
+        if ((ret = smf_maintain_instance(instance, flags)) != SCF_SUCCESS)
+                return (ret);
+
+        return (wait_for_transition(instance, SCF_STATE_STRING_MAINT));
+}
+
+int
+smf_degrade_instance_synchronous(const char *instance, int flags)
+{
+        int ret;
+
+        if ((ret = smf_degrade_instance(instance, flags)) != SCF_SUCCESS)
+                return (ret);
+
+        return (wait_for_transition(instance, SCF_STATE_STRING_DEGRADED));
+}
+
+int
+smf_restore_instance_synchronous(const char *instance)
+{
+        int ret;
+
+        if ((ret = smf_restore_instance(instance)) != SCF_SUCCESS)
+                return (ret);
+
+        return (wait_for_transition(instance, SCF_STATE_STRING_ONLINE));
+}
+
 char *
 smf_get_state(const char *instance)
 {
         scf_simple_prop_t               *prop;
         const char                      *state_str;