SOURCES: kernel-desktop-cpuset_virtualization.patch (NEW) - linux-...

sparky sparky at pld-linux.org
Mon Jun 19 14:02:59 CEST 2006


Author: sparky                       Date: Mon Jun 19 12:02:59 2006 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- linux-2.6-cpuset_virtualization.patch at LINUX_2_6

---- Files affected:
SOURCES:
   kernel-desktop-cpuset_virtualization.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/kernel-desktop-cpuset_virtualization.patch
diff -u /dev/null SOURCES/kernel-desktop-cpuset_virtualization.patch:1.1
--- /dev/null	Mon Jun 19 14:02:59 2006
+++ SOURCES/kernel-desktop-cpuset_virtualization.patch	Mon Jun 19 14:02:54 2006
@@ -0,0 +1,511 @@
+diff -ur linux-2.6.14.3/arch/i386/kernel/cpu/proc.c linux-2.6.14.3-cpusetvirt/arch/i386/kernel/cpu/proc.c
+--- linux-2.6.14.3/arch/i386/kernel/cpu/proc.c	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/arch/i386/kernel/cpu/proc.c	2005-11-25 19:28:28.088979320 +0100
+@@ -3,6 +3,7 @@
+ #include <asm/semaphore.h>
+ #include <linux/seq_file.h>
+ #include <linux/cpufreq.h>
++#include <linux/cpuset.h>
+ 
+ /*
+  *	Get CPU information for use by the procfs.
+@@ -69,12 +70,20 @@
+ 	if (!cpu_online(n))
+ 		return 0;
+ #endif
++#ifdef CONFIG_CPUSETS
++	if (!cpu_visible_in_cpuset(n, current->cpuset))
++		return 0;
++#endif
+ 	seq_printf(m, "processor\t: %d\n"
+ 		"vendor_id\t: %s\n"
+ 		"cpu family\t: %d\n"
+ 		"model\t\t: %d\n"
+ 		"model name\t: %s\n",
++#ifdef CONFIG_CPUSETS
++		cpuid_in_cpuset(n, current->cpuset),
++#else
+ 		n,
++#endif
+ 		c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+ 		c->x86,
+ 		c->x86_model,
+diff -ur linux-2.6.14.3/arch/ia64/kernel/setup.c linux-2.6.14.3-cpusetvirt/arch/ia64/kernel/setup.c
+--- linux-2.6.14.3/arch/ia64/kernel/setup.c	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/arch/ia64/kernel/setup.c	2005-11-25 19:28:28.090979016 +0100
+@@ -43,6 +43,7 @@
+ #include <linux/platform.h>
+ #include <linux/pm.h>
+ #include <linux/cpufreq.h>
++#include <linux/cpuset.h>
+ 
+ #include <asm/ia32.h>
+ #include <asm/machvec.h>
+@@ -476,6 +477,11 @@
+ 	unsigned long mask;
+ 	int i;
+ 
++#ifdef CONFIG_CPUSETS
++	if (!cpu_visible_in_cpuset(cpunum, current->cpuset))
++		return 0;
++#endif
++	
+ 	mask = c->features;
+ 
+ 	switch (c->family) {
+@@ -520,7 +526,12 @@
+ 		   "cpu MHz    : %lu.%06lu\n"
+ 		   "itc MHz    : %lu.%06lu\n"
+ 		   "BogoMIPS   : %lu.%02lu\n",
+-		   cpunum, c->vendor, family, c->model, c->revision, c->archrev,
++#ifdef CONFIG_CPUSETS
++		   cpuid_in_cpuset(cpunum, current->cpuset),
++#else
++		   cpunum,
++#endif
++		   c->vendor, family, c->model, c->revision, c->archrev,
+ 		   features, c->ppn, c->number,
+ 		   c->proc_freq / 1000000, c->proc_freq % 1000000,
+ 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
+diff -ur linux-2.6.14.3/arch/x86_64/kernel/setup.c linux-2.6.14.3-cpusetvirt/arch/x86_64/kernel/setup.c
+--- linux-2.6.14.3/arch/x86_64/kernel/setup.c	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/arch/x86_64/kernel/setup.c	2005-11-25 19:37:48.755745016 +0100
+@@ -42,6 +42,7 @@
+ #include <linux/cpufreq.h>
+ #include <linux/dmi.h>
+ #include <linux/dma-mapping.h>
++#include <linux/cpuset.h>
+ 
+ #include <asm/mtrr.h>
+ #include <asm/uaccess.h>
+@@ -1249,13 +1250,20 @@
+ 	if (!cpu_online(c-cpu_data))
+ 		return 0;
+ #endif
+-
++#ifdef CONFIG_CPUSETS
++	if (!cpu_visible_in_cpuset(c-cpu_data, current->cpuset))
++		return 0;
++#endif
+ 	seq_printf(m,"processor\t: %u\n"
+ 		     "vendor_id\t: %s\n"
+ 		     "cpu family\t: %d\n"
+ 		     "model\t\t: %d\n"
+ 		     "model name\t: %s\n",
++#ifdef CONFIG_CPUSETS
++		     cpuid_in_cpuset(c-cpu_data, current->cpuset),
++#else
+ 		     (unsigned)(c-cpu_data),
++#endif
+ 		     c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+ 		     c->x86,
+ 		     (int)c->x86_model,
+diff -ur linux-2.6.14.3/fs/proc/proc_misc.c linux-2.6.14.3-cpusetvirt/fs/proc/proc_misc.c
+--- linux-2.6.14.3/fs/proc/proc_misc.c	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/fs/proc/proc_misc.c	2005-11-25 19:28:28.092978712 +0100
+@@ -44,6 +44,7 @@
+ #include <linux/jiffies.h>
+ #include <linux/sysrq.h>
+ #include <linux/vmalloc.h>
++#include <linux/cpuset.h>
+ #include <linux/crash_dump.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -353,6 +354,10 @@
+ 	for_each_cpu(i) {
+ 		int j;
+ 
++#ifdef CONFIG_CPUSETS
++		if (!cpu_visible_in_cpuset(i, current->cpuset))
++			continue;
++#endif
+ 		user = cputime64_add(user, kstat_cpu(i).cpustat.user);
+ 		nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
+ 		system = cputime64_add(system, kstat_cpu(i).cpustat.system);
+@@ -376,6 +381,10 @@
+ 		(unsigned long long)cputime64_to_clock_t(steal));
+ 	for_each_online_cpu(i) {
+ 
++#ifdef CONFIG_CPUSETS
++		if (!cpu_visible_in_cpuset(i, current->cpuset))
++			continue;
++#endif
+ 		/* Copy values here to work around gcc-2.95.3, gcc-2.96 */
+ 		user = kstat_cpu(i).cpustat.user;
+ 		nice = kstat_cpu(i).cpustat.nice;
+@@ -386,7 +395,11 @@
+ 		softirq = kstat_cpu(i).cpustat.softirq;
+ 		steal = kstat_cpu(i).cpustat.steal;
+ 		seq_printf(p, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu\n",
++#ifdef CONFIG_CPUSETS
++			cpuid_in_cpuset(i, current->cpuset),
++#else
+ 			i,
++#endif
+ 			(unsigned long long)cputime64_to_clock_t(user),
+ 			(unsigned long long)cputime64_to_clock_t(nice),
+ 			(unsigned long long)cputime64_to_clock_t(system),
+diff -ur linux-2.6.14.3/include/linux/cpuset.h linux-2.6.14.3-cpusetvirt/include/linux/cpuset.h
+--- linux-2.6.14.3/include/linux/cpuset.h	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/include/linux/cpuset.h	2005-11-25 19:28:28.093978560 +0100
+@@ -28,6 +28,9 @@
+ extern struct file_operations proc_cpuset_operations;
+ extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
+ 
++int cpu_visible_in_cpuset(int cpu, struct cpuset * cs);
++int cpuid_in_cpuset(int cpu, struct cpuset * cs);
++
+ #else /* !CONFIG_CPUSETS */
+ 
+ static inline int cpuset_init(void) { return 0; }
+diff -ur linux-2.6.14.3/include/linux/init_task.h linux-2.6.14.3-cpusetvirt/include/linux/init_task.h
+--- linux-2.6.14.3/include/linux/init_task.h	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/include/linux/init_task.h	2005-11-25 19:28:28.079980688 +0100
+@@ -88,6 +88,7 @@
+ 	.static_prio	= MAX_PRIO-20,					\
+ 	.policy		= SCHED_NORMAL,					\
+ 	.cpus_allowed	= CPU_MASK_ALL,					\
++	.cpus_virt_allowed	= CPU_MASK_ALL,				\
+ 	.mm		= NULL,						\
+ 	.active_mm	= &init_mm,					\
+ 	.run_list	= LIST_HEAD_INIT(tsk.run_list),			\
+diff -ur linux-2.6.14.3/include/linux/sched.h linux-2.6.14.3-cpusetvirt/include/linux/sched.h
+--- linux-2.6.14.3/include/linux/sched.h	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/include/linux/sched.h	2005-11-25 19:28:28.081980384 +0100
+@@ -808,6 +808,7 @@
+ 	struct mempolicy *mempolicy;
+ 	short il_next;
+ #endif
++	cpumask_t cpus_virt_allowed;
+ #ifdef CONFIG_CPUSETS
+ 	struct cpuset *cpuset;
+ 	nodemask_t mems_allowed;
+diff -ur linux-2.6.14.3/kernel/cpuset.c linux-2.6.14.3-cpusetvirt/kernel/cpuset.c
+--- linux-2.6.14.3/kernel/cpuset.c	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/kernel/cpuset.c	2005-11-25 19:28:28.084979928 +0100
+@@ -83,6 +83,7 @@
+ 	CS_CPU_EXCLUSIVE,
+ 	CS_MEM_EXCLUSIVE,
+ 	CS_MEMORY_MIGRATE,
++	CS_VIRTUALIZED,
+ 	CS_REMOVED,
+ 	CS_NOTIFY_ON_RELEASE
+ } cpuset_flagbits_t;
+@@ -98,6 +99,10 @@
+ 	return !!test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
+ }
+ 
++static inline int is_virtualized(const struct cpuset *cs)
++{
++	return !!test_bit(CS_VIRTUALIZED, &cs->flags);
++}
+ static inline int is_removed(const struct cpuset *cs)
+ {
+ 	return !!test_bit(CS_REMOVED, &cs->flags);
+@@ -590,6 +595,145 @@
+ 		is_mem_exclusive(p) <= is_mem_exclusive(q);
+ }
+ 
++#define cyclic_next_cpu(index, mask)	__cyclic_next_cpu(index, &mask)
++static inline int __cyclic_next_cpu(int index, const cpumask_t * mask)
++{
++	int i;
++	i = next_cpu(index, *mask);
++	if (i >= NR_CPUS) {
++		if (cpu_isset(0, *mask))
++			return 0;
++		i = next_cpu(0, *mask);
++	}
++	return i;
++}
++
++/**
++ *	cpuset_combine_mask - translate a user cpu mask to a physical one.
++ *	@virt_allowed:	the mask given by the user to sched_setaffinity()
++ *	@cs_allowed:	the mask of the current cpuset.
++ *
++ *	Returns combined mask in *mask.
++ */
++static int combine_mask(cpumask_t *mask, const cpumask_t virt_allowed, const cpumask_t cs_allowed)
++{
++	int i;
++
++	/* start with current cpu out of the mask
++	 * so the first call to next_cpu will take the first cpu
++	 * even if it is cpu zero
++	 */
++	int cpu = NR_CPUS;
++	cpus_clear(*mask);
++
++	if (cpus_empty(virt_allowed)) return 0;
++	if (cpus_empty(cs_allowed)) return 0;
++
++	for (i = 0; i < NR_CPUS; i++) {
++		cpu = cyclic_next_cpu(cpu, cs_allowed);
++		if (cpu_isset(i, virt_allowed))
++			cpu_set(cpu, *mask);
++	}
++	return 0;
++}
++
++/**
++ * Find out whether a cpu should be listed in /proc/cpuinfo
++ *
++ * For virtualized cpusets, only cpus present in the cpuset are shown
++ */
++int cpu_visible_in_cpuset(int cpu, struct cpuset * cs)
++{
++	/* all cpus are visible in non-virtualized cpusets */
++	if (!is_virtualized(cs))
++		return 1;
++
++	return cpu_isset(cpu, cs->cpus_allowed);
++}
++
++/**
++ *	cpuid_in_cpuset - translate a "real" cpu number to a "inside cpuset" (logical)
++ *	@cs:	the cpuset where all the magic occurs.
++ *	@cpu:	cpu number to be translated
++ *
++ *	Used for /proc/cpuinfo.
++ *	Returns the translated cpu number.
++ */
++int cpuid_in_cpuset(int cpu, struct cpuset * cs)
++{
++	int i;
++	int l = 0;
++	
++	/* translation needed only for virtualized cpusets */
++	if (!is_virtualized(cs))
++		return cpu;
++		
++	for(i=0; i < NR_CPUS; i++)
++	{
++		if (i == cpu) return l;
++		if (cpu_isset(i, cs->cpus_allowed))
++			l++;
++	}
++	/* NOT REACHED */
++	BUG();
++	return 0;
++}
++
++/**
++ *	set_cpus_virt_allowed - updated cpus_virt_allowed AND cpus_allowed masks
++ *	@virt_allowed:        the mask given by the user to sched_setaffinity()
++ *	@p:		the task
++ *
++ *	This function does not mess with scheduler internals. Here we rely
++ *	on set_cpus_allowed(), that should, for instance, migrate the task 
++ *	if necessary.
++ */
++static int set_cpus_virt_allowed(task_t *p, cpumask_t mask)
++{
++	cpumask_t new_mask;
++	int retval;
++
++	p->cpus_virt_allowed = mask;
++	combine_mask(&new_mask, p->cpus_virt_allowed, p->cpuset->cpus_allowed);
++	retval = set_cpus_allowed(p, new_mask);
++	return retval;
++}
++
++/**
++ *	This is the exported entry point that will be called
++ *	by sched_setaffinity().
++ */
++int cpuset_set_cpus_affinity(task_t *p, cpumask_t mask)
++{
++	int retval;
++
++	down(&callback_sem);
++	if (is_virtualized(p->cpuset))
++		retval = set_cpus_virt_allowed(p, mask);
++	else {
++		cpumask_t cpus_allowed;
++		cpus_allowed = cpuset_cpus_allowed(p);
++		cpus_and(mask, mask, cpus_allowed);
++		retval = set_cpus_allowed(p, mask);
++	}
++	up(&callback_sem);
++	return retval;
++}
++
++/**
++ *	This is the exported entry point that will be called
++ *	by sched_getaffinity().
++ */
++int cpuset_get_cpus_virt_affinity(task_t *p, cpumask_t *mask)
++{
++	if (is_virtualized(p->cpuset)) {
++		*mask = p->cpus_virt_allowed;
++		return 0;
++	}
++	return -1;
++}
++
++
+ /*
+  * validate_change() - Used to validate that any proposed cpuset change
+  *		       follows the structural rules for cpusets.
+@@ -624,6 +768,11 @@
+ 	if ((par = cur->parent) == NULL)
+ 		return 0;
+ 
++	/* virtualization can only be turned on/off on empty cpusets  */
++	if ((atomic_read(&cur->count) > 0) || (!list_empty(&cur->children)))
++		if (is_virtualized(cur) != is_virtualized(trial))
++			return -EBUSY;
++
+ 	/* We must be a subset of our parent cpuset */
+ 	if (!is_cpuset_subset(trial, par))
+ 		return -EACCES;
+@@ -818,11 +967,29 @@
+ 		return -ESRCH;
+ 	}
+ 	atomic_inc(&cs->count);
++
++	/* depending on current and future cpuset for this task,
++	 * affinity masks may be meaningful or not
++	 */
++	cpumask_t virt_allowed, allowed;
++	if (is_virtualized(cs) == is_virtualized(tsk->cpuset)) {
++		virt_allowed = tsk->cpus_virt_allowed;
++		allowed = tsk->cpus_allowed;
++	} else {
++		virt_allowed = CPU_MASK_ALL;
++		allowed = CPU_MASK_ALL;
++	}
++		
+ 	rcu_assign_pointer(tsk->cpuset, cs);
+ 	task_unlock(tsk);
+ 
+-	guarantee_online_cpus(cs, &cpus);
+-	set_cpus_allowed(tsk, cpus);
++
++	if (is_virtualized(cs))
++		set_cpus_virt_allowed(tsk, virt_allowed);
++	else {
++		guarantee_online_cpus(cs, &cpus);
++		set_cpus_allowed(tsk, cpus);
++	}
+ 
+ 	from = oldcs->mems_allowed;
+ 	to = cs->mems_allowed;
+@@ -839,6 +1006,7 @@
+ 	FILE_MEMLIST,
+ 	FILE_CPU_EXCLUSIVE,
+ 	FILE_MEM_EXCLUSIVE,
++	FILE_VIRTUALIZE,
+ 	FILE_NOTIFY_ON_RELEASE,
+ 	FILE_TASKLIST,
+ } cpuset_filetype_t;
+@@ -887,6 +1055,9 @@
+ 	case FILE_MEM_EXCLUSIVE:
+ 		retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
+ 		break;
++	case FILE_VIRTUALIZE:
++		retval = update_flag(CS_VIRTUALIZED, cs, buffer);
++		break;
+ 	case FILE_NOTIFY_ON_RELEASE:
+ 		retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
+ 		break;
+@@ -987,6 +1158,9 @@
+ 	case FILE_MEM_EXCLUSIVE:
+ 		*s++ = is_mem_exclusive(cs) ? '1' : '0';
+ 		break;
++	case FILE_VIRTUALIZE:
++		*s++ = is_virtualized(cs) ? '1' : '0';
++		break;
+ 	case FILE_NOTIFY_ON_RELEASE:
+ 		*s++ = notify_on_release(cs) ? '1' : '0';
+ 		break;
+@@ -1310,6 +1484,11 @@
+ 	.private = FILE_MEM_EXCLUSIVE,
+ };
+ 
++static struct cftype cft_virtualize = {
++	.name = "virtualize",
++	.private = FILE_VIRTUALIZE,
++};
++
+ static struct cftype cft_notify_on_release = {
+ 	.name = "notify_on_release",
+ 	.private = FILE_NOTIFY_ON_RELEASE,
+@@ -1327,6 +1506,8 @@
+ 		return err;
+ 	if ((err = cpuset_add_file(cs_dentry, &cft_mem_exclusive)) < 0)
+ 		return err;
++	if ((err = cpuset_add_file(cs_dentry, &cft_virtualize)) < 0)
++		return err;
+ 	if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
+ 		return err;
+ 	if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
+diff -ur linux-2.6.14.3/kernel/kthread.c linux-2.6.14.3-cpusetvirt/kernel/kthread.c
+--- linux-2.6.14.3/kernel/kthread.c	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/kernel/kthread.c	2005-11-25 19:28:28.094978408 +0100
+@@ -160,6 +160,15 @@
+ 	wait_task_inactive(k);
+ 	set_task_cpu(k, cpu);
+ 	k->cpus_allowed = cpumask_of_cpu(cpu);
++#ifdef CONFIG_CPUSETS
++	/* kthreads don't use sched_setaffinity() to bind themselves to
++	 * CPUs, we need to take care.
++	 * This should not be problem since it is unlikely that kthreads
++	 * will run in a virtualized cpuset.
++	 * But better be ready, so:
++	 */
++	k->cpus_virt_allowed = cpumask_of_cpu(cpu);
++#endif
+ }
+ EXPORT_SYMBOL(kthread_bind);
+ 
+diff -ur linux-2.6.14.3/kernel/sched.c linux-2.6.14.3-cpusetvirt/kernel/sched.c
+--- linux-2.6.14.3/kernel/sched.c	2005-11-24 23:10:21.000000000 +0100
++++ linux-2.6.14.3-cpusetvirt/kernel/sched.c	2005-11-25 19:28:28.087979472 +0100
+@@ -3798,11 +3798,15 @@
+ 	return retval;
+ }
+ 
++#ifdef CONFIG_CPUSETS
++int cpuset_set_cpus_affinity(task_t *p, cpumask_t mask);
++int cpuset_get_cpus_virt_affinity(task_t *p, cpumask_t *mask);
++#endif
++
+ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
+ {
+ 	task_t *p;
+ 	int retval;
+-	cpumask_t cpus_allowed;
+ 
+ 	lock_cpu_hotplug();
+ 	read_lock(&tasklist_lock);
+@@ -3827,9 +3827,11 @@
+ 			!capable(CAP_SYS_NICE))
+ 		goto out_unlock;
+ 
+-	cpus_allowed = cpuset_cpus_allowed(p);
+-	cpus_and(new_mask, new_mask, cpus_allowed);
+-	retval = set_cpus_allowed(p, new_mask);
++#ifdef CONFIG_CPUSETS
++	retval = cpuset_set_cpus_affinity(p, new_mask);
++#else
++  	retval = set_cpus_allowed(p, new_mask);
++#endif
+ 
+ out_unlock:
+ 	put_task_struct(p);
+@@ -3897,7 +3904,12 @@
+ 		goto out_unlock;
+ 
+ 	retval = 0;
+-	cpus_and(*mask, p->cpus_allowed, cpu_online_map);
++#ifdef CONFIG_CPUSETS
++	if (cpuset_get_cpus_virt_affinity(p, mask) < 0)
++		cpus_and(*mask, p->cpus_allowed, cpu_online_map);
++#else
++  	cpus_and(*mask, p->cpus_allowed, cpu_online_map);
++#endif
+ 
+ out_unlock:
+ 	read_unlock(&tasklist_lock);
================================================================


More information about the pld-cvs-commit mailing list