aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpuset.c
diff options
context:
space:
mode:
authorPaul Jackson <pj@sgi.com>2006-01-08 04:00:56 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:12:43 -0500
commit45b07ef31d1182d2cfde7711327e3afb268bb1ac (patch)
tree3bf820531f920b43d4ed963643b1f565c82bcaa4 /kernel/cpuset.c
parentd0d963281ccb22e6f339bfdd75c6b2e31351929f (diff)
[PATCH] cpusets: swap migration interface
Add a boolean "memory_migrate" to each cpuset, represented by a file containing "0" or "1" in each directory below /dev/cpuset. It defaults to false (file contains "0"). It can be set true by writing "1" to the file. If true, then anytime that a task is attached to the cpuset so marked, the pages of that task will be moved to that cpuset, preserving, to the extent practical, the cpuset-relative placement of the pages. Also anytime that a cpuset so marked has its memory placement changed (by writing to its "mems" file), the tasks in that cpuset will have their pages moved to the cpusets new nodes, preserving, to the extent practical, the cpuset-relative placement of the moved pages. Signed-off-by: Paul Jackson <pj@sgi.com> Cc: Christoph Lameter <christoph@lameter.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r--kernel/cpuset.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 7430640f9816..f63383e01ec7 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -87,6 +87,7 @@ struct cpuset {
87typedef enum { 87typedef enum {
88 CS_CPU_EXCLUSIVE, 88 CS_CPU_EXCLUSIVE,
89 CS_MEM_EXCLUSIVE, 89 CS_MEM_EXCLUSIVE,
90 CS_MEMORY_MIGRATE,
90 CS_REMOVED, 91 CS_REMOVED,
91 CS_NOTIFY_ON_RELEASE 92 CS_NOTIFY_ON_RELEASE
92} cpuset_flagbits_t; 93} cpuset_flagbits_t;
@@ -112,6 +113,11 @@ static inline int notify_on_release(const struct cpuset *cs)
112 return !!test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags); 113 return !!test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
113} 114}
114 115
116static inline int is_memory_migrate(const struct cpuset *cs)
117{
118 return !!test_bit(CS_MEMORY_MIGRATE, &cs->flags);
119}
120
115/* 121/*
116 * Increment this atomic integer everytime any cpuset changes its 122 * Increment this atomic integer everytime any cpuset changes its
117 * mems_allowed value. Users of cpusets can track this generation 123 * mems_allowed value. Users of cpusets can track this generation
@@ -602,16 +608,24 @@ static void refresh_mems(void)
602 if (current->cpuset_mems_generation != my_cpusets_mem_gen) { 608 if (current->cpuset_mems_generation != my_cpusets_mem_gen) {
603 struct cpuset *cs; 609 struct cpuset *cs;
604 nodemask_t oldmem = current->mems_allowed; 610 nodemask_t oldmem = current->mems_allowed;
611 int migrate;
605 612
606 down(&callback_sem); 613 down(&callback_sem);
607 task_lock(current); 614 task_lock(current);
608 cs = current->cpuset; 615 cs = current->cpuset;
616 migrate = is_memory_migrate(cs);
609 guarantee_online_mems(cs, &current->mems_allowed); 617 guarantee_online_mems(cs, &current->mems_allowed);
610 current->cpuset_mems_generation = cs->mems_generation; 618 current->cpuset_mems_generation = cs->mems_generation;
611 task_unlock(current); 619 task_unlock(current);
612 up(&callback_sem); 620 up(&callback_sem);
613 if (!nodes_equal(oldmem, current->mems_allowed)) 621 if (!nodes_equal(oldmem, current->mems_allowed)) {
614 numa_policy_rebind(&oldmem, &current->mems_allowed); 622 numa_policy_rebind(&oldmem, &current->mems_allowed);
623 if (migrate) {
624 do_migrate_pages(current->mm, &oldmem,
625 &current->mems_allowed,
626 MPOL_MF_MOVE_ALL);
627 }
628 }
615 } 629 }
616} 630}
617 631
@@ -795,7 +809,7 @@ static int update_nodemask(struct cpuset *cs, char *buf)
795/* 809/*
796 * update_flag - read a 0 or a 1 in a file and update associated flag 810 * update_flag - read a 0 or a 1 in a file and update associated flag
797 * bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE, 811 * bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
798 * CS_NOTIFY_ON_RELEASE) 812 * CS_NOTIFY_ON_RELEASE, CS_MEMORY_MIGRATE)
799 * cs: the cpuset to update 813 * cs: the cpuset to update
800 * buf: the buffer where we read the 0 or 1 814 * buf: the buffer where we read the 0 or 1
801 * 815 *
@@ -848,6 +862,7 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
848 struct task_struct *tsk; 862 struct task_struct *tsk;
849 struct cpuset *oldcs; 863 struct cpuset *oldcs;
850 cpumask_t cpus; 864 cpumask_t cpus;
865 nodemask_t from, to;
851 866
852 if (sscanf(pidbuf, "%d", &pid) != 1) 867 if (sscanf(pidbuf, "%d", &pid) != 1)
853 return -EIO; 868 return -EIO;
@@ -893,7 +908,12 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
893 guarantee_online_cpus(cs, &cpus); 908 guarantee_online_cpus(cs, &cpus);
894 set_cpus_allowed(tsk, cpus); 909 set_cpus_allowed(tsk, cpus);
895 910
911 from = oldcs->mems_allowed;
912 to = cs->mems_allowed;
913
896 up(&callback_sem); 914 up(&callback_sem);
915 if (is_memory_migrate(cs))
916 do_migrate_pages(tsk->mm, &from, &to, MPOL_MF_MOVE_ALL);
897 put_task_struct(tsk); 917 put_task_struct(tsk);
898 if (atomic_dec_and_test(&oldcs->count)) 918 if (atomic_dec_and_test(&oldcs->count))
899 check_for_release(oldcs, ppathbuf); 919 check_for_release(oldcs, ppathbuf);
@@ -905,6 +925,7 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
905typedef enum { 925typedef enum {
906 FILE_ROOT, 926 FILE_ROOT,
907 FILE_DIR, 927 FILE_DIR,
928 FILE_MEMORY_MIGRATE,
908 FILE_CPULIST, 929 FILE_CPULIST,
909 FILE_MEMLIST, 930 FILE_MEMLIST,
910 FILE_CPU_EXCLUSIVE, 931 FILE_CPU_EXCLUSIVE,
@@ -960,6 +981,9 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
960 case FILE_NOTIFY_ON_RELEASE: 981 case FILE_NOTIFY_ON_RELEASE:
961 retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer); 982 retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
962 break; 983 break;
984 case FILE_MEMORY_MIGRATE:
985 retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
986 break;
963 case FILE_TASKLIST: 987 case FILE_TASKLIST:
964 retval = attach_task(cs, buffer, &pathbuf); 988 retval = attach_task(cs, buffer, &pathbuf);
965 break; 989 break;
@@ -1060,6 +1084,9 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
1060 case FILE_NOTIFY_ON_RELEASE: 1084 case FILE_NOTIFY_ON_RELEASE:
1061 *s++ = notify_on_release(cs) ? '1' : '0'; 1085 *s++ = notify_on_release(cs) ? '1' : '0';
1062 break; 1086 break;
1087 case FILE_MEMORY_MIGRATE:
1088 *s++ = is_memory_migrate(cs) ? '1' : '0';
1089 break;
1063 default: 1090 default:
1064 retval = -EINVAL; 1091 retval = -EINVAL;
1065 goto out; 1092 goto out;
@@ -1408,6 +1435,11 @@ static struct cftype cft_notify_on_release = {
1408 .private = FILE_NOTIFY_ON_RELEASE, 1435 .private = FILE_NOTIFY_ON_RELEASE,
1409}; 1436};
1410 1437
1438static struct cftype cft_memory_migrate = {
1439 .name = "memory_migrate",
1440 .private = FILE_MEMORY_MIGRATE,
1441};
1442
1411static int cpuset_populate_dir(struct dentry *cs_dentry) 1443static int cpuset_populate_dir(struct dentry *cs_dentry)
1412{ 1444{
1413 int err; 1445 int err;
@@ -1422,6 +1454,8 @@ static int cpuset_populate_dir(struct dentry *cs_dentry)
1422 return err; 1454 return err;
1423 if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0) 1455 if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
1424 return err; 1456 return err;
1457 if ((err = cpuset_add_file(cs_dentry, &cft_memory_migrate)) < 0)
1458 return err;
1425 if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0) 1459 if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
1426 return err; 1460 return err;
1427 return 0; 1461 return 0;