aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Kruchinin <dkruchinin@acm.org>2010-07-14 06:33:08 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2010-07-19 01:50:19 -0400
commit5e017dc3f8bc9e4a28983666e6bc00114a2018bb (patch)
tree4057e6322bc43d5b833b65b5f7372ae57a709fb3
parente15bacbebb9dcc95f148f28dfc83a6d5e48b60b8 (diff)
padata: Added sysfs primitives to padata subsystem
Added sysfs primitives to padata subsystem. Now API user may embedded kobject each padata instance contains into any sysfs hierarchy. For now padata sysfs interface provides only two objects: serial_cpumask [RW] - cpumask for serial workers parallel_cpumask [RW] - cpumask for parallel workers Signed-off-by: Dan Kruchinin <dkruchinin@acm.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--include/linux/padata.h5
-rw-r--r--kernel/padata.c155
2 files changed, 150 insertions, 10 deletions
diff --git a/include/linux/padata.h b/include/linux/padata.h
index 621e7736690c..293ad46ffced 100644
--- a/include/linux/padata.h
+++ b/include/linux/padata.h
@@ -26,6 +26,7 @@
26#include <linux/list.h> 26#include <linux/list.h>
27#include <linux/timer.h> 27#include <linux/timer.h>
28#include <linux/notifier.h> 28#include <linux/notifier.h>
29#include <linux/kobject.h>
29 30
30#define PADATA_CPU_SERIAL 0x01 31#define PADATA_CPU_SERIAL 0x01
31#define PADATA_CPU_PARALLEL 0x02 32#define PADATA_CPU_PARALLEL 0x02
@@ -142,7 +143,8 @@ struct parallel_data {
142 * cbcpu for parallel and serial works respectivly. 143 * cbcpu for parallel and serial works respectivly.
143 * @cpumask_change_notifier: Notifiers chain for user-defined notify 144 * @cpumask_change_notifier: Notifiers chain for user-defined notify
144 * callbacks that will be called when either @pcpu or @cbcpu 145 * callbacks that will be called when either @pcpu or @cbcpu
145 * or both cpumasks change. 146 * or both cpumasks change.
147 * @kobj: padata instance kernel object.
146 * @lock: padata instance lock. 148 * @lock: padata instance lock.
147 * @flags: padata flags. 149 * @flags: padata flags.
148 */ 150 */
@@ -155,6 +157,7 @@ struct padata_instance {
155 cpumask_var_t cbcpu; 157 cpumask_var_t cbcpu;
156 } cpumask; 158 } cpumask;
157 struct blocking_notifier_head cpumask_change_notifier; 159 struct blocking_notifier_head cpumask_change_notifier;
160 struct kobject kobj;
158 struct mutex lock; 161 struct mutex lock;
159 u8 flags; 162 u8 flags;
160#define PADATA_INIT 1 163#define PADATA_INIT 1
diff --git a/kernel/padata.c b/kernel/padata.c
index 84d0ca9dac9c..526f9ea2fcc8 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -26,6 +26,7 @@
26#include <linux/mutex.h> 26#include <linux/mutex.h>
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/sysfs.h>
29#include <linux/rcupdate.h> 30#include <linux/rcupdate.h>
30 31
31#define MAX_SEQ_NR (INT_MAX - NR_CPUS) 32#define MAX_SEQ_NR (INT_MAX - NR_CPUS)
@@ -924,6 +925,149 @@ static int padata_cpu_callback(struct notifier_block *nfb,
924} 925}
925#endif 926#endif
926 927
928static void __padata_free(struct padata_instance *pinst)
929{
930#ifdef CONFIG_HOTPLUG_CPU
931 unregister_hotcpu_notifier(&pinst->cpu_notifier);
932#endif
933
934 padata_stop(pinst);
935 padata_free_pd(pinst->pd);
936 free_cpumask_var(pinst->cpumask.pcpu);
937 free_cpumask_var(pinst->cpumask.cbcpu);
938 kfree(pinst);
939}
940
941#define kobj2pinst(_kobj) \
942 container_of(_kobj, struct padata_instance, kobj)
943#define attr2pentry(_attr) \
944 container_of(_attr, struct padata_sysfs_entry, attr)
945
946static void padata_sysfs_release(struct kobject *kobj)
947{
948 struct padata_instance *pinst = kobj2pinst(kobj);
949 __padata_free(pinst);
950}
951
952struct padata_sysfs_entry {
953 struct attribute attr;
954 ssize_t (*show)(struct padata_instance *, struct attribute *, char *);
955 ssize_t (*store)(struct padata_instance *, struct attribute *,
956 const char *, size_t);
957};
958
959static ssize_t show_cpumask(struct padata_instance *pinst,
960 struct attribute *attr, char *buf)
961{
962 struct cpumask *cpumask;
963 ssize_t len;
964
965 mutex_lock(&pinst->lock);
966 if (!strcmp(attr->name, "serial_cpumask"))
967 cpumask = pinst->cpumask.cbcpu;
968 else
969 cpumask = pinst->cpumask.pcpu;
970
971 len = bitmap_scnprintf(buf, PAGE_SIZE, cpumask_bits(cpumask),
972 nr_cpu_ids);
973 if (PAGE_SIZE - len < 2)
974 len = -EINVAL;
975 else
976 len += sprintf(buf + len, "\n");
977
978 mutex_unlock(&pinst->lock);
979 return len;
980}
981
982static ssize_t store_cpumask(struct padata_instance *pinst,
983 struct attribute *attr,
984 const char *buf, size_t count)
985{
986 cpumask_var_t new_cpumask;
987 ssize_t ret;
988 int mask_type;
989
990 if (!alloc_cpumask_var(&new_cpumask, GFP_KERNEL))
991 return -ENOMEM;
992
993 ret = bitmap_parse(buf, count, cpumask_bits(new_cpumask),
994 nr_cpumask_bits);
995 if (ret < 0)
996 goto out;
997
998 mask_type = !strcmp(attr->name, "serial_cpumask") ?
999 PADATA_CPU_SERIAL : PADATA_CPU_PARALLEL;
1000 ret = padata_set_cpumask(pinst, mask_type, new_cpumask);
1001 if (!ret)
1002 ret = count;
1003
1004out:
1005 free_cpumask_var(new_cpumask);
1006 return ret;
1007}
1008
1009#define PADATA_ATTR_RW(_name, _show_name, _store_name) \
1010 static struct padata_sysfs_entry _name##_attr = \
1011 __ATTR(_name, 0644, _show_name, _store_name)
1012#define PADATA_ATTR_RO(_name, _show_name) \
1013 static struct padata_sysfs_entry _name##_attr = \
1014 __ATTR(_name, 0400, _show_name, NULL)
1015
1016PADATA_ATTR_RW(serial_cpumask, show_cpumask, store_cpumask);
1017PADATA_ATTR_RW(parallel_cpumask, show_cpumask, store_cpumask);
1018
1019/*
1020 * Padata sysfs provides the following objects:
1021 * serial_cpumask [RW] - cpumask for serial workers
1022 * parallel_cpumask [RW] - cpumask for parallel workers
1023 */
1024static struct attribute *padata_default_attrs[] = {
1025 &serial_cpumask_attr.attr,
1026 &parallel_cpumask_attr.attr,
1027 NULL,
1028};
1029
1030static ssize_t padata_sysfs_show(struct kobject *kobj,
1031 struct attribute *attr, char *buf)
1032{
1033 struct padata_instance *pinst;
1034 struct padata_sysfs_entry *pentry;
1035 ssize_t ret = -EIO;
1036
1037 pinst = kobj2pinst(kobj);
1038 pentry = attr2pentry(attr);
1039 if (pentry->show)
1040 ret = pentry->show(pinst, attr, buf);
1041
1042 return ret;
1043}
1044
1045static ssize_t padata_sysfs_store(struct kobject *kobj, struct attribute *attr,
1046 const char *buf, size_t count)
1047{
1048 struct padata_instance *pinst;
1049 struct padata_sysfs_entry *pentry;
1050 ssize_t ret = -EIO;
1051
1052 pinst = kobj2pinst(kobj);
1053 pentry = attr2pentry(attr);
1054 if (pentry->show)
1055 ret = pentry->store(pinst, attr, buf, count);
1056
1057 return ret;
1058}
1059
1060static const struct sysfs_ops padata_sysfs_ops = {
1061 .show = padata_sysfs_show,
1062 .store = padata_sysfs_store,
1063};
1064
1065static struct kobj_type padata_attr_type = {
1066 .sysfs_ops = &padata_sysfs_ops,
1067 .default_attrs = padata_default_attrs,
1068 .release = padata_sysfs_release,
1069};
1070
927/** 1071/**
928 * padata_alloc - Allocate and initialize padata instance. 1072 * padata_alloc - Allocate and initialize padata instance.
929 * Use default cpumask(cpu_possible_mask) 1073 * Use default cpumask(cpu_possible_mask)
@@ -989,6 +1133,7 @@ struct padata_instance *__padata_alloc(struct workqueue_struct *wq,
989 put_online_cpus(); 1133 put_online_cpus();
990 1134
991 BLOCKING_INIT_NOTIFIER_HEAD(&pinst->cpumask_change_notifier); 1135 BLOCKING_INIT_NOTIFIER_HEAD(&pinst->cpumask_change_notifier);
1136 kobject_init(&pinst->kobj, &padata_attr_type);
992 mutex_init(&pinst->lock); 1137 mutex_init(&pinst->lock);
993 1138
994 return pinst; 1139 return pinst;
@@ -1011,14 +1156,6 @@ EXPORT_SYMBOL(__padata_alloc);
1011 */ 1156 */
1012void padata_free(struct padata_instance *pinst) 1157void padata_free(struct padata_instance *pinst)
1013{ 1158{
1014#ifdef CONFIG_HOTPLUG_CPU 1159 kobject_put(&pinst->kobj);
1015 unregister_hotcpu_notifier(&pinst->cpu_notifier);
1016#endif
1017
1018 padata_stop(pinst);
1019 padata_free_pd(pinst->pd);
1020 free_cpumask_var(pinst->cpumask.pcpu);
1021 free_cpumask_var(pinst->cpumask.cbcpu);
1022 kfree(pinst);
1023} 1160}
1024EXPORT_SYMBOL(padata_free); 1161EXPORT_SYMBOL(padata_free);