diff options
author | Philippe Jung <Philippe.Jung@Sun.COM> | 2008-09-03 00:00:40 -0700 |
---|---|---|
committer | Philippe Jung <Philippe.Jung@Sun.COM> | 2008-09-03 00:00:40 -0700 |
commit | 70cbfe41f2338b77c15f79c6625eca6e70c412f3 (patch) | |
tree | 7dd8cf514b3381d51819a68779f3a64e48cebc97 | |
parent | 28a27262607274108141b82c5960bbaa1b3a9aae (diff) | |
download | illumos-joyent-70cbfe41f2338b77c15f79c6625eca6e70c412f3.tar.gz |
6438829 SMF svcs are not removed when performing a pkgrm in an alternate root
-rw-r--r-- | usr/src/cmd/svc/common/manifest_hash.c | 28 | ||||
-rw-r--r-- | usr/src/cmd/svc/common/manifest_hash.h | 5 | ||||
-rw-r--r-- | usr/src/cmd/svc/mfstscan/mfstscan.c | 6 | ||||
-rw-r--r-- | usr/src/cmd/svc/milestone/manifest-import | 22 | ||||
-rw-r--r-- | usr/src/cmd/svc/startd/Makefile | 5 | ||||
-rw-r--r-- | usr/src/cmd/svc/startd/deathrow.c | 257 | ||||
-rw-r--r-- | usr/src/cmd/svc/startd/graph.c | 89 | ||||
-rw-r--r-- | usr/src/cmd/svc/startd/libscf.c | 84 | ||||
-rw-r--r-- | usr/src/cmd/svc/startd/startd.h | 9 | ||||
-rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg.h | 2 | ||||
-rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg.l | 2 | ||||
-rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg.y | 24 | ||||
-rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg_engine.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg_help.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/svc/svccfg/svccfg_libscf.c | 36 | ||||
-rw-r--r-- | usr/src/lib/libscf/inc/libscf.h | 10 | ||||
-rw-r--r-- | usr/src/lib/libscf/inc/libscf_priv.h | 4 | ||||
-rw-r--r-- | usr/src/pkgdefs/common_files/i.manifest | 70 | ||||
-rw-r--r-- | usr/src/pkgdefs/common_files/r.manifest | 56 |
19 files changed, 657 insertions, 59 deletions
diff --git a/usr/src/cmd/svc/common/manifest_hash.c b/usr/src/cmd/svc/common/manifest_hash.c index 7c27c5f491..547f791df9 100644 --- a/usr/src/cmd/svc/common/manifest_hash.c +++ b/usr/src/cmd/svc/common/manifest_hash.c @@ -19,11 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/stat.h> #include <sys/types.h> @@ -48,18 +47,27 @@ /* * Translate a file name to property name. Return an allocated string or NULL - * if realpath() fails. + * if realpath() fails. If deathrow is true, realpath() is skipped. This + * allows to return the property name even if the file doesn't exist. */ char * -mhash_filename_to_propname(const char *in) +mhash_filename_to_propname(const char *in, boolean_t deathrow) { char *out, *cp, *base; size_t len, piece_len; out = uu_zalloc(PATH_MAX + 1); - if (realpath(in, out) == NULL) { - uu_free(out); - return (NULL); + if (deathrow) { + /* used only for service deathrow handling */ + if (strlcpy(out, in, PATH_MAX + 1) >= (PATH_MAX + 1)) { + uu_free(out); + return (NULL); + } + } else { + if (realpath(in, out) == NULL) { + uu_free(out); + return (NULL); + } } base = getenv("PKG_INSTALL_ROOT"); @@ -517,7 +525,7 @@ mhash_test_file(scf_handle_t *hndl, const char *file, uint_t is_profile, return (MHASH_NEWFILE); } - pname = mhash_filename_to_propname(file); + pname = mhash_filename_to_propname(file, B_FALSE); if (pname == NULL) return (MHASH_FAILURE); @@ -538,9 +546,9 @@ mhash_test_file(scf_handle_t *hndl, const char *file, uint_t is_profile, return (MHASH_NEWFILE); } - do + do { ret = stat64(file, &st); - while (ret < 0 && errno == EINTR); + } while (ret < 0 && errno == EINTR); if (ret < 0) { uu_free(pname); return (MHASH_FAILURE); diff --git a/usr/src/cmd/svc/common/manifest_hash.h b/usr/src/cmd/svc/common/manifest_hash.h index e641fbdcd1..ec718b9c76 100644 --- a/usr/src/cmd/svc/common/manifest_hash.h +++ b/usr/src/cmd/svc/common/manifest_hash.h @@ -19,14 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MANIFEST_HASH_H #define _MANIFEST_HASH_H -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> #include <libscf.h> @@ -50,7 +49,7 @@ extern "C" { #define MHASH_RECONCILED (1) #define MHASH_FAILURE (-1) -char *mhash_filename_to_propname(const char *); +char *mhash_filename_to_propname(const char *, boolean_t); int mhash_retrieve_entry(scf_handle_t *, const char *, uchar_t *); int mhash_store_entry(scf_handle_t *, const char *, uchar_t *, char **); int mhash_test_file(scf_handle_t *, const char *, uint_t, char **, uchar_t *); diff --git a/usr/src/cmd/svc/mfstscan/mfstscan.c b/usr/src/cmd/svc/mfstscan/mfstscan.c index 1bb1cbe2a0..62aa465b7d 100644 --- a/usr/src/cmd/svc/mfstscan/mfstscan.c +++ b/usr/src/cmd/svc/mfstscan/mfstscan.c @@ -19,11 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> @@ -113,7 +112,8 @@ main(int argc, char *argv[]) for (i = optind; i < argc; i++) { if (tflag) { - char *pname = mhash_filename_to_propname(argv[i]); + char *pname = mhash_filename_to_propname(argv[i], + B_FALSE); if (pname != NULL) (void) puts(pname); diff --git a/usr/src/cmd/svc/milestone/manifest-import b/usr/src/cmd/svc/milestone/manifest-import index 07f6ba0328..0b3586d0ae 100644 --- a/usr/src/cmd/svc/milestone/manifest-import +++ b/usr/src/cmd/svc/milestone/manifest-import @@ -23,9 +23,8 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -# 0. Initialization. +# 0a Initialization. [ -f /lib/svc/share/smf_include.sh ] || exit 1 @@ -338,10 +337,27 @@ prepare_last_import () { } } +# +# 0b Cleanup deathrow +# +deathrow=/etc/svc/deathrow +if [ -s $deathrow ];then + # + # svc.startd has unconfigured the services found in deathrow, + # clean them now. + # + while read fmri mfst pkgname; do + # Delete services and instances from the deathrow file. + /usr/sbin/svccfg delete -f $fmri >/dev/null 2>&1 + # Remove deathrow manifest hash. + /usr/sbin/svccfg delhash -d $mfst >/dev/null 2>&1 + done < $deathrow + /usr/bin/mv $deathrow $deathrow.old +fi SVCCFG_CHECKHASH=1 export SVCCFG_CHECKHASH # -# 0. Clean up repository +# 0c Clean up repository # if [ -z "$X" ] && /usr/bin/svcprop smf/manifest 2>/dev/null | /usr/bin/grep '^ar_svc_[^/]*/md5sum opaque ' >/dev/null diff --git a/usr/src/cmd/svc/startd/Makefile b/usr/src/cmd/svc/startd/Makefile index 0aacf0e373..f5b20e6e81 100644 --- a/usr/src/cmd/svc/startd/Makefile +++ b/usr/src/cmd/svc/startd/Makefile @@ -19,15 +19,14 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -# PROG = svc.startd OBJS = \ contract.o \ + deathrow.o \ dict.o \ env.o \ expand.o \ diff --git a/usr/src/cmd/svc/startd/deathrow.c b/usr/src/cmd/svc/startd/deathrow.c new file mode 100644 index 0000000000..e4e0ab2977 --- /dev/null +++ b/usr/src/cmd/svc/startd/deathrow.c @@ -0,0 +1,257 @@ +/* + * CDDL HEADER START + * + * 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] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/param.h> +#include "startd.h" + +/* + * The service deathrow mechanism addresses the problem of removing services + * from a non accessible SMF repository. In this case, we can't simply use the + * "SVCCFG_REPOSITORY=$ROOT/etc/svc/repository.db svccfg delete service_fmri" + * command as the alternate repository format is not committed and could be + * incompatible with the local SMF commands version. + * + * The idea is to manage a file (/etc/svc/deathrow) on the alternate root + * directory that lists the FMRIs that need to disappear from the repository + * when the system that uses this root directory boots up. + * r.manifest and i.manifest update the file /etc/svc/deathrow in the alternate + * root case. + * + * When svc.startd daemon launches, it first reads the /etc/svc/deathrow file + * and for all FMRIs listed in this file, the service is not configured and + * dependencies on it are forced satisfied (during svc.startd init time only). + * + * Than manifest-import service will actually, as first task, delete the + * unconfigured services found in the /etc/svc/deathrow file and the + * manifest hash entry from the repository. + * + */ + +#define SVC_DEATHROW_FILE "/etc/svc/deathrow" + +/* + * These data structures are unprotected because they + * are modified by a single thread, at startup time. + * After initialization, these data structures are + * used only in read mode, thus requiring no protection. + */ + +/* list of deathrow fmris, created from the file SVC_DEATHROW_FILE */ +typedef struct deathrow { + char *fmri; + uu_list_node_t deathrow_link; +} deathrow_t; + +static uu_list_pool_t *deathrow_pool; +static uu_list_t *deathrow_list; + +static boolean_t deathrow_handling_status = B_FALSE; + +static deathrow_t *fmri_in_deathrow_internal(const char *); +static void deathrow_add(const char *); + +static void +deathrow_handling_start() +{ + assert(deathrow_handling_status == B_FALSE); + deathrow_handling_status = B_TRUE; +} + +static void +deathrow_handling_stop() +{ + assert(deathrow_handling_status == B_TRUE); + deathrow_handling_status = B_FALSE; +} + +void +deathrow_init() +{ + FILE *file; + char *line; + char *fmri; + char *manifest; + char *pkgname; + size_t line_size, sz; + unsigned int line_parsed = 0; + + log_framework(LOG_DEBUG, "Deathrow init\n"); + + while ((file = fopen(SVC_DEATHROW_FILE, "r")) == NULL) { + if (errno == EINTR) { + continue; + } + if (errno != ENOENT) { + log_framework(LOG_ERR, + "Deathrow not processed. " + "Error opening file (%s): %s\n", + SVC_DEATHROW_FILE, strerror(errno)); + } + return; + } + + deathrow_pool = uu_list_pool_create("deathrow", + sizeof (deathrow_t), offsetof(deathrow_t, deathrow_link), + NULL, UU_LIST_POOL_DEBUG); + if (deathrow_pool == NULL) { + uu_die("deathrow_init couldn't create deathrow_pool"); + } + + deathrow_list = uu_list_create(deathrow_pool, deathrow_list, 0); + if (deathrow_list == NULL) { + uu_die("deathrow_init couldn't create deathrow_list"); + } + + /* + * A deathrow file line looks like: + * <fmri>< ><manifest path>< ><package name><\n> + * (field separator is a space character) + */ + line_size = max_scf_fmri_size + 3 + MAXPATHLEN + MAXNAMELEN; + line = (char *)startd_alloc(line_size); + *line = '\0'; + + while (fgets(line, line_size, file) != NULL) { + line_parsed++; + fmri = NULL; + manifest = NULL; + pkgname = NULL; + sz = strlen(line); + if (sz > 0) { + /* remove linefeed */ + if (line[sz - 1] == '\n') { + line[sz - 1] = '\0'; + } + manifest = strchr(line, ' '); + if (manifest != NULL) { + fmri = line; + *manifest = '\0'; + manifest++; + pkgname = strchr(manifest, ' '); + if (pkgname != NULL) { + *pkgname = '\0'; + pkgname++; + } + } + } + if (fmri != NULL && strlen(fmri) > 0 && + strlen(fmri) < max_scf_fmri_size && + manifest != NULL && strlen(manifest) > 0 && + pkgname != NULL && strlen(pkgname) > 0) { + log_framework(LOG_DEBUG, + "Deathrow parser <%s><%s><%s>\n", + fmri, manifest, pkgname); + if (fmri_in_deathrow_internal(fmri) == NULL) { + /* fmri is not in list, add fmri */ + deathrow_add(fmri); + } + } else { + log_framework(LOG_ERR, + "Deathrow error processing file (%s). " + "Skipping line %u.\n", + SVC_DEATHROW_FILE, line_parsed); + } + *line = '\0'; + } + startd_free(line, line_size); + (void) fclose(file); + + if (uu_list_first(deathrow_list) != NULL) { + deathrow_handling_start(); + } +} + +void +deathrow_fini() +{ + deathrow_t *d; + void *cookie = NULL; + + if (deathrow_handling_status == B_FALSE) { + log_framework(LOG_DEBUG, "Deathrow fini\n"); + return; + } + deathrow_handling_stop(); + + while ((d = uu_list_teardown(deathrow_list, &cookie)) != NULL) { + startd_free(d->fmri, strlen(d->fmri) + 1); + startd_free(d, sizeof (deathrow_t)); + } + + uu_list_destroy(deathrow_list); + uu_list_pool_destroy(deathrow_pool); + deathrow_pool = NULL; + deathrow_list = NULL; + log_framework(LOG_DEBUG, "Deathrow fini\n"); +} + +static void +deathrow_add(const char *fmri) +{ + deathrow_t *d; + + assert(fmri != NULL); + + d = startd_alloc(sizeof (deathrow_t)); + d->fmri = startd_alloc(strlen(fmri) + 1); + (void) strcpy(d->fmri, fmri); + uu_list_node_init(d, &d->deathrow_link, deathrow_pool); + (void) uu_list_insert_after(deathrow_list, NULL, d); + + log_framework(LOG_DEBUG, "Deathrow added <%s>\n", d->fmri); +} + +static deathrow_t * +fmri_in_deathrow_internal(const char *fmri) +{ + deathrow_t *d; + + assert(fmri != NULL); + assert(deathrow_pool != NULL); + assert(deathrow_list != NULL); + + for ((d = uu_list_first(deathrow_list)); d != NULL; + d = uu_list_next(deathrow_list, d)) { + if (strcmp(fmri, d->fmri) == 0) { + return (d); + } + } + return (NULL); +} + +boolean_t +is_fmri_in_deathrow(const char *fmri) +{ + if (deathrow_handling_status == B_FALSE) { + return (B_FALSE); + } + return ((fmri_in_deathrow_internal(fmri) != NULL) ? B_TRUE : B_FALSE); +} diff --git a/usr/src/cmd/svc/startd/graph.c b/usr/src/cmd/svc/startd/graph.c index 57b04d33ae..e45faeb7dd 100644 --- a/usr/src/cmd/svc/startd/graph.c +++ b/usr/src/cmd/svc/startd/graph.c @@ -1504,8 +1504,16 @@ dependency_satisfied(graph_vertex_t *v, boolean_t satbility) { switch (v->gv_type) { case GVT_INST: - if ((v->gv_flags & GV_CONFIGURED) == 0) + if ((v->gv_flags & GV_CONFIGURED) == 0) { + if (v->gv_flags & GV_DEATHROW) { + /* + * A dependency on an instance with GV_DEATHROW + * flag is always considered as satisfied. + */ + return (1); + } return (-1); + } switch (v->gv_state) { case RESTARTER_STATE_ONLINE: @@ -2869,6 +2877,7 @@ configure_vertex(graph_vertex_t *v, scf_instance_t *inst) int enabled, enabled_ovr; int err; int *path; + int deathrow; restarter_fmri[0] = '\0'; @@ -2880,11 +2889,86 @@ configure_vertex(graph_vertex_t *v, scf_instance_t *inst) assert(should_be_in_subgraph(v) == ((v->gv_flags & GV_INSUBGRAPH) != 0)); - log_framework(LOG_DEBUG, "Graph adding %s.\n", v->gv_name); + /* + * If the instance fmri is in the deathrow list then set the + * GV_DEATHROW flag on the vertex and create and set to true the + * SCF_PROPERTY_DEATHROW boolean property in the non-persistent + * repository for this instance fmri. + */ + if ((v->gv_flags & GV_DEATHROW) || + (is_fmri_in_deathrow(v->gv_name) == B_TRUE)) { + if ((v->gv_flags & GV_DEATHROW) == 0) { + /* + * Set flag GV_DEATHROW, create and set to true + * the SCF_PROPERTY_DEATHROW property in the + * non-persistent repository for this instance fmri. + */ + v->gv_flags |= GV_DEATHROW; + + switch (err = libscf_set_deathrow(inst, 1)) { + case 0: + break; + + case ECONNABORTED: + case ECANCELED: + startd_free(restarter_fmri, max_scf_value_size); + return (err); + + case EROFS: + log_error(LOG_WARNING, "Could not set %s/%s " + "for deathrow %s: %s.\n", + SCF_PG_DEATHROW, SCF_PROPERTY_DEATHROW, + v->gv_name, strerror(err)); + break; + + case EPERM: + uu_die("Permission denied.\n"); + /* NOTREACHED */ + + default: + bad_error("libscf_set_deathrow", err); + } + log_framework(LOG_DEBUG, "Deathrow, graph set %s.\n", + v->gv_name); + } + startd_free(restarter_fmri, max_scf_value_size); + return (0); + } h = scf_instance_handle(inst); /* + * Using a temporary deathrow boolean property, set through + * libscf_set_deathrow(), only for fmris on deathrow, is necessary + * because deathrow_fini() may already have been called, and in case + * of a refresh, GV_DEATHROW may need to be set again. + * libscf_get_deathrow() sets deathrow to 1 only if this instance + * has a temporary boolean property named 'deathrow' valued true + * in a property group 'deathrow', -1 or 0 in all other cases. + */ + err = libscf_get_deathrow(h, inst, &deathrow); + switch (err) { + case 0: + break; + + case ECONNABORTED: + case ECANCELED: + startd_free(restarter_fmri, max_scf_value_size); + return (err); + + default: + bad_error("libscf_get_deathrow", err); + } + + if (deathrow == 1) { + v->gv_flags |= GV_DEATHROW; + startd_free(restarter_fmri, max_scf_value_size); + return (0); + } + + log_framework(LOG_DEBUG, "Graph adding %s.\n", v->gv_name); + + /* * If the instance does not have a restarter property group, * initialize its state to uninitialized/none, in case the restarter * is not enabled. @@ -4296,6 +4380,7 @@ dgraph_remove_instance(const char *fmri, scf_handle_t *h) graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART); v->gv_flags &= ~GV_CONFIGURED; + v->gv_flags &= ~GV_DEATHROW; graph_walk_dependents(v, propagate_start, NULL); propagate_satbility(v); diff --git a/usr/src/cmd/svc/startd/libscf.c b/usr/src/cmd/svc/startd/libscf.c index 741d17cfe6..4584babf95 100644 --- a/usr/src/cmd/svc/startd/libscf.c +++ b/usr/src/cmd/svc/startd/libscf.c @@ -24,7 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/contract/process.h> #include <assert.h> @@ -931,6 +930,72 @@ libscf_lookup_instance(const char *fmri, scf_instance_t *inst) } /* + * int libscf_get_deathrow() + * Read deathrow for inst. Returns 0, ECONNABORTED if the connection to the + * repository is broken, ECANCELED if inst is deleted, or ENOENT if inst + * has no deathrow property group. + * + * If deathrow/deathrow was missing or invalid, *deathrow will be -1 and a + * debug message is logged. + */ +int +libscf_get_deathrow(scf_handle_t *h, scf_instance_t *inst, int *deathrow) +{ + scf_propertygroup_t *pg; + int r; + uint8_t deathrow_8; + + pg = safe_scf_pg_create(h); + + if (scf_instance_get_pg_composed(inst, NULL, SCF_PG_DEATHROW, pg) != + 0) { + switch (scf_error()) { + case SCF_ERROR_CONNECTION_BROKEN: + default: + scf_pg_destroy(pg); + return (ECONNABORTED); + + case SCF_ERROR_DELETED: + scf_pg_destroy(pg); + return (ECANCELED); + + case SCF_ERROR_NOT_FOUND: + *deathrow = -1; + break; + + case SCF_ERROR_HANDLE_MISMATCH: + case SCF_ERROR_INVALID_ARGUMENT: + case SCF_ERROR_NOT_SET: + bad_error("libscf_get_deathrow", scf_error()); + } + } else { + switch (r = get_boolean(pg, + SCF_PROPERTY_DEATHROW, &deathrow_8)) { + case 0: + *deathrow = deathrow_8; + break; + + case ECONNABORTED: + case ECANCELED: + scf_pg_destroy(pg); + return (r); + + case ENOENT: + case EINVAL: + *deathrow = -1; + break; + + default: + bad_error("get_boolean", r); + } + } + + scf_pg_destroy(pg); + + return (0); +} + +/* * void libscf_get_basic_instance_data() * Read enabled, enabled_ovr, and restarter_fmri (into an allocated * buffer) for inst. Returns 0, ECONNABORTED if the connection to the @@ -1498,6 +1563,19 @@ libscf_set_enable_ovr(scf_instance_t *inst, int enable) } /* + * Returns 0 on success, ECONNABORTED if the repository connection is broken, + * ECANCELED if inst is deleted, EROFS if the backend is readonly, or EPERM if + * permission was denied. + */ +int +libscf_set_deathrow(scf_instance_t *inst, int deathrow) +{ + return (libscf_inst_set_boolean_prop(inst, SCF_PG_DEATHROW, + SCF_PG_DEATHROW_TYPE, SCF_PG_DEATHROW_FLAGS, + SCF_PROPERTY_DEATHROW, deathrow)); +} + +/* * Returns * 0 - success * ECONNABORTED - repository connection broken @@ -2776,6 +2854,8 @@ libscf_populate_graph(scf_handle_t *h) svc_iter = safe_scf_iter_create(h); inst_iter = safe_scf_iter_create(h); + deathrow_init(); + if ((ret = scf_handle_get_local_scope(h, scope)) != SCF_SUCCESS) uu_die("retrieving local scope failed: %d\n", ret); @@ -2803,6 +2883,8 @@ libscf_populate_graph(scf_handle_t *h) } } + deathrow_fini(); + scf_iter_destroy(inst_iter); scf_iter_destroy(svc_iter); scf_instance_destroy(inst); diff --git a/usr/src/cmd/svc/startd/startd.h b/usr/src/cmd/svc/startd/startd.h index 99b88c7699..7040a4a52d 100644 --- a/usr/src/cmd/svc/startd/startd.h +++ b/usr/src/cmd/svc/startd/startd.h @@ -26,7 +26,6 @@ #ifndef _STARTD_H #define _STARTD_H -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/time.h> #include <librestart.h> @@ -287,6 +286,7 @@ typedef enum { #define GV_ENABLED 0x02 /* Service should be online */ #define GV_ENBLD_NOOVR 0x04 /* GV_ENABLED, ignoring override */ #define GV_INSUBGRAPH 0x08 /* Current milestone depends on service */ +#define GV_DEATHROW 0x10 /* Service is on deathrow */ /* ID must come first to support search */ typedef struct graph_vertex { @@ -619,6 +619,7 @@ int libscf_inst_set_count_prop(scf_instance_t *, const char *, const char *pgtype, uint32_t, const char *, uint64_t); /* libscf.c - used by graph.c */ +int libscf_get_deathrow(scf_handle_t *, scf_instance_t *, int *); int libscf_get_basic_instance_data(scf_handle_t *, scf_instance_t *, const char *, int *, int *, char **); int libscf_inst_get_or_add_pg(scf_instance_t *, const char *, const char *, @@ -630,6 +631,7 @@ gv_type_t depgroup_read_scheme(scf_handle_t *, scf_propertygroup_t *); depgroup_type_t depgroup_read_grouping(scf_handle_t *, scf_propertygroup_t *); restarter_error_t depgroup_read_restart(scf_handle_t *, scf_propertygroup_t *); int libscf_set_enable_ovr(scf_instance_t *, int); +int libscf_set_deathrow(scf_instance_t *, int); int libscf_inst_delete_prop(scf_instance_t *, const char *, const char *); int libscf_delete_enable_ovr(scf_instance_t *); int libscf_get_milestone(scf_instance_t *, scf_property_t *, scf_value_t *, @@ -756,6 +758,11 @@ void wait_ignore_by_fmri(const char *); /* proc.c */ ctid_t proc_get_ctid(); +/* deathrow.c */ +extern void deathrow_init(); +extern void deathrow_fini(); +extern boolean_t is_fmri_in_deathrow(const char *); + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/svc/svccfg/svccfg.h b/usr/src/cmd/svc/svccfg/svccfg.h index 971f4175f2..e63c24c111 100644 --- a/usr/src/cmd/svc/svccfg/svccfg.h +++ b/usr/src/cmd/svc/svccfg/svccfg.h @@ -27,7 +27,6 @@ #ifndef _CMD_SVCCFG_H #define _CMD_SVCCFG_H -#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> @@ -337,6 +336,7 @@ void lscf_add(const char *); void lscf_listpg(const char *); void lscf_addpg(const char *, const char *, const char *); void lscf_delpg(char *); +void lscf_delhash(char *, int); void lscf_listprop(const char *); void lscf_addprop(char *, const char *, const uu_list_t *); void lscf_delprop(char *); diff --git a/usr/src/cmd/svc/svccfg/svccfg.l b/usr/src/cmd/svc/svccfg/svccfg.l index 9ecff499e4..4bf42e18b3 100644 --- a/usr/src/cmd/svc/svccfg/svccfg.l +++ b/usr/src/cmd/svc/svccfg/svccfg.l @@ -25,7 +25,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #pragma error_messages(off, E_BLOCK_DECL_UNUSED) #pragma error_messages(off, E_EQUALITY_NOT_ASSIGNMENT) @@ -100,6 +99,7 @@ extern int yyerror(const char *); <INITIAL>listpg { BEGIN WORD; return (SCC_LISTPG); } <INITIAL>addpg { BEGIN WORD; return (SCC_ADDPG); } <INITIAL>delpg { BEGIN WORD; return (SCC_DELPG); } +<INITIAL>delhash { BEGIN WORD; return (SCC_DELHASH); } <INITIAL>listprop { BEGIN WORD; return (SCC_LISTPROP); } <INITIAL>setprop { BEGIN WORD; return (SCC_SETPROP); } <INITIAL>delprop { BEGIN WORD; return (SCC_DELPROP); } diff --git a/usr/src/cmd/svc/svccfg/svccfg.y b/usr/src/cmd/svc/svccfg/svccfg.y index 53c92b49c7..2cc0b04ab7 100644 --- a/usr/src/cmd/svc/svccfg/svccfg.y +++ b/usr/src/cmd/svc/svccfg/svccfg.y @@ -25,7 +25,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <libintl.h> @@ -46,7 +45,7 @@ uu_list_pool_t *string_pool; %token SCC_VALIDATE SCC_IMPORT SCC_EXPORT SCC_ARCHIVE SCC_APPLY SCC_EXTRACT %token SCC_REPOSITORY SCC_INVENTORY SCC_SET SCC_END SCC_HELP SCC_RESTORE %token SCC_LIST SCC_ADD SCC_DELETE SCC_SELECT SCC_UNSELECT -%token SCC_LISTPG SCC_ADDPG SCC_DELPG +%token SCC_LISTPG SCC_ADDPG SCC_DELPG SCC_DELHASH %token SCC_LISTPROP SCC_SETPROP SCC_DELPROP SCC_EDITPROP %token SCC_ADDPROPVALUE SCC_DELPROPVALUE SCC_SETENV SCC_UNSETENV %token SCC_LISTSNAP SCC_SELECTSNAP SCC_REVERT SCC_REFRESH @@ -92,6 +91,7 @@ command : terminator | listpg_cmd | addpg_cmd | delpg_cmd + | delhash_cmd | listprop_cmd | setprop_cmd | delprop_cmd @@ -346,6 +346,25 @@ delpg_cmd : SCC_DELPG SCV_WORD terminator { lscf_delpg($2); free($2); } | SCC_DELPG error terminator { synerr(SCC_DELPG); return(0); } +delhash_cmd : SCC_DELHASH SCV_WORD terminator + { + lscf_delhash($2, 0); free($2); + } + | SCC_DELHASH SCV_WORD SCV_WORD terminator + { + if (strcmp($2, "-d") == 0) { + lscf_delhash($3, 1); + free($2); + free($3); + } else { + synerr(SCC_DELHASH); + free($2); + free($3); + return(0); + } + } + | SCC_DELHASH error terminator { synerr(SCC_DELHASH); return(0); } + listprop_cmd : SCC_LISTPROP opt_word terminator { lscf_listprop($2); free($2); } | SCC_LISTPROP error terminator { synerr(SCC_LISTPROP); return(0); } @@ -527,6 +546,7 @@ command_token : SCC_VALIDATE { $$ = SCC_VALIDATE; } | SCC_LISTPG { $$ = SCC_LISTPG; } | SCC_ADDPG { $$ = SCC_ADDPG; } | SCC_DELPG { $$ = SCC_DELPG; } + | SCC_DELHASH { $$ = SCC_DELHASH; } | SCC_LISTPROP { $$ = SCC_LISTPROP; } | SCC_SETPROP { $$ = SCC_SETPROP; } | SCC_DELPROP { $$ = SCC_DELPROP; } diff --git a/usr/src/cmd/svc/svccfg/svccfg_engine.c b/usr/src/cmd/svc/svccfg/svccfg_engine.c index 105c166778..e610814274 100644 --- a/usr/src/cmd/svc/svccfg/svccfg_engine.c +++ b/usr/src/cmd/svc/svccfg/svccfg_engine.c @@ -24,7 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * svccfg(1) interpreter and command execution engine. @@ -216,6 +215,7 @@ static struct cmd_info { { "listpg", CS_SVC | CS_INST | CS_SNAP, NULL }, { "addpg", CS_SVC | CS_INST, NULL }, { "delpg", CS_SVC | CS_INST, NULL }, + { "delhash", CS_GLOBAL, complete_single_xml_file_arg }, { "listprop", CS_SVC | CS_INST | CS_SNAP, NULL }, { "setprop", CS_SVC | CS_INST, NULL }, { "delprop", CS_SVC | CS_INST, NULL }, diff --git a/usr/src/cmd/svc/svccfg/svccfg_help.c b/usr/src/cmd/svc/svccfg/svccfg_help.c index a9b8713fb8..0a03767614 100644 --- a/usr/src/cmd/svc/svccfg/svccfg_help.c +++ b/usr/src/cmd/svc/svccfg/svccfg_help.c @@ -24,7 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include "svccfg.h" #include "svccfg_grammar.h" @@ -80,6 +79,10 @@ struct help_message help_messages[] = { { SCC_DELPG, "delpg name\n\n" "Delete the named property group from the currently selected entity." }, + { SCC_DELHASH, "delhash [-d] manifest\n\n" +"Delete the named manifest hash entry (from smf/manifest).\n" +"With -d, manifest file doesn't need to exist." + }, { SCC_LISTPROP, "listprop [glob_pattern]\n\n" "List property groups and properties of the currently selected entity." }, diff --git a/usr/src/cmd/svc/svccfg/svccfg_libscf.c b/usr/src/cmd/svc/svccfg/svccfg_libscf.c index c152e2cd10..9c133a37c4 100644 --- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c +++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c @@ -24,7 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <alloca.h> #include <assert.h> @@ -48,6 +47,7 @@ #include <libxml/tree.h> #include "svccfg.h" +#include "manifest_hash.h" /* The colon namespaces in each entity (each followed by a newline). */ #define COLON_NAMESPACES ":properties\n" @@ -11022,6 +11022,40 @@ lscf_delpg(char *name) lscf_delprop(name); } +/* + * scf_delhash() is used to remove the property group related to the + * hash entry for a specific manifest in the repository. pgname will be + * constructed from the location of the manifest file. If deathrow isn't 0, + * manifest file doesn't need to exist (manifest string will be used as + * an absolute path). + */ +void +lscf_delhash(char *manifest, int deathrow) +{ + char *pgname; + + if (cur_snap != NULL || + cur_inst != NULL || cur_svc != NULL) { + warn(gettext("error, an entity is selected\n")); + return; + } + + /* select smf/manifest */ + lscf_select("smf/manifest"); + /* + * Translate the manifest file name to property name. In the deathrow + * case, the manifest file does not need to exist. + */ + pgname = mhash_filename_to_propname(manifest, + deathrow ? B_TRUE : B_FALSE); + if (pgname == NULL) { + warn(gettext("cannot resolve pathname for %s\n"), manifest); + return; + } + /* delete the hash property name */ + lscf_delpg(pgname); +} + void lscf_listprop(const char *pattern) { diff --git a/usr/src/lib/libscf/inc/libscf.h b/usr/src/lib/libscf/inc/libscf.h index 5bb5a19869..3bdd12f7b9 100644 --- a/usr/src/lib/libscf/inc/libscf.h +++ b/usr/src/lib/libscf/inc/libscf.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -20,14 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LIBSCF_H #define _LIBSCF_H -#pragma ident "%Z%%M% %I% %E% SMI" #include <stddef.h> #include <sys/types.h> @@ -178,6 +176,7 @@ typedef enum scf_error { #define SCF_PG_OPTIONS_OVR ((const char *)"options_ovr") #define SCF_PG_STARTD ((const char *)"startd") #define SCF_PG_STARTD_PRIVATE ((const char *)"svc-startd-private") +#define SCF_PG_DEATHROW ((const char *)"deathrow") /* * Template property group names and prefix @@ -198,6 +197,7 @@ typedef enum scf_error { #define SCF_PROPERTY_DEGRADE_IMMEDIATE ((const char *)"degrade_immediate") #define SCF_PROPERTY_DURATION ((const char *)"duration") #define SCF_PROPERTY_ENABLED ((const char *)"enabled") +#define SCF_PROPERTY_DEATHROW ((const char *)"deathrow") #define SCF_PROPERTY_ENTITY_STABILITY ((const char *)"entity_stability") #define SCF_PROPERTY_ENTITIES ((const char *)"entities") #define SCF_PROPERTY_EXEC ((const char *)"exec") diff --git a/usr/src/lib/libscf/inc/libscf_priv.h b/usr/src/lib/libscf/inc/libscf_priv.h index 5c44c9b757..ab4ad553c5 100644 --- a/usr/src/lib/libscf/inc/libscf_priv.h +++ b/usr/src/lib/libscf/inc/libscf_priv.h @@ -26,7 +26,6 @@ #ifndef _LIBSCF_PRIV_H #define _LIBSCF_PRIV_H -#pragma ident "%Z%%M% %I% %E% SMI" #include <libscf.h> #include <unistd.h> @@ -48,6 +47,9 @@ extern "C" { #define SCF_PG_GENERAL_OVR_TYPE SCF_GROUP_FRAMEWORK #define SCF_PG_GENERAL_OVR_FLAGS SCF_PG_FLAG_NONPERSISTENT +#define SCF_PG_DEATHROW_TYPE SCF_GROUP_FRAMEWORK +#define SCF_PG_DEATHROW_FLAGS SCF_PG_FLAG_NONPERSISTENT + #define SCF_PG_OPTIONS_TYPE SCF_GROUP_FRAMEWORK #define SCF_PG_OPTIONS_FLAGS 0 diff --git a/usr/src/pkgdefs/common_files/i.manifest b/usr/src/pkgdefs/common_files/i.manifest index 72ebfddd04..07c4b8ca78 100644 --- a/usr/src/pkgdefs/common_files/i.manifest +++ b/usr/src/pkgdefs/common_files/i.manifest @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -21,17 +20,58 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -# # i.manifest - smf(5) service manifest install class action script # repfile=$PKG_INSTALL_ROOT/etc/svc/repository.db export repfile +SVCCFG=/usr/sbin/svccfg +AWK=/usr/bin/awk +RM=/usr/bin/rm +CP=/usr/bin/cp +MV=/usr/bin/mv +CHMOD=/usr/bin/chmod +CHOWN=/usr/bin/chown + +# +# Helper function. Handle services deathrow file. +# Arguments: $1:manifest file. +# +svc_deathrow() +{ + TEMP=/tmp/svc_deathrow.$$ + DEATHROW_FILE=${PKG_INSTALL_ROOT}/etc/svc/deathrow + # + # Services deathrow file handling, file format: + # <fmri>< ><manifest file>< ><package name> + # (field separator is a space character) + # + if [ -s ${DEATHROW_FILE} ]; then + # + # Manifest file could be from another Solaris version, bypass + # the service bundle and validation (we only need the fmris + # list). Calling svccfg inventory with SVCCFG_NOVALIDATE=1 is + # safe because there is no access to the alternate repository. + # + ENTITIES=`SVCCFG_NOVALIDATE=1 $SVCCFG inventory $1` + for fmri in $ENTITIES; do + # + # If fmri matches one in deathrow file, remove the + # line from the file. + # + >${TEMP} + $AWK "(\$1==\"$fmri\") \ + {next}; {print}" ${DEATHROW_FILE} >>${TEMP} && \ + $MV ${TEMP} ${DEATHROW_FILE} + $RM -f ${TEMP} + done + fi +} + # # If the repository does not yet exist, create it from the appropriate seed. If # for some reason the seeds do not exist, svccfg(1M) will create the repository @@ -41,15 +81,13 @@ if [ ! -f $repfile ]; then if [ -n "$SUNW_PKG_INSTALL_ZONENAME" -a \ "$SUNW_PKG_INSTALL_ZONENAME" != "global" ]; then [ -f $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db ] && \ - /usr/bin/cp $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db \ - $repfile + $CP $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db $repfile else [ -f $PKG_INSTALL_ROOT/lib/svc/seed/global.db ] && \ - /usr/bin/cp $PKG_INSTALL_ROOT/lib/svc/seed/global.db \ - $repfile + $CP $PKG_INSTALL_ROOT/lib/svc/seed/global.db $repfile fi - /usr/bin/chmod 0600 $repfile - /usr/bin/chown root:sys $repfile + $CHMOD 0600 $repfile + $CHOWN root:sys $repfile fi if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then @@ -59,17 +97,19 @@ if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then # cannot consistently handle dependent placement. Defer to next boot. # while read src dst; do - /usr/bin/cp -p $src $dst + $CP -p $src $dst + # deathrow handling + svc_deathrow $dst done else # # Local package install. # while read src dst; do - /usr/bin/cp -p $src $dst + $CP -p $src $dst [ "$PKG_INSTALL_ROOT" = "" -o "$PKG_INSTALL_ROOT" = "/" ] && \ - SVCCFG_CHECKHASH=1 /usr/sbin/svccfg import $dst + SVCCFG_CHECKHASH=1 $SVCCFG import $dst done fi diff --git a/usr/src/pkgdefs/common_files/r.manifest b/usr/src/pkgdefs/common_files/r.manifest index cf6a0dc956..879016a302 100644 --- a/usr/src/pkgdefs/common_files/r.manifest +++ b/usr/src/pkgdefs/common_files/r.manifest @@ -31,10 +31,56 @@ MFSTSCAN=/lib/svc/bin/mfstscan SVCCFG=/usr/sbin/svccfg SVCPROP=/usr/bin/svcprop SVCADM=/usr/sbin/svcadm +AWK=/usr/bin/awk +CP=/usr/bin/cp +RM=/usr/bin/rm # number of seconds to wait before killing processes STOP_DELAY=60 +# +# Helper function. Delete the manifest hash value. +# Arguments: $1: manifest file. +# +svc_delhash() +{ + $SVCCFG delhash $1 >/dev/null 2>&1 + if [ "$?" != "0" ];then + # this Solaris release doesn't have delhash command + pg_name=`$MFSTSCAN -t $1` + if $SVCPROP -q -p $pg_name smf/manifest; then + $SVCCFG -s smf/manifest delpg $pg_name + fi + fi +} + +# +# Helper function. Handle services deathrow file. +# Arguments: $1:manifest file, $2:package name. +# +svc_deathrow() +{ + DEATHROW_FILE=${PKG_INSTALL_ROOT}/etc/svc/deathrow + # remove alternate root from manifest path + manifest=`echo "${PKG_INSTALL_ROOT} $1" | $AWK \ + '{ print substr($2, length($1)+1); }'` + # + # Services deathrow file handling, file format: + # <fmri>< ><manifest file>< ><package name> + # (field separator is a space character) + # + # Manifest file could be from another Solaris version, bypass the + # the service bundle and validation (we only need the fmris list). + # Calling svccfg inventory with SVCCFG_NOVALIDATE=1 is safe because + # there is no access to the alternate repository. + # + ENTITIES=`SVCCFG_NOVALIDATE=1 $SVCCFG inventory $1` + for fmri in $ENTITIES; do + # add to services deathrow file + echo ${fmri} ${manifest} $2 >> ${DEATHROW_FILE} + done +} + wait_disable() { svcinst=$1 wait_time=$2 @@ -128,13 +174,13 @@ while read mfst; do # # Delete the manifest hash value. # - pg_name=`$MFSTSCAN -t $mfst` - if $SVCPROP -q -p $pg_name smf/manifest; then - $SVCCFG -s smf/manifest delpg $pg_name - fi + svc_delhash $mfst + else + # deathrow handling + svc_deathrow $mfst $PKGINST fi - /usr/bin/rm $mfst + $RM -f $mfst done exit 0 |