[PATCH/RFC 13/14] Shared Policy: per cpuset mapped file policy control
Lee Schermerhorn <[email protected]> Thu, 11 Nov 2010 14:13:39 -0500
| Newsgroups | org.kernel.vger.linux-numa |
|---|---|
| Message-ID | <[email protected]> |
Shared Policy Infrastracture - per cpuset mapped file policy control
As for shared hugetlbfs file mappings, add a per cpuset
"shared_file_policy" control file to enable shared file policy
for tasks in the cpuset. Default is disabled, resulting in
the old behavior--i.e., we continue to ignore mbind() on
address ranges backed by shared file mappings. The
"shared_file_policy" file depends on CONFIG_NUMA.
Why "per cpuset"? cpusets are numa-aware task groupings and
memory policy is a numa concept. Applications that need/want
shared file policy can be grouped in a cpuset with this feature
enabled, while other applications in other cpusets need not see
this feature.
The default may be overridden--e.g., to enabled--on the kernel
command line using the "shared_file_policy_default" parameter.
When cpusets are configured, this policy sets the default value
of "shared_file_policy" for the top cpuset, which is then inherited
by all subsequently created descendant cpusets. When cpusets are
not configured, this parameter sets the "shared_file_policy_enabled"
flag for the init process, which is then inherited by all descendant
processes.
A subsequent patch will "hook up" generic file .{set|get}_policy
vm_ops to install a shared policy on a memory mapped file
if the capability has been enabled for the caller's cpuset, or
for the system in the case of no cpusets.
Signed-off-by: Lee Schermerhorn <[email protected]>
include/linux/cpuset.h | 6 ++++++
include/linux/sched.h | 19 ++++++++++++++++++-
include/linux/shared_policy.h | 2 ++
kernel/cpuset.c | 42 +++++++++++++++++++++++++++++++++++++++++-
mm/mempolicy.c | 20 +++++++++++++++++++-
5 files changed, 86 insertions(+), 3 deletions(-)
Index: linux-2.6.36-mmotm-101103-1217/include/linux/sched.h
===================================================================
--- linux-2.6.36-mmotm-101103-1217.orig/include/linux/sched.h
+++ linux-2.6.36-mmotm-101103-1217/include/linux/sched.h
@@ -1455,7 +1455,8 @@ struct task_struct {
#ifdef CONFIG_NUMA
struct mempolicy *mempolicy; /* Protected by alloc_lock */
short il_next;
- short shared_huge_policy_enabled;
+ short shared_huge_policy_enabled:1;
+ short shared_file_policy_enabled:1;
#endif
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
@@ -1882,12 +1883,28 @@ static inline int shared_huge_policy_ena
return tsk->shared_huge_policy_enabled;
}
+static inline void set_shared_file_policy_enabled(struct task_struct *tsk,
+ int val)
+{
+ tsk->shared_file_policy_enabled = !!val;
+}
+static inline int shared_file_policy_enabled(struct task_struct *tsk)
+{
+ return tsk->shared_file_policy_enabled;
+}
+
#else
static void set_shared_huge_policy_enabled(struct task_struct *tsk, int val) { }
static int shared_huge_policy_enabled(struct task_struct *tsk)
{
return 0;
}
+
+static void set_shared_file_policy_enabled(struct task_struct *tsk, int val) { }
+static int shared_file_policy_enabled(struct task_struct *tsk)
+{
+ return 0;
+}
#endif
#ifdef CONFIG_HOTPLUG_CPU
Index: linux-2.6.36-mmotm-101103-1217/kernel/cpuset.c
===================================================================
--- linux-2.6.36-mmotm-101103-1217.orig/kernel/cpuset.c
+++ linux-2.6.36-mmotm-101103-1217/kernel/cpuset.c
@@ -133,6 +133,7 @@ typedef enum {
CS_SPREAD_PAGE,
CS_SPREAD_SLAB,
CS_SHARED_HUGE_POLICY,
+ CS_SHARED_FILE_POLICY,
} cpuset_flagbits_t;
/* convenient tests for these bits */
@@ -176,6 +177,11 @@ static inline int is_shared_huge_policy(
return test_bit(CS_SHARED_HUGE_POLICY, &cs->flags);
}
+static inline int is_shared_file_policy(const struct cpuset *cs)
+{
+ return test_bit(CS_SHARED_FILE_POLICY, &cs->flags);
+}
+
static struct cpuset top_cpuset = {
.flags = ((1 << CS_CPU_EXCLUSIVE) | (1 << CS_MEM_EXCLUSIVE)),
};
@@ -331,6 +337,10 @@ static void cpuset_update_task_cpuset_fl
set_shared_huge_policy_enabled(tsk, 1);
else
set_shared_huge_policy_enabled(tsk, 0);
+ if (is_shared_file_policy(cs))
+ set_shared_file_policy_enabled(tsk, 1);
+ else
+ set_shared_file_policy_enabled(tsk, 0);
}
/*
@@ -1270,7 +1280,8 @@ static int update_flag(cpuset_flagbits_t
cpuset_flags_changed = ((is_spread_slab(cs) != is_spread_slab(trialcs))
|| (is_spread_page(cs) != is_spread_page(trialcs))
- || (is_shared_huge_policy(cs) != is_shared_huge_policy(trialcs)));
+ || (is_shared_huge_policy(cs) != is_shared_huge_policy(trialcs))
+ || (is_shared_file_policy(cs) != is_shared_file_policy(trialcs)));
mutex_lock(&callback_mutex);
cs->flags = trialcs->flags;
@@ -1507,6 +1518,7 @@ typedef enum {
FILE_SPREAD_PAGE,
FILE_SPREAD_SLAB,
FILE_SHARED_HUGE_POLICY,
+ FILE_SHARED_FILE_POLICY,
} cpuset_filetype_t;
static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
@@ -1549,6 +1561,9 @@ static int cpuset_write_u64(struct cgrou
case FILE_SHARED_HUGE_POLICY:
retval = update_flag(CS_SHARED_HUGE_POLICY, cs, val);
break;
+ case FILE_SHARED_FILE_POLICY:
+ retval = update_flag(CS_SHARED_FILE_POLICY, cs, val);
+ break;
default:
retval = -EINVAL;
break;
@@ -1715,6 +1730,8 @@ static u64 cpuset_read_u64(struct cgroup
return is_spread_slab(cs);
case FILE_SHARED_HUGE_POLICY:
return is_shared_huge_policy(cs);
+ case FILE_SHARED_FILE_POLICY:
+ return is_shared_file_policy(cs);
default:
BUG();
}
@@ -1839,6 +1856,13 @@ static struct cftype cft_shared_huge_pol
.private = FILE_SHARED_HUGE_POLICY,
};
+static struct cftype cft_shared_file_policy = {
+ .name = "shared_file_policy",
+ .read_u64 = cpuset_read_u64,
+ .write_u64 = cpuset_write_u64,
+ .private = FILE_SHARED_FILE_POLICY,
+};
+
static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
{
int err;
@@ -1852,6 +1876,9 @@ static int cpuset_populate(struct cgroup
err = add_shared_xxx_policy_file(cont, ss, &cft_shared_huge_policy);
if (err < 0)
return err;
+ err = add_shared_xxx_policy_file(cont, ss, &cft_shared_file_policy);
+ if (err < 0)
+ return err;
/* memory_pressure_enabled is in root cpuset only */
if (!cont->parent)
err = cgroup_add_file(cont, ss,
@@ -1928,6 +1955,8 @@ static struct cgroup_subsys_state *cpuse
set_bit(CS_SPREAD_SLAB, &cs->flags);
if (is_shared_huge_policy(parent))
set_bit(CS_SHARED_HUGE_POLICY, &cs->flags);
+ if (is_shared_file_policy(parent))
+ set_bit(CS_SHARED_FILE_POLICY, &cs->flags);
set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
cpumask_clear(cs->cpus_allowed);
nodes_clear(cs->mems_allowed);
@@ -2012,6 +2041,17 @@ void __init cpuset_init_shared_huge_poli
}
/**
+ * cpuset_init_shared_file_policy - set default value for shared_file_policy
+ * enablement.
+ */
+
+void __init cpuset_init_shared_file_policy(int dflt)
+{
+ if (dflt)
+ set_bit(CS_SHARED_FILE_POLICY, &top_cpuset.flags);
+}
+
+/**
* cpuset_do_move_task - move a given task to another cpuset
* @tsk: pointer to task_struct the task to move
* @scan: struct cgroup_scanner contained in its struct cpuset_hotplug_scanner
Index: linux-2.6.36-mmotm-101103-1217/include/linux/cpuset.h
===================================================================
--- linux-2.6.36-mmotm-101103-1217.orig/include/linux/cpuset.h
+++ linux-2.6.36-mmotm-101103-1217/include/linux/cpuset.h
@@ -149,6 +149,7 @@ static inline int add_shared_xxx_policy_
#endif
extern void __init cpuset_init_shared_huge_policy(int dflt);
+extern void __init cpuset_init_shared_file_policy(int dflt);
#else /* !CONFIG_CPUSETS */
@@ -268,6 +269,11 @@ static inline void cpuset_init_shared_hu
{
current->shared_file_policy_enabled = dflt;
}
+
+static inline void cpuset_init_shared_file_policy(int dflt)
+{
+ current->shared_file_policy_enabled = dflt;
+}
#endif /* !CONFIG_CPUSETS */
Index: linux-2.6.36-mmotm-101103-1217/mm/mempolicy.c
===================================================================
--- linux-2.6.36-mmotm-101103-1217.orig/mm/mempolicy.c
+++ linux-2.6.36-mmotm-101103-1217/mm/mempolicy.c
@@ -2131,6 +2131,23 @@ static int __init setup_shared_huge_poli
__setup("shared_huge_policy_default=", setup_shared_huge_policy_default);
/*
+ * default state of per cpuset shared_file_policy_enablement
+ */
+int shared_file_policy_default;
+
+static int __init setup_shared_file_policy_default(char *str)
+{
+ int ret, val;
+ ret = get_option(&str, &val);
+ if (!ret)
+ return 0;
+ shared_file_policy_default = !!val;
+ return 1;
+}
+__setup("shared_file_policy_default=", setup_shared_file_policy_default);
+
+
+/*
* Remember policies even when nobody has shared memory mapped.
* The policies are kept in Red-Black tree linked from the inode.
* They are protected by the sp->lock spinlock, which should be held
@@ -2510,10 +2527,11 @@ void __init numa_policy_init(void)
printk("numa_policy_init: interleaving failed\n");
/*
- * initialize per cpuset shared huge policy enablement
+ * initialize per cpuset shared [huge] file policy enablement
* from default.
*/
cpuset_init_shared_huge_policy(shared_huge_policy_default);
+ cpuset_init_shared_file_policy(shared_file_policy_default);
}
/* Reset policy of current process to default */
Index: linux-2.6.36-mmotm-101103-1217/include/linux/shared_policy.h
===================================================================
--- linux-2.6.36-mmotm-101103-1217.orig/include/linux/shared_policy.h
+++ linux-2.6.36-mmotm-101103-1217/include/linux/shared_policy.h
@@ -36,6 +36,7 @@ struct shared_policy {
#define SPOL_F_PERSIST 0x01 /* for shmem use */
extern int shared_file_policy_default;
+extern int shared_file_policy_default;
extern struct shared_policy *mpol_shared_policy_new(
struct address_space *mapping,
@@ -51,6 +52,7 @@ extern struct mempolicy *mpol_shared_pol
struct shared_policy {};
#define shared_file_policy_default 0
+#define shared_file_policy_default 0
static inline int mpol_set_shared_policy(struct shared_policy *info,
pgoff_t pgoff, unsigned long sz,