Print this page
OS-11 rcapd behaves poorly when under extreme load
OS-399 zone phys. mem. cap should be a rctl and have associated kstat
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c
+++ new/usr/src/cmd/rcap/rcapd/rcapd_collection_zone.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright 2011 Joyent, Inc. All rights reserved.
24 25 */
25 26
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 27 #include <procfs.h>
29 28 #include <project.h>
30 29 #include <stdlib.h>
31 30 #include <strings.h>
32 31 #include <zone.h>
33 32 #include <libzonecfg.h>
33 +#include <dirent.h>
34 +#include <libproc.h>
34 35 #include "rcapd.h"
35 36 #include "utils.h"
36 37
37 38 extern boolean_t gz_capped;
38 39
39 40 /* round up to next y = 2^n */
40 41 #define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
41 42
42 -static void
43 -update_zone(zone_entry_t *zent, void *walk_data)
43 +static struct ps_prochandle *
44 +grab_zone_proc(zoneid_t zid)
44 45 {
45 - void(*update_notification_cb)(char *, char *, int, uint64_t, int) =
46 - (void(*)(char *, char *, int, uint64_t, int))walk_data;
47 - int changes;
48 - int64_t max_rss;
46 + DIR *dirp;
47 + struct dirent *dentp;
48 + int pid, pid_self, tmp;
49 + psinfo_t psinfo;
50 + struct ps_prochandle *pr = NULL;
51 +
52 + pid_self = getpid();
53 +
54 + if ((dirp = opendir("/proc")) == NULL)
55 + return (NULL);
56 +
57 + while (dentp = readdir(dirp)) {
58 + pid = atoi(dentp->d_name);
59 +
60 + /* Skip self */
61 + if (pid == pid_self)
62 + continue;
63 +
64 + if (proc_get_psinfo(pid, &psinfo) != 0)
65 + continue;
66 +
67 + if (psinfo.pr_zoneid != zid)
68 + continue;
69 +
70 + /* attempt to grab process */
71 + if ((pr = Pgrab(pid, 0, &tmp)) != NULL) {
72 + if (Psetflags(pr, PR_RLC) != 0) {
73 + Prelease(pr, 0);
74 + }
75 + if (Pcreate_agent(pr) == 0) {
76 + if (pr_getzoneid(pr) != zid) {
77 + Prelease(pr, 0);
78 + continue;
79 + }
80 +
81 + (void) closedir(dirp);
82 + return (pr);
83 + } else {
84 + Prelease(pr, 0);
85 + }
86 + }
87 + }
88 +
89 + (void) closedir(dirp);
90 + return (NULL);
91 +}
92 +
93 +static uint64_t
94 +get_zone_cap(zoneid_t zid)
95 +{
96 + rctlblk_t *rblk;
49 97 uint64_t mcap;
50 - lcollection_t *lcol;
51 - rcid_t colid;
98 + struct ps_prochandle *pr;
52 99
53 - if (zone_getattr(zent->zid, ZONE_ATTR_PHYS_MCAP, &mcap,
54 - sizeof (mcap)) != -1 && mcap != 0)
55 - max_rss = ROUNDUP(mcap, 1024) / 1024;
56 - else
57 - max_rss = 0;
100 + if ((rblk = (rctlblk_t *)malloc(rctlblk_size())) == NULL)
101 + return (UINT64_MAX);
58 102
59 - if (zent->zid == GLOBAL_ZONEID) {
60 - if (max_rss > 0)
61 - gz_capped = B_TRUE;
62 - else
63 - gz_capped = B_FALSE;
103 + if ((pr = grab_zone_proc(zid)) == NULL) {
104 + free(rblk);
105 + return (UINT64_MAX);
64 106 }
65 107
108 + if (pr_getrctl(pr, "zone.max-physical-memory", NULL, rblk,
109 + RCTL_FIRST)) {
110 + Pdestroy_agent(pr);
111 + Prelease(pr, 0);
112 + free(rblk);
113 + return (UINT64_MAX);
114 + }
66 115
67 - colid.rcid_type = RCIDT_ZONE;
68 - colid.rcid_val = zent->zid;
116 + Pdestroy_agent(pr);
117 + Prelease(pr, 0);
69 118
70 - lcol = lcollection_insert_update(&colid, max_rss, zent->zname,
71 - &changes);
72 - if (update_notification_cb != NULL)
73 - update_notification_cb("zone", zent->zname, changes, max_rss,
74 - (lcol != NULL) ? lcol->lcol_mark : 0);
119 + mcap = rctlblk_get_value(rblk);
120 + free(rblk);
121 + return (mcap);
75 122 }
76 123
77 -
124 +/*
125 + * For zones, rcapd only caps the global zone, since each non-global zone
126 + * caps itself.
127 + */
78 128 /* ARGSUSED */
79 129 void
80 130 lcollection_update_zone(lcollection_update_type_t ut,
81 131 void(*update_notification_cb)(char *, char *, int, uint64_t, int))
82 132 {
83 - int i;
84 - uint_t nzents;
85 - zone_entry_t *zents;
133 + int changes;
134 + int64_t max_rss;
135 + uint64_t mcap;
136 + lcollection_t *lcol;
137 + rcid_t colid;
86 138
87 - /*
88 - * Enumerate running zones.
89 - */
90 - if (get_running_zones(&nzents, &zents) != 0)
91 - return;
92 -
93 - for (i = 0; i < nzents; i++) {
94 - update_zone(&zents[i], (void *)update_notification_cb);
95 -
139 + mcap = get_zone_cap(GLOBAL_ZONEID);
140 + if (mcap != 0 && mcap != UINT64_MAX) {
141 + max_rss = ROUNDUP(mcap, 1024) / 1024;
142 + gz_capped = B_TRUE;
143 + } else {
144 + max_rss = UINT64_MAX / 1024;
145 + gz_capped = B_FALSE;
96 146 }
97 147
98 - free(zents);
148 + colid.rcid_type = RCIDT_ZONE;
149 + colid.rcid_val = GLOBAL_ZONEID;
150 +
151 + lcol = lcollection_insert_update(&colid, max_rss, GLOBAL_ZONENAME,
152 + &changes);
153 + if (update_notification_cb != NULL)
154 + update_notification_cb("zone", GLOBAL_ZONENAME, changes,
155 + max_rss, (lcol != NULL) ? lcol->lcol_mark : 0);
99 156 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX