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