--- old/usr/src/cmd/coreadm/coreadm.c	Sun May 28 12:20:30 2017
+++ new/usr/src/cmd/coreadm/coreadm.c	Sun May 28 12:20:30 2017
@@ -21,6 +21,8 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2017 RackTop Systems.
  */
 
 #include <stdio.h>
@@ -77,7 +79,7 @@
 
 static	int		report_settings(void);
 static	int		do_processes(int, char **);
-static	int		do_modify(boolean_t);
+static	int		do_modify(void);
 static	int		do_update(void);
 static	int		do_legacy(void);
 
@@ -86,12 +88,13 @@
 static scf_propvec_t prop_ipattern = { INIT_PATTERN, NULL, SCF_TYPE_ASTRING };
 static scf_propvec_t prop_icontent = { INIT_CONTENT, NULL, SCF_TYPE_ASTRING };
 static scf_propvec_t prop_option[] = {
-    { GLOBAL_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_PATH },
-    { PROCESS_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_PROCESS_PATH },
-    { GLOBAL_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_SETID },
-    { PROCESS_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_PROCESS_SETID },
-    { GLOBAL_LOG_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_LOG },
-    { NULL }
+	{ GLOBAL_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_PATH },
+	{ PROCESS_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_PROCESS_PATH },
+	{ GLOBAL_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_SETID },
+	{ PROCESS_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL,
+	    CC_PROCESS_SETID },
+	{ GLOBAL_LOG_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_LOG },
+	{ NULL }
 };
 #define	MAX_PROPS	(4 + (sizeof (prop_option) / sizeof (scf_propvec_t)))
 
@@ -243,6 +246,12 @@
 		    command);
 		usage();
 	}
+	if (glob_pattern != NULL && glob_pattern[0] != '/') {
+		(void) fprintf(stderr, gettext(
+		    "%s: the -g option must specify an absolute path\n"),
+		    command);
+		usage();
+	}
 	if ((proc_pattern != NULL || proc_content != CC_CONTENT_INVALID) &&
 	    npids == 0) {
 		(void) sprintf(curpid, "%u", (uint_t)getppid());
@@ -255,7 +264,7 @@
 	if (update)
 		return (do_update());
 	if (modify)
-		return (do_modify(B_FALSE));
+		return (do_modify());
 	if (npids != 0)
 		return (do_processes(npids, pidlist));
 
@@ -382,15 +391,49 @@
 	props[count].pv_ptr = ptr;
 }
 
-static boolean_t
-is_online(const char *fmri)
+static int
+make_active(void)
 {
-	char *state = smf_get_state(fmri);
-	boolean_t result = state != NULL &&
-	    strcmp(state, SCF_STATE_STRING_ONLINE) == 0;
+	char *state = smf_get_state(COREADM_INST_FMRI);
 
-	free(state);
-	return (result);
+	switch (state == NULL ? -1 : smf_state_from_string(state)) {
+	case SCF_STATE_ONLINE:
+		if (smf_refresh_instance_synchronous(COREADM_INST_FMRI) != 0) {
+			(void) fprintf(stderr,
+			    gettext("%s: Unable to refresh %s: %s\n"),
+			    command, COREADM_INST_FMRI,
+			    scf_strerror(scf_error()));
+			return (-1);
+		}
+		break;
+	case SCF_STATE_DEGRADED:
+	case SCF_STATE_MAINT:
+		if (smf_restore_instance_synchronous(COREADM_INST_FMRI) != 0) {
+			(void) fprintf(stderr,
+			    gettext("%s: Unable to clear %s: %s\n"),
+			    command, COREADM_INST_FMRI,
+			    scf_strerror(scf_error()));
+			return (-1);
+		}
+		break;
+	case SCF_STATE_DISABLED:
+		if (smf_enable_instance_synchronous(COREADM_INST_FMRI,
+		    0) != 0) {
+			(void) fprintf(stderr,
+			    gettext("%s: Unable to enable %s: %s\n"),
+			    command, COREADM_INST_FMRI,
+			    scf_strerror(scf_error()));
+			return (-1);
+		}
+		break;
+	case SCF_STATE_OFFLINE:
+	default:
+		(void) fprintf(stderr,
+		    gettext("%s: coreadm service not online\n"), command);
+		return (-1);
+	}
+
+	return (0);
 }
 
 /*
@@ -401,7 +444,7 @@
  * configuration information from the repository to the kernel.
  */
 static int
-do_modify(boolean_t method)
+do_modify(void)
 {
 	char gcontentstr[PRCONTENTBUFSZ];
 	char icontentstr[PRCONTENTBUFSZ];
@@ -409,12 +452,6 @@
 	scf_propvec_t properties[MAX_PROPS + 1];
 	int count = 0;
 
-	if (!method && !is_online(COREADM_INST_FMRI)) {
-		(void) fprintf(stderr,
-		    gettext("%s: coreadm service not online\n"), command);
-		return (E_ERROR);
-	}
-
 	if (glob_pattern != NULL)
 		addprop(properties, MAX_PROPS, count++, &prop_gpattern,
 		    glob_pattern);
@@ -458,11 +495,9 @@
 		return (E_ERROR);
 	}
 
-	if (smf_refresh_instance(COREADM_INST_FMRI) != 0) {
-		(void) fprintf(stderr,
-		    gettext("%s: Unable to refresh %s: %s\n"
-		    "Configuration stored but not made active.\n"),
-		    command, COREADM_INST_FMRI, scf_strerror(scf_error()));
+	if (make_active() != 0) {
+		(void) fprintf(stderr, gettext(
+		    "Configuration stored but not made active.\n"));
 		return (E_ERROR);
 	}
 
@@ -622,7 +657,7 @@
 		if ((errstr = write_kernel()) != NULL)
 			goto error;
 
-		if (do_modify(B_TRUE) != 0 ||
+		if (do_modify() != 0 ||
 		    rename(PATH_CONFIG, PATH_CONFIG_OLD) != 0) {
 			(void) fprintf(stderr, gettext(
 			    "%s: failed to import legacy configuration.\n"),
@@ -641,7 +676,7 @@
 	properties[count].pv_prop = NULL;
 
 	alloptions = CC_OPTIONS;
-	if (scf_read_propvec(COREADM_INST_FMRI, CONFIG_PARAMS, B_TRUE,
+	if (scf_read_propvec(COREADM_INST_FMRI, CONFIG_PARAMS, B_FALSE,
 	    properties, &prop) == SCF_FAILED) {
 		if (prop != NULL) {
 			(void) fprintf(stderr, gettext(
@@ -669,7 +704,7 @@
 		return (SMF_EXIT_ERR_PERM);
 	}
 	perror(errstr);
-	return (SMF_EXIT_ERR_FATAL);
+	return (errno == EINVAL ? SMF_EXIT_ERR_CONFIG : SMF_EXIT_ERR_FATAL);
 }
 
 static int do_legacy()
--- old/usr/src/lib/libscf/common/mapfile-vers	Sun May 28 12:20:30 2017
+++ new/usr/src/lib/libscf/common/mapfile-vers	Sun May 28 12:20:30 2017
@@ -20,6 +20,7 @@
 #
 #
 # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2017 RackTop Systems.
 #
 
 #
@@ -38,6 +39,16 @@
 
 $mapfile_version 2
 
+SYMBOL_VERSION ILLUMOS_0.1 {
+	smf_degrade_instance_synchronous;
+	smf_disable_instance_synchronous;
+	smf_enable_instance_synchronous;
+	smf_maintain_instance_synchronous;
+	smf_refresh_instance_synchronous;
+	smf_restart_instance_synchronous;
+	smf_restore_instance_synchronous;
+} SUNW_1.2;
+
 SYMBOL_VERSION SUNW_1.2 {
     global:
         scf_count_ranges_destroy;
--- old/usr/src/lib/libscf/common/midlevel.c	Sun May 28 12:20:31 2017
+++ new/usr/src/lib/libscf/common/midlevel.c	Sun May 28 12:20:31 2017
@@ -22,6 +22,7 @@
 /*
  * 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"
@@ -1276,6 +1277,138 @@
 	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)
 {
--- old/usr/src/lib/libscf/inc/libscf.h	Sun May 28 12:20:31 2017
+++ new/usr/src/lib/libscf/inc/libscf.h	Sun May 28 12:20:31 2017
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2016 RackTop Systems.
+ * Copyright 2017 RackTop Systems.
  */
 
 #ifndef	_LIBSCF_H
@@ -812,6 +812,13 @@
 int smf_maintain_instance(const char *, int);
 int smf_degrade_instance(const char *, int);
 int smf_restore_instance(const char *);
+int smf_enable_instance_synchronous(const char *, int);
+int smf_disable_instance_synchronous(const char *, int);
+int smf_refresh_instance_synchronous(const char *);
+int smf_restart_instance_synchronous(const char *);
+int smf_maintain_instance_synchronous(const char *, int);
+int smf_degrade_instance_synchronous(const char *, int);
+int smf_restore_instance_synchronous(const char *);
 char *smf_get_state(const char *);
 
 int scf_simple_walk_instances(uint_t, void *,
