summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2019-09-12 20:26:08 +0000
committerJohn Levon <john.levon@joyent.com>2019-10-23 23:21:01 +0100
commita2e92fdb91a6e5451ecb5488b74ee1e95a4bafd0 (patch)
treefc5e3924684aeacd23b74204404d951eba4c08c6 /usr
parent3ef756924267e272e432add760e4dc8597faef89 (diff)
downloadillumos-joyent-a2e92fdb91a6e5451ecb5488b74ee1e95a4bafd0.tar.gz
11691 ptree could show service FMRIs
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Jason King <jason.king@joyent.com> Reviewed by: Andy Fiddaman <andy@omniosce.org> Reviewed by: Peter Tribble <peter.tribble@gmail.com> Approved by: Robert Mustacchi <rm@fingolfin.org>
Diffstat (limited to 'usr')
-rw-r--r--usr/src/cmd/ptools/ptree/ptree.c180
-rw-r--r--usr/src/man/man1/ptree.137
-rw-r--r--usr/src/uts/common/contract/process.c7
3 files changed, 173 insertions, 51 deletions
diff --git a/usr/src/cmd/ptools/ptree/ptree.c b/usr/src/cmd/ptools/ptree/ptree.c
index 27fef9b7f0..caedc4ac82 100644
--- a/usr/src/cmd/ptools/ptree/ptree.c
+++ b/usr/src/cmd/ptools/ptree/ptree.c
@@ -21,14 +21,13 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2019 Joyent, Inc.
*/
/*
* ptree -- print family tree of processes
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <assert.h>
#include <stdio.h>
#include <string.h>
@@ -48,6 +47,7 @@
#include <sys/ctfs.h>
#include <libcontract_priv.h>
#include <sys/stat.h>
+#include <stdbool.h>
#define FAKEDPID0(p) (p->pid == 0 && p->psargs[0] == '\0')
@@ -61,6 +61,7 @@ typedef struct ps {
pid_t sid;
zoneid_t zoneid;
ctid_t ctid;
+ char *svc_fmri;
timestruc_t start;
char psargs[PRARGSZ];
struct ps *pp; /* parent */
@@ -81,16 +82,22 @@ static char *command;
static int aflag = 0;
static int cflag = 0;
+static int sflag = 0;
static int zflag = 0;
static zoneid_t zoneid;
+static char *match_svc;
+static char *match_inst;
static int columns = 80;
-static void markprocs(ps_t *p);
-static int printone(ps_t *p, int level);
+static bool match_proc(ps_t *);
+static void markprocs(ps_t *);
+static int printone(ps_t *, int);
static void insertchild(ps_t *, ps_t *);
-static void prsort(ps_t *p);
-static void printsubtree(ps_t *p, int level);
-static zoneid_t getzone(char *arg);
+static void prsort(ps_t *);
+static void printsubtree(ps_t *, int);
+static void p_get_svc_fmri(ps_t *, ct_stathdl_t);
+static char *parse_svc(const char *, char **);
+static zoneid_t getzone(const char *);
static ps_t *fakepid0(void);
int
@@ -117,7 +124,7 @@ main(int argc, char **argv)
command++;
/* options */
- while ((opt = getopt(argc, argv, "acz:")) != EOF) {
+ while ((opt = getopt(argc, argv, "acs:z:")) != EOF) {
switch (opt) {
case 'a': /* include children of process 0 */
aflag = 1;
@@ -125,6 +132,10 @@ main(int argc, char **argv)
case 'c': /* display contract ownership */
aflag = cflag = 1;
break;
+ case 's':
+ sflag = 1;
+ match_svc = parse_svc(optarg, &match_inst);
+ break;
case 'z': /* only processes in given zone */
zflag = 1;
zoneid = getzone(optarg);
@@ -140,7 +151,7 @@ main(int argc, char **argv)
if (errflg) {
(void) fprintf(stderr,
- "usage:\t%s [-ac] [-z zone] [ {pid|user} ... ]\n",
+ "usage:\t%s [-ac] [-s svc] [-z zone] [ {pid|user} ... ]\n",
command);
(void) fprintf(stderr,
" (show process trees)\n");
@@ -149,7 +160,9 @@ main(int argc, char **argv)
(void) fprintf(stderr,
" -a : include children of process 0\n");
(void) fprintf(stderr,
- " -c : show contract ownership\n");
+ " -c : show contracts\n");
+ (void) fprintf(stderr,
+ " -s : print only processes with given service FMRI\n");
(void) fprintf(stderr,
" -z : print only processes in given zone\n");
return (2);
@@ -221,8 +234,8 @@ retry:
return (1);
}
}
- if ((p = malloc(sizeof (ps_t))) == NULL) {
- perror("malloc()");
+ if ((p = calloc(1, sizeof (ps_t))) == NULL) {
+ perror("calloc()");
return (1);
}
ps[nps++] = p;
@@ -249,6 +262,10 @@ retry:
p->pp = NULL;
p->sp = NULL;
p->cp = NULL;
+
+ if (sflag)
+ p_get_svc_fmri(p, NULL);
+
if (p->pid == p->ppid)
proc0 = p;
if (p->pid == 1)
@@ -335,8 +352,7 @@ retry:
p->done != 1 && p->pid != 0;
p = p->pp)
if ((p->ppid != 0 || aflag) &&
- (!zflag ||
- p->zoneid == zoneid))
+ match_proc(p))
p->done = 1;
if (uid == (uid_t)-1)
break;
@@ -368,8 +384,9 @@ printone(ps_t *p, int level)
PIDWIDTH, (int)p->pid, n, p->psargs);
} else {
assert(cflag != 0);
- (void) printf("%*.*s[process contract %d]\n",
- indent, indent, " ", (int)p->ctid);
+ (void) printf("%*.*s[process contract %d: %s]\n",
+ indent, indent, " ", (int)p->ctid,
+ p->svc_fmri == NULL ? "?" : p->svc_fmri);
}
return (1);
}
@@ -398,11 +415,50 @@ insertchild(ps_t *pp, ps_t *cp)
*here = cp;
}
+static ct_stathdl_t
+ct_status_open(ctid_t ctid, struct stat64 *stp)
+{
+ ct_stathdl_t hdl;
+ int fd;
+
+ if ((fd = contract_open(ctid, "process", "status", O_RDONLY)) == -1)
+ return (NULL);
+
+ if (fstat64(fd, stp) == -1 || ct_status_read(fd, CTD_FIXED, &hdl)) {
+ (void) close(fd);
+ return (NULL);
+ }
+
+ (void) close(fd);
+
+ return (hdl);
+}
+
+/*
+ * strdup() failure is OK - better to report something than fail totally.
+ */
+static void
+p_get_svc_fmri(ps_t *p, ct_stathdl_t inhdl)
+{
+ ct_stathdl_t hdl = inhdl;
+ struct stat64 st;
+ char *fmri;
+
+ if (hdl == NULL && (hdl = ct_status_open(p->ctid, &st)) == NULL)
+ return;
+
+ if (ct_pr_status_get_svc_fmri(hdl, &fmri) == 0)
+ p->svc_fmri = strdup(fmri);
+
+ if (inhdl == NULL)
+ ct_status_free(hdl);
+}
+
static void
ctsort(ctid_t ctid, ps_t *p)
{
ps_t *pp;
- int fd, n;
+ int n;
ct_stathdl_t hdl;
struct stat64 st;
@@ -412,13 +468,8 @@ ctsort(ctid_t ctid, ps_t *p)
return;
}
- if ((fd = contract_open(ctid, "process", "status", O_RDONLY)) == -1)
- return;
- if (fstat64(fd, &st) == -1 || ct_status_read(fd, CTD_COMMON, &hdl)) {
- (void) close(fd);
+ if ((hdl = ct_status_open(ctid, &st)) == NULL)
return;
- }
- (void) close(fd);
if (nctps >= ctsize) {
if ((ctsize *= 2) == 0)
@@ -437,10 +488,14 @@ ctsort(ctid_t ctid, ps_t *p)
pp->pid = -1;
pp->ctid = ctid;
+
+ p_get_svc_fmri(pp, hdl);
+
pp->start.tv_sec = st.st_ctime;
insertchild(pp, p);
pp->zoneid = ct_status_get_zoneid(hdl);
+
/*
* In a zlogin <zonename>, the contract belongs to the
* global zone and the shell opened belongs to <zonename>.
@@ -510,11 +565,51 @@ printsubtree(ps_t *p, int level)
printsubtree(p, level);
}
+/*
+ * Match against the service name (and just the final component), and any
+ * specified instance name.
+ */
+static bool
+match_proc(ps_t *p)
+{
+ bool matched = false;
+ const char *cp;
+ char *p_inst;
+ char *p_svc;
+
+ if (zflag && p->zoneid != zoneid)
+ return (false);
+
+ if (!sflag)
+ return (true);
+
+ if (p->svc_fmri == NULL)
+ return (false);
+
+ p_svc = parse_svc(p->svc_fmri, &p_inst);
+
+ if (strcmp(p_svc, match_svc) != 0 &&
+ ((cp = strrchr(p_svc, '/')) == NULL ||
+ strcmp(cp + 1, match_svc) != 0)) {
+ goto out;
+ }
+
+ if (strlen(match_inst) == 0 ||
+ strcmp(p_inst, match_inst) == 0)
+ matched = true;
+
+out:
+ free(p_svc);
+ free(p_inst);
+ return (matched);
+}
+
static void
markprocs(ps_t *p)
{
- if (!zflag || p->zoneid == zoneid)
+ if (match_proc(p))
p->done = 1;
+
for (p = p->cp; p != NULL; p = p->sp)
markprocs(p);
}
@@ -529,8 +624,8 @@ fakepid0(void)
ps_t *p0, *p;
int n;
- if ((p0 = malloc(sizeof (ps_t))) == NULL) {
- perror("malloc()");
+ if ((p0 = calloc(1, sizeof (ps_t))) == NULL) {
+ perror("calloc()");
exit(1);
}
(void) memset(p0, '\0', sizeof (ps_t));
@@ -556,7 +651,7 @@ fakepid0(void)
/* convert string containing zone name or id to a numeric id */
static zoneid_t
-getzone(char *arg)
+getzone(const char *arg)
{
zoneid_t zoneid;
@@ -566,3 +661,34 @@ getzone(char *arg)
}
return (zoneid);
}
+
+/* svc:/mysvc:default -> mysvc, default */
+static char *
+parse_svc(const char *arg, char **instp)
+{
+ const char *p = arg;
+ char *ret;
+ char *cp;
+
+ if (strncmp(p, "svc:/", strlen("svc:/")) == 0)
+ p += strlen("svc:/");
+
+ if ((ret = strdup(p)) == NULL) {
+ perror("strdup()");
+ exit(1);
+ }
+
+ if ((cp = strrchr(ret, ':')) != NULL) {
+ *cp = '\0';
+ cp++;
+ } else {
+ cp = "";
+ }
+
+ if ((*instp = strdup(cp)) == NULL) {
+ perror("strdup()");
+ exit(1);
+ }
+
+ return (ret);
+}
diff --git a/usr/src/man/man1/ptree.1 b/usr/src/man/man1/ptree.1
index a8de77c0bd..8777a8e235 100644
--- a/usr/src/man/man1/ptree.1
+++ b/usr/src/man/man1/ptree.1
@@ -1,27 +1,23 @@
'\" te
.\" Copyright (c) 2005, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2019 Joyent, Inc.
.\" 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 PTREE 1 "Oct 11, 2005"
+.TH PTREE 1 "Sep 3, 2019"
.SH NAME
ptree \- print process trees
.SH SYNOPSIS
-.LP
.nf
-\fB/usr/bin/ptree\fR [\fB-a\fR] [\fB-c\fR] [\fB-z\fR \fIzone\fR] [\fIpid\fR | \fIuser\fR]...
+\fB/usr/bin/ptree\fR [\fB-a\fR] [\fB-c\fR] [\fB-s\fR \fIsvc\fR] [\fB-z\fR \fIzone\fR] [\fIpid\fR | \fIuser\fR]...
.fi
.SH DESCRIPTION
-.sp
-.LP
The \fBptree\fR utility prints the process trees containing the specified
\fIpid\fRs or \fIuser\fRs, with child processes indented from their respective
parent processes. An argument of all digits is taken to be a process-ID,
otherwise it is assumed to be a user login name. The default is all processes.
.SH OPTIONS
-.sp
-.LP
The following options are supported:
.sp
.ne 2
@@ -38,8 +34,21 @@ All. Print all processes, including children of process 0.
\fB\fB-c\fR\fR
.ad
.RS 11n
-Contracts. Print process contract memberships in addition to parent-child
-relationships. See \fBprocess\fR(4). This option implies the \fB-a\fR option.
+Contracts. Print process contract memberships and their associated SMF FMRIs,
+in addition to parent-child relationships. See \fBprocess\fR(4).
+This option implies the \fB-a\fR option.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-s\fR \fIsvc\fR\fR
+.ad
+.RS 11n
+Print only processes with an SMF service FMRI matching the argument. The FMRI
+may be in truncated form (such as 'console-login'). This includes child
+processes even if they are not members of the service contract.
+See \fBprocess\fR(4).
.RE
.sp
@@ -55,8 +64,6 @@ This option is only useful when executed in the global zone.
.RE
.SH OPERANDS
-.sp
-.LP
The following operands are supported:
.sp
.ne 2
@@ -80,7 +87,6 @@ given are displayed.
.RE
.SH EXAMPLES
-.LP
\fBExample 1 \fRUsing ptree
.sp
.LP
@@ -104,8 +110,6 @@ $ ptree -a `pgrep ssh`
.sp
.SH EXIT STATUS
-.sp
-.LP
The following exit values are returned:
.sp
.ne 2
@@ -126,7 +130,6 @@ An error has occurred.
.RE
.SH FILES
-.sp
.ne 2
.na
\fB\fB/proc/*\fR\fR
@@ -136,8 +139,6 @@ process files
.RE
.SH ATTRIBUTES
-.sp
-.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -155,8 +156,6 @@ Interface Stability See below.
.LP
The human readable output is Unstable. The options are Evolving.
.SH SEE ALSO
-.sp
-.LP
\fBgcore\fR(1), \fBldd\fR(1), \fBpargs\fR(1), \fBpgrep\fR(1), \fBpkill\fR(1),
\fBplimit\fR(1), \fBpmap\fR(1), \fBpreap\fR(1), \fBproc\fR(1), \fBps\fR(1),
\fBppgsz\fR(1), \fBpwd\fR(1), \fBrlogin\fR(1), \fBtime\fR(1), \fBtruss\fR(1),
diff --git a/usr/src/uts/common/contract/process.c b/usr/src/uts/common/contract/process.c
index 9fd23fdb61..8475549c74 100644
--- a/usr/src/uts/common/contract/process.c
+++ b/usr/src/uts/common/contract/process.c
@@ -21,6 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2019 Joyent, Inc.
*/
#include <sys/mutex.h>
@@ -736,13 +737,11 @@ contract_process_status(contract_t *ct, zone_t *zone, int detail, nvlist_t *nvl,
* if we are in a local zone and svc_fmri was inherited from
* the global zone, we provide fake svc_fmri and svc_ctid
*/
- if (local_svc_zone_enter == 0||
+ if (local_svc_zone_enter == 0 ||
zone->zone_uniqid == GLOBAL_ZONEUNIQID) {
if (detail > CTD_COMMON) {
VERIFY(nvlist_add_int32(nvl, CTPS_SVC_CTID,
ctp->conp_svc_ctid) == 0);
- }
- if (detail == CTD_ALL) {
VERIFY(nvlist_add_string(nvl, CTPS_SVC_FMRI,
refstr_value(ctp->conp_svc_fmri)) == 0);
}
@@ -750,8 +749,6 @@ contract_process_status(contract_t *ct, zone_t *zone, int detail, nvlist_t *nvl,
if (detail > CTD_COMMON) {
VERIFY(nvlist_add_int32(nvl, CTPS_SVC_CTID,
local_svc_zone_enter) == 0);
- }
- if (detail == CTD_ALL) {
VERIFY(nvlist_add_string(nvl, CTPS_SVC_FMRI,
CT_PR_SVC_FMRI_ZONE_ENTER) == 0);
}