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 <lee.schermerhorn@xxxxxx> 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, -- To unsubscribe from this list: send the line "unsubscribe linux-numa" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html