--- old/usr/src/cmd/svc/startd/graph.c	Mon Dec  4 17:58:48 2017
+++ new/usr/src/cmd/svc/startd/graph.c	Mon Dec  4 17:58:48 2017
@@ -23,7 +23,7 @@
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2015, Syneto S.R.L. All rights reserved.
  * Copyright 2016 Toomas Soome <tsoome@me.com>
- * Copyright 2016 RackTop Systems.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -901,7 +901,9 @@
 		break;
 
 	case RESTARTER_EVENT_TYPE_REMOVE_INSTANCE:
+	case RESTARTER_EVENT_TYPE_ADMIN_RESTORE:
 	case RESTARTER_EVENT_TYPE_ADMIN_DEGRADED:
+	case RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE:
 	case RESTARTER_EVENT_TYPE_ADMIN_REFRESH:
 	case RESTARTER_EVENT_TYPE_ADMIN_RESTART:
 	case RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF:
--- old/usr/src/cmd/svc/startd/log.c	Mon Dec  4 17:58:49 2017
+++ new/usr/src/cmd/svc/startd/log.c	Mon Dec  4 17:58:49 2017
@@ -22,6 +22,7 @@
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  * Copyright 2011 Nexenta Systems. All rights reserved.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -475,6 +476,10 @@
 		severity = LOG_INFO;
 	} else {
 		switch (outcome) {
+		case DEGRADE_REQUESTED:
+			action = gettext("transitioned to degraded by "
+			    "request (see 'svcs -xv' for details)");
+			break;
 		case MAINT_REQUESTED:
 			action = gettext("transitioned to maintenance by "
 			    "request (see 'svcs -xv' for details)");
--- old/usr/src/cmd/svc/startd/method.c	Mon Dec  4 17:58:49 2017
+++ new/usr/src/cmd/svc/startd/method.c	Mon Dec  4 17:58:49 2017
@@ -1169,7 +1169,7 @@
 
 	r = method_run(&inst, info->sf_method_type, &exit_code);
 
-	if (r == 0 && exit_code == 0) {
+	if (r == 0 && (exit_code == 0 || exit_code == SMF_EXIT_MON_DEGRADE)) {
 		/* Success! */
 		assert(inst->ri_i.i_next_state != RESTARTER_STATE_NONE);
 
@@ -1187,7 +1187,18 @@
 			else
 				method_remove_contract(inst, B_TRUE, B_TRUE);
 		}
+
 		/*
+		 * When a start method returns with SMF_EXIT_MON_DEGRADE we
+		 * transition the service into degraded.
+		 */
+		if (info->sf_method_type == METHOD_START &&
+		    exit_code == SMF_EXIT_MON_DEGRADE) {
+			inst->ri_i.i_next_state = RESTARTER_STATE_DEGRADED;
+			info->sf_reason = restarter_str_method_failed;
+		}
+
+		/*
 		 * We don't care whether the handle was rebound because this is
 		 * the last thing we do with it.
 		 */
--- old/usr/src/cmd/svc/startd/restarter.c	Mon Dec  4 17:58:49 2017
+++ new/usr/src/cmd/svc/startd/restarter.c	Mon Dec  4 17:58:49 2017
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -1747,11 +1748,63 @@
 	scf_instance_destroy(inst);
 }
 
+static void
+degrade_instance(scf_handle_t *h, restarter_inst_t *rip, restarter_str_t reason)
+{
+	scf_instance_t *scf_inst = NULL;
+
+	assert(MUTEX_HELD(&rip->ri_lock));
+
+	log_instance(rip, B_TRUE, "Marking degraded due to %s.",
+	    restarter_get_str_short(reason));
+	log_framework(LOG_DEBUG, "%s: marking degraded due to %s.\n",
+	    rip->ri_i.i_fmri, restarter_get_str_short(reason));
+
+	/* Services that aren't online are ignored */
+	if (rip->ri_i.i_state != RESTARTER_STATE_ONLINE) {
+		log_framework(LOG_DEBUG,
+		    "%s: degrade_instance -> is not online\n",
+		    rip->ri_i.i_fmri);
+		return;
+	}
+
+	/*
+	 * If reason state is restarter_str_service_request and
+	 * restarter_actions/auxiliary_fmri property is set with a valid fmri,
+	 * copy the fmri to restarter/auxiliary_fmri so svcs -x can use.
+	 */
+	if (reason == restarter_str_service_request &&
+	    libscf_fmri_get_instance(h, rip->ri_i.i_fmri, &scf_inst) == 0) {
+		if (restarter_inst_validate_ractions_aux_fmri(scf_inst) == 0) {
+			if (restarter_inst_set_aux_fmri(scf_inst))
+				log_framework(LOG_DEBUG, "%s: "
+				    "restarter_inst_set_aux_fmri failed: ",
+				    rip->ri_i.i_fmri);
+		} else {
+			log_framework(LOG_DEBUG, "%s: "
+			    "restarter_inst_validate_ractions_aux_fmri "
+			    "failed: ", rip->ri_i.i_fmri);
+
+			if (restarter_inst_reset_aux_fmri(scf_inst))
+				log_framework(LOG_DEBUG, "%s: "
+				    "restarter_inst_reset_aux_fmri failed: ",
+				    rip->ri_i.i_fmri);
+		}
+		scf_instance_destroy(scf_inst);
+	}
+
+	(void) restarter_instance_update_states(h, rip,
+	    RESTARTER_STATE_DEGRADED, RESTARTER_STATE_NONE, RERR_NONE, reason);
+
+	log_transition(rip, DEGRADE_REQUESTED);
+}
+
 const char *event_names[] = { "INVALID", "ADD_INSTANCE", "REMOVE_INSTANCE",
-	"ENABLE", "DISABLE", "ADMIN_DEGRADED", "ADMIN_REFRESH",
-	"ADMIN_RESTART", "ADMIN_MAINT_OFF", "ADMIN_MAINT_ON",
-	"ADMIN_MAINT_ON_IMMEDIATE", "STOP", "START", "DEPENDENCY_CYCLE",
-	"INVALID_DEPENDENCY", "ADMIN_DISABLE", "STOP_RESET"
+	"ENABLE", "DISABLE", "ADMIN_RESTORE", "ADMIN_DEGRADED",
+	"ADMIN_DEGRADE_IMMEDIATE", "ADMIN_REFRESH", "ADMIN_RESTART",
+	"ADMIN_MAINT_OFF", "ADMIN_MAINT_ON", "ADMIN_MAINT_ON_IMMEDIATE",
+	"STOP", "START", "DEPENDENCY_CYCLE", "INVALID_DEPENDENCY",
+	"ADMIN_DISABLE", "STOP_RESET"
 };
 
 /*
@@ -1866,11 +1919,16 @@
 			break;
 
 		case RESTARTER_EVENT_TYPE_ADMIN_DEGRADED:
-			log_framework(LOG_WARNING, "Restarter: "
-			    "%s command (for %s) unimplemented.\n",
-			    event_names[event->riq_type], inst->ri_i.i_fmri);
+		case RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE:
+			if (event_from_tty(h, inst) == 0)
+				degrade_instance(h, inst,
+				    restarter_str_service_request);
+			else
+				degrade_instance(h, inst,
+				    restarter_str_administrative_request);
 			break;
 
+		case RESTARTER_EVENT_TYPE_ADMIN_RESTORE:
 		case RESTARTER_EVENT_TYPE_ADMIN_RESTART:
 			if (!instance_started(inst)) {
 				log_framework(LOG_DEBUG, "Restarter: "
@@ -1947,6 +2005,8 @@
 	case RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF:
 	case RESTARTER_EVENT_TYPE_ADMIN_REFRESH:
 	case RESTARTER_EVENT_TYPE_ADMIN_DEGRADED:
+	case RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE:
+	case RESTARTER_EVENT_TYPE_ADMIN_RESTORE:
 	case RESTARTER_EVENT_TYPE_ADMIN_RESTART:
 		return (1);
 	default:
--- old/usr/src/cmd/svc/startd/startd.c	Mon Dec  4 17:58:49 2017
+++ new/usr/src/cmd/svc/startd/startd.c	Mon Dec  4 17:58:49 2017
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2015, Joyent, Inc.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -239,7 +240,9 @@
 boolean_t booting_to_single_user = B_FALSE;
 
 const char * const admin_actions[] = {
+    SCF_PROPERTY_RESTORE,
     SCF_PROPERTY_DEGRADED,
+    SCF_PROPERTY_DEGRADE_IMMEDIATE,
     SCF_PROPERTY_MAINT_OFF,
     SCF_PROPERTY_MAINT_ON,
     SCF_PROPERTY_MAINT_ON_IMMEDIATE,
@@ -248,7 +251,9 @@
 };
 
 const int admin_events[NACTIONS] = {
+    RESTARTER_EVENT_TYPE_ADMIN_RESTORE,
     RESTARTER_EVENT_TYPE_ADMIN_DEGRADED,
+    RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE,
     RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF,
     RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON,
     RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE,
--- old/usr/src/cmd/svc/startd/startd.h	Mon Dec  4 17:58:50 2017
+++ new/usr/src/cmd/svc/startd/startd.h	Mon Dec  4 17:58:50 2017
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2015, Joyent, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
  */
 
 #ifndef	_STARTD_H
@@ -164,7 +165,7 @@
  *   Note that the ordering in admin_action_t, admin_actions, and admin_events
  *   must match.  admin_actions and admin_events are defined in startd.c.
  */
-#define	NACTIONS			6
+#define	NACTIONS			8
 
 typedef enum {
 	ADMIN_EVENT_DEGRADED = 0x0,
@@ -344,6 +345,7 @@
  * Restarter transition outcomes
  */
 typedef enum {
+	DEGRADE_REQUESTED,
 	MAINT_REQUESTED,
 	START_REQUESTED,
 	START_FAILED_REPEATEDLY,
--- old/usr/src/cmd/svc/svcadm/svcadm.c	Mon Dec  4 17:58:50 2017
+++ new/usr/src/cmd/svc/svcadm/svcadm.c	Mon Dec  4 17:58:50 2017
@@ -25,6 +25,7 @@
 
 /*
  * Copyright 2015, Joyent, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -1931,6 +1932,13 @@
 		return (0);
 	}
 
+	if ((flags & MARK_TEMPORARY) == 0) {
+		uu_warn(gettext("Instance \"%s\" cannot be degraded "
+		    "permantently.\n"), wip->fmri);
+		exit_status = 1;
+		return (0);
+	}
+
 	set_inst_action(wip->fmri, wip->inst, (flags & MARK_IMMEDIATE) ?
 	    SCF_PROPERTY_DEGRADE_IMMEDIATE : SCF_PROPERTY_DEGRADED);
 
@@ -2507,11 +2515,7 @@
 			usage();
 
 		if (strcmp(argv[optind], "degraded") == 0) {
-			if (flags & MARK_TEMPORARY)
-				uu_xdie(UU_EXIT_USAGE, gettext("-t may not be "
-				    "used with degraded.\n"));
 			callback = force_degraded;
-
 		} else if (strcmp(argv[optind], "maintenance") == 0) {
 			callback = force_maintenance;
 		} else {
@@ -2529,7 +2533,7 @@
 			usage();
 
 		if ((err = scf_walk_fmri(h, argc, argv, WALK_FLAGS, callback,
-		    NULL, &exit_status, pr_warn)) != 0) {
+		    (void *)flags, &exit_status, pr_warn)) != 0) {
 			pr_warn(gettext("failed to iterate over "
 			    "instances: %s\n"),
 			    scf_strerror(err));
--- old/usr/src/cmd/svc/svcs/explain.c	Mon Dec  4 17:58:50 2017
+++ new/usr/src/cmd/svc/svcs/explain.c	Mon Dec  4 17:58:50 2017
@@ -23,6 +23,7 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  * Copyright (c) 2015, Joyent, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
@@ -1196,6 +1197,9 @@
 		 * excluding another service.
 		 */
 		add_svcptr(svcp->causes, svcp);
+		if (strcmp(svcp->state, SCF_STATE_STRING_DEGRADED) == 0)
+			add_svcptr(g_causes, svcp);
+
 		return (UU_WALK_NEXT);
 	}
 
@@ -1488,6 +1492,10 @@
 				(void) strlcpy(buf, gettext(
 				    "exited with $SMF_EXIT_ERR_FATAL"),
 				    sizeof (buf));
+			} else if (WEXITSTATUS(stat) == SMF_EXIT_MON_DEGRADE) {
+				(void) strlcpy(buf, gettext(
+				    "exited with $SMF_EXIT_MON_DEGRADE"),
+				    sizeof (buf));
 			} else {
 				(void) snprintf(buf, sizeof (buf),
 				    gettext("exited with status %d"),
@@ -1808,8 +1816,25 @@
 		}
 
 	} else if (strcmp(svcp->state, SCF_STATE_STRING_DEGRADED) == 0) {
-		(void) puts(gettext("Reason: Degraded by an administrator."));
-		dc = DC_ADMINDEGR;
+		if (strcmp(svcp->aux_state, "administrative_request") == 0) {
+			(void) puts(gettext("Reason: Degraded by an "
+			    "administrator."));
+			dc = DC_ADMINDEGR;
+		} else if (strcmp(svcp->aux_state, "service_request") == 0) {
+			if (svcp->aux_fmri) {
+				(void) printf(gettext("Reason: Degraded by "
+				    "\"%s\"\n"), svcp->aux_fmri);
+				print_aux_fmri_logs(svcp->aux_fmri);
+			} else {
+				(void) puts(gettext("Reason: Degraded by "
+				    "another service."));
+			}
+		} else if (strcmp(svcp->aux_state, "method_failed") == 0) {
+			print_method_failure(svcp, &dc);
+		} else {
+			(void) puts(gettext("Reason: Unknown."));
+			dc = DC_UNKNOWN;
+		}
 
 	} else {
 		(void) printf(gettext("Reason: Not in valid state (%s).\n"),
@@ -1818,7 +1843,7 @@
 	}
 
 diagcode:
-	if (g_msgbase != NULL)
+	if (g_msgbase != NULL && dc != NULL)
 		(void) printf(gettext("   See: %s%s\n"), g_msgbase, dc);
 }
 
--- old/usr/src/lib/librestart/common/librestart.h	Mon Dec  4 17:58:50 2017
+++ new/usr/src/lib/librestart/common/librestart.h	Mon Dec  4 17:58:50 2017
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2017 RackTop Systems.
  */
 
 #ifndef	_LIBRESTART_H
@@ -91,7 +92,9 @@
  *		RESTARTER_EVENT_TYPE_START
  *	RESTARTER_EVENT_TYPE_DISABLE
  *		no guarantee that instance was running
+ *	RESTARTER_EVENT_TYPE_ADMIN_RESTORE
  *	RESTARTER_EVENT_TYPE_ADMIN_DEGRADED
+ *	RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE
  *	RESTARTER_EVENT_TYPE_ADMIN_REFRESH
  *	RESTARTER_EVENT_TYPE_ADMIN_RESTART
  *	RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
@@ -125,6 +128,8 @@
 #define	RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY		14
 #define	RESTARTER_EVENT_TYPE_ADMIN_DISABLE		15
 #define	RESTARTER_EVENT_TYPE_STOP_RESET			16
+#define	RESTARTER_EVENT_TYPE_ADMIN_RESTORE		17
+#define	RESTARTER_EVENT_TYPE_ADMIN_DEGRADE_IMMEDIATE	18
 
 #define	RESTARTER_EVENT_ERROR			-1
 
--- old/usr/src/man/man1m/svcadm.1m	Mon Dec  4 17:58:50 2017
+++ new/usr/src/man/man1m/svcadm.1m	Mon Dec  4 17:58:51 2017
@@ -1,9 +1,10 @@
 '\" te
 .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2017 RackTop Systems.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SVCADM 1M "Oct 17, 2017"
+.TH SVCADM 1M "Dec 4, 2017"
 .SH NAME
 svcadm \- manipulate service instances
 .SH SYNOPSIS
@@ -246,7 +247,7 @@
 .sp
 If the \fB-I\fR option is specified, the request is flagged as immediate.
 .sp
-The \fB-t\fR option is only valid for maintenance requests. When this option is
+The \fB-t\fR option is mandatory for degrade requests. When this option is
 specified, the request is flagged as temporary, and its effect will only last
 until the next reboot.
 .RE
--- old/usr/src/man/man5/smf_method.5	Mon Dec  4 17:58:51 2017
+++ new/usr/src/man/man5/smf_method.5	Mon Dec  4 17:58:51 2017
@@ -1,9 +1,10 @@
 '\" te
 .\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2017 RackTop Systems.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
 .\"  See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with
 .\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SMF_METHOD 5 "June 6, 2016"
+.TH SMF_METHOD 5 "Dec 4, 2017"
 .SH NAME
 smf_method \- service management framework conventions for methods
 .SH DESCRIPTION
@@ -275,6 +276,9 @@
 \fBSMF_EXIT_ERR_CONFIG\fR	\fB96\fR	T{
 Unrecoverable configuration error. A common condition that returns this exit status is the absence of required configuration files for an enabled service instance.
 T}
+\fBSMF_EXIT_MON_DEGRADE\fR	\fB97\fR	T{
+Method encountered some problems and may not be fully functional.
+T}
 \fBSMF_EXIT_ERR_NOSMF\fR	\fB99\fR	T{
 Method has been mistakenly invoked outside the \fBsmf\fR(5) facility. Services that depend on \fBsmf\fR(5) capabilities should exit with this status value.
 T}
