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

*** 19,99 **** * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - #pragma ident "%Z%%M% %I% %E% SMI" - #include <procfs.h> #include <project.h> #include <stdlib.h> #include <strings.h> #include <zone.h> #include <libzonecfg.h> #include "rcapd.h" #include "utils.h" extern boolean_t gz_capped; /* 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) { ! 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; uint64_t mcap; ! lcollection_t *lcol; ! rcid_t colid; ! 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 (zent->zid == GLOBAL_ZONEID) { ! if (max_rss > 0) ! gz_capped = B_TRUE; ! else ! gz_capped = B_FALSE; } ! colid.rcid_type = RCIDT_ZONE; ! colid.rcid_val = zent->zid; ! 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); } ! /* 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; ! /* ! * 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); ! } ! free(zents); } --- 19,156 ---- * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent, Inc. All rights reserved. */ #include <procfs.h> #include <project.h> #include <stdlib.h> #include <strings.h> #include <zone.h> #include <libzonecfg.h> + #include <dirent.h> + #include <libproc.h> #include "rcapd.h" #include "utils.h" extern boolean_t gz_capped; /* round up to next y = 2^n */ #define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) ! static struct ps_prochandle * ! grab_zone_proc(zoneid_t zid) { ! 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; ! struct ps_prochandle *pr; ! if ((rblk = (rctlblk_t *)malloc(rctlblk_size())) == NULL) ! return (UINT64_MAX); ! 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); + } ! Pdestroy_agent(pr); ! Prelease(pr, 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 changes; ! int64_t max_rss; ! uint64_t mcap; ! lcollection_t *lcol; ! rcid_t colid; ! 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; } ! 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); }