From: Sudhir K. <sk...@li...> - 2008-04-28 21:10:41
|
Hi All, This patch adds the first testcase for memory controller which checks for the old memory allocation for task migration. Signed-off-by: Sudhir Kumar <sk...@li...> Index: ltp-full-20080229/testcases/kernel/controllers/Makefile =================================================================== --- ltp-full-20080229.orig/testcases/kernel/controllers/Makefile +++ ltp-full-20080229/testcases/kernel/controllers/Makefile @@ -1,5 +1,6 @@ -SUBDIRS = libcontrollers cpuctl +SUBDIRS = libcontrollers cpuctl memctl CHECK_CPUCTL = $(shell grep -w cpu /proc/cgroups|cut -f1) +CHECK_MEMCTL = $(shell grep -w memory /proc/cgroups|cut -f1) all: @set -e; ifeq ($(CHECK_CPUCTL),cpu) @@ -9,6 +10,13 @@ else echo "Kernel is not compiled with cpu controller support"; endif +ifeq ($(CHECK_MEMCTL),memory) + + for i in $(SUBDIRS); do $(MAKE) -C $$i $@ ;done; +else + echo "Kernel is not compiled with memory resource controller support"; +endif + install: @set -e; \ ln -f test_controllers.sh ../../bin/test_controllers.sh; @@ -21,5 +29,13 @@ else echo "Kernel is not compiled with cpu controller support"; endif +ifeq ($(CHECK_MEMCTL),memory) + + for i in $(SUBDIRS); do $(MAKE) -C $$i install ; done; \ + chmod ugo+x test_controllers.sh; +else + echo "Kernel is not compiled with memory resource controller support"; +endif + clean: @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i clean ; done Index: ltp-full-20080229/testcases/kernel/controllers/memctl/Makefile =================================================================== --- /dev/null +++ ltp-full-20080229/testcases/kernel/controllers/memctl/Makefile @@ -0,0 +1,16 @@ +CFLAGS += -Wall +CPPFLAGS += -I../../../../include -I../libcontrollers +LDLIBS += -lm -L../../../../lib/ -L../libcontrollers -lcontrollers -lltp + +SRCS = $(wildcard *.c) + +TARGETS = $(patsubst %.c,%,$(SRCS)) + +all: $(TARGETS) + +clean: + rm -f $(TARGETS) *.o + +install: + @set -e; for i in $(TARGETS) run_memctl_test.sh myfunctions.sh; do ln -f $$i ../../../bin/$$i ; chmod +x $$i ; done + Index: ltp-full-20080229/testcases/kernel/controllers/memctl/memctl_test01.c =================================================================== --- /dev/null +++ ltp-full-20080229/testcases/kernel/controllers/memctl/memctl_test01.c @@ -0,0 +1,176 @@ +/******************************************************************************/ +/* */ +/* Copyright (c) International Business Machines Corp., 2008 */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ +/* the GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* File: memctl_test01.c */ +/* */ +/* Description: This is a c program that allocates memory in chunks of size */ +/* as given by the calling script. The program touches all the */ +/* allocated pages by writing a string on each page. */ +/* */ +/* Total Tests: 1 */ +/* */ +/* Test Name: mem_controller_test01 */ +/* */ +/* */ +/* Test Assertion */ +/* Please refer to the file memctl_testplan.txt */ +/* */ +/* Author: Sudhir Kumar sk...@li... */ +/* */ +/* History: */ +/* Created 12/03/2008 Sudhir Kumar <sk...@li...> */ +/* */ +/******************************************************************************/ + +/* Standard Include Files */ +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "../libcontrollers/libcontrollers.h" +#include "test.h" + + +extern int Tst_count; +char *TCID = "memory_controller_test01"; +int TST_TOTAL = 1; + +pid_t scriptpid; +typedef size_t record_t; +record_t **array_of_chunks; +record_t tmp; +int num_of_chunks, chunk_size, test_num, limit; + +extern void cleanup(); +void signal_handler_sigusr1 (int signal); +int allocate_memory(void); + +int main(int argc, char *argv[]) +{ + int ret; + char mygroup[64], mytaskfile[64]; + char *mygroup_p, *script_pid_p, *test_num_p, *chunk_size_p, *num_chunks_p; + struct sigaction newaction1, oldaction1; + + /* Signal handling for SIGUSR1 recieved from script */ + sigemptyset (&newaction1.sa_mask); + newaction1.sa_handler = signal_handler_sigusr1; + newaction1.sa_flags=0; + sigaction (SIGUSR1, &newaction1, &oldaction1); + + /* + *Capture variables from the script environment + */ + test_num_p = getenv("TEST_NUM"); + mygroup_p = getenv("MYGROUP"); + script_pid_p = getenv("SCRIPT_PID"); + chunk_size_p = getenv("CHUNK_SIZE"); + num_chunks_p = getenv("NUM_CHUNKS"); + + if ((test_num_p != NULL) && (mygroup_p != NULL) && (script_pid_p != NULL) && \ + (chunk_size_p != NULL) && (num_chunks_p != NULL)) + { + scriptpid = atoi(script_pid_p); + test_num = atoi(test_num_p); + chunk_size = atoi(chunk_size_p); + num_of_chunks = atoi(num_chunks_p); + sprintf(mygroup,"%s", mygroup_p); + } + else + { + tst_brkm (TBROK, cleanup, "Invalid parameters recieved from script\n"); + } + + sprintf(mytaskfile, "%s", mygroup); + strcat (mytaskfile,"/tasks"); + /* Assign the task to it's group */ + write_to_file (mytaskfile, "a", getpid()); /* Assign the task to it's group*/ + + ret = allocate_memory(); /*should i check ret?*/ + + return 0; +} + +/* + * Function: cleanup() + * signals for system cleanup in case test breaks + */ +void cleanup() +{ + kill (scriptpid, SIGUSR1);/* Inform the shell to do cleanup*/ + tst_exit (); /* Report exit status*/ +} + +/* + * Function: signal_handler_sigusr1() + * signal handler for the new action + */ + +void signal_handler_sigusr1 (int signal) +{ + int i; + for (i=0; i< num_of_chunks; ++i) + free(array_of_chunks[i]); + free(array_of_chunks); + exit (0); +} + +int allocate_memory() +{ + int i, j; + /* + * Allocate array which contains base addresses of all chunks + */ + array_of_chunks = (record_t *) malloc(sizeof(record_t *) * num_of_chunks); + if (array_of_chunks == NULL) + tst_brkm (TBROK, cleanup, "Memory allocation failed for array_of_chunks"); + /* + * Allocate chunks of memory + */ + + for (i=0; i< num_of_chunks; ++i) + { + array_of_chunks[i] = (record_t *) malloc(chunk_size); + if (array_of_chunks[i] == NULL) + tst_brkm (TBROK, cleanup, "Memory allocation failed for chunks. Try smaller chunk size"); + } + + /* + * Touch all the pages of allocated memory by writing some string + */ + limit = chunk_size / sizeof(record_t); + + for (i=0; i< num_of_chunks; ++i) + for (j=0; j< limit; ++j) + array_of_chunks[i][j] = 0xaa; + + /* + * Just keep on accessing the allocated pages and do nothing relevant + */ + while (1) + { + for (i=0; i< num_of_chunks; ++i) + for (j=0; j< limit; ++j) + tmp = array_of_chunks[i][j]; + } + return 0; +} Index: ltp-full-20080229/testcases/kernel/controllers/memctl/myfunctions.sh =================================================================== --- /dev/null +++ ltp-full-20080229/testcases/kernel/controllers/memctl/myfunctions.sh @@ -0,0 +1,119 @@ +#!/bin/bash +# usage ./functions.sh + +################################################################################# +# Copyright (c) International Business Machines Corp., 2008 # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See # +# the GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +################################################################################# +# Name Of File: myfunctions.sh # +# # +# Description: This file has functions for the setup for testing cpucontroller # +# setup includes creating controller device, mounting it with # +# cgroup filesystem with option cpu and creating groups in it. # +# # +# Functions: get_num_groups(): decides number of groups based on num of cpus# +# setup(): creaes /dev/cpuctl, mounts cgroup fs on it, creates # +# groups in that, creates fifo to fire tasks at one time. # +# cleanup(): Does full system cleanup # +# # +# Author: Sudhir Kumar <sk...@li...> # +# # +# History: # +# # +# DATE NAME EMAIL DESC # +# # +# 20/12/07 Sudhir Kumar <sk...@li...> Created this test # +# # +################################################################################# + + # Write the cleanup function +cleanup () +{ + echo "Cleanup called"; + rm -f memctl_task_* 2>/dev/null + rmdir /dev/memctl/group* 2> /dev/null + umount /dev/memctl 2> /dev/null + rmdir /dev/memctl 2> /dev/null +} + # Create /dev/memctl & mount the cgroup file system with memory controller + #clean any group created eralier (if any) + +setup () +{ + if [ -e /dev/memctl ] + then + echo "WARN:/dev/memctl already exist..overwriting"; + cleanup; + mkdir /dev/memctl; + else + mkdir /dev/memctl + fi + mount -t cgroup -omemory cgroup /dev/memctl 2> /dev/null + if [ $? -ne 0 ] + then + echo "ERROR: Could not mount cgroup filesystem on /dev/memctl..Exiting test"; + cleanup; + exit -1; + fi + + # Group created earlier may again be visible if not cleaned properly...so clean them + if [ -e /dev/memctl/group_1 ] + then + rmdir /dev/memctl/group* + echo "WARN: Earlier groups found and removed..."; + fi + + # Create different groups + for i in $(seq 1 $NUM_GROUPS) + do + group=group_$i; + mkdir /dev/memctl/$group;# 2>/dev/null + if [ $? -ne 0 ] + then + echo "ERROR: Can't create $group...Check your permissions..Exiting test"; + cleanup; + exit -1; + fi + done +} + +# The usage of the script file +usage() +{ + echo "Could not start memory controller test"; + echo "usage: run_memctl_test.sh test_num"; + echo "Skipping the memory controller test..."; +} + +# Function to set memory limits for different groups +setmemlimits() +{ + for i in $(seq 1 $NUM_GROUPS) + do + limit=MEMLIMIT_GROUP_${i}; + eval limit=\$$limit; + echo -n $limit >/dev/memctl/group_$i/memory.limit_in_bytes; + if [ $? -ne 0 ] + then + echo "Error in setting the memory limits for group_$i" + cleanup; + exit -1; + fi; + done +} + + Index: ltp-full-20080229/testcases/kernel/controllers/memctl/run_memctl_test.sh =================================================================== --- /dev/null +++ ltp-full-20080229/testcases/kernel/controllers/memctl/run_memctl_test.sh @@ -0,0 +1,209 @@ +#!/bin/bash +# usage ./runmemctl_test.sh test_num + +################################################################################# +# Copyright (c) International Business Machines Corp., 2008 # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See # +# the GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +################################################################################# +# Name Of File: run_memctl_test.sh # +# # +# Description: This file runs the setup for testing different memory resource # +# controller features. After setup it runs diff test cases in diff # +# setup. # +# # +# Test 01: Tests group memory usage on task migration # +# # +# Precaution: Avoid system use by other applications/users to get fair and # +# appropriate results (avoid unnecessary killing of applicatio) # +# # +# Author: Sudhir Kumar <sk...@li...> # +# # +# History: # +# # +# DATE NAME EMAIL DESC # +# # +# 12/03/08 Sudhir Kumar <sk...@li...> Created this test # +# # +################################################################################# + +export TCID="memctl_test01"; +export TST_TOTAL=1; +export TST_COUNT=1; + +TEST_NUM=$1; +SCRIPT_PID=$$; # trap? +RC=0; +PWD=`pwd`; +cd $LTPROOT/testcases/bin/ +. myfunctions.sh +################################################################################# +# ****************************** WARNING ********************************* # +# User can change the parameters in different cases below but before doing # +# any change user is supposed to know what he is doing. At any point when # +# memory usage of a group becomes more than the group limit OOM Killer will # +# be invoked and some of the tasks will be killed. Need to add code to handle # +# the OOM Killer issues. # +################################################################################# + +# First of all check if the system has sufficient memory +# Checking Inactive memory is sufficient. Is'nt it?? +MEM_AVAIL=`cat /proc/meminfo | grep Inactive | tr -s [:space:] | cut -d" " -f2`; +if [ $MEM_AVAIL -lt 262144 ] #256MB +then + echo System does not have sufficient free memory.; + echo Skipping execution of memory controller tests.; + exit; +fi + +case ${TEST_NUM} in + +"1" ) NUM_GROUPS=2; + MEMLIMIT_GROUP_1=100M; + MEMLIMIT_GROUP_2=100M; + CHUNK_SIZE=6291456; # malloc n chunks of size m + NUM_CHUNKS=10; # (say)60 MB memory(6*10) + TOTAL_TASKS=1; # num of tasks in a group(1) + NUM_MIG_TASKS=$TOTAL_TASKS # num of tasks to migrate + MEM_TASK=`expr $CHUNK_SIZE \* $NUM_CHUNKS`; # memory allocated by a task + MEM_TOTAL=`expr $MEM_TASK \* $TOTAL_TASKS`; # total memory allocated in a group + TEST_NAME=" TASK MIGRATION TEST:"; + ;; + +* ) usage; + exit -1 + ;; + esac + +echo "TEST $TEST_NUM: MEMORY CONTROLLER TESTING"; +echo "RUNNING SETUP....."; +setup; + +# Trap the signal from any abnormaly terminated task +# and kill all others and let cleanup be called +trap 'echo "signal caught from task"; killall memctl_task_*;\ +cleanup; exit -1;' SIGUSR1;#??? may need changes here + +echo "TEST STARTED: Please avoid using system while this test executes"; +#Check if C source file has been compiled and then run it in different groups + +case $TEST_NUM in +"1") + setmemlimits; + if [ -f memctl_test01 ] + then + for i in $(seq 1 $TOTAL_TASKS) + do + MYGROUP=/dev/memctl/group_1; + cp memctl_test01 memctl_task_$i # 2>/dev/null; + chmod +x memctl_task_$i; + TEST_NUM=$TEST_NUM MYGROUP=$MYGROUP SCRIPT_PID=$SCRIPT_PID CHUNK_SIZE=$CHUNK_SIZE \ + NUM_CHUNKS=$NUM_CHUNKS ./memctl_task_$i & + if [ $? -ne 0 ] + then + echo "Error: Could not run ./memctl_task_$i" + cleanup; + exit -1; + else + PID[$i]=$!; + fi + done; # tasks are now running in group1 + + # Wait untill tasks allocate memory from group1 + while [ 1 -gt 0 ] + do + sleep 1; + GRP1_MEMUSAGE=`cat /dev/memctl/group_1/memory.usage_in_bytes`; + if [ $GRP1_MEMUSAGE -gt $MEM_TOTAL ] + then + break; + fi + done + GRP2_MEMUSAGE_OLD=`cat /dev/memctl/group_2/memory.usage_in_bytes`; + echo Before task migration to group2 + echo group2 memory usage: $GRP2_MEMUSAGE_OLD Bytes + + # Now migrate the tasks to another group + for i in $(seq 1 $NUM_MIG_TASKS) + do + echo ${PID[$i]} >>/dev/memctl/group_2/tasks; + if [ $? -ne 0 ] + then + echo "TFAIL Task migration failed from group_1 to group_2"; + fi + done + + # double check + GRP2_TASKS=`cat /dev/memctl/group_2/tasks|wc -l`; + if [ $GRP2_TASKS -ne $NUM_MIG_TASKS ] + then + echo "TFAIL Task Migration failed for some of the tasks"; + fi; + + # Wait for some time to check if memory usage of group_2 increases + # This is not the right approach however working. ??? thoughts??? + sleep 10; + GRP2_MEMUSAGE_NEW=`cat /dev/memctl/group_2/memory.usage_in_bytes`; + echo After task migration to group2 + echo group2 memory usage: $GRP2_MEMUSAGE_NEW Bytes + + # Decision formula: decides PASS or FAIL + if [ $GRP2_MEMUSAGE_NEW -gt $GRP2_MEMUSAGE_OLD ] + then + echo "TFAIL Memory resource Controller: Task Migration test FAILED"; + else + echo "TPASS Memory Resource Controller: Task Migration test PASSED"; + fi + + # here we can add another testcases + + # Now we can signal the task to finish and do the cleanup + for i in $(seq 1 $TOTAL_TASKS) + do + kill -SIGUSR1 ${PID[$i]}; + done + else + echo "Source file not compiled..Plz check Makefile...Exiting test" + cleanup; + exit -1; + fi; + ;; + + "*" ) + usage; + exit -1; + ;; + esac + + for i in $(seq 1 $TOTAL_TASKS) + do + wait ${PID[$i]}; + RC=$?; # Return status of the task being waited + # In abnormal termination of anyone trap will kill all others + # and they will return non zero exit status. So Test broke!! + if [ $RC -ne 0 ] + then + echo "Task $i exited abnormaly with return value: $RC"; + tst_resm TINFO "Test could not execute for the expected duration"; + cleanup; + exit -1; + fi + done + + echo "Memory Resource Controller test executed successfully."; + cleanup; + cd $PWD + exit 0; #to let PAN reprt success of test Index: ltp-full-20080229/testcases/kernel/controllers/test_controllers.sh =================================================================== --- ltp-full-20080229.orig/testcases/kernel/controllers/test_controllers.sh +++ ltp-full-20080229/testcases/kernel/controllers/test_controllers.sh @@ -37,6 +37,8 @@ if [ -f /proc/cgroups ] then CPU_CONTROLLER=`grep -w cpu /proc/cgroups | cut -f1`; + MEM_CONTROLLER=`grep -w memory /proc/cgroups | cut -f1`; + if [ "$CPU_CONTROLLER" = "cpu" ] then $LTPROOT/testcases/bin/run_cpuctl_test.sh 1; @@ -48,10 +50,20 @@ then $LTPROOT/testcases/bin/run_cpuctl_stress_test.sh 8; $LTPROOT/testcases/bin/run_cpuctl_stress_test.sh 9; $LTPROOT/testcases/bin/run_cpuctl_stress_test.sh 10; + echo else echo "CONTROLLERS TESTCASES: WARNING"; echo "Kernel does not support for cpu controller"; echo "Skipping all cpu controller testcases...."; + fi; + + if [ "$MEM_CONTROLLER" = "memory" ] + then + $LTPROOT/testcases/bin/run_memctl_test.sh 1; + else + echo "CONTROLLERS TESTCASES: WARNING"; + echo "Kernel does not support for memory controller"; + echo "Skipping all memory controller testcases...."; fi else echo "CONTROLLERS TESTCASES: WARNING" Thanks sudhir |