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 
  
 |