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);
}