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