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