--- old/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c	Wed Oct  5 00:31:39 2016
+++ new/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c	Wed Oct  5 00:31:39 2016
@@ -21,10 +21,9 @@
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc.  All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <procfs.h>
 #include <project.h>
 #include <stdlib.h>
@@ -31,6 +30,8 @@
 #include <strings.h>
 #include <zone.h>
 #include <libzonecfg.h>
+#include <dirent.h>
+#include <libproc.h>
 #include "rcapd.h"
 #include "utils.h"
 
@@ -39,61 +40,117 @@
 				/* round up to next y = 2^n */
 #define	ROUNDUP(x, y)		(((x) + ((y) - 1)) & ~((y) - 1))
 
-static void
-update_zone(zone_entry_t *zent, void *walk_data)
+static struct ps_prochandle *
+grab_zone_proc(zoneid_t zid)
 {
-	void(*update_notification_cb)(char *, char *, int, uint64_t, int) =
-	    (void(*)(char *, char *, int, uint64_t, int))walk_data;
-	int changes;
-	int64_t max_rss;
+	DIR *dirp;
+	struct dirent *dentp;
+	int pid, pid_self, tmp;
+	psinfo_t psinfo;
+	struct ps_prochandle *pr = NULL;
+
+	pid_self = getpid();
+
+	if ((dirp = opendir("/proc")) == NULL)
+		return (NULL);
+
+	while (dentp = readdir(dirp)) {
+		pid = atoi(dentp->d_name);
+
+		/* Skip self */
+		if (pid == pid_self)
+			continue;
+
+		if (proc_get_psinfo(pid, &psinfo) != 0)
+			continue;
+
+		if (psinfo.pr_zoneid != zid)
+			continue;
+
+		/* attempt to grab process */
+		if ((pr = Pgrab(pid, 0, &tmp)) != NULL) {
+			if (Psetflags(pr, PR_RLC) != 0) {
+				Prelease(pr, 0);
+			}
+			if (Pcreate_agent(pr) == 0) {
+				if (pr_getzoneid(pr) != zid) {
+					Prelease(pr, 0);
+					continue;
+				}
+
+				(void) closedir(dirp);
+				return (pr);
+			} else {
+				Prelease(pr, 0);
+			}
+		}
+	}
+
+	(void) closedir(dirp);
+	return (NULL);
+}
+
+static uint64_t
+get_zone_cap(zoneid_t zid)
+{
+	rctlblk_t *rblk;
 	uint64_t mcap;
-	lcollection_t *lcol;
-	rcid_t colid;
+	struct ps_prochandle *pr;
 
-	if (zone_getattr(zent->zid, ZONE_ATTR_PHYS_MCAP, &mcap,
-	    sizeof (mcap)) != -1 && mcap != 0)
-		max_rss = ROUNDUP(mcap, 1024) / 1024;
-	else
-		max_rss = 0;
+	if ((rblk = (rctlblk_t *)malloc(rctlblk_size())) == NULL)
+		return (UINT64_MAX);
 
-	if (zent->zid == GLOBAL_ZONEID) {
-		if (max_rss > 0)
-			gz_capped = B_TRUE;
-		else
-			gz_capped = B_FALSE;
+	if ((pr = grab_zone_proc(zid)) == NULL) {
+		free(rblk);
+		return (UINT64_MAX);
 	}
 
+	if (pr_getrctl(pr, "zone.max-physical-memory", NULL, rblk,
+	    RCTL_FIRST)) {
+		Pdestroy_agent(pr);
+		Prelease(pr, 0);
+		free(rblk);
+		return (UINT64_MAX);
+	}
 
-	colid.rcid_type = RCIDT_ZONE;
-	colid.rcid_val = zent->zid;
+	Pdestroy_agent(pr);
+	Prelease(pr, 0);
 
-	lcol = lcollection_insert_update(&colid, max_rss, zent->zname,
-	    &changes);
-	if (update_notification_cb != NULL)
-		update_notification_cb("zone", zent->zname, changes, max_rss,
-		    (lcol != NULL) ? lcol->lcol_mark : 0);
+	mcap = rctlblk_get_value(rblk);
+	free(rblk);
+	return (mcap);
 }
 
-
+/*
+ * For zones, rcapd only caps the global zone, since each non-global zone
+ * caps itself.
+ */
 /* ARGSUSED */
 void
 lcollection_update_zone(lcollection_update_type_t ut,
     void(*update_notification_cb)(char *, char *, int, uint64_t, int))
 {
-	int i;
-	uint_t nzents;
-	zone_entry_t *zents;
+	int changes;
+	int64_t max_rss;
+	uint64_t mcap;
+	lcollection_t *lcol;
+	rcid_t colid;
 
-	/*
-	 * Enumerate running zones.
-	 */
-	if (get_running_zones(&nzents, &zents) != 0)
-		return;
-
-	for (i = 0; i < nzents; i++) {
-		update_zone(&zents[i], (void *)update_notification_cb);
-
+	mcap = get_zone_cap(GLOBAL_ZONEID);
+	if (mcap != 0 && mcap != UINT64_MAX) {
+		max_rss = ROUNDUP(mcap, 1024) / 1024;
+		gz_capped = B_TRUE;
+	} else {
+		max_rss = UINT64_MAX / 1024;
+		gz_capped = B_FALSE;
 	}
 
-	free(zents);
+	colid.rcid_type = RCIDT_ZONE;
+	colid.rcid_val = GLOBAL_ZONEID;
+
+	lcol = lcollection_insert_update(&colid, max_rss, GLOBAL_ZONENAME,
+	    &changes);
+	if (update_notification_cb != NULL)
+		update_notification_cb("zone", GLOBAL_ZONENAME, changes,
+		    max_rss, (lcol != NULL) ? lcol->lcol_mark : 0);
 }
