4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 #include <alloca.h>
26 #include <assert.h>
27 #include <dirent.h>
28 #include <dlfcn.h>
29 #include <door.h>
30 #include <errno.h>
31 #include <exacct.h>
32 #include <ctype.h>
33 #include <fcntl.h>
34 #include <kstat.h>
35 #include <libcontract.h>
36 #include <libintl.h>
37 #include <libscf.h>
38 #include <zonestat.h>
39 #include <zonestat_impl.h>
40 #include <limits.h>
41 #include <pool.h>
42 #include <procfs.h>
43 #include <rctl.h>
2173 if (getrctl(name, NULL, rblk, RCTL_FIRST)
2174 != 0) {
2175 return (ZS_LIMIT_NONE);
2176 }
2177 return (rctlblk_get_value(rblk));
2178 }
2179
2180 static uint64_t
2181 zsd_get_zone_rctl_usage(char *name)
2182 {
2183 rctlblk_t *rblk;
2184
2185 rblk = (rctlblk_t *)alloca(rctlblk_size());
2186 if (getrctl(name, NULL, rblk, RCTL_USAGE)
2187 != 0) {
2188 return (0);
2189 }
2190 return (rctlblk_get_value(rblk));
2191 }
2192
2193 #define ZSD_NUM_RCTL_VALS 19
2194
2195 /*
2196 * Fetch the limit information for a zone. This uses zone_enter() as the
2197 * getrctl(2) system call only returns rctl information for the zone of
2198 * the caller.
2199 */
2200 static int
2201 zsd_get_zone_caps(zsd_ctl_t *ctl, zsd_zone_t *zone, uint64_t *cpu_shares,
2202 uint64_t *cpu_cap, uint64_t *ram_cap, uint64_t *locked_cap,
2203 uint64_t *vm_cap, uint64_t *processes_cap, uint64_t *processes,
2204 uint64_t *lwps_cap, uint64_t *lwps, uint64_t *shm_cap, uint64_t *shm,
2205 uint64_t *shmids_cap, uint64_t *shmids, uint64_t *semids_cap,
2206 uint64_t *semids, uint64_t *msgids_cap, uint64_t *msgids,
2207 uint64_t *lofi_cap, uint64_t *lofi, uint_t *sched)
2208 {
2209 int p[2], pid, tmpl_fd, ret;
2210 ctid_t ct;
2211 char class[PC_CLNMSZ];
2212 uint64_t vals[ZSD_NUM_RCTL_VALS];
2213 zsd_system_t *sys = ctl->zsctl_system;
2220 *ram_cap = ZS_LIMIT_NONE;
2221 *locked_cap = ZS_LIMIT_NONE;
2222 *vm_cap = ZS_LIMIT_NONE;
2223
2224 *processes_cap = ZS_LIMIT_NONE;
2225 *lwps_cap = ZS_LIMIT_NONE;
2226 *shm_cap = ZS_LIMIT_NONE;
2227 *shmids_cap = ZS_LIMIT_NONE;
2228 *semids_cap = ZS_LIMIT_NONE;
2229 *msgids_cap = ZS_LIMIT_NONE;
2230 *lofi_cap = ZS_LIMIT_NONE;
2231
2232 *processes = 0;
2233 *lwps = 0;
2234 *shm = 0;
2235 *shmids = 0;
2236 *semids = 0;
2237 *msgids = 0;
2238 *lofi = 0;
2239
2240 /* Get the ram cap first since it is a zone attr */
2241 ret = zone_getattr(zone->zsz_id, ZONE_ATTR_PHYS_MCAP,
2242 ram_cap, sizeof (*ram_cap));
2243 if (ret < 0 || *ram_cap == 0)
2244 *ram_cap = ZS_LIMIT_NONE;
2245
2246 /* Get the zone's default scheduling class */
2247 ret = zone_getattr(zone->zsz_id, ZONE_ATTR_SCHED_CLASS,
2248 class, sizeof (class));
2249 if (ret < 0)
2250 return (-1);
2251
2252 *sched = zsd_schedname2int(class, 0);
2253
2254 /* rctl caps must be fetched from within the zone */
2255 if (pipe(p) != 0)
2256 return (-1);
2257
2258 if ((tmpl_fd = init_template()) == -1) {
2259 (void) close(p[0]);
2260 (void) close(p[1]);
2261 return (-1);
2262 }
2263 pid = forkx(0);
2264 if (pid < 0) {
2265 (void) ct_tmpl_clear(tmpl_fd);
2281
2282 /* Get caps for zone, and write them to zonestatd parent. */
2283 vals[i++] = zsd_get_zone_rctl_limit("zone.cpu-shares");
2284 vals[i++] = zsd_get_zone_rctl_limit("zone.cpu-cap");
2285 vals[i++] = zsd_get_zone_rctl_limit("zone.max-locked-memory");
2286 vals[i++] = zsd_get_zone_rctl_limit("zone.max-swap");
2287 vals[i++] = zsd_get_zone_rctl_limit("zone.max-processes");
2288 vals[i++] = zsd_get_zone_rctl_usage("zone.max-processes");
2289 vals[i++] = zsd_get_zone_rctl_limit("zone.max-lwps");
2290 vals[i++] = zsd_get_zone_rctl_usage("zone.max-lwps");
2291 vals[i++] = zsd_get_zone_rctl_limit("zone.max-shm-memory");
2292 vals[i++] = zsd_get_zone_rctl_usage("zone.max-shm-memory");
2293 vals[i++] = zsd_get_zone_rctl_limit("zone.max-shm-ids");
2294 vals[i++] = zsd_get_zone_rctl_usage("zone.max-shm-ids");
2295 vals[i++] = zsd_get_zone_rctl_limit("zone.max-sem-ids");
2296 vals[i++] = zsd_get_zone_rctl_usage("zone.max-sem-ids");
2297 vals[i++] = zsd_get_zone_rctl_limit("zone.max-msg-ids");
2298 vals[i++] = zsd_get_zone_rctl_usage("zone.max-msg-ids");
2299 vals[i++] = zsd_get_zone_rctl_limit("zone.max-lofi");
2300 vals[i++] = zsd_get_zone_rctl_usage("zone.max-lofi");
2301
2302 if (write(p[1], vals, ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) !=
2303 ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) {
2304 (void) close(p[1]);
2305 _exit(1);
2306 }
2307
2308 (void) close(p[1]);
2309 _exit(0);
2310 }
2311 if (contract_latest(&ct) == -1)
2312 ct = -1;
2313
2314 (void) ct_tmpl_clear(tmpl_fd);
2315 (void) close(tmpl_fd);
2316 (void) close(p[1]);
2317 while (waitpid(pid, NULL, 0) != pid)
2318 ;
2319
2320 /* Read cap from child in zone */
2325 }
2326 i = 0;
2327 *cpu_shares = vals[i++];
2328 *cpu_cap = vals[i++];
2329 *locked_cap = vals[i++];
2330 *vm_cap = vals[i++];
2331 *processes_cap = vals[i++];
2332 *processes = vals[i++];
2333 *lwps_cap = vals[i++];
2334 *lwps = vals[i++];
2335 *shm_cap = vals[i++];
2336 *shm = vals[i++];
2337 *shmids_cap = vals[i++];
2338 *shmids = vals[i++];
2339 *semids_cap = vals[i++];
2340 *semids = vals[i++];
2341 *msgids_cap = vals[i++];
2342 *msgids = vals[i++];
2343 *lofi_cap = vals[i++];
2344 *lofi = vals[i++];
2345
2346 /* Interpret maximum values as no cap */
2347 if (*cpu_cap == UINT32_MAX || *cpu_cap == 0)
2348 *cpu_cap = ZS_LIMIT_NONE;
2349 if (*processes_cap == sys->zss_processes_max)
2350 *processes_cap = ZS_LIMIT_NONE;
2351 if (*lwps_cap == sys->zss_lwps_max)
2352 *lwps_cap = ZS_LIMIT_NONE;
2353 if (*shm_cap == sys->zss_shm_max)
2354 *shm_cap = ZS_LIMIT_NONE;
2355 if (*shmids_cap == sys->zss_shmids_max)
2356 *shmids_cap = ZS_LIMIT_NONE;
2357 if (*semids_cap == sys->zss_semids_max)
2358 *semids_cap = ZS_LIMIT_NONE;
2359 if (*msgids_cap == sys->zss_msgids_max)
2360 *msgids_cap = ZS_LIMIT_NONE;
2361 if (*lofi_cap == sys->zss_lofi_max)
2362 *lofi_cap = ZS_LIMIT_NONE;
2363
2364
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent, Inc. All rights reserved.
25 */
26 #include <alloca.h>
27 #include <assert.h>
28 #include <dirent.h>
29 #include <dlfcn.h>
30 #include <door.h>
31 #include <errno.h>
32 #include <exacct.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <kstat.h>
36 #include <libcontract.h>
37 #include <libintl.h>
38 #include <libscf.h>
39 #include <zonestat.h>
40 #include <zonestat_impl.h>
41 #include <limits.h>
42 #include <pool.h>
43 #include <procfs.h>
44 #include <rctl.h>
2174 if (getrctl(name, NULL, rblk, RCTL_FIRST)
2175 != 0) {
2176 return (ZS_LIMIT_NONE);
2177 }
2178 return (rctlblk_get_value(rblk));
2179 }
2180
2181 static uint64_t
2182 zsd_get_zone_rctl_usage(char *name)
2183 {
2184 rctlblk_t *rblk;
2185
2186 rblk = (rctlblk_t *)alloca(rctlblk_size());
2187 if (getrctl(name, NULL, rblk, RCTL_USAGE)
2188 != 0) {
2189 return (0);
2190 }
2191 return (rctlblk_get_value(rblk));
2192 }
2193
2194 #define ZSD_NUM_RCTL_VALS 20
2195
2196 /*
2197 * Fetch the limit information for a zone. This uses zone_enter() as the
2198 * getrctl(2) system call only returns rctl information for the zone of
2199 * the caller.
2200 */
2201 static int
2202 zsd_get_zone_caps(zsd_ctl_t *ctl, zsd_zone_t *zone, uint64_t *cpu_shares,
2203 uint64_t *cpu_cap, uint64_t *ram_cap, uint64_t *locked_cap,
2204 uint64_t *vm_cap, uint64_t *processes_cap, uint64_t *processes,
2205 uint64_t *lwps_cap, uint64_t *lwps, uint64_t *shm_cap, uint64_t *shm,
2206 uint64_t *shmids_cap, uint64_t *shmids, uint64_t *semids_cap,
2207 uint64_t *semids, uint64_t *msgids_cap, uint64_t *msgids,
2208 uint64_t *lofi_cap, uint64_t *lofi, uint_t *sched)
2209 {
2210 int p[2], pid, tmpl_fd, ret;
2211 ctid_t ct;
2212 char class[PC_CLNMSZ];
2213 uint64_t vals[ZSD_NUM_RCTL_VALS];
2214 zsd_system_t *sys = ctl->zsctl_system;
2221 *ram_cap = ZS_LIMIT_NONE;
2222 *locked_cap = ZS_LIMIT_NONE;
2223 *vm_cap = ZS_LIMIT_NONE;
2224
2225 *processes_cap = ZS_LIMIT_NONE;
2226 *lwps_cap = ZS_LIMIT_NONE;
2227 *shm_cap = ZS_LIMIT_NONE;
2228 *shmids_cap = ZS_LIMIT_NONE;
2229 *semids_cap = ZS_LIMIT_NONE;
2230 *msgids_cap = ZS_LIMIT_NONE;
2231 *lofi_cap = ZS_LIMIT_NONE;
2232
2233 *processes = 0;
2234 *lwps = 0;
2235 *shm = 0;
2236 *shmids = 0;
2237 *semids = 0;
2238 *msgids = 0;
2239 *lofi = 0;
2240
2241 /* Get the zone's default scheduling class */
2242 ret = zone_getattr(zone->zsz_id, ZONE_ATTR_SCHED_CLASS,
2243 class, sizeof (class));
2244 if (ret < 0)
2245 return (-1);
2246
2247 *sched = zsd_schedname2int(class, 0);
2248
2249 /* rctl caps must be fetched from within the zone */
2250 if (pipe(p) != 0)
2251 return (-1);
2252
2253 if ((tmpl_fd = init_template()) == -1) {
2254 (void) close(p[0]);
2255 (void) close(p[1]);
2256 return (-1);
2257 }
2258 pid = forkx(0);
2259 if (pid < 0) {
2260 (void) ct_tmpl_clear(tmpl_fd);
2276
2277 /* Get caps for zone, and write them to zonestatd parent. */
2278 vals[i++] = zsd_get_zone_rctl_limit("zone.cpu-shares");
2279 vals[i++] = zsd_get_zone_rctl_limit("zone.cpu-cap");
2280 vals[i++] = zsd_get_zone_rctl_limit("zone.max-locked-memory");
2281 vals[i++] = zsd_get_zone_rctl_limit("zone.max-swap");
2282 vals[i++] = zsd_get_zone_rctl_limit("zone.max-processes");
2283 vals[i++] = zsd_get_zone_rctl_usage("zone.max-processes");
2284 vals[i++] = zsd_get_zone_rctl_limit("zone.max-lwps");
2285 vals[i++] = zsd_get_zone_rctl_usage("zone.max-lwps");
2286 vals[i++] = zsd_get_zone_rctl_limit("zone.max-shm-memory");
2287 vals[i++] = zsd_get_zone_rctl_usage("zone.max-shm-memory");
2288 vals[i++] = zsd_get_zone_rctl_limit("zone.max-shm-ids");
2289 vals[i++] = zsd_get_zone_rctl_usage("zone.max-shm-ids");
2290 vals[i++] = zsd_get_zone_rctl_limit("zone.max-sem-ids");
2291 vals[i++] = zsd_get_zone_rctl_usage("zone.max-sem-ids");
2292 vals[i++] = zsd_get_zone_rctl_limit("zone.max-msg-ids");
2293 vals[i++] = zsd_get_zone_rctl_usage("zone.max-msg-ids");
2294 vals[i++] = zsd_get_zone_rctl_limit("zone.max-lofi");
2295 vals[i++] = zsd_get_zone_rctl_usage("zone.max-lofi");
2296 vals[i++] = zsd_get_zone_rctl_usage("zone.max-physical-memory");
2297
2298 if (write(p[1], vals, ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) !=
2299 ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) {
2300 (void) close(p[1]);
2301 _exit(1);
2302 }
2303
2304 (void) close(p[1]);
2305 _exit(0);
2306 }
2307 if (contract_latest(&ct) == -1)
2308 ct = -1;
2309
2310 (void) ct_tmpl_clear(tmpl_fd);
2311 (void) close(tmpl_fd);
2312 (void) close(p[1]);
2313 while (waitpid(pid, NULL, 0) != pid)
2314 ;
2315
2316 /* Read cap from child in zone */
2321 }
2322 i = 0;
2323 *cpu_shares = vals[i++];
2324 *cpu_cap = vals[i++];
2325 *locked_cap = vals[i++];
2326 *vm_cap = vals[i++];
2327 *processes_cap = vals[i++];
2328 *processes = vals[i++];
2329 *lwps_cap = vals[i++];
2330 *lwps = vals[i++];
2331 *shm_cap = vals[i++];
2332 *shm = vals[i++];
2333 *shmids_cap = vals[i++];
2334 *shmids = vals[i++];
2335 *semids_cap = vals[i++];
2336 *semids = vals[i++];
2337 *msgids_cap = vals[i++];
2338 *msgids = vals[i++];
2339 *lofi_cap = vals[i++];
2340 *lofi = vals[i++];
2341 *ram_cap = vals[i++];
2342
2343 /* Interpret maximum values as no cap */
2344 if (*cpu_cap == UINT32_MAX || *cpu_cap == 0)
2345 *cpu_cap = ZS_LIMIT_NONE;
2346 if (*processes_cap == sys->zss_processes_max)
2347 *processes_cap = ZS_LIMIT_NONE;
2348 if (*lwps_cap == sys->zss_lwps_max)
2349 *lwps_cap = ZS_LIMIT_NONE;
2350 if (*shm_cap == sys->zss_shm_max)
2351 *shm_cap = ZS_LIMIT_NONE;
2352 if (*shmids_cap == sys->zss_shmids_max)
2353 *shmids_cap = ZS_LIMIT_NONE;
2354 if (*semids_cap == sys->zss_semids_max)
2355 *semids_cap = ZS_LIMIT_NONE;
2356 if (*msgids_cap == sys->zss_msgids_max)
2357 *msgids_cap = ZS_LIMIT_NONE;
2358 if (*lofi_cap == sys->zss_lofi_max)
2359 *lofi_cap = ZS_LIMIT_NONE;
2360
2361
|