1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <procfs.h> 30*0Sstevel@tonic-gate #include <project.h> 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <strings.h> 33*0Sstevel@tonic-gate #include "rcapd.h" 34*0Sstevel@tonic-gate #include "utils.h" 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate /* absolute cap name */ 37*0Sstevel@tonic-gate #define PJ_ABS_ATTR_NAME "rcap.max-rss" 38*0Sstevel@tonic-gate /* round up to next y = 2^n */ 39*0Sstevel@tonic-gate #define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate static rcid_t rc_proj_getidbypsinfo(psinfo_t *); 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate void 44*0Sstevel@tonic-gate lcollection_set_type_project(void) 45*0Sstevel@tonic-gate { 46*0Sstevel@tonic-gate rc_getidbypsinfo = rc_proj_getidbypsinfo; 47*0Sstevel@tonic-gate } 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate static int 50*0Sstevel@tonic-gate lcollection_update_project_cb(const struct project *proj, void *walk_data) 51*0Sstevel@tonic-gate { 52*0Sstevel@tonic-gate void(*update_notification_cb)(char *, int, uint64_t, int) = 53*0Sstevel@tonic-gate (void(*)(char *, int, uint64_t, int))walk_data; 54*0Sstevel@tonic-gate char *capattr_abs; 55*0Sstevel@tonic-gate char *end; 56*0Sstevel@tonic-gate int changes; 57*0Sstevel@tonic-gate int64_t max_rss; 58*0Sstevel@tonic-gate lcollection_t *lcol; 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate capattr_abs = strstr(proj->pj_attr, PJ_ABS_ATTR_NAME "="); 61*0Sstevel@tonic-gate if (capattr_abs != NULL) { 62*0Sstevel@tonic-gate if (capattr_abs > proj->pj_attr) 63*0Sstevel@tonic-gate if (*(capattr_abs - 1) != ';') { 64*0Sstevel@tonic-gate /* 65*0Sstevel@tonic-gate * PJ_ABS_ATTR_NAME only matched part 66*0Sstevel@tonic-gate * of an attribute. 67*0Sstevel@tonic-gate */ 68*0Sstevel@tonic-gate return (0); 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate capattr_abs += strlen(PJ_ABS_ATTR_NAME "="); 71*0Sstevel@tonic-gate max_rss = ROUNDUP(strtoll(capattr_abs, &end, 10), 1024) / 1024; 72*0Sstevel@tonic-gate if (end == capattr_abs || *end != ';' && *end != 0) 73*0Sstevel@tonic-gate warn(gettext("%s %s: malformed %s value " 74*0Sstevel@tonic-gate "'%s'\n"), rcfg.rcfg_mode_name, proj->pj_name, 75*0Sstevel@tonic-gate PJ_ABS_ATTR_NAME, capattr_abs); 76*0Sstevel@tonic-gate } else 77*0Sstevel@tonic-gate max_rss = 0; 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate lcol = lcollection_insert_update(proj->pj_projid, max_rss, 80*0Sstevel@tonic-gate proj->pj_name, &changes); 81*0Sstevel@tonic-gate if (update_notification_cb != NULL) 82*0Sstevel@tonic-gate update_notification_cb(proj->pj_name, changes, max_rss, (lcol != 83*0Sstevel@tonic-gate NULL) ? lcol->lcol_mark : 0); 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate return (0); 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate static int 89*0Sstevel@tonic-gate lcollection_update_project_byid_cb(const projid_t id, void *walk_data) 90*0Sstevel@tonic-gate { 91*0Sstevel@tonic-gate char buf[PROJECT_BUFSZ]; 92*0Sstevel@tonic-gate struct project proj; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate if (getprojbyid(id, &proj, buf, sizeof (buf)) != NULL && proj.pj_attr != 95*0Sstevel@tonic-gate NULL) 96*0Sstevel@tonic-gate return (lcollection_update_project_cb(&proj, walk_data)); 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate return (0); 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate static int 102*0Sstevel@tonic-gate lcollection_update_onceactive_cb(lcollection_t *lcol, void *walk_data) 103*0Sstevel@tonic-gate { 104*0Sstevel@tonic-gate void(*update_notification_cb)(char *, int, uint64_t, int) = 105*0Sstevel@tonic-gate (void(*)(char *, int, uint64_t, int))walk_data; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate return (lcollection_update_project_byid_cb(lcol->lcol_id, 108*0Sstevel@tonic-gate (void *)update_notification_cb)); 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate static int 112*0Sstevel@tonic-gate project_walk_all(int(*cb)(const struct project *, void *), void *walk_data) 113*0Sstevel@tonic-gate { 114*0Sstevel@tonic-gate char buf[PROJECT_BUFSZ]; 115*0Sstevel@tonic-gate struct project proj; 116*0Sstevel@tonic-gate int res = 0; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate setprojent(); 119*0Sstevel@tonic-gate while (getprojent(&proj, buf, sizeof (buf)) != NULL && res == 0) 120*0Sstevel@tonic-gate res = cb(&proj, walk_data); 121*0Sstevel@tonic-gate endprojent(); 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate return (res); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate void 127*0Sstevel@tonic-gate lcollection_update_project(lcollection_update_type_t ut, 128*0Sstevel@tonic-gate void(*update_notification_cb)(char *, int, uint64_t, int)) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate switch (ut) { 131*0Sstevel@tonic-gate case LCU_ACTIVE_ONLY: 132*0Sstevel@tonic-gate /* 133*0Sstevel@tonic-gate * Enumerate active projects. This is much faster than 134*0Sstevel@tonic-gate * enumerating all projects (as is done below, in the default 135*0Sstevel@tonic-gate * case), and is done to efficiently and incrementally update 136*0Sstevel@tonic-gate * lcollection with capped projects. The default case performs 137*0Sstevel@tonic-gate * the initialization. 138*0Sstevel@tonic-gate */ 139*0Sstevel@tonic-gate (void) project_walk(lcollection_update_project_byid_cb, 140*0Sstevel@tonic-gate (void *)update_notification_cb); 141*0Sstevel@tonic-gate /* 142*0Sstevel@tonic-gate * Enumerate once-active projects, including the active 143*0Sstevel@tonic-gate * projects just enumerated, meaning active projects will be 144*0Sstevel@tonic-gate * updated and marked twice. 145*0Sstevel@tonic-gate */ 146*0Sstevel@tonic-gate list_walk_collection(lcollection_update_onceactive_cb, 147*0Sstevel@tonic-gate (void *)update_notification_cb); 148*0Sstevel@tonic-gate break; 149*0Sstevel@tonic-gate default: 150*0Sstevel@tonic-gate /* 151*0Sstevel@tonic-gate * Enumerate all projects. 152*0Sstevel@tonic-gate */ 153*0Sstevel@tonic-gate (void) project_walk_all(lcollection_update_project_cb, 154*0Sstevel@tonic-gate (void *)update_notification_cb); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate static rcid_t 159*0Sstevel@tonic-gate rc_proj_getidbypsinfo(psinfo_t *psinfo) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate return (psinfo->pr_projid); 162*0Sstevel@tonic-gate } 163