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
↓ 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