17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0209230bSgjelinek * Common Development and Distribution License (the "License"). 6*0209230bSgjelinek * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*0209230bSgjelinek * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <procfs.h> 297c478bd9Sstevel@tonic-gate #include <project.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate #include "rcapd.h" 337c478bd9Sstevel@tonic-gate #include "utils.h" 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* absolute cap name */ 367c478bd9Sstevel@tonic-gate #define PJ_ABS_ATTR_NAME "rcap.max-rss" 377c478bd9Sstevel@tonic-gate /* round up to next y = 2^n */ 387c478bd9Sstevel@tonic-gate #define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate static int 417c478bd9Sstevel@tonic-gate lcollection_update_project_cb(const struct project *proj, void *walk_data) 427c478bd9Sstevel@tonic-gate { 43*0209230bSgjelinek void(*update_notification_cb)(char *, char *, int, uint64_t, int) = 44*0209230bSgjelinek (void(*)(char *, char *, int, uint64_t, int))walk_data; 457c478bd9Sstevel@tonic-gate char *capattr_abs; 467c478bd9Sstevel@tonic-gate char *end; 477c478bd9Sstevel@tonic-gate int changes; 487c478bd9Sstevel@tonic-gate int64_t max_rss; 497c478bd9Sstevel@tonic-gate lcollection_t *lcol; 50*0209230bSgjelinek rcid_t colid; 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate capattr_abs = strstr(proj->pj_attr, PJ_ABS_ATTR_NAME "="); 537c478bd9Sstevel@tonic-gate if (capattr_abs != NULL) { 547c478bd9Sstevel@tonic-gate if (capattr_abs > proj->pj_attr) 557c478bd9Sstevel@tonic-gate if (*(capattr_abs - 1) != ';') { 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * PJ_ABS_ATTR_NAME only matched part 587c478bd9Sstevel@tonic-gate * of an attribute. 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate return (0); 617c478bd9Sstevel@tonic-gate } 627c478bd9Sstevel@tonic-gate capattr_abs += strlen(PJ_ABS_ATTR_NAME "="); 637c478bd9Sstevel@tonic-gate max_rss = ROUNDUP(strtoll(capattr_abs, &end, 10), 1024) / 1024; 647c478bd9Sstevel@tonic-gate if (end == capattr_abs || *end != ';' && *end != 0) 65*0209230bSgjelinek warn(gettext("project %s: malformed %s value '%s'\n"), 66*0209230bSgjelinek proj->pj_name, PJ_ABS_ATTR_NAME, capattr_abs); 677c478bd9Sstevel@tonic-gate } else 687c478bd9Sstevel@tonic-gate max_rss = 0; 697c478bd9Sstevel@tonic-gate 70*0209230bSgjelinek colid.rcid_type = RCIDT_PROJECT; 71*0209230bSgjelinek colid.rcid_val = proj->pj_projid; 72*0209230bSgjelinek 73*0209230bSgjelinek lcol = lcollection_insert_update(&colid, max_rss, proj->pj_name, 74*0209230bSgjelinek &changes); 757c478bd9Sstevel@tonic-gate if (update_notification_cb != NULL) 76*0209230bSgjelinek update_notification_cb("project", proj->pj_name, changes, 77*0209230bSgjelinek max_rss, (lcol != NULL) ? lcol->lcol_mark : 0); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate return (0); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static int 837c478bd9Sstevel@tonic-gate lcollection_update_project_byid_cb(const projid_t id, void *walk_data) 847c478bd9Sstevel@tonic-gate { 857c478bd9Sstevel@tonic-gate char buf[PROJECT_BUFSZ]; 867c478bd9Sstevel@tonic-gate struct project proj; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if (getprojbyid(id, &proj, buf, sizeof (buf)) != NULL && proj.pj_attr != 897c478bd9Sstevel@tonic-gate NULL) 907c478bd9Sstevel@tonic-gate return (lcollection_update_project_cb(&proj, walk_data)); 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate return (0); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate static int 967c478bd9Sstevel@tonic-gate lcollection_update_onceactive_cb(lcollection_t *lcol, void *walk_data) 977c478bd9Sstevel@tonic-gate { 98*0209230bSgjelinek void(*update_notification_cb)(char *, char *, int, uint64_t, int) = 99*0209230bSgjelinek (void(*)(char *, char *, int, uint64_t, int))walk_data; 1007c478bd9Sstevel@tonic-gate 101*0209230bSgjelinek if (lcol->lcol_id.rcid_type != RCIDT_PROJECT) 102*0209230bSgjelinek return (0); 103*0209230bSgjelinek 104*0209230bSgjelinek return (lcollection_update_project_byid_cb(lcol->lcol_id.rcid_val, 1057c478bd9Sstevel@tonic-gate (void *)update_notification_cb)); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static int 1097c478bd9Sstevel@tonic-gate project_walk_all(int(*cb)(const struct project *, void *), void *walk_data) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate char buf[PROJECT_BUFSZ]; 1127c478bd9Sstevel@tonic-gate struct project proj; 1137c478bd9Sstevel@tonic-gate int res = 0; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate setprojent(); 1167c478bd9Sstevel@tonic-gate while (getprojent(&proj, buf, sizeof (buf)) != NULL && res == 0) 1177c478bd9Sstevel@tonic-gate res = cb(&proj, walk_data); 1187c478bd9Sstevel@tonic-gate endprojent(); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate return (res); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate void 1247c478bd9Sstevel@tonic-gate lcollection_update_project(lcollection_update_type_t ut, 125*0209230bSgjelinek void(*update_notification_cb)(char *, char *, int, uint64_t, int)) 1267c478bd9Sstevel@tonic-gate { 1277c478bd9Sstevel@tonic-gate switch (ut) { 1287c478bd9Sstevel@tonic-gate case LCU_ACTIVE_ONLY: 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * Enumerate active projects. This is much faster than 1317c478bd9Sstevel@tonic-gate * enumerating all projects (as is done below, in the default 1327c478bd9Sstevel@tonic-gate * case), and is done to efficiently and incrementally update 1337c478bd9Sstevel@tonic-gate * lcollection with capped projects. The default case performs 1347c478bd9Sstevel@tonic-gate * the initialization. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate (void) project_walk(lcollection_update_project_byid_cb, 1377c478bd9Sstevel@tonic-gate (void *)update_notification_cb); 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Enumerate once-active projects, including the active 1407c478bd9Sstevel@tonic-gate * projects just enumerated, meaning active projects will be 1417c478bd9Sstevel@tonic-gate * updated and marked twice. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate list_walk_collection(lcollection_update_onceactive_cb, 1447c478bd9Sstevel@tonic-gate (void *)update_notification_cb); 1457c478bd9Sstevel@tonic-gate break; 1467c478bd9Sstevel@tonic-gate default: 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * Enumerate all projects. 1497c478bd9Sstevel@tonic-gate */ 1507c478bd9Sstevel@tonic-gate (void) project_walk_all(lcollection_update_project_cb, 1517c478bd9Sstevel@tonic-gate (void *)update_notification_cb); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } 154