1/******************************************************************************/ 2/* */ 3/* Copyright (c) International Business Machines Corp., 2007 */ 4/* */ 5/* This program is free software; you can redistribute it and/or modify */ 6/* it under the terms of the GNU General Public License as published by */ 7/* the Free Software Foundation; either version 2 of the License, or */ 8/* (at your option) any later version. */ 9/* */ 10/* This program is distributed in the hope that it will be useful, */ 11/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 13/* the GNU General Public License for more details. */ 14/* */ 15/* You should have received a copy of the GNU General Public License */ 16/* along with this program; if not, write to the Free Software */ 17/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18/* */ 19/******************************************************************************/ 20 21/******************************************************************************/ 22/* */ 23/* File: libcontrollers.c */ 24/* */ 25/* Description: This file contains the definitions for the functions/apis */ 26/* for the controllers library. This library is used by the */ 27/* controllers testcases. */ 28/* */ 29/* Author: Sudhir Kumar skumar@linux.vnet.ibm.com */ 30/* */ 31/* History: */ 32/* Created- 15/02/2008 -Sudhir Kumar <skumar@linux.vnet.ibm.com> */ 33/* */ 34/******************************************************************************/ 35 36#include "libcontrollers.h" 37 38char fullpath[PATH_MAX]; 39int FLAG; 40volatile int timer_expired = 0; 41int retval; 42unsigned int num_line; 43unsigned int current_shares; 44unsigned int total_shares; 45unsigned int *shares_pointer; 46char target[LINE_MAX]; 47struct dirent *dir_pointer; 48 49/* 50 * Function: scan_shares_file() 51 * This function scans all the shares files under the mountpoint 52 * of the controller and returns the total added shares of all 53 * the groups (currently excludes default group) ?? 54 */ 55int scan_shares_files(unsigned int *shares_pointer) 56{ 57 struct stat statbuffer; 58 DIR *dp; 59 char *path_pointer; 60 61 /* 62 * Check if we can get stat of the file 63 */ 64 if (lstat(fullpath, &statbuffer) < 0) { 65 error_function("Can not read stat for file ", fullpath); 66 return -1; 67 } 68 69 if (S_ISDIR(statbuffer.st_mode) == 0) { /* not a directory */ 70 /* 71 * We run all user tasks in the created groups and not default groups. So 72 * exclude the shares of default group. FLAG to ensure dir_pointer is non NULL 73 */ 74 if ((FLAG == 1) 75 && (strcmp(fullpath, "/dev/cpuctl/cpu.shares") != 0) 76 && (strcmp(dir_pointer->d_name, "cpu.shares") == 0)) { 77 *shares_pointer += read_shares_file(fullpath); 78 } 79 return 0; 80 } 81 82 /* 83 * Now it's a directory. let the path_pointer point to the end 84 * of fullpath to append new files names 85 */ 86 87 path_pointer = fullpath + strlen(fullpath); 88 *path_pointer++ = '/'; 89 *path_pointer = 0; 90 91 if ((dp = opendir(fullpath)) == NULL) { /* Error in opening directory */ 92 error_function("Can't open ", fullpath); 93 return -1; 94 } 95 /* 96 * search all groups recursively and get total shares 97 */ 98 99 while ((dir_pointer = readdir(dp)) != NULL) { /* Error in reading directory */ 100 if ((strcmp(dir_pointer->d_name, ".") == 0) 101 || (strcmp(dir_pointer->d_name, "..") == 0)) 102 continue; /* ignore current and parent directory */ 103 104 FLAG = 1; 105 strcpy(path_pointer, dir_pointer->d_name); /* append name to fullpath */ 106 107 if ((retval = scan_shares_files(shares_pointer)) != 0) 108 break; 109 } 110 111 /* 112 * This directory is searched fully. let us go back to parent directory again 113 */ 114 115 path_pointer[-1] = 0; 116 117 if (closedir(dp) < 0) { 118 error_function("Could not close dir ", fullpath); 119 return -1; 120 } 121 return 0; 122} 123 124/* 125 * Function: read_file () 126 * This function is written keeping in mind the support 127 * to read other files also if required in future. 128 * Each file under a group contains some diff parameter/s 129 */ 130 131int read_file(char *filepath, int action, unsigned int *value) 132{ 133 int num_line = 0; 134 FILE *fp; 135 int tmp; 136 switch (action) { 137 case GET_SHARES: 138 tmp = read_shares_file(filepath); 139 if (tmp == -1) 140 return -1; 141 *value = (unsigned int)tmp; 142 break; 143 144 case GET_TASKS: 145 fp = fopen(filepath, "r"); 146 if (fp == NULL) { 147 error_function("Could not open file", filepath); 148 return -1; 149 } 150 while (fgets(target, LINE_MAX, fp) != NULL) 151 num_line++; 152 *value = (unsigned int)num_line; 153 if (fclose(fp)) { 154 error_function("Could not close file", filepath); 155 return -1; 156 } 157 break; 158 159 default: 160 error_function("Wrong action type passed to fun read_file for ", 161 filepath); 162 return -1; 163 } 164 return 0; 165} 166 167/* 168 * Function: error_function() 169 * Prints error message and returns -1 170 */ 171 172static inline void error_function(char *msg1, char *msg2) 173{ 174 fprintf(stdout, "ERROR: %s ", msg1); 175 fprintf(stdout, "%s\n", msg2); 176} 177 178/* Function: read_shares_file() 179 * Reads shares value from a given shares file and writes them to 180 * the given pointer location. Returns 0 if success 181 */ 182 183int read_shares_file(char *filepath) 184{ 185 FILE *fp; 186 unsigned int shares; 187 fp = fopen(filepath, "r"); 188 if (fp == NULL) { 189 error_function("Could not open file", filepath); 190 return -1; 191 } 192 fscanf(fp, "%u", &shares); 193 if (fclose(fp)) { 194 error_function("Could not close file", filepath); 195 return -1; 196 } 197 return shares; 198} 199 200/* Function: write_to_file() 201 * writes value to shares file or pid to tasks file 202 */ 203 204int write_to_file(char *file, const char *mode, unsigned int value) 205{ 206 FILE *fp; 207 fp = fopen(file, mode); 208 if (fp == NULL) { 209 error_function("in opening file for writing:", file); 210 return -1; 211 } 212 fprintf(fp, "%u\n", value); 213 fclose(fp); 214 return 0; 215} 216 217/* Function: signal_handler_alarm() 218 * signal handler for the new action 219 */ 220 221void signal_handler_alarm(int signal) 222{ 223 timer_expired = 1; 224} 225