Merge branch 'linus' into sched/urgent
This commit is contained in:
+1
-4
@@ -159,11 +159,8 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
|
||||
return __audit_signal_info(sig, t);
|
||||
return 0;
|
||||
}
|
||||
extern enum audit_state audit_filter_inodes(struct task_struct *,
|
||||
struct audit_context *);
|
||||
extern void audit_set_auditable(struct audit_context *);
|
||||
extern void audit_filter_inodes(struct task_struct *, struct audit_context *);
|
||||
#else
|
||||
#define audit_signal_info(s,t) AUDIT_DISABLED
|
||||
#define audit_filter_inodes(t,c) AUDIT_DISABLED
|
||||
#define audit_set_auditable(c)
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -450,6 +450,7 @@ static void kill_rules(struct audit_tree *tree)
|
||||
audit_log_end(ab);
|
||||
rule->tree = NULL;
|
||||
list_del_rcu(&entry->list);
|
||||
list_del(&entry->rule.list);
|
||||
call_rcu(&entry->rcu, audit_free_rule_rcu);
|
||||
}
|
||||
}
|
||||
@@ -617,7 +618,7 @@ int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
|
||||
|
||||
if (pathname[0] != '/' ||
|
||||
rule->listnr != AUDIT_FILTER_EXIT ||
|
||||
op & ~AUDIT_EQUAL ||
|
||||
op != Audit_equal ||
|
||||
rule->inode_f || rule->watch || rule->tree)
|
||||
return -EINVAL;
|
||||
rule->tree = alloc_tree(pathname);
|
||||
|
||||
+163
-162
@@ -86,6 +86,14 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
|
||||
#error Fix audit_filter_list initialiser
|
||||
#endif
|
||||
};
|
||||
static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = {
|
||||
LIST_HEAD_INIT(audit_rules_list[0]),
|
||||
LIST_HEAD_INIT(audit_rules_list[1]),
|
||||
LIST_HEAD_INIT(audit_rules_list[2]),
|
||||
LIST_HEAD_INIT(audit_rules_list[3]),
|
||||
LIST_HEAD_INIT(audit_rules_list[4]),
|
||||
LIST_HEAD_INIT(audit_rules_list[5]),
|
||||
};
|
||||
|
||||
DEFINE_MUTEX(audit_filter_mutex);
|
||||
|
||||
@@ -244,7 +252,8 @@ static inline int audit_to_inode(struct audit_krule *krule,
|
||||
struct audit_field *f)
|
||||
{
|
||||
if (krule->listnr != AUDIT_FILTER_EXIT ||
|
||||
krule->watch || krule->inode_f || krule->tree)
|
||||
krule->watch || krule->inode_f || krule->tree ||
|
||||
(f->op != Audit_equal && f->op != Audit_not_equal))
|
||||
return -EINVAL;
|
||||
|
||||
krule->inode_f = f;
|
||||
@@ -262,7 +271,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len,
|
||||
|
||||
if (path[0] != '/' || path[len-1] == '/' ||
|
||||
krule->listnr != AUDIT_FILTER_EXIT ||
|
||||
op & ~AUDIT_EQUAL ||
|
||||
op != Audit_equal ||
|
||||
krule->inode_f || krule->watch || krule->tree)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -412,12 +421,32 @@ exit_err:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static u32 audit_ops[] =
|
||||
{
|
||||
[Audit_equal] = AUDIT_EQUAL,
|
||||
[Audit_not_equal] = AUDIT_NOT_EQUAL,
|
||||
[Audit_bitmask] = AUDIT_BIT_MASK,
|
||||
[Audit_bittest] = AUDIT_BIT_TEST,
|
||||
[Audit_lt] = AUDIT_LESS_THAN,
|
||||
[Audit_gt] = AUDIT_GREATER_THAN,
|
||||
[Audit_le] = AUDIT_LESS_THAN_OR_EQUAL,
|
||||
[Audit_ge] = AUDIT_GREATER_THAN_OR_EQUAL,
|
||||
};
|
||||
|
||||
static u32 audit_to_op(u32 op)
|
||||
{
|
||||
u32 n;
|
||||
for (n = Audit_equal; n < Audit_bad && audit_ops[n] != op; n++)
|
||||
;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/* Translate struct audit_rule to kernel's rule respresentation.
|
||||
* Exists for backward compatibility with userspace. */
|
||||
static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
|
||||
{
|
||||
struct audit_entry *entry;
|
||||
struct audit_field *ino_f;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
@@ -427,12 +456,28 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
|
||||
|
||||
for (i = 0; i < rule->field_count; i++) {
|
||||
struct audit_field *f = &entry->rule.fields[i];
|
||||
u32 n;
|
||||
|
||||
n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
|
||||
|
||||
/* Support for legacy operators where
|
||||
* AUDIT_NEGATE bit signifies != and otherwise assumes == */
|
||||
if (n & AUDIT_NEGATE)
|
||||
f->op = Audit_not_equal;
|
||||
else if (!n)
|
||||
f->op = Audit_equal;
|
||||
else
|
||||
f->op = audit_to_op(n);
|
||||
|
||||
entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1;
|
||||
|
||||
f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
|
||||
f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
|
||||
f->val = rule->values[i];
|
||||
|
||||
err = -EINVAL;
|
||||
if (f->op == Audit_bad)
|
||||
goto exit_free;
|
||||
|
||||
switch(f->type) {
|
||||
default:
|
||||
goto exit_free;
|
||||
@@ -454,11 +499,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
|
||||
case AUDIT_EXIT:
|
||||
case AUDIT_SUCCESS:
|
||||
/* bit ops are only useful on syscall args */
|
||||
if (f->op == AUDIT_BIT_MASK ||
|
||||
f->op == AUDIT_BIT_TEST) {
|
||||
err = -EINVAL;
|
||||
if (f->op == Audit_bitmask || f->op == Audit_bittest)
|
||||
goto exit_free;
|
||||
}
|
||||
break;
|
||||
case AUDIT_ARG0:
|
||||
case AUDIT_ARG1:
|
||||
@@ -467,11 +509,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
|
||||
break;
|
||||
/* arch is only allowed to be = or != */
|
||||
case AUDIT_ARCH:
|
||||
if ((f->op != AUDIT_NOT_EQUAL) && (f->op != AUDIT_EQUAL)
|
||||
&& (f->op != AUDIT_NEGATE) && (f->op)) {
|
||||
err = -EINVAL;
|
||||
if (f->op != Audit_not_equal && f->op != Audit_equal)
|
||||
goto exit_free;
|
||||
}
|
||||
entry->rule.arch_f = f;
|
||||
break;
|
||||
case AUDIT_PERM:
|
||||
@@ -488,33 +527,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
|
||||
goto exit_free;
|
||||
break;
|
||||
}
|
||||
|
||||
entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
|
||||
|
||||
/* Support for legacy operators where
|
||||
* AUDIT_NEGATE bit signifies != and otherwise assumes == */
|
||||
if (f->op & AUDIT_NEGATE)
|
||||
f->op = AUDIT_NOT_EQUAL;
|
||||
else if (!f->op)
|
||||
f->op = AUDIT_EQUAL;
|
||||
else if (f->op == AUDIT_OPERATORS) {
|
||||
err = -EINVAL;
|
||||
goto exit_free;
|
||||
}
|
||||
}
|
||||
|
||||
ino_f = entry->rule.inode_f;
|
||||
if (ino_f) {
|
||||
switch(ino_f->op) {
|
||||
case AUDIT_NOT_EQUAL:
|
||||
entry->rule.inode_f = NULL;
|
||||
case AUDIT_EQUAL:
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
goto exit_free;
|
||||
}
|
||||
}
|
||||
if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
|
||||
entry->rule.inode_f = NULL;
|
||||
|
||||
exit_nofree:
|
||||
return entry;
|
||||
@@ -530,7 +546,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||
{
|
||||
int err = 0;
|
||||
struct audit_entry *entry;
|
||||
struct audit_field *ino_f;
|
||||
void *bufp;
|
||||
size_t remain = datasz - sizeof(struct audit_rule_data);
|
||||
int i;
|
||||
@@ -546,11 +561,11 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||
struct audit_field *f = &entry->rule.fields[i];
|
||||
|
||||
err = -EINVAL;
|
||||
if (!(data->fieldflags[i] & AUDIT_OPERATORS) ||
|
||||
data->fieldflags[i] & ~AUDIT_OPERATORS)
|
||||
|
||||
f->op = audit_to_op(data->fieldflags[i]);
|
||||
if (f->op == Audit_bad)
|
||||
goto exit_free;
|
||||
|
||||
f->op = data->fieldflags[i] & AUDIT_OPERATORS;
|
||||
f->type = data->fields[i];
|
||||
f->val = data->values[i];
|
||||
f->lsm_str = NULL;
|
||||
@@ -662,18 +677,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||
}
|
||||
}
|
||||
|
||||
ino_f = entry->rule.inode_f;
|
||||
if (ino_f) {
|
||||
switch(ino_f->op) {
|
||||
case AUDIT_NOT_EQUAL:
|
||||
entry->rule.inode_f = NULL;
|
||||
case AUDIT_EQUAL:
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
goto exit_free;
|
||||
}
|
||||
}
|
||||
if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
|
||||
entry->rule.inode_f = NULL;
|
||||
|
||||
exit_nofree:
|
||||
return entry;
|
||||
@@ -713,10 +718,10 @@ static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
|
||||
rule->fields[i] = krule->fields[i].type;
|
||||
|
||||
if (krule->vers_ops == 1) {
|
||||
if (krule->fields[i].op & AUDIT_NOT_EQUAL)
|
||||
if (krule->fields[i].op == Audit_not_equal)
|
||||
rule->fields[i] |= AUDIT_NEGATE;
|
||||
} else {
|
||||
rule->fields[i] |= krule->fields[i].op;
|
||||
rule->fields[i] |= audit_ops[krule->fields[i].op];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
|
||||
@@ -744,7 +749,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
|
||||
struct audit_field *f = &krule->fields[i];
|
||||
|
||||
data->fields[i] = f->type;
|
||||
data->fieldflags[i] = f->op;
|
||||
data->fieldflags[i] = audit_ops[f->op];
|
||||
switch(f->type) {
|
||||
case AUDIT_SUBJ_USER:
|
||||
case AUDIT_SUBJ_ROLE:
|
||||
@@ -919,6 +924,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
|
||||
new->action = old->action;
|
||||
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
|
||||
new->mask[i] = old->mask[i];
|
||||
new->prio = old->prio;
|
||||
new->buflen = old->buflen;
|
||||
new->inode_f = old->inode_f;
|
||||
new->watch = NULL;
|
||||
@@ -987,9 +993,8 @@ static void audit_update_watch(struct audit_parent *parent,
|
||||
|
||||
/* If the update involves invalidating rules, do the inode-based
|
||||
* filtering now, so we don't omit records. */
|
||||
if (invalidating && current->audit_context &&
|
||||
audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT)
|
||||
audit_set_auditable(current->audit_context);
|
||||
if (invalidating && current->audit_context)
|
||||
audit_filter_inodes(current, current->audit_context);
|
||||
|
||||
nwatch = audit_dupe_watch(owatch);
|
||||
if (IS_ERR(nwatch)) {
|
||||
@@ -1007,12 +1012,15 @@ static void audit_update_watch(struct audit_parent *parent,
|
||||
list_del_rcu(&oentry->list);
|
||||
|
||||
nentry = audit_dupe_rule(&oentry->rule, nwatch);
|
||||
if (IS_ERR(nentry))
|
||||
if (IS_ERR(nentry)) {
|
||||
list_del(&oentry->rule.list);
|
||||
audit_panic("error updating watch, removing");
|
||||
else {
|
||||
} else {
|
||||
int h = audit_hash_ino((u32)ino);
|
||||
list_add(&nentry->rule.rlist, &nwatch->rules);
|
||||
list_add_rcu(&nentry->list, &audit_inode_hash[h]);
|
||||
list_replace(&oentry->rule.list,
|
||||
&nentry->rule.list);
|
||||
}
|
||||
|
||||
call_rcu(&oentry->rcu, audit_free_rule_rcu);
|
||||
@@ -1077,6 +1085,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
|
||||
audit_log_end(ab);
|
||||
}
|
||||
list_del(&r->rlist);
|
||||
list_del(&r->list);
|
||||
list_del_rcu(&e->list);
|
||||
call_rcu(&e->rcu, audit_free_rule_rcu);
|
||||
}
|
||||
@@ -1102,12 +1111,16 @@ static void audit_inotify_unregister(struct list_head *in_list)
|
||||
/* Find an existing audit rule.
|
||||
* Caller must hold audit_filter_mutex to prevent stale rule data. */
|
||||
static struct audit_entry *audit_find_rule(struct audit_entry *entry,
|
||||
struct list_head *list)
|
||||
struct list_head **p)
|
||||
{
|
||||
struct audit_entry *e, *found = NULL;
|
||||
struct list_head *list;
|
||||
int h;
|
||||
|
||||
if (entry->rule.watch) {
|
||||
if (entry->rule.inode_f) {
|
||||
h = audit_hash_ino(entry->rule.inode_f->val);
|
||||
*p = list = &audit_inode_hash[h];
|
||||
} else if (entry->rule.watch) {
|
||||
/* we don't know the inode number, so must walk entire hash */
|
||||
for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
|
||||
list = &audit_inode_hash[h];
|
||||
@@ -1118,6 +1131,8 @@ static struct audit_entry *audit_find_rule(struct audit_entry *entry,
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
} else {
|
||||
*p = list = &audit_filter_list[entry->rule.listnr];
|
||||
}
|
||||
|
||||
list_for_each_entry(e, list, list)
|
||||
@@ -1258,15 +1273,17 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u64 prio_low = ~0ULL/2;
|
||||
static u64 prio_high = ~0ULL/2 - 1;
|
||||
|
||||
/* Add rule to given filterlist if not a duplicate. */
|
||||
static inline int audit_add_rule(struct audit_entry *entry,
|
||||
struct list_head *list)
|
||||
static inline int audit_add_rule(struct audit_entry *entry)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
struct audit_field *inode_f = entry->rule.inode_f;
|
||||
struct audit_watch *watch = entry->rule.watch;
|
||||
struct audit_tree *tree = entry->rule.tree;
|
||||
struct nameidata *ndp = NULL, *ndw = NULL;
|
||||
struct list_head *list;
|
||||
int h, err;
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
int dont_count = 0;
|
||||
@@ -1277,13 +1294,8 @@ static inline int audit_add_rule(struct audit_entry *entry,
|
||||
dont_count = 1;
|
||||
#endif
|
||||
|
||||
if (inode_f) {
|
||||
h = audit_hash_ino(inode_f->val);
|
||||
list = &audit_inode_hash[h];
|
||||
}
|
||||
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
e = audit_find_rule(entry, list);
|
||||
e = audit_find_rule(entry, &list);
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
if (e) {
|
||||
err = -EEXIST;
|
||||
@@ -1319,10 +1331,22 @@ static inline int audit_add_rule(struct audit_entry *entry,
|
||||
}
|
||||
}
|
||||
|
||||
entry->rule.prio = ~0ULL;
|
||||
if (entry->rule.listnr == AUDIT_FILTER_EXIT) {
|
||||
if (entry->rule.flags & AUDIT_FILTER_PREPEND)
|
||||
entry->rule.prio = ++prio_high;
|
||||
else
|
||||
entry->rule.prio = --prio_low;
|
||||
}
|
||||
|
||||
if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
|
||||
list_add(&entry->rule.list,
|
||||
&audit_rules_list[entry->rule.listnr]);
|
||||
list_add_rcu(&entry->list, list);
|
||||
entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
|
||||
} else {
|
||||
list_add_tail(&entry->rule.list,
|
||||
&audit_rules_list[entry->rule.listnr]);
|
||||
list_add_tail_rcu(&entry->list, list);
|
||||
}
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
@@ -1345,15 +1369,14 @@ error:
|
||||
}
|
||||
|
||||
/* Remove an existing rule from filterlist. */
|
||||
static inline int audit_del_rule(struct audit_entry *entry,
|
||||
struct list_head *list)
|
||||
static inline int audit_del_rule(struct audit_entry *entry)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
struct audit_field *inode_f = entry->rule.inode_f;
|
||||
struct audit_watch *watch, *tmp_watch = entry->rule.watch;
|
||||
struct audit_tree *tree = entry->rule.tree;
|
||||
struct list_head *list;
|
||||
LIST_HEAD(inotify_list);
|
||||
int h, ret = 0;
|
||||
int ret = 0;
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
int dont_count = 0;
|
||||
|
||||
@@ -1363,13 +1386,8 @@ static inline int audit_del_rule(struct audit_entry *entry,
|
||||
dont_count = 1;
|
||||
#endif
|
||||
|
||||
if (inode_f) {
|
||||
h = audit_hash_ino(inode_f->val);
|
||||
list = &audit_inode_hash[h];
|
||||
}
|
||||
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
e = audit_find_rule(entry, list);
|
||||
e = audit_find_rule(entry, &list);
|
||||
if (!e) {
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
ret = -ENOENT;
|
||||
@@ -1404,6 +1422,7 @@ static inline int audit_del_rule(struct audit_entry *entry,
|
||||
audit_remove_tree_rule(&e->rule);
|
||||
|
||||
list_del_rcu(&e->list);
|
||||
list_del(&e->rule.list);
|
||||
call_rcu(&e->rcu, audit_free_rule_rcu);
|
||||
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
@@ -1432,30 +1451,16 @@ out:
|
||||
static void audit_list(int pid, int seq, struct sk_buff_head *q)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct audit_entry *entry;
|
||||
struct audit_krule *r;
|
||||
int i;
|
||||
|
||||
/* This is a blocking read, so use audit_filter_mutex instead of rcu
|
||||
* iterator to sync with list writers. */
|
||||
for (i=0; i<AUDIT_NR_FILTERS; i++) {
|
||||
list_for_each_entry(entry, &audit_filter_list[i], list) {
|
||||
list_for_each_entry(r, &audit_rules_list[i], list) {
|
||||
struct audit_rule *rule;
|
||||
|
||||
rule = audit_krule_to_rule(&entry->rule);
|
||||
if (unlikely(!rule))
|
||||
break;
|
||||
skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
|
||||
rule, sizeof(*rule));
|
||||
if (skb)
|
||||
skb_queue_tail(q, skb);
|
||||
kfree(rule);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < AUDIT_INODE_BUCKETS; i++) {
|
||||
list_for_each_entry(entry, &audit_inode_hash[i], list) {
|
||||
struct audit_rule *rule;
|
||||
|
||||
rule = audit_krule_to_rule(&entry->rule);
|
||||
rule = audit_krule_to_rule(r);
|
||||
if (unlikely(!rule))
|
||||
break;
|
||||
skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
|
||||
@@ -1474,30 +1479,16 @@ static void audit_list(int pid, int seq, struct sk_buff_head *q)
|
||||
static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct audit_entry *e;
|
||||
struct audit_krule *r;
|
||||
int i;
|
||||
|
||||
/* This is a blocking read, so use audit_filter_mutex instead of rcu
|
||||
* iterator to sync with list writers. */
|
||||
for (i=0; i<AUDIT_NR_FILTERS; i++) {
|
||||
list_for_each_entry(e, &audit_filter_list[i], list) {
|
||||
list_for_each_entry(r, &audit_rules_list[i], list) {
|
||||
struct audit_rule_data *data;
|
||||
|
||||
data = audit_krule_to_data(&e->rule);
|
||||
if (unlikely(!data))
|
||||
break;
|
||||
skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
|
||||
data, sizeof(*data) + data->buflen);
|
||||
if (skb)
|
||||
skb_queue_tail(q, skb);
|
||||
kfree(data);
|
||||
}
|
||||
}
|
||||
for (i=0; i< AUDIT_INODE_BUCKETS; i++) {
|
||||
list_for_each_entry(e, &audit_inode_hash[i], list) {
|
||||
struct audit_rule_data *data;
|
||||
|
||||
data = audit_krule_to_data(&e->rule);
|
||||
data = audit_krule_to_data(r);
|
||||
if (unlikely(!data))
|
||||
break;
|
||||
skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
|
||||
@@ -1603,8 +1594,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||
if (IS_ERR(entry))
|
||||
return PTR_ERR(entry);
|
||||
|
||||
err = audit_add_rule(entry,
|
||||
&audit_filter_list[entry->rule.listnr]);
|
||||
err = audit_add_rule(entry);
|
||||
audit_log_rule_change(loginuid, sessionid, sid, "add",
|
||||
&entry->rule, !err);
|
||||
|
||||
@@ -1620,8 +1610,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||
if (IS_ERR(entry))
|
||||
return PTR_ERR(entry);
|
||||
|
||||
err = audit_del_rule(entry,
|
||||
&audit_filter_list[entry->rule.listnr]);
|
||||
err = audit_del_rule(entry);
|
||||
audit_log_rule_change(loginuid, sessionid, sid, "remove",
|
||||
&entry->rule, !err);
|
||||
|
||||
@@ -1634,28 +1623,29 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||
return err;
|
||||
}
|
||||
|
||||
int audit_comparator(const u32 left, const u32 op, const u32 right)
|
||||
int audit_comparator(u32 left, u32 op, u32 right)
|
||||
{
|
||||
switch (op) {
|
||||
case AUDIT_EQUAL:
|
||||
case Audit_equal:
|
||||
return (left == right);
|
||||
case AUDIT_NOT_EQUAL:
|
||||
case Audit_not_equal:
|
||||
return (left != right);
|
||||
case AUDIT_LESS_THAN:
|
||||
case Audit_lt:
|
||||
return (left < right);
|
||||
case AUDIT_LESS_THAN_OR_EQUAL:
|
||||
case Audit_le:
|
||||
return (left <= right);
|
||||
case AUDIT_GREATER_THAN:
|
||||
case Audit_gt:
|
||||
return (left > right);
|
||||
case AUDIT_GREATER_THAN_OR_EQUAL:
|
||||
case Audit_ge:
|
||||
return (left >= right);
|
||||
case AUDIT_BIT_MASK:
|
||||
case Audit_bitmask:
|
||||
return (left & right);
|
||||
case AUDIT_BIT_TEST:
|
||||
case Audit_bittest:
|
||||
return ((left & right) == right);
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compare given dentry name with last component in given path,
|
||||
@@ -1778,6 +1768,43 @@ unlock_and_return:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int update_lsm_rule(struct audit_krule *r)
|
||||
{
|
||||
struct audit_entry *entry = container_of(r, struct audit_entry, rule);
|
||||
struct audit_entry *nentry;
|
||||
struct audit_watch *watch;
|
||||
struct audit_tree *tree;
|
||||
int err = 0;
|
||||
|
||||
if (!security_audit_rule_known(r))
|
||||
return 0;
|
||||
|
||||
watch = r->watch;
|
||||
tree = r->tree;
|
||||
nentry = audit_dupe_rule(r, watch);
|
||||
if (IS_ERR(nentry)) {
|
||||
/* save the first error encountered for the
|
||||
* return value */
|
||||
err = PTR_ERR(nentry);
|
||||
audit_panic("error updating LSM filters");
|
||||
if (watch)
|
||||
list_del(&r->rlist);
|
||||
list_del_rcu(&entry->list);
|
||||
list_del(&r->list);
|
||||
} else {
|
||||
if (watch) {
|
||||
list_add(&nentry->rule.rlist, &watch->rules);
|
||||
list_del(&r->rlist);
|
||||
} else if (tree)
|
||||
list_replace_init(&r->rlist, &nentry->rule.rlist);
|
||||
list_replace_rcu(&entry->list, &nentry->list);
|
||||
list_replace(&r->list, &nentry->rule.list);
|
||||
}
|
||||
call_rcu(&entry->rcu, audit_free_rule_rcu);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* This function will re-initialize the lsm_rule field of all applicable rules.
|
||||
* It will traverse the filter lists serarching for rules that contain LSM
|
||||
* specific filter fields. When such a rule is found, it is copied, the
|
||||
@@ -1785,45 +1812,19 @@ unlock_and_return:
|
||||
* updated rule. */
|
||||
int audit_update_lsm_rules(void)
|
||||
{
|
||||
struct audit_entry *entry, *n, *nentry;
|
||||
struct audit_watch *watch;
|
||||
struct audit_tree *tree;
|
||||
struct audit_krule *r, *n;
|
||||
int i, err = 0;
|
||||
|
||||
/* audit_filter_mutex synchronizes the writers */
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
|
||||
for (i = 0; i < AUDIT_NR_FILTERS; i++) {
|
||||
list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
|
||||
if (!security_audit_rule_known(&entry->rule))
|
||||
continue;
|
||||
|
||||
watch = entry->rule.watch;
|
||||
tree = entry->rule.tree;
|
||||
nentry = audit_dupe_rule(&entry->rule, watch);
|
||||
if (IS_ERR(nentry)) {
|
||||
/* save the first error encountered for the
|
||||
* return value */
|
||||
if (!err)
|
||||
err = PTR_ERR(nentry);
|
||||
audit_panic("error updating LSM filters");
|
||||
if (watch)
|
||||
list_del(&entry->rule.rlist);
|
||||
list_del_rcu(&entry->list);
|
||||
} else {
|
||||
if (watch) {
|
||||
list_add(&nentry->rule.rlist,
|
||||
&watch->rules);
|
||||
list_del(&entry->rule.rlist);
|
||||
} else if (tree)
|
||||
list_replace_init(&entry->rule.rlist,
|
||||
&nentry->rule.rlist);
|
||||
list_replace_rcu(&entry->list, &nentry->list);
|
||||
}
|
||||
call_rcu(&entry->rcu, audit_free_rule_rcu);
|
||||
list_for_each_entry_safe(r, n, &audit_rules_list[i], list) {
|
||||
int res = update_lsm_rule(r);
|
||||
if (!err)
|
||||
err = res;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
|
||||
return err;
|
||||
|
||||
+290
-449
File diff suppressed because it is too large
Load Diff
+1
-3
@@ -280,9 +280,7 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = audit_log_capset(pid, new, current_cred());
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
audit_log_capset(pid, new, current_cred());
|
||||
|
||||
return commit_creds(new);
|
||||
|
||||
|
||||
+5
-1
@@ -2945,7 +2945,11 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
|
||||
parent = task_cgroup(tsk, subsys->subsys_id);
|
||||
|
||||
/* Pin the hierarchy */
|
||||
atomic_inc(&parent->root->sb->s_active);
|
||||
if (!atomic_inc_not_zero(&parent->root->sb->s_active)) {
|
||||
/* We race with the final deactivate_super() */
|
||||
mutex_unlock(&cgroup_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Keep the cgroup alive */
|
||||
get_css_set(cg);
|
||||
|
||||
+31
-20
@@ -454,16 +454,16 @@ asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
|
||||
}
|
||||
|
||||
static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
|
||||
unsigned len, cpumask_t *new_mask)
|
||||
unsigned len, struct cpumask *new_mask)
|
||||
{
|
||||
unsigned long *k;
|
||||
|
||||
if (len < sizeof(cpumask_t))
|
||||
memset(new_mask, 0, sizeof(cpumask_t));
|
||||
else if (len > sizeof(cpumask_t))
|
||||
len = sizeof(cpumask_t);
|
||||
if (len < cpumask_size())
|
||||
memset(new_mask, 0, cpumask_size());
|
||||
else if (len > cpumask_size())
|
||||
len = cpumask_size();
|
||||
|
||||
k = cpus_addr(*new_mask);
|
||||
k = cpumask_bits(new_mask);
|
||||
return compat_get_bitmap(k, user_mask_ptr, len * 8);
|
||||
}
|
||||
|
||||
@@ -471,40 +471,51 @@ asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
|
||||
unsigned int len,
|
||||
compat_ulong_t __user *user_mask_ptr)
|
||||
{
|
||||
cpumask_t new_mask;
|
||||
cpumask_var_t new_mask;
|
||||
int retval;
|
||||
|
||||
retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
return sched_setaffinity(pid, &new_mask);
|
||||
retval = compat_get_user_cpu_mask(user_mask_ptr, len, new_mask);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
retval = sched_setaffinity(pid, new_mask);
|
||||
out:
|
||||
free_cpumask_var(new_mask);
|
||||
return retval;
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
|
||||
compat_ulong_t __user *user_mask_ptr)
|
||||
{
|
||||
int ret;
|
||||
cpumask_t mask;
|
||||
cpumask_var_t mask;
|
||||
unsigned long *k;
|
||||
unsigned int min_length = sizeof(cpumask_t);
|
||||
unsigned int min_length = cpumask_size();
|
||||
|
||||
if (NR_CPUS <= BITS_PER_COMPAT_LONG)
|
||||
if (nr_cpu_ids <= BITS_PER_COMPAT_LONG)
|
||||
min_length = sizeof(compat_ulong_t);
|
||||
|
||||
if (len < min_length)
|
||||
return -EINVAL;
|
||||
|
||||
ret = sched_getaffinity(pid, &mask);
|
||||
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sched_getaffinity(pid, mask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
k = cpus_addr(mask);
|
||||
k = cpumask_bits(mask);
|
||||
ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
ret = min_length;
|
||||
|
||||
return min_length;
|
||||
out:
|
||||
free_cpumask_var(mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_compat_itimerspec(struct itimerspec *dst,
|
||||
|
||||
+100
-45
@@ -15,29 +15,8 @@
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
/*
|
||||
* Represents all cpu's present in the system
|
||||
* In systems capable of hotplug, this map could dynamically grow
|
||||
* as new cpu's are detected in the system via any platform specific
|
||||
* method, such as ACPI for e.g.
|
||||
*/
|
||||
cpumask_t cpu_present_map __read_mostly;
|
||||
EXPORT_SYMBOL(cpu_present_map);
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
|
||||
/*
|
||||
* Represents all cpu's that are currently online.
|
||||
*/
|
||||
cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL;
|
||||
EXPORT_SYMBOL(cpu_online_map);
|
||||
|
||||
cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL;
|
||||
EXPORT_SYMBOL(cpu_possible_map);
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
/* Serializes the updates to cpu_online_map, cpu_present_map */
|
||||
#ifdef CONFIG_SMP
|
||||
/* Serializes the updates to cpu_online_mask, cpu_present_mask */
|
||||
static DEFINE_MUTEX(cpu_add_remove_lock);
|
||||
|
||||
static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain);
|
||||
@@ -64,8 +43,6 @@ void __init cpu_hotplug_init(void)
|
||||
cpu_hotplug.refcount = 0;
|
||||
}
|
||||
|
||||
cpumask_t cpu_active_map;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
|
||||
void get_online_cpus(void)
|
||||
@@ -96,7 +73,7 @@ EXPORT_SYMBOL_GPL(put_online_cpus);
|
||||
|
||||
/*
|
||||
* The following two API's must be used when attempting
|
||||
* to serialize the updates to cpu_online_map, cpu_present_map.
|
||||
* to serialize the updates to cpu_online_mask, cpu_present_mask.
|
||||
*/
|
||||
void cpu_maps_update_begin(void)
|
||||
{
|
||||
@@ -217,7 +194,7 @@ static int __ref take_cpu_down(void *_param)
|
||||
static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
|
||||
{
|
||||
int err, nr_calls = 0;
|
||||
cpumask_t old_allowed, tmp;
|
||||
cpumask_var_t old_allowed;
|
||||
void *hcpu = (void *)(long)cpu;
|
||||
unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
|
||||
struct take_cpu_down_param tcd_param = {
|
||||
@@ -231,6 +208,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
|
||||
if (!cpu_online(cpu))
|
||||
return -EINVAL;
|
||||
|
||||
if (!alloc_cpumask_var(&old_allowed, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
cpu_hotplug_begin();
|
||||
err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
|
||||
hcpu, -1, &nr_calls);
|
||||
@@ -245,13 +225,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
|
||||
}
|
||||
|
||||
/* Ensure that we are not runnable on dying cpu */
|
||||
old_allowed = current->cpus_allowed;
|
||||
cpus_setall(tmp);
|
||||
cpu_clear(cpu, tmp);
|
||||
set_cpus_allowed_ptr(current, &tmp);
|
||||
tmp = cpumask_of_cpu(cpu);
|
||||
cpumask_copy(old_allowed, ¤t->cpus_allowed);
|
||||
set_cpus_allowed_ptr(current,
|
||||
cpumask_of(cpumask_any_but(cpu_online_mask, cpu)));
|
||||
|
||||
err = __stop_machine(take_cpu_down, &tcd_param, &tmp);
|
||||
err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
|
||||
if (err) {
|
||||
/* CPU didn't die: tell everyone. Can't complain. */
|
||||
if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
|
||||
@@ -277,7 +255,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
|
||||
check_for_tasks(cpu);
|
||||
|
||||
out_allowed:
|
||||
set_cpus_allowed_ptr(current, &old_allowed);
|
||||
set_cpus_allowed_ptr(current, old_allowed);
|
||||
out_release:
|
||||
cpu_hotplug_done();
|
||||
if (!err) {
|
||||
@@ -285,6 +263,7 @@ out_release:
|
||||
hcpu) == NOTIFY_BAD)
|
||||
BUG();
|
||||
}
|
||||
free_cpumask_var(old_allowed);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -303,7 +282,7 @@ int __ref cpu_down(unsigned int cpu)
|
||||
|
||||
/*
|
||||
* Make sure the all cpus did the reschedule and are not
|
||||
* using stale version of the cpu_active_map.
|
||||
* using stale version of the cpu_active_mask.
|
||||
* This is not strictly necessary becuase stop_machine()
|
||||
* that we run down the line already provides the required
|
||||
* synchronization. But it's really a side effect and we do not
|
||||
@@ -367,7 +346,7 @@ out_notify:
|
||||
int __cpuinit cpu_up(unsigned int cpu)
|
||||
{
|
||||
int err = 0;
|
||||
if (!cpu_isset(cpu, cpu_possible_map)) {
|
||||
if (!cpu_possible(cpu)) {
|
||||
printk(KERN_ERR "can't online cpu %d because it is not "
|
||||
"configured as may-hotadd at boot time\n", cpu);
|
||||
#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
|
||||
@@ -392,25 +371,25 @@ out:
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP_SMP
|
||||
static cpumask_t frozen_cpus;
|
||||
static cpumask_var_t frozen_cpus;
|
||||
|
||||
int disable_nonboot_cpus(void)
|
||||
{
|
||||
int cpu, first_cpu, error = 0;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
first_cpu = first_cpu(cpu_online_map);
|
||||
first_cpu = cpumask_first(cpu_online_mask);
|
||||
/* We take down all of the non-boot CPUs in one shot to avoid races
|
||||
* with the userspace trying to use the CPU hotplug at the same time
|
||||
*/
|
||||
cpus_clear(frozen_cpus);
|
||||
cpumask_clear(frozen_cpus);
|
||||
printk("Disabling non-boot CPUs ...\n");
|
||||
for_each_online_cpu(cpu) {
|
||||
if (cpu == first_cpu)
|
||||
continue;
|
||||
error = _cpu_down(cpu, 1);
|
||||
if (!error) {
|
||||
cpu_set(cpu, frozen_cpus);
|
||||
cpumask_set_cpu(cpu, frozen_cpus);
|
||||
printk("CPU%d is down\n", cpu);
|
||||
} else {
|
||||
printk(KERN_ERR "Error taking CPU%d down: %d\n",
|
||||
@@ -436,11 +415,11 @@ void __ref enable_nonboot_cpus(void)
|
||||
/* Allow everyone to use the CPU hotplug again */
|
||||
cpu_maps_update_begin();
|
||||
cpu_hotplug_disabled = 0;
|
||||
if (cpus_empty(frozen_cpus))
|
||||
if (cpumask_empty(frozen_cpus))
|
||||
goto out;
|
||||
|
||||
printk("Enabling non-boot CPUs ...\n");
|
||||
for_each_cpu_mask_nr(cpu, frozen_cpus) {
|
||||
for_each_cpu(cpu, frozen_cpus) {
|
||||
error = _cpu_up(cpu, 1);
|
||||
if (!error) {
|
||||
printk("CPU%d is up\n", cpu);
|
||||
@@ -448,10 +427,18 @@ void __ref enable_nonboot_cpus(void)
|
||||
}
|
||||
printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
|
||||
}
|
||||
cpus_clear(frozen_cpus);
|
||||
cpumask_clear(frozen_cpus);
|
||||
out:
|
||||
cpu_maps_update_done();
|
||||
}
|
||||
|
||||
static int alloc_frozen_cpus(void)
|
||||
{
|
||||
if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
core_initcall(alloc_frozen_cpus);
|
||||
#endif /* CONFIG_PM_SLEEP_SMP */
|
||||
|
||||
/**
|
||||
@@ -467,7 +454,7 @@ void __cpuinit notify_cpu_starting(unsigned int cpu)
|
||||
unsigned long val = CPU_STARTING;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP_SMP
|
||||
if (cpu_isset(cpu, frozen_cpus))
|
||||
if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus))
|
||||
val = CPU_STARTING_FROZEN;
|
||||
#endif /* CONFIG_PM_SLEEP_SMP */
|
||||
raw_notifier_call_chain(&cpu_chain, val, (void *)(long)cpu);
|
||||
@@ -479,7 +466,7 @@ void __cpuinit notify_cpu_starting(unsigned int cpu)
|
||||
* cpu_bit_bitmap[] is a special, "compressed" data structure that
|
||||
* represents all NR_CPUS bits binary values of 1<<nr.
|
||||
*
|
||||
* It is used by cpumask_of_cpu() to get a constant address to a CPU
|
||||
* It is used by cpumask_of() to get a constant address to a CPU
|
||||
* mask value that has a single bit set only.
|
||||
*/
|
||||
|
||||
@@ -502,3 +489,71 @@ EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
|
||||
|
||||
const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
|
||||
EXPORT_SYMBOL(cpu_all_bits);
|
||||
|
||||
#ifdef CONFIG_INIT_ALL_POSSIBLE
|
||||
static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly
|
||||
= CPU_BITS_ALL;
|
||||
#else
|
||||
static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
#endif
|
||||
const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
|
||||
EXPORT_SYMBOL(cpu_possible_mask);
|
||||
|
||||
static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
|
||||
EXPORT_SYMBOL(cpu_online_mask);
|
||||
|
||||
static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);
|
||||
EXPORT_SYMBOL(cpu_present_mask);
|
||||
|
||||
static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits);
|
||||
EXPORT_SYMBOL(cpu_active_mask);
|
||||
|
||||
void set_cpu_possible(unsigned int cpu, bool possible)
|
||||
{
|
||||
if (possible)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));
|
||||
}
|
||||
|
||||
void set_cpu_present(unsigned int cpu, bool present)
|
||||
{
|
||||
if (present)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits));
|
||||
}
|
||||
|
||||
void set_cpu_online(unsigned int cpu, bool online)
|
||||
{
|
||||
if (online)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
|
||||
}
|
||||
|
||||
void set_cpu_active(unsigned int cpu, bool active)
|
||||
{
|
||||
if (active)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits));
|
||||
}
|
||||
|
||||
void init_cpu_present(const struct cpumask *src)
|
||||
{
|
||||
cpumask_copy(to_cpumask(cpu_present_bits), src);
|
||||
}
|
||||
|
||||
void init_cpu_possible(const struct cpumask *src)
|
||||
{
|
||||
cpumask_copy(to_cpumask(cpu_possible_bits), src);
|
||||
}
|
||||
|
||||
void init_cpu_online(const struct cpumask *src)
|
||||
{
|
||||
cpumask_copy(to_cpumask(cpu_online_bits), src);
|
||||
}
|
||||
|
||||
+2
-2
@@ -896,7 +896,7 @@ static int update_cpumask(struct cpuset *cs, const char *buf)
|
||||
if (!*buf) {
|
||||
cpus_clear(trialcs.cpus_allowed);
|
||||
} else {
|
||||
retval = cpulist_parse(buf, trialcs.cpus_allowed);
|
||||
retval = cpulist_parse(buf, &trialcs.cpus_allowed);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@@ -1482,7 +1482,7 @@ static int cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
|
||||
mask = cs->cpus_allowed;
|
||||
mutex_unlock(&callback_mutex);
|
||||
|
||||
return cpulist_scnprintf(page, PAGE_SIZE, mask);
|
||||
return cpulist_scnprintf(page, PAGE_SIZE, &mask);
|
||||
}
|
||||
|
||||
static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ void dynamic_irq_init(unsigned int irq)
|
||||
desc->irq_count = 0;
|
||||
desc->irqs_unhandled = 0;
|
||||
#ifdef CONFIG_SMP
|
||||
cpus_setall(desc->affinity);
|
||||
cpumask_setall(&desc->affinity);
|
||||
#endif
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
+18
-13
@@ -16,8 +16,15 @@
|
||||
#include "internals.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cpumask_var_t irq_default_affinity;
|
||||
|
||||
cpumask_t irq_default_affinity = CPU_MASK_ALL;
|
||||
static int init_irq_default_affinity(void)
|
||||
{
|
||||
alloc_cpumask_var(&irq_default_affinity, GFP_KERNEL);
|
||||
cpumask_setall(irq_default_affinity);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(init_irq_default_affinity);
|
||||
|
||||
/**
|
||||
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
|
||||
@@ -79,7 +86,7 @@ int irq_can_set_affinity(unsigned int irq)
|
||||
* @cpumask: cpumask
|
||||
*
|
||||
*/
|
||||
int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
|
||||
int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
unsigned long flags;
|
||||
@@ -91,14 +98,14 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
|
||||
|
||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||
if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) {
|
||||
desc->affinity = cpumask;
|
||||
cpumask_copy(&desc->affinity, cpumask);
|
||||
desc->chip->set_affinity(irq, cpumask);
|
||||
} else {
|
||||
desc->status |= IRQ_MOVE_PENDING;
|
||||
desc->pending_mask = cpumask;
|
||||
cpumask_copy(&desc->pending_mask, cpumask);
|
||||
}
|
||||
#else
|
||||
desc->affinity = cpumask;
|
||||
cpumask_copy(&desc->affinity, cpumask);
|
||||
desc->chip->set_affinity(irq, cpumask);
|
||||
#endif
|
||||
desc->status |= IRQ_AFFINITY_SET;
|
||||
@@ -112,26 +119,24 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
|
||||
*/
|
||||
int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
cpumask_t mask;
|
||||
|
||||
if (!irq_can_set_affinity(irq))
|
||||
return 0;
|
||||
|
||||
cpus_and(mask, cpu_online_map, irq_default_affinity);
|
||||
|
||||
/*
|
||||
* Preserve an userspace affinity setup, but make sure that
|
||||
* one of the targets is online.
|
||||
*/
|
||||
if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
|
||||
if (cpus_intersects(desc->affinity, cpu_online_map))
|
||||
mask = desc->affinity;
|
||||
if (cpumask_any_and(&desc->affinity, cpu_online_mask)
|
||||
< nr_cpu_ids)
|
||||
goto set_affinity;
|
||||
else
|
||||
desc->status &= ~IRQ_AFFINITY_SET;
|
||||
}
|
||||
|
||||
desc->affinity = mask;
|
||||
desc->chip->set_affinity(irq, mask);
|
||||
cpumask_and(&desc->affinity, cpu_online_mask, irq_default_affinity);
|
||||
set_affinity:
|
||||
desc->chip->set_affinity(irq, &desc->affinity);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
void move_masked_irq(int irq)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
cpumask_t tmp;
|
||||
|
||||
if (likely(!(desc->status & IRQ_MOVE_PENDING)))
|
||||
return;
|
||||
@@ -19,7 +18,7 @@ void move_masked_irq(int irq)
|
||||
|
||||
desc->status &= ~IRQ_MOVE_PENDING;
|
||||
|
||||
if (unlikely(cpus_empty(desc->pending_mask)))
|
||||
if (unlikely(cpumask_empty(&desc->pending_mask)))
|
||||
return;
|
||||
|
||||
if (!desc->chip->set_affinity)
|
||||
@@ -27,8 +26,6 @@ void move_masked_irq(int irq)
|
||||
|
||||
assert_spin_locked(&desc->lock);
|
||||
|
||||
cpus_and(tmp, desc->pending_mask, cpu_online_map);
|
||||
|
||||
/*
|
||||
* If there was a valid mask to work with, please
|
||||
* do the disable, re-program, enable sequence.
|
||||
@@ -41,10 +38,13 @@ void move_masked_irq(int irq)
|
||||
* For correct operation this depends on the caller
|
||||
* masking the irqs.
|
||||
*/
|
||||
if (likely(!cpus_empty(tmp))) {
|
||||
desc->chip->set_affinity(irq,tmp);
|
||||
if (likely(cpumask_any_and(&desc->pending_mask, cpu_online_mask)
|
||||
< nr_cpu_ids)) {
|
||||
cpumask_and(&desc->affinity,
|
||||
&desc->pending_mask, cpu_online_mask);
|
||||
desc->chip->set_affinity(irq, &desc->affinity);
|
||||
}
|
||||
cpus_clear(desc->pending_mask);
|
||||
cpumask_clear(&desc->pending_mask);
|
||||
}
|
||||
|
||||
void move_native_irq(int irq)
|
||||
|
||||
+38
-19
@@ -20,7 +20,7 @@ static struct proc_dir_entry *root_irq_dir;
|
||||
static int irq_affinity_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc((long)m->private);
|
||||
cpumask_t *mask = &desc->affinity;
|
||||
const struct cpumask *mask = &desc->affinity;
|
||||
|
||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||
if (desc->status & IRQ_MOVE_PENDING)
|
||||
@@ -40,33 +40,42 @@ static ssize_t irq_affinity_proc_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *pos)
|
||||
{
|
||||
unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data;
|
||||
cpumask_t new_value;
|
||||
cpumask_var_t new_value;
|
||||
int err;
|
||||
|
||||
if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity ||
|
||||
irq_balancing_disabled(irq))
|
||||
return -EIO;
|
||||
|
||||
if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
err = cpumask_parse_user(buffer, count, new_value);
|
||||
if (err)
|
||||
return err;
|
||||
goto free_cpumask;
|
||||
|
||||
if (!is_affinity_mask_valid(new_value))
|
||||
return -EINVAL;
|
||||
if (!is_affinity_mask_valid(new_value)) {
|
||||
err = -EINVAL;
|
||||
goto free_cpumask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not allow disabling IRQs completely - it's a too easy
|
||||
* way to make the system unusable accidentally :-) At least
|
||||
* one online CPU still has to be targeted.
|
||||
*/
|
||||
if (!cpus_intersects(new_value, cpu_online_map))
|
||||
if (!cpumask_intersects(new_value, cpu_online_mask)) {
|
||||
/* Special case for empty set - allow the architecture
|
||||
code to set default SMP affinity. */
|
||||
return irq_select_affinity_usr(irq) ? -EINVAL : count;
|
||||
err = irq_select_affinity_usr(irq) ? -EINVAL : count;
|
||||
} else {
|
||||
irq_set_affinity(irq, new_value);
|
||||
err = count;
|
||||
}
|
||||
|
||||
irq_set_affinity(irq, new_value);
|
||||
|
||||
return count;
|
||||
free_cpumask:
|
||||
free_cpumask_var(new_value);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int irq_affinity_proc_open(struct inode *inode, struct file *file)
|
||||
@@ -84,7 +93,7 @@ static const struct file_operations irq_affinity_proc_fops = {
|
||||
|
||||
static int default_affinity_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_cpumask(m, &irq_default_affinity);
|
||||
seq_cpumask(m, irq_default_affinity);
|
||||
seq_putc(m, '\n');
|
||||
return 0;
|
||||
}
|
||||
@@ -92,27 +101,37 @@ static int default_affinity_show(struct seq_file *m, void *v)
|
||||
static ssize_t default_affinity_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
cpumask_t new_value;
|
||||
cpumask_var_t new_value;
|
||||
int err;
|
||||
|
||||
if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
err = cpumask_parse_user(buffer, count, new_value);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
|
||||
if (!is_affinity_mask_valid(new_value))
|
||||
return -EINVAL;
|
||||
if (!is_affinity_mask_valid(new_value)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not allow disabling IRQs completely - it's a too easy
|
||||
* way to make the system unusable accidentally :-) At least
|
||||
* one online CPU still has to be targeted.
|
||||
*/
|
||||
if (!cpus_intersects(new_value, cpu_online_map))
|
||||
return -EINVAL;
|
||||
if (!cpumask_intersects(new_value, cpu_online_mask)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
irq_default_affinity = new_value;
|
||||
cpumask_copy(irq_default_affinity, new_value);
|
||||
err = count;
|
||||
|
||||
return count;
|
||||
out:
|
||||
free_cpumask_var(new_value);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int default_affinity_open(struct inode *inode, struct file *file)
|
||||
|
||||
+1
-1
@@ -1116,7 +1116,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
|
||||
struct elf_prstatus prstatus;
|
||||
u32 *buf;
|
||||
|
||||
if ((cpu < 0) || (cpu >= NR_CPUS))
|
||||
if ((cpu < 0) || (cpu >= nr_cpu_ids))
|
||||
return;
|
||||
|
||||
/* Using ELF notes here is opportunistic.
|
||||
|
||||
@@ -27,7 +27,7 @@ static DECLARE_WORK(poweroff_work, do_poweroff);
|
||||
static void handle_poweroff(int key, struct tty_struct *tty)
|
||||
{
|
||||
/* run sysrq poweroff on boot cpu */
|
||||
schedule_work_on(first_cpu(cpu_online_map), &poweroff_work);
|
||||
schedule_work_on(cpumask_first(cpu_online_mask), &poweroff_work);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_poweroff_op = {
|
||||
|
||||
+25
-13
@@ -45,7 +45,7 @@ static unsigned long prof_len, prof_shift;
|
||||
int prof_on __read_mostly;
|
||||
EXPORT_SYMBOL_GPL(prof_on);
|
||||
|
||||
static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
|
||||
static cpumask_var_t prof_cpu_mask;
|
||||
#ifdef CONFIG_SMP
|
||||
static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
|
||||
static DEFINE_PER_CPU(int, cpu_profile_flip);
|
||||
@@ -113,9 +113,13 @@ int __ref profile_init(void)
|
||||
buffer_bytes = prof_len*sizeof(atomic_t);
|
||||
if (!slab_is_available()) {
|
||||
prof_buffer = alloc_bootmem(buffer_bytes);
|
||||
alloc_bootmem_cpumask_var(&prof_cpu_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!alloc_cpumask_var(&prof_cpu_mask, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL);
|
||||
if (prof_buffer)
|
||||
return 0;
|
||||
@@ -128,6 +132,7 @@ int __ref profile_init(void)
|
||||
if (prof_buffer)
|
||||
return 0;
|
||||
|
||||
free_cpumask_var(prof_cpu_mask);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -386,13 +391,15 @@ out_free:
|
||||
return NOTIFY_BAD;
|
||||
case CPU_ONLINE:
|
||||
case CPU_ONLINE_FROZEN:
|
||||
cpu_set(cpu, prof_cpu_mask);
|
||||
if (prof_cpu_mask != NULL)
|
||||
cpumask_set_cpu(cpu, prof_cpu_mask);
|
||||
break;
|
||||
case CPU_UP_CANCELED:
|
||||
case CPU_UP_CANCELED_FROZEN:
|
||||
case CPU_DEAD:
|
||||
case CPU_DEAD_FROZEN:
|
||||
cpu_clear(cpu, prof_cpu_mask);
|
||||
if (prof_cpu_mask != NULL)
|
||||
cpumask_clear_cpu(cpu, prof_cpu_mask);
|
||||
if (per_cpu(cpu_profile_hits, cpu)[0]) {
|
||||
page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[0]);
|
||||
per_cpu(cpu_profile_hits, cpu)[0] = NULL;
|
||||
@@ -430,7 +437,8 @@ void profile_tick(int type)
|
||||
|
||||
if (type == CPU_PROFILING && timer_hook)
|
||||
timer_hook(regs);
|
||||
if (!user_mode(regs) && cpu_isset(smp_processor_id(), prof_cpu_mask))
|
||||
if (!user_mode(regs) && prof_cpu_mask != NULL &&
|
||||
cpumask_test_cpu(smp_processor_id(), prof_cpu_mask))
|
||||
profile_hit(type, (void *)profile_pc(regs));
|
||||
}
|
||||
|
||||
@@ -442,7 +450,7 @@ void profile_tick(int type)
|
||||
static int prof_cpu_mask_read_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
|
||||
int len = cpumask_scnprintf(page, count, data);
|
||||
if (count - len < 2)
|
||||
return -EINVAL;
|
||||
len += sprintf(page + len, "\n");
|
||||
@@ -452,16 +460,20 @@ static int prof_cpu_mask_read_proc(char *page, char **start, off_t off,
|
||||
static int prof_cpu_mask_write_proc(struct file *file,
|
||||
const char __user *buffer, unsigned long count, void *data)
|
||||
{
|
||||
cpumask_t *mask = (cpumask_t *)data;
|
||||
struct cpumask *mask = data;
|
||||
unsigned long full_count = count, err;
|
||||
cpumask_t new_value;
|
||||
cpumask_var_t new_value;
|
||||
|
||||
if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
err = cpumask_parse_user(buffer, count, new_value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*mask = new_value;
|
||||
return full_count;
|
||||
if (!err) {
|
||||
cpumask_copy(mask, new_value);
|
||||
err = full_count;
|
||||
}
|
||||
free_cpumask_var(new_value);
|
||||
return err;
|
||||
}
|
||||
|
||||
void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
|
||||
@@ -472,7 +484,7 @@ void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
|
||||
entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
|
||||
if (!entry)
|
||||
return;
|
||||
entry->data = (void *)&prof_cpu_mask;
|
||||
entry->data = prof_cpu_mask;
|
||||
entry->read_proc = prof_cpu_mask_read_proc;
|
||||
entry->write_proc = prof_cpu_mask_write_proc;
|
||||
}
|
||||
|
||||
+17
-15
@@ -63,14 +63,14 @@ static struct rcu_ctrlblk rcu_ctrlblk = {
|
||||
.completed = -300,
|
||||
.pending = -300,
|
||||
.lock = __SPIN_LOCK_UNLOCKED(&rcu_ctrlblk.lock),
|
||||
.cpumask = CPU_MASK_NONE,
|
||||
.cpumask = CPU_BITS_NONE,
|
||||
};
|
||||
static struct rcu_ctrlblk rcu_bh_ctrlblk = {
|
||||
.cur = -300,
|
||||
.completed = -300,
|
||||
.pending = -300,
|
||||
.lock = __SPIN_LOCK_UNLOCKED(&rcu_bh_ctrlblk.lock),
|
||||
.cpumask = CPU_MASK_NONE,
|
||||
.cpumask = CPU_BITS_NONE,
|
||||
};
|
||||
|
||||
DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L };
|
||||
@@ -85,7 +85,6 @@ static void force_quiescent_state(struct rcu_data *rdp,
|
||||
struct rcu_ctrlblk *rcp)
|
||||
{
|
||||
int cpu;
|
||||
cpumask_t cpumask;
|
||||
unsigned long flags;
|
||||
|
||||
set_need_resched();
|
||||
@@ -96,10 +95,10 @@ static void force_quiescent_state(struct rcu_data *rdp,
|
||||
* Don't send IPI to itself. With irqs disabled,
|
||||
* rdp->cpu is the current cpu.
|
||||
*
|
||||
* cpu_online_map is updated by the _cpu_down()
|
||||
* cpu_online_mask is updated by the _cpu_down()
|
||||
* using __stop_machine(). Since we're in irqs disabled
|
||||
* section, __stop_machine() is not exectuting, hence
|
||||
* the cpu_online_map is stable.
|
||||
* the cpu_online_mask is stable.
|
||||
*
|
||||
* However, a cpu might have been offlined _just_ before
|
||||
* we disabled irqs while entering here.
|
||||
@@ -107,13 +106,14 @@ static void force_quiescent_state(struct rcu_data *rdp,
|
||||
* notification, leading to the offlined cpu's bit
|
||||
* being set in the rcp->cpumask.
|
||||
*
|
||||
* Hence cpumask = (rcp->cpumask & cpu_online_map) to prevent
|
||||
* Hence cpumask = (rcp->cpumask & cpu_online_mask) to prevent
|
||||
* sending smp_reschedule() to an offlined CPU.
|
||||
*/
|
||||
cpus_and(cpumask, rcp->cpumask, cpu_online_map);
|
||||
cpu_clear(rdp->cpu, cpumask);
|
||||
for_each_cpu_mask_nr(cpu, cpumask)
|
||||
smp_send_reschedule(cpu);
|
||||
for_each_cpu_and(cpu,
|
||||
to_cpumask(rcp->cpumask), cpu_online_mask) {
|
||||
if (cpu != rdp->cpu)
|
||||
smp_send_reschedule(cpu);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&rcp->lock, flags);
|
||||
}
|
||||
@@ -193,7 +193,7 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp)
|
||||
|
||||
printk(KERN_ERR "INFO: RCU detected CPU stalls:");
|
||||
for_each_possible_cpu(cpu) {
|
||||
if (cpu_isset(cpu, rcp->cpumask))
|
||||
if (cpumask_test_cpu(cpu, to_cpumask(rcp->cpumask)))
|
||||
printk(" %d", cpu);
|
||||
}
|
||||
printk(" (detected by %d, t=%ld jiffies)\n",
|
||||
@@ -221,7 +221,8 @@ static void check_cpu_stall(struct rcu_ctrlblk *rcp)
|
||||
long delta;
|
||||
|
||||
delta = jiffies - rcp->jiffies_stall;
|
||||
if (cpu_isset(smp_processor_id(), rcp->cpumask) && delta >= 0) {
|
||||
if (cpumask_test_cpu(smp_processor_id(), to_cpumask(rcp->cpumask)) &&
|
||||
delta >= 0) {
|
||||
|
||||
/* We haven't checked in, so go dump stack. */
|
||||
print_cpu_stall(rcp);
|
||||
@@ -393,7 +394,8 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp)
|
||||
* unnecessarily.
|
||||
*/
|
||||
smp_mb();
|
||||
cpus_andnot(rcp->cpumask, cpu_online_map, nohz_cpu_mask);
|
||||
cpumask_andnot(to_cpumask(rcp->cpumask),
|
||||
cpu_online_mask, nohz_cpu_mask);
|
||||
|
||||
rcp->signaled = 0;
|
||||
}
|
||||
@@ -406,8 +408,8 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp)
|
||||
*/
|
||||
static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp)
|
||||
{
|
||||
cpu_clear(cpu, rcp->cpumask);
|
||||
if (cpus_empty(rcp->cpumask)) {
|
||||
cpumask_clear_cpu(cpu, to_cpumask(rcp->cpumask));
|
||||
if (cpumask_empty(to_cpumask(rcp->cpumask))) {
|
||||
/* batch completed ! */
|
||||
rcp->completed = rcp->cur;
|
||||
rcu_start_batch(rcp);
|
||||
|
||||
+10
-9
@@ -164,7 +164,8 @@ static char *rcu_try_flip_state_names[] =
|
||||
{ "idle", "waitack", "waitzero", "waitmb" };
|
||||
#endif /* #ifdef CONFIG_RCU_TRACE */
|
||||
|
||||
static cpumask_t rcu_cpu_online_map __read_mostly = CPU_MASK_NONE;
|
||||
static DECLARE_BITMAP(rcu_cpu_online_map, NR_CPUS) __read_mostly
|
||||
= CPU_BITS_NONE;
|
||||
|
||||
/*
|
||||
* Enum and per-CPU flag to determine when each CPU has seen
|
||||
@@ -758,7 +759,7 @@ rcu_try_flip_idle(void)
|
||||
|
||||
/* Now ask each CPU for acknowledgement of the flip. */
|
||||
|
||||
for_each_cpu_mask_nr(cpu, rcu_cpu_online_map) {
|
||||
for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map)) {
|
||||
per_cpu(rcu_flip_flag, cpu) = rcu_flipped;
|
||||
dyntick_save_progress_counter(cpu);
|
||||
}
|
||||
@@ -776,7 +777,7 @@ rcu_try_flip_waitack(void)
|
||||
int cpu;
|
||||
|
||||
RCU_TRACE_ME(rcupreempt_trace_try_flip_a1);
|
||||
for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
|
||||
for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map))
|
||||
if (rcu_try_flip_waitack_needed(cpu) &&
|
||||
per_cpu(rcu_flip_flag, cpu) != rcu_flip_seen) {
|
||||
RCU_TRACE_ME(rcupreempt_trace_try_flip_ae1);
|
||||
@@ -808,7 +809,7 @@ rcu_try_flip_waitzero(void)
|
||||
/* Check to see if the sum of the "last" counters is zero. */
|
||||
|
||||
RCU_TRACE_ME(rcupreempt_trace_try_flip_z1);
|
||||
for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
|
||||
for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map))
|
||||
sum += RCU_DATA_CPU(cpu)->rcu_flipctr[lastidx];
|
||||
if (sum != 0) {
|
||||
RCU_TRACE_ME(rcupreempt_trace_try_flip_ze1);
|
||||
@@ -823,7 +824,7 @@ rcu_try_flip_waitzero(void)
|
||||
smp_mb(); /* ^^^^^^^^^^^^ */
|
||||
|
||||
/* Call for a memory barrier from each CPU. */
|
||||
for_each_cpu_mask_nr(cpu, rcu_cpu_online_map) {
|
||||
for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map)) {
|
||||
per_cpu(rcu_mb_flag, cpu) = rcu_mb_needed;
|
||||
dyntick_save_progress_counter(cpu);
|
||||
}
|
||||
@@ -843,7 +844,7 @@ rcu_try_flip_waitmb(void)
|
||||
int cpu;
|
||||
|
||||
RCU_TRACE_ME(rcupreempt_trace_try_flip_m1);
|
||||
for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
|
||||
for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map))
|
||||
if (rcu_try_flip_waitmb_needed(cpu) &&
|
||||
per_cpu(rcu_mb_flag, cpu) != rcu_mb_done) {
|
||||
RCU_TRACE_ME(rcupreempt_trace_try_flip_me1);
|
||||
@@ -1032,7 +1033,7 @@ void rcu_offline_cpu(int cpu)
|
||||
RCU_DATA_CPU(cpu)->rcu_flipctr[0] = 0;
|
||||
RCU_DATA_CPU(cpu)->rcu_flipctr[1] = 0;
|
||||
|
||||
cpu_clear(cpu, rcu_cpu_online_map);
|
||||
cpumask_clear_cpu(cpu, to_cpumask(rcu_cpu_online_map));
|
||||
|
||||
spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
|
||||
|
||||
@@ -1072,7 +1073,7 @@ void __cpuinit rcu_online_cpu(int cpu)
|
||||
struct rcu_data *rdp;
|
||||
|
||||
spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
|
||||
cpu_set(cpu, rcu_cpu_online_map);
|
||||
cpumask_set_cpu(cpu, to_cpumask(rcu_cpu_online_map));
|
||||
spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
|
||||
|
||||
/*
|
||||
@@ -1430,7 +1431,7 @@ void __init __rcu_init(void)
|
||||
* We don't need protection against CPU-Hotplug here
|
||||
* since
|
||||
* a) If a CPU comes online while we are iterating over the
|
||||
* cpu_online_map below, we would only end up making a
|
||||
* cpu_online_mask below, we would only end up making a
|
||||
* duplicate call to rcu_online_cpu() which sets the corresponding
|
||||
* CPU's mask in the rcu_cpu_online_map.
|
||||
*
|
||||
|
||||
+15
-12
@@ -868,49 +868,52 @@ static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
|
||||
*/
|
||||
static void rcu_torture_shuffle_tasks(void)
|
||||
{
|
||||
cpumask_t tmp_mask;
|
||||
cpumask_var_t tmp_mask;
|
||||
int i;
|
||||
|
||||
cpus_setall(tmp_mask);
|
||||
if (!alloc_cpumask_var(&tmp_mask, GFP_KERNEL))
|
||||
BUG();
|
||||
|
||||
cpumask_setall(tmp_mask);
|
||||
get_online_cpus();
|
||||
|
||||
/* No point in shuffling if there is only one online CPU (ex: UP) */
|
||||
if (num_online_cpus() == 1) {
|
||||
put_online_cpus();
|
||||
return;
|
||||
}
|
||||
if (num_online_cpus() == 1)
|
||||
goto out;
|
||||
|
||||
if (rcu_idle_cpu != -1)
|
||||
cpu_clear(rcu_idle_cpu, tmp_mask);
|
||||
cpumask_clear_cpu(rcu_idle_cpu, tmp_mask);
|
||||
|
||||
set_cpus_allowed_ptr(current, &tmp_mask);
|
||||
set_cpus_allowed_ptr(current, tmp_mask);
|
||||
|
||||
if (reader_tasks) {
|
||||
for (i = 0; i < nrealreaders; i++)
|
||||
if (reader_tasks[i])
|
||||
set_cpus_allowed_ptr(reader_tasks[i],
|
||||
&tmp_mask);
|
||||
tmp_mask);
|
||||
}
|
||||
|
||||
if (fakewriter_tasks) {
|
||||
for (i = 0; i < nfakewriters; i++)
|
||||
if (fakewriter_tasks[i])
|
||||
set_cpus_allowed_ptr(fakewriter_tasks[i],
|
||||
&tmp_mask);
|
||||
tmp_mask);
|
||||
}
|
||||
|
||||
if (writer_task)
|
||||
set_cpus_allowed_ptr(writer_task, &tmp_mask);
|
||||
set_cpus_allowed_ptr(writer_task, tmp_mask);
|
||||
|
||||
if (stats_task)
|
||||
set_cpus_allowed_ptr(stats_task, &tmp_mask);
|
||||
set_cpus_allowed_ptr(stats_task, tmp_mask);
|
||||
|
||||
if (rcu_idle_cpu == -1)
|
||||
rcu_idle_cpu = num_online_cpus() - 1;
|
||||
else
|
||||
rcu_idle_cpu--;
|
||||
|
||||
out:
|
||||
put_online_cpus();
|
||||
free_cpumask_var(tmp_mask);
|
||||
}
|
||||
|
||||
/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
|
||||
|
||||
+623
-467
File diff suppressed because it is too large
Load Diff
+28
-11
@@ -67,24 +67,21 @@ static int convert_prio(int prio)
|
||||
* Returns: (int)bool - CPUs were found
|
||||
*/
|
||||
int cpupri_find(struct cpupri *cp, struct task_struct *p,
|
||||
cpumask_t *lowest_mask)
|
||||
struct cpumask *lowest_mask)
|
||||
{
|
||||
int idx = 0;
|
||||
int task_pri = convert_prio(p->prio);
|
||||
|
||||
for_each_cpupri_active(cp->pri_active, idx) {
|
||||
struct cpupri_vec *vec = &cp->pri_to_cpu[idx];
|
||||
cpumask_t mask;
|
||||
|
||||
if (idx >= task_pri)
|
||||
break;
|
||||
|
||||
cpus_and(mask, p->cpus_allowed, vec->mask);
|
||||
|
||||
if (cpus_empty(mask))
|
||||
if (cpumask_any_and(&p->cpus_allowed, vec->mask) >= nr_cpu_ids)
|
||||
continue;
|
||||
|
||||
*lowest_mask = mask;
|
||||
cpumask_and(lowest_mask, &p->cpus_allowed, vec->mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -126,7 +123,7 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri)
|
||||
vec->count--;
|
||||
if (!vec->count)
|
||||
clear_bit(oldpri, cp->pri_active);
|
||||
cpu_clear(cpu, vec->mask);
|
||||
cpumask_clear_cpu(cpu, vec->mask);
|
||||
|
||||
spin_unlock_irqrestore(&vec->lock, flags);
|
||||
}
|
||||
@@ -136,7 +133,7 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri)
|
||||
|
||||
spin_lock_irqsave(&vec->lock, flags);
|
||||
|
||||
cpu_set(cpu, vec->mask);
|
||||
cpumask_set_cpu(cpu, vec->mask);
|
||||
vec->count++;
|
||||
if (vec->count == 1)
|
||||
set_bit(newpri, cp->pri_active);
|
||||
@@ -150,10 +147,11 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri)
|
||||
/**
|
||||
* cpupri_init - initialize the cpupri structure
|
||||
* @cp: The cpupri context
|
||||
* @bootmem: true if allocations need to use bootmem
|
||||
*
|
||||
* Returns: (void)
|
||||
* Returns: -ENOMEM if memory fails.
|
||||
*/
|
||||
void cpupri_init(struct cpupri *cp)
|
||||
int cpupri_init(struct cpupri *cp, bool bootmem)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -164,11 +162,30 @@ void cpupri_init(struct cpupri *cp)
|
||||
|
||||
spin_lock_init(&vec->lock);
|
||||
vec->count = 0;
|
||||
cpus_clear(vec->mask);
|
||||
if (bootmem)
|
||||
alloc_bootmem_cpumask_var(&vec->mask);
|
||||
else if (!alloc_cpumask_var(&vec->mask, GFP_KERNEL))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for_each_possible_cpu(i)
|
||||
cp->cpu_to_pri[i] = CPUPRI_INVALID;
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
for (i--; i >= 0; i--)
|
||||
free_cpumask_var(cp->pri_to_cpu[i].mask);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpupri_cleanup - clean up the cpupri structure
|
||||
* @cp: The cpupri context
|
||||
*/
|
||||
void cpupri_cleanup(struct cpupri *cp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CPUPRI_NR_PRIORITIES; i++)
|
||||
free_cpumask_var(cp->pri_to_cpu[i].mask);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
struct cpupri_vec {
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
cpumask_t mask;
|
||||
cpumask_var_t mask;
|
||||
};
|
||||
|
||||
struct cpupri {
|
||||
@@ -27,7 +27,8 @@ struct cpupri {
|
||||
int cpupri_find(struct cpupri *cp,
|
||||
struct task_struct *p, cpumask_t *lowest_mask);
|
||||
void cpupri_set(struct cpupri *cp, int cpu, int pri);
|
||||
void cpupri_init(struct cpupri *cp);
|
||||
int cpupri_init(struct cpupri *cp, bool bootmem);
|
||||
void cpupri_cleanup(struct cpupri *cp);
|
||||
#else
|
||||
#define cpupri_set(cp, cpu, pri) do { } while (0)
|
||||
#define cpupri_init() do { } while (0)
|
||||
|
||||
+24
-8
@@ -1013,16 +1013,33 @@ static void yield_task_fair(struct rq *rq)
|
||||
* search starts with cpus closest then further out as needed,
|
||||
* so we always favor a closer, idle cpu.
|
||||
* Domains may include CPUs that are not usable for migration,
|
||||
* hence we need to mask them out (cpu_active_map)
|
||||
* hence we need to mask them out (cpu_active_mask)
|
||||
*
|
||||
* Returns the CPU we should wake onto.
|
||||
*/
|
||||
#if defined(ARCH_HAS_SCHED_WAKE_IDLE)
|
||||
static int wake_idle(int cpu, struct task_struct *p)
|
||||
{
|
||||
cpumask_t tmp;
|
||||
struct sched_domain *sd;
|
||||
int i;
|
||||
unsigned int chosen_wakeup_cpu;
|
||||
int this_cpu;
|
||||
|
||||
/*
|
||||
* At POWERSAVINGS_BALANCE_WAKEUP level, if both this_cpu and prev_cpu
|
||||
* are idle and this is not a kernel thread and this task's affinity
|
||||
* allows it to be moved to preferred cpu, then just move!
|
||||
*/
|
||||
|
||||
this_cpu = smp_processor_id();
|
||||
chosen_wakeup_cpu =
|
||||
cpu_rq(this_cpu)->rd->sched_mc_preferred_wakeup_cpu;
|
||||
|
||||
if (sched_mc_power_savings >= POWERSAVINGS_BALANCE_WAKEUP &&
|
||||
idle_cpu(cpu) && idle_cpu(this_cpu) &&
|
||||
p->mm && !(p->flags & PF_KTHREAD) &&
|
||||
cpu_isset(chosen_wakeup_cpu, p->cpus_allowed))
|
||||
return chosen_wakeup_cpu;
|
||||
|
||||
/*
|
||||
* If it is idle, then it is the best cpu to run this task.
|
||||
@@ -1040,10 +1057,9 @@ static int wake_idle(int cpu, struct task_struct *p)
|
||||
if ((sd->flags & SD_WAKE_IDLE)
|
||||
|| ((sd->flags & SD_WAKE_IDLE_FAR)
|
||||
&& !task_hot(p, task_rq(p)->clock, sd))) {
|
||||
cpus_and(tmp, sd->span, p->cpus_allowed);
|
||||
cpus_and(tmp, tmp, cpu_active_map);
|
||||
for_each_cpu_mask_nr(i, tmp) {
|
||||
if (idle_cpu(i)) {
|
||||
for_each_cpu_and(i, sched_domain_span(sd),
|
||||
&p->cpus_allowed) {
|
||||
if (cpu_active(i) && idle_cpu(i)) {
|
||||
if (i != task_cpu(p)) {
|
||||
schedstat_inc(p,
|
||||
se.nr_wakeups_idle);
|
||||
@@ -1236,13 +1252,13 @@ static int select_task_rq_fair(struct task_struct *p, int sync)
|
||||
* this_cpu and prev_cpu are present in:
|
||||
*/
|
||||
for_each_domain(this_cpu, sd) {
|
||||
if (cpu_isset(prev_cpu, sd->span)) {
|
||||
if (cpumask_test_cpu(prev_cpu, sched_domain_span(sd))) {
|
||||
this_sd = sd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
|
||||
if (unlikely(!cpumask_test_cpu(this_cpu, &p->cpus_allowed)))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
|
||||
+45
-29
@@ -15,7 +15,7 @@ static inline void rt_set_overload(struct rq *rq)
|
||||
if (!rq->online)
|
||||
return;
|
||||
|
||||
cpu_set(rq->cpu, rq->rd->rto_mask);
|
||||
cpumask_set_cpu(rq->cpu, rq->rd->rto_mask);
|
||||
/*
|
||||
* Make sure the mask is visible before we set
|
||||
* the overload count. That is checked to determine
|
||||
@@ -34,7 +34,7 @@ static inline void rt_clear_overload(struct rq *rq)
|
||||
|
||||
/* the order here really doesn't matter */
|
||||
atomic_dec(&rq->rd->rto_count);
|
||||
cpu_clear(rq->cpu, rq->rd->rto_mask);
|
||||
cpumask_clear_cpu(rq->cpu, rq->rd->rto_mask);
|
||||
}
|
||||
|
||||
static void update_rt_migration(struct rq *rq)
|
||||
@@ -139,14 +139,14 @@ static int rt_se_boosted(struct sched_rt_entity *rt_se)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static inline cpumask_t sched_rt_period_mask(void)
|
||||
static inline const struct cpumask *sched_rt_period_mask(void)
|
||||
{
|
||||
return cpu_rq(smp_processor_id())->rd->span;
|
||||
}
|
||||
#else
|
||||
static inline cpumask_t sched_rt_period_mask(void)
|
||||
static inline const struct cpumask *sched_rt_period_mask(void)
|
||||
{
|
||||
return cpu_online_map;
|
||||
return cpu_online_mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -212,9 +212,9 @@ static inline int rt_rq_throttled(struct rt_rq *rt_rq)
|
||||
return rt_rq->rt_throttled;
|
||||
}
|
||||
|
||||
static inline cpumask_t sched_rt_period_mask(void)
|
||||
static inline const struct cpumask *sched_rt_period_mask(void)
|
||||
{
|
||||
return cpu_online_map;
|
||||
return cpu_online_mask;
|
||||
}
|
||||
|
||||
static inline
|
||||
@@ -241,11 +241,11 @@ static int do_balance_runtime(struct rt_rq *rt_rq)
|
||||
int i, weight, more = 0;
|
||||
u64 rt_period;
|
||||
|
||||
weight = cpus_weight(rd->span);
|
||||
weight = cpumask_weight(rd->span);
|
||||
|
||||
spin_lock(&rt_b->rt_runtime_lock);
|
||||
rt_period = ktime_to_ns(rt_b->rt_period);
|
||||
for_each_cpu_mask_nr(i, rd->span) {
|
||||
for_each_cpu(i, rd->span) {
|
||||
struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i);
|
||||
s64 diff;
|
||||
|
||||
@@ -324,7 +324,7 @@ static void __disable_runtime(struct rq *rq)
|
||||
/*
|
||||
* Greedy reclaim, take back as much as we can.
|
||||
*/
|
||||
for_each_cpu_mask(i, rd->span) {
|
||||
for_each_cpu(i, rd->span) {
|
||||
struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i);
|
||||
s64 diff;
|
||||
|
||||
@@ -429,13 +429,13 @@ static inline int balance_runtime(struct rt_rq *rt_rq)
|
||||
static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun)
|
||||
{
|
||||
int i, idle = 1;
|
||||
cpumask_t span;
|
||||
const struct cpumask *span;
|
||||
|
||||
if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF)
|
||||
return 1;
|
||||
|
||||
span = sched_rt_period_mask();
|
||||
for_each_cpu_mask(i, span) {
|
||||
for_each_cpu(i, span) {
|
||||
int enqueue = 0;
|
||||
struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i);
|
||||
struct rq *rq = rq_of_rt_rq(rt_rq);
|
||||
@@ -805,17 +805,20 @@ static int select_task_rq_rt(struct task_struct *p, int sync)
|
||||
|
||||
static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
|
||||
{
|
||||
cpumask_t mask;
|
||||
cpumask_var_t mask;
|
||||
|
||||
if (rq->curr->rt.nr_cpus_allowed == 1)
|
||||
return;
|
||||
|
||||
if (p->rt.nr_cpus_allowed != 1
|
||||
&& cpupri_find(&rq->rd->cpupri, p, &mask))
|
||||
if (!alloc_cpumask_var(&mask, GFP_ATOMIC))
|
||||
return;
|
||||
|
||||
if (!cpupri_find(&rq->rd->cpupri, rq->curr, &mask))
|
||||
return;
|
||||
if (p->rt.nr_cpus_allowed != 1
|
||||
&& cpupri_find(&rq->rd->cpupri, p, mask))
|
||||
goto free;
|
||||
|
||||
if (!cpupri_find(&rq->rd->cpupri, rq->curr, mask))
|
||||
goto free;
|
||||
|
||||
/*
|
||||
* There appears to be other cpus that can accept
|
||||
@@ -824,6 +827,8 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
|
||||
*/
|
||||
requeue_task_rt(rq, p, 1);
|
||||
resched_task(rq->curr);
|
||||
free:
|
||||
free_cpumask_var(mask);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
@@ -914,7 +919,7 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep);
|
||||
static int pick_rt_task(struct rq *rq, struct task_struct *p, int cpu)
|
||||
{
|
||||
if (!task_running(rq, p) &&
|
||||
(cpu < 0 || cpu_isset(cpu, p->cpus_allowed)) &&
|
||||
(cpu < 0 || cpumask_test_cpu(cpu, &p->cpus_allowed)) &&
|
||||
(p->rt.nr_cpus_allowed > 1))
|
||||
return 1;
|
||||
return 0;
|
||||
@@ -953,7 +958,7 @@ static struct task_struct *pick_next_highest_task_rt(struct rq *rq, int cpu)
|
||||
return next;
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(cpumask_t, local_cpu_mask);
|
||||
static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask);
|
||||
|
||||
static inline int pick_optimal_cpu(int this_cpu, cpumask_t *mask)
|
||||
{
|
||||
@@ -973,7 +978,7 @@ static inline int pick_optimal_cpu(int this_cpu, cpumask_t *mask)
|
||||
static int find_lowest_rq(struct task_struct *task)
|
||||
{
|
||||
struct sched_domain *sd;
|
||||
cpumask_t *lowest_mask = &__get_cpu_var(local_cpu_mask);
|
||||
struct cpumask *lowest_mask = __get_cpu_var(local_cpu_mask);
|
||||
int this_cpu = smp_processor_id();
|
||||
int cpu = task_cpu(task);
|
||||
|
||||
@@ -988,7 +993,7 @@ static int find_lowest_rq(struct task_struct *task)
|
||||
* I guess we might want to change cpupri_find() to ignore those
|
||||
* in the first place.
|
||||
*/
|
||||
cpus_and(*lowest_mask, *lowest_mask, cpu_active_map);
|
||||
cpumask_and(lowest_mask, lowest_mask, cpu_active_mask);
|
||||
|
||||
/*
|
||||
* At this point we have built a mask of cpus representing the
|
||||
@@ -998,7 +1003,7 @@ static int find_lowest_rq(struct task_struct *task)
|
||||
* We prioritize the last cpu that the task executed on since
|
||||
* it is most likely cache-hot in that location.
|
||||
*/
|
||||
if (cpu_isset(cpu, *lowest_mask))
|
||||
if (cpumask_test_cpu(cpu, lowest_mask))
|
||||
return cpu;
|
||||
|
||||
/*
|
||||
@@ -1013,7 +1018,8 @@ static int find_lowest_rq(struct task_struct *task)
|
||||
cpumask_t domain_mask;
|
||||
int best_cpu;
|
||||
|
||||
cpus_and(domain_mask, sd->span, *lowest_mask);
|
||||
cpumask_and(&domain_mask, sched_domain_span(sd),
|
||||
lowest_mask);
|
||||
|
||||
best_cpu = pick_optimal_cpu(this_cpu,
|
||||
&domain_mask);
|
||||
@@ -1054,8 +1060,8 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
|
||||
* Also make sure that it wasn't scheduled on its rq.
|
||||
*/
|
||||
if (unlikely(task_rq(task) != rq ||
|
||||
!cpu_isset(lowest_rq->cpu,
|
||||
task->cpus_allowed) ||
|
||||
!cpumask_test_cpu(lowest_rq->cpu,
|
||||
&task->cpus_allowed) ||
|
||||
task_running(rq, task) ||
|
||||
!task->se.on_rq)) {
|
||||
|
||||
@@ -1176,7 +1182,7 @@ static int pull_rt_task(struct rq *this_rq)
|
||||
|
||||
next = pick_next_task_rt(this_rq);
|
||||
|
||||
for_each_cpu_mask_nr(cpu, this_rq->rd->rto_mask) {
|
||||
for_each_cpu(cpu, this_rq->rd->rto_mask) {
|
||||
if (this_cpu == cpu)
|
||||
continue;
|
||||
|
||||
@@ -1305,9 +1311,9 @@ move_one_task_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
|
||||
}
|
||||
|
||||
static void set_cpus_allowed_rt(struct task_struct *p,
|
||||
const cpumask_t *new_mask)
|
||||
const struct cpumask *new_mask)
|
||||
{
|
||||
int weight = cpus_weight(*new_mask);
|
||||
int weight = cpumask_weight(new_mask);
|
||||
|
||||
BUG_ON(!rt_task(p));
|
||||
|
||||
@@ -1328,7 +1334,7 @@ static void set_cpus_allowed_rt(struct task_struct *p,
|
||||
update_rt_migration(rq);
|
||||
}
|
||||
|
||||
p->cpus_allowed = *new_mask;
|
||||
cpumask_copy(&p->cpus_allowed, new_mask);
|
||||
p->rt.nr_cpus_allowed = weight;
|
||||
}
|
||||
|
||||
@@ -1371,6 +1377,15 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p,
|
||||
if (!rq->rt.rt_nr_running)
|
||||
pull_rt_task(rq);
|
||||
}
|
||||
|
||||
static inline void init_sched_rt_class(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for_each_possible_cpu(i)
|
||||
alloc_cpumask_var_node(&per_cpu(local_cpu_mask, i),
|
||||
GFP_KERNEL, cpu_to_node(i));
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
@@ -1541,3 +1556,4 @@ static void print_rt_stats(struct seq_file *m, int cpu)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
#endif /* CONFIG_SCHED_DEBUG */
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ static int show_schedstat(struct seq_file *seq, void *v)
|
||||
for_each_domain(cpu, sd) {
|
||||
enum cpu_idle_type itype;
|
||||
|
||||
cpumask_scnprintf(mask_str, mask_len, sd->span);
|
||||
cpumask_scnprintf(mask_str, mask_len,
|
||||
sched_domain_span(sd));
|
||||
seq_printf(seq, "domain%d %s", dcount++, mask_str);
|
||||
for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
|
||||
itype++) {
|
||||
|
||||
+54
-89
@@ -24,8 +24,8 @@ struct call_function_data {
|
||||
struct call_single_data csd;
|
||||
spinlock_t lock;
|
||||
unsigned int refs;
|
||||
cpumask_t cpumask;
|
||||
struct rcu_head rcu_head;
|
||||
unsigned long cpumask_bits[];
|
||||
};
|
||||
|
||||
struct call_single_queue {
|
||||
@@ -110,13 +110,13 @@ void generic_smp_call_function_interrupt(void)
|
||||
list_for_each_entry_rcu(data, &call_function_queue, csd.list) {
|
||||
int refs;
|
||||
|
||||
if (!cpu_isset(cpu, data->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, to_cpumask(data->cpumask_bits)))
|
||||
continue;
|
||||
|
||||
data->csd.func(data->csd.info);
|
||||
|
||||
spin_lock(&data->lock);
|
||||
cpu_clear(cpu, data->cpumask);
|
||||
cpumask_clear_cpu(cpu, to_cpumask(data->cpumask_bits));
|
||||
WARN_ON(data->refs == 0);
|
||||
data->refs--;
|
||||
refs = data->refs;
|
||||
@@ -223,7 +223,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
|
||||
local_irq_save(flags);
|
||||
func(info);
|
||||
local_irq_restore(flags);
|
||||
} else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) {
|
||||
} else if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) {
|
||||
struct call_single_data *data = NULL;
|
||||
|
||||
if (!wait) {
|
||||
@@ -266,51 +266,19 @@ void __smp_call_function_single(int cpu, struct call_single_data *data)
|
||||
generic_exec_single(cpu, data);
|
||||
}
|
||||
|
||||
/* Dummy function */
|
||||
static void quiesce_dummy(void *unused)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure stack based data used in call function mask is safe to free.
|
||||
*
|
||||
* This is needed by smp_call_function_mask when using on-stack data, because
|
||||
* a single call function queue is shared by all CPUs, and any CPU may pick up
|
||||
* the data item on the queue at any time before it is deleted. So we need to
|
||||
* ensure that all CPUs have transitioned through a quiescent state after
|
||||
* this call.
|
||||
*
|
||||
* This is a very slow function, implemented by sending synchronous IPIs to
|
||||
* all possible CPUs. For this reason, we have to alloc data rather than use
|
||||
* stack based data even in the case of synchronous calls. The stack based
|
||||
* data is then just used for deadlock/oom fallback which will be very rare.
|
||||
*
|
||||
* If a faster scheme can be made, we could go back to preferring stack based
|
||||
* data -- the data allocation/free is non-zero cost.
|
||||
*/
|
||||
static void smp_call_function_mask_quiesce_stack(cpumask_t mask)
|
||||
{
|
||||
struct call_single_data data;
|
||||
int cpu;
|
||||
|
||||
data.func = quiesce_dummy;
|
||||
data.info = NULL;
|
||||
|
||||
for_each_cpu_mask(cpu, mask) {
|
||||
data.flags = CSD_FLAG_WAIT;
|
||||
generic_exec_single(cpu, &data);
|
||||
}
|
||||
}
|
||||
/* FIXME: Shim for archs using old arch_send_call_function_ipi API. */
|
||||
#ifndef arch_send_call_function_ipi_mask
|
||||
#define arch_send_call_function_ipi_mask(maskp) \
|
||||
arch_send_call_function_ipi(*(maskp))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* smp_call_function_mask(): Run a function on a set of other CPUs.
|
||||
* @mask: The set of cpus to run on.
|
||||
* smp_call_function_many(): Run a function on a set of other CPUs.
|
||||
* @mask: The set of cpus to run on (only runs on online subset).
|
||||
* @func: The function to run. This must be fast and non-blocking.
|
||||
* @info: An arbitrary pointer to pass to the function.
|
||||
* @wait: If true, wait (atomically) until function has completed on other CPUs.
|
||||
*
|
||||
* Returns 0 on success, else a negative status code.
|
||||
*
|
||||
* If @wait is true, then returns once @func has returned. Note that @wait
|
||||
* will be implicitly turned on in case of allocation failures, since
|
||||
* we fall back to on-stack allocation.
|
||||
@@ -319,53 +287,57 @@ static void smp_call_function_mask_quiesce_stack(cpumask_t mask)
|
||||
* hardware interrupt handler or from a bottom half handler. Preemption
|
||||
* must be disabled when calling this function.
|
||||
*/
|
||||
int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
|
||||
int wait)
|
||||
void smp_call_function_many(const struct cpumask *mask,
|
||||
void (*func)(void *), void *info,
|
||||
bool wait)
|
||||
{
|
||||
struct call_function_data d;
|
||||
struct call_function_data *data = NULL;
|
||||
cpumask_t allbutself;
|
||||
struct call_function_data *data;
|
||||
unsigned long flags;
|
||||
int cpu, num_cpus;
|
||||
int slowpath = 0;
|
||||
int cpu, next_cpu;
|
||||
|
||||
/* Can deadlock when called with interrupts disabled */
|
||||
WARN_ON(irqs_disabled());
|
||||
|
||||
cpu = smp_processor_id();
|
||||
allbutself = cpu_online_map;
|
||||
cpu_clear(cpu, allbutself);
|
||||
cpus_and(mask, mask, allbutself);
|
||||
num_cpus = cpus_weight(mask);
|
||||
/* So, what's a CPU they want? Ignoring this one. */
|
||||
cpu = cpumask_first_and(mask, cpu_online_mask);
|
||||
if (cpu == smp_processor_id())
|
||||
cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
|
||||
/* No online cpus? We're done. */
|
||||
if (cpu >= nr_cpu_ids)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If zero CPUs, return. If just a single CPU, turn this request
|
||||
* into a targetted single call instead since it's faster.
|
||||
*/
|
||||
if (!num_cpus)
|
||||
return 0;
|
||||
else if (num_cpus == 1) {
|
||||
cpu = first_cpu(mask);
|
||||
return smp_call_function_single(cpu, func, info, wait);
|
||||
/* Do we have another CPU which isn't us? */
|
||||
next_cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
|
||||
if (next_cpu == smp_processor_id())
|
||||
next_cpu = cpumask_next_and(next_cpu, mask, cpu_online_mask);
|
||||
|
||||
/* Fastpath: do that cpu by itself. */
|
||||
if (next_cpu >= nr_cpu_ids) {
|
||||
smp_call_function_single(cpu, func, info, wait);
|
||||
return;
|
||||
}
|
||||
|
||||
data = kmalloc(sizeof(*data), GFP_ATOMIC);
|
||||
if (data) {
|
||||
data->csd.flags = CSD_FLAG_ALLOC;
|
||||
if (wait)
|
||||
data->csd.flags |= CSD_FLAG_WAIT;
|
||||
} else {
|
||||
data = &d;
|
||||
data->csd.flags = CSD_FLAG_WAIT;
|
||||
wait = 1;
|
||||
slowpath = 1;
|
||||
data = kmalloc(sizeof(*data) + cpumask_size(), GFP_ATOMIC);
|
||||
if (unlikely(!data)) {
|
||||
/* Slow path. */
|
||||
for_each_online_cpu(cpu) {
|
||||
if (cpu == smp_processor_id())
|
||||
continue;
|
||||
if (cpumask_test_cpu(cpu, mask))
|
||||
smp_call_function_single(cpu, func, info, wait);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_init(&data->lock);
|
||||
data->csd.flags = CSD_FLAG_ALLOC;
|
||||
if (wait)
|
||||
data->csd.flags |= CSD_FLAG_WAIT;
|
||||
data->csd.func = func;
|
||||
data->csd.info = info;
|
||||
data->refs = num_cpus;
|
||||
data->cpumask = mask;
|
||||
cpumask_and(to_cpumask(data->cpumask_bits), mask, cpu_online_mask);
|
||||
cpumask_clear_cpu(smp_processor_id(), to_cpumask(data->cpumask_bits));
|
||||
data->refs = cpumask_weight(to_cpumask(data->cpumask_bits));
|
||||
|
||||
spin_lock_irqsave(&call_function_lock, flags);
|
||||
list_add_tail_rcu(&data->csd.list, &call_function_queue);
|
||||
@@ -377,18 +349,13 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
|
||||
smp_mb();
|
||||
|
||||
/* Send a message to all CPUs in the map */
|
||||
arch_send_call_function_ipi(mask);
|
||||
arch_send_call_function_ipi_mask(to_cpumask(data->cpumask_bits));
|
||||
|
||||
/* optionally wait for the CPUs to complete */
|
||||
if (wait) {
|
||||
if (wait)
|
||||
csd_flag_wait(&data->csd);
|
||||
if (unlikely(slowpath))
|
||||
smp_call_function_mask_quiesce_stack(mask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(smp_call_function_mask);
|
||||
EXPORT_SYMBOL(smp_call_function_many);
|
||||
|
||||
/**
|
||||
* smp_call_function(): Run a function on all other CPUs.
|
||||
@@ -396,7 +363,7 @@ EXPORT_SYMBOL(smp_call_function_mask);
|
||||
* @info: An arbitrary pointer to pass to the function.
|
||||
* @wait: If true, wait (atomically) until function has completed on other CPUs.
|
||||
*
|
||||
* Returns 0 on success, else a negative status code.
|
||||
* Returns 0.
|
||||
*
|
||||
* If @wait is true, then returns once @func has returned; otherwise
|
||||
* it returns just before the target cpu calls @func. In case of allocation
|
||||
@@ -407,12 +374,10 @@ EXPORT_SYMBOL(smp_call_function_mask);
|
||||
*/
|
||||
int smp_call_function(void (*func)(void *), void *info, int wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
preempt_disable();
|
||||
ret = smp_call_function_mask(cpu_online_map, func, info, wait);
|
||||
smp_call_function_many(cpu_online_mask, func, info, wait);
|
||||
preempt_enable();
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(smp_call_function);
|
||||
|
||||
|
||||
+1
-1
@@ -733,7 +733,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb,
|
||||
break;
|
||||
/* Unbind so it can run. Fall thru. */
|
||||
kthread_bind(per_cpu(ksoftirqd, hotcpu),
|
||||
any_online_cpu(cpu_online_map));
|
||||
cpumask_any(cpu_online_mask));
|
||||
case CPU_DEAD:
|
||||
case CPU_DEAD_FROZEN: {
|
||||
struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
|
||||
|
||||
+4
-6
@@ -303,17 +303,15 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
break;
|
||||
case CPU_ONLINE:
|
||||
case CPU_ONLINE_FROZEN:
|
||||
check_cpu = any_online_cpu(cpu_online_map);
|
||||
check_cpu = cpumask_any(cpu_online_mask);
|
||||
wake_up_process(per_cpu(watchdog_task, hotcpu));
|
||||
break;
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
case CPU_DOWN_PREPARE:
|
||||
case CPU_DOWN_PREPARE_FROZEN:
|
||||
if (hotcpu == check_cpu) {
|
||||
cpumask_t temp_cpu_online_map = cpu_online_map;
|
||||
|
||||
cpu_clear(hotcpu, temp_cpu_online_map);
|
||||
check_cpu = any_online_cpu(temp_cpu_online_map);
|
||||
/* Pick any other online cpu. */
|
||||
check_cpu = cpumask_any_but(cpu_online_mask, hotcpu);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -323,7 +321,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
break;
|
||||
/* Unbind so it can run. Fall thru. */
|
||||
kthread_bind(per_cpu(watchdog_task, hotcpu),
|
||||
any_online_cpu(cpu_online_map));
|
||||
cpumask_any(cpu_online_mask));
|
||||
case CPU_DEAD:
|
||||
case CPU_DEAD_FROZEN:
|
||||
p = per_cpu(watchdog_task, hotcpu);
|
||||
|
||||
@@ -69,10 +69,10 @@ static void stop_cpu(struct work_struct *unused)
|
||||
int err;
|
||||
|
||||
if (!active_cpus) {
|
||||
if (cpu == first_cpu(cpu_online_map))
|
||||
if (cpu == cpumask_first(cpu_online_mask))
|
||||
smdata = &active;
|
||||
} else {
|
||||
if (cpu_isset(cpu, *active_cpus))
|
||||
if (cpumask_test_cpu(cpu, active_cpus))
|
||||
smdata = &active;
|
||||
}
|
||||
/* Simple state machine */
|
||||
@@ -109,7 +109,7 @@ static int chill(void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
|
||||
int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
|
||||
{
|
||||
struct work_struct *sm_work;
|
||||
int i, ret;
|
||||
@@ -142,7 +142,7 @@ int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
|
||||
int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
+26
-17
@@ -290,18 +290,17 @@ ret:
|
||||
return;
|
||||
}
|
||||
|
||||
static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
|
||||
static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
|
||||
{
|
||||
struct listener_list *listeners;
|
||||
struct listener *s, *tmp;
|
||||
unsigned int cpu;
|
||||
cpumask_t mask = *maskp;
|
||||
|
||||
if (!cpus_subset(mask, cpu_possible_map))
|
||||
if (!cpumask_subset(mask, cpu_possible_mask))
|
||||
return -EINVAL;
|
||||
|
||||
if (isadd == REGISTER) {
|
||||
for_each_cpu_mask_nr(cpu, mask) {
|
||||
for_each_cpu(cpu, mask) {
|
||||
s = kmalloc_node(sizeof(struct listener), GFP_KERNEL,
|
||||
cpu_to_node(cpu));
|
||||
if (!s)
|
||||
@@ -320,7 +319,7 @@ static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
|
||||
|
||||
/* Deregister or cleanup */
|
||||
cleanup:
|
||||
for_each_cpu_mask_nr(cpu, mask) {
|
||||
for_each_cpu(cpu, mask) {
|
||||
listeners = &per_cpu(listener_array, cpu);
|
||||
down_write(&listeners->sem);
|
||||
list_for_each_entry_safe(s, tmp, &listeners->list, list) {
|
||||
@@ -335,7 +334,7 @@ cleanup:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse(struct nlattr *na, cpumask_t *mask)
|
||||
static int parse(struct nlattr *na, struct cpumask *mask)
|
||||
{
|
||||
char *data;
|
||||
int len;
|
||||
@@ -352,7 +351,7 @@ static int parse(struct nlattr *na, cpumask_t *mask)
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
nla_strlcpy(data, na, len);
|
||||
ret = cpulist_parse(data, *mask);
|
||||
ret = cpulist_parse(data, mask);
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
@@ -428,23 +427,33 @@ err:
|
||||
|
||||
static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct sk_buff *rep_skb;
|
||||
struct taskstats *stats;
|
||||
size_t size;
|
||||
cpumask_t mask;
|
||||
cpumask_var_t mask;
|
||||
|
||||
rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (rc == 0)
|
||||
return add_del_listener(info->snd_pid, &mask, REGISTER);
|
||||
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], &mask);
|
||||
rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], mask);
|
||||
if (rc < 0)
|
||||
goto free_return_rc;
|
||||
if (rc == 0) {
|
||||
rc = add_del_listener(info->snd_pid, mask, REGISTER);
|
||||
goto free_return_rc;
|
||||
}
|
||||
|
||||
rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], mask);
|
||||
if (rc < 0)
|
||||
goto free_return_rc;
|
||||
if (rc == 0) {
|
||||
rc = add_del_listener(info->snd_pid, mask, DEREGISTER);
|
||||
free_return_rc:
|
||||
free_cpumask_var(mask);
|
||||
return rc;
|
||||
if (rc == 0)
|
||||
return add_del_listener(info->snd_pid, &mask, DEREGISTER);
|
||||
}
|
||||
free_cpumask_var(mask);
|
||||
|
||||
/*
|
||||
* Size includes space for nested attributes
|
||||
|
||||
@@ -166,6 +166,8 @@ static void clockevents_notify_released(void)
|
||||
void clockevents_register_device(struct clock_event_device *dev)
|
||||
{
|
||||
BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
|
||||
BUG_ON(!dev->cpumask);
|
||||
|
||||
/*
|
||||
* A nsec2cyc multiplicator of 0 is invalid and we'd crash
|
||||
* on it, so fix it up and emit a warning:
|
||||
|
||||
@@ -145,10 +145,11 @@ static void clocksource_watchdog(unsigned long data)
|
||||
* Cycle through CPUs to check if the CPUs stay
|
||||
* synchronized to each other.
|
||||
*/
|
||||
int next_cpu = next_cpu_nr(raw_smp_processor_id(), cpu_online_map);
|
||||
int next_cpu = cpumask_next(raw_smp_processor_id(),
|
||||
cpu_online_mask);
|
||||
|
||||
if (next_cpu >= nr_cpu_ids)
|
||||
next_cpu = first_cpu(cpu_online_map);
|
||||
next_cpu = cpumask_first(cpu_online_mask);
|
||||
watchdog_timer.expires += WATCHDOG_INTERVAL;
|
||||
add_timer_on(&watchdog_timer, next_cpu);
|
||||
}
|
||||
@@ -173,7 +174,7 @@ static void clocksource_check_watchdog(struct clocksource *cs)
|
||||
watchdog_last = watchdog->read();
|
||||
watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
|
||||
add_timer_on(&watchdog_timer,
|
||||
first_cpu(cpu_online_map));
|
||||
cpumask_first(cpu_online_mask));
|
||||
}
|
||||
} else {
|
||||
if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
|
||||
@@ -195,7 +196,7 @@ static void clocksource_check_watchdog(struct clocksource *cs)
|
||||
watchdog_timer.expires =
|
||||
jiffies + WATCHDOG_INTERVAL;
|
||||
add_timer_on(&watchdog_timer,
|
||||
first_cpu(cpu_online_map));
|
||||
cpumask_first(cpu_online_mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
*/
|
||||
|
||||
struct tick_device tick_broadcast_device;
|
||||
static cpumask_t tick_broadcast_mask;
|
||||
/* FIXME: Use cpumask_var_t. */
|
||||
static DECLARE_BITMAP(tick_broadcast_mask, NR_CPUS);
|
||||
static DECLARE_BITMAP(tmpmask, NR_CPUS);
|
||||
static DEFINE_SPINLOCK(tick_broadcast_lock);
|
||||
static int tick_broadcast_force;
|
||||
|
||||
@@ -46,9 +48,9 @@ struct tick_device *tick_get_broadcast_device(void)
|
||||
return &tick_broadcast_device;
|
||||
}
|
||||
|
||||
cpumask_t *tick_get_broadcast_mask(void)
|
||||
struct cpumask *tick_get_broadcast_mask(void)
|
||||
{
|
||||
return &tick_broadcast_mask;
|
||||
return to_cpumask(tick_broadcast_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -72,7 +74,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev)
|
||||
|
||||
clockevents_exchange_device(NULL, dev);
|
||||
tick_broadcast_device.evtdev = dev;
|
||||
if (!cpus_empty(tick_broadcast_mask))
|
||||
if (!cpumask_empty(tick_get_broadcast_mask()))
|
||||
tick_broadcast_start_periodic(dev);
|
||||
return 1;
|
||||
}
|
||||
@@ -104,7 +106,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
|
||||
*/
|
||||
if (!tick_device_is_functional(dev)) {
|
||||
dev->event_handler = tick_handle_periodic;
|
||||
cpu_set(cpu, tick_broadcast_mask);
|
||||
cpumask_set_cpu(cpu, tick_get_broadcast_mask());
|
||||
tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
|
||||
ret = 1;
|
||||
} else {
|
||||
@@ -116,7 +118,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
|
||||
if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
cpu_clear(cpu, tick_broadcast_mask);
|
||||
cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
|
||||
tick_broadcast_clear_oneshot(cpu);
|
||||
}
|
||||
}
|
||||
@@ -125,9 +127,9 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
|
||||
}
|
||||
|
||||
/*
|
||||
* Broadcast the event to the cpus, which are set in the mask
|
||||
* Broadcast the event to the cpus, which are set in the mask (mangled).
|
||||
*/
|
||||
static void tick_do_broadcast(cpumask_t mask)
|
||||
static void tick_do_broadcast(struct cpumask *mask)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct tick_device *td;
|
||||
@@ -135,21 +137,20 @@ static void tick_do_broadcast(cpumask_t mask)
|
||||
/*
|
||||
* Check, if the current cpu is in the mask
|
||||
*/
|
||||
if (cpu_isset(cpu, mask)) {
|
||||
cpu_clear(cpu, mask);
|
||||
if (cpumask_test_cpu(cpu, mask)) {
|
||||
cpumask_clear_cpu(cpu, mask);
|
||||
td = &per_cpu(tick_cpu_device, cpu);
|
||||
td->evtdev->event_handler(td->evtdev);
|
||||
}
|
||||
|
||||
if (!cpus_empty(mask)) {
|
||||
if (!cpumask_empty(mask)) {
|
||||
/*
|
||||
* It might be necessary to actually check whether the devices
|
||||
* have different broadcast functions. For now, just use the
|
||||
* one of the first device. This works as long as we have this
|
||||
* misfeature only on x86 (lapic)
|
||||
*/
|
||||
cpu = first_cpu(mask);
|
||||
td = &per_cpu(tick_cpu_device, cpu);
|
||||
td = &per_cpu(tick_cpu_device, cpumask_first(mask));
|
||||
td->evtdev->broadcast(mask);
|
||||
}
|
||||
}
|
||||
@@ -160,12 +161,11 @@ static void tick_do_broadcast(cpumask_t mask)
|
||||
*/
|
||||
static void tick_do_periodic_broadcast(void)
|
||||
{
|
||||
cpumask_t mask;
|
||||
|
||||
spin_lock(&tick_broadcast_lock);
|
||||
|
||||
cpus_and(mask, cpu_online_map, tick_broadcast_mask);
|
||||
tick_do_broadcast(mask);
|
||||
cpumask_and(to_cpumask(tmpmask),
|
||||
cpu_online_mask, tick_get_broadcast_mask());
|
||||
tick_do_broadcast(to_cpumask(tmpmask));
|
||||
|
||||
spin_unlock(&tick_broadcast_lock);
|
||||
}
|
||||
@@ -228,13 +228,13 @@ static void tick_do_broadcast_on_off(void *why)
|
||||
if (!tick_device_is_functional(dev))
|
||||
goto out;
|
||||
|
||||
bc_stopped = cpus_empty(tick_broadcast_mask);
|
||||
bc_stopped = cpumask_empty(tick_get_broadcast_mask());
|
||||
|
||||
switch (*reason) {
|
||||
case CLOCK_EVT_NOTIFY_BROADCAST_ON:
|
||||
case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
|
||||
if (!cpu_isset(cpu, tick_broadcast_mask)) {
|
||||
cpu_set(cpu, tick_broadcast_mask);
|
||||
if (!cpumask_test_cpu(cpu, tick_get_broadcast_mask())) {
|
||||
cpumask_set_cpu(cpu, tick_get_broadcast_mask());
|
||||
if (tick_broadcast_device.mode ==
|
||||
TICKDEV_MODE_PERIODIC)
|
||||
clockevents_shutdown(dev);
|
||||
@@ -244,8 +244,8 @@ static void tick_do_broadcast_on_off(void *why)
|
||||
break;
|
||||
case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
|
||||
if (!tick_broadcast_force &&
|
||||
cpu_isset(cpu, tick_broadcast_mask)) {
|
||||
cpu_clear(cpu, tick_broadcast_mask);
|
||||
cpumask_test_cpu(cpu, tick_get_broadcast_mask())) {
|
||||
cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
|
||||
if (tick_broadcast_device.mode ==
|
||||
TICKDEV_MODE_PERIODIC)
|
||||
tick_setup_periodic(dev, 0);
|
||||
@@ -253,7 +253,7 @@ static void tick_do_broadcast_on_off(void *why)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cpus_empty(tick_broadcast_mask)) {
|
||||
if (cpumask_empty(tick_get_broadcast_mask())) {
|
||||
if (!bc_stopped)
|
||||
clockevents_shutdown(bc);
|
||||
} else if (bc_stopped) {
|
||||
@@ -272,7 +272,7 @@ out:
|
||||
*/
|
||||
void tick_broadcast_on_off(unsigned long reason, int *oncpu)
|
||||
{
|
||||
if (!cpu_isset(*oncpu, cpu_online_map))
|
||||
if (!cpumask_test_cpu(*oncpu, cpu_online_mask))
|
||||
printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
|
||||
"offline CPU #%d\n", *oncpu);
|
||||
else
|
||||
@@ -303,10 +303,10 @@ void tick_shutdown_broadcast(unsigned int *cpup)
|
||||
spin_lock_irqsave(&tick_broadcast_lock, flags);
|
||||
|
||||
bc = tick_broadcast_device.evtdev;
|
||||
cpu_clear(cpu, tick_broadcast_mask);
|
||||
cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
|
||||
|
||||
if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
|
||||
if (bc && cpus_empty(tick_broadcast_mask))
|
||||
if (bc && cpumask_empty(tick_get_broadcast_mask()))
|
||||
clockevents_shutdown(bc);
|
||||
}
|
||||
|
||||
@@ -342,10 +342,10 @@ int tick_resume_broadcast(void)
|
||||
|
||||
switch (tick_broadcast_device.mode) {
|
||||
case TICKDEV_MODE_PERIODIC:
|
||||
if(!cpus_empty(tick_broadcast_mask))
|
||||
if (!cpumask_empty(tick_get_broadcast_mask()))
|
||||
tick_broadcast_start_periodic(bc);
|
||||
broadcast = cpu_isset(smp_processor_id(),
|
||||
tick_broadcast_mask);
|
||||
broadcast = cpumask_test_cpu(smp_processor_id(),
|
||||
tick_get_broadcast_mask());
|
||||
break;
|
||||
case TICKDEV_MODE_ONESHOT:
|
||||
broadcast = tick_resume_broadcast_oneshot(bc);
|
||||
@@ -360,14 +360,15 @@ int tick_resume_broadcast(void)
|
||||
|
||||
#ifdef CONFIG_TICK_ONESHOT
|
||||
|
||||
static cpumask_t tick_broadcast_oneshot_mask;
|
||||
/* FIXME: use cpumask_var_t. */
|
||||
static DECLARE_BITMAP(tick_broadcast_oneshot_mask, NR_CPUS);
|
||||
|
||||
/*
|
||||
* Debugging: see timer_list.c
|
||||
* Exposed for debugging: see timer_list.c
|
||||
*/
|
||||
cpumask_t *tick_get_broadcast_oneshot_mask(void)
|
||||
struct cpumask *tick_get_broadcast_oneshot_mask(void)
|
||||
{
|
||||
return &tick_broadcast_oneshot_mask;
|
||||
return to_cpumask(tick_broadcast_oneshot_mask);
|
||||
}
|
||||
|
||||
static int tick_broadcast_set_event(ktime_t expires, int force)
|
||||
@@ -389,7 +390,7 @@ int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
|
||||
*/
|
||||
void tick_check_oneshot_broadcast(int cpu)
|
||||
{
|
||||
if (cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
|
||||
if (cpumask_test_cpu(cpu, to_cpumask(tick_broadcast_oneshot_mask))) {
|
||||
struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
|
||||
|
||||
clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_ONESHOT);
|
||||
@@ -402,7 +403,6 @@ void tick_check_oneshot_broadcast(int cpu)
|
||||
static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
|
||||
{
|
||||
struct tick_device *td;
|
||||
cpumask_t mask;
|
||||
ktime_t now, next_event;
|
||||
int cpu;
|
||||
|
||||
@@ -410,13 +410,13 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
|
||||
again:
|
||||
dev->next_event.tv64 = KTIME_MAX;
|
||||
next_event.tv64 = KTIME_MAX;
|
||||
mask = CPU_MASK_NONE;
|
||||
cpumask_clear(to_cpumask(tmpmask));
|
||||
now = ktime_get();
|
||||
/* Find all expired events */
|
||||
for_each_cpu_mask_nr(cpu, tick_broadcast_oneshot_mask) {
|
||||
for_each_cpu(cpu, tick_get_broadcast_oneshot_mask()) {
|
||||
td = &per_cpu(tick_cpu_device, cpu);
|
||||
if (td->evtdev->next_event.tv64 <= now.tv64)
|
||||
cpu_set(cpu, mask);
|
||||
cpumask_set_cpu(cpu, to_cpumask(tmpmask));
|
||||
else if (td->evtdev->next_event.tv64 < next_event.tv64)
|
||||
next_event.tv64 = td->evtdev->next_event.tv64;
|
||||
}
|
||||
@@ -424,7 +424,7 @@ again:
|
||||
/*
|
||||
* Wakeup the cpus which have an expired event.
|
||||
*/
|
||||
tick_do_broadcast(mask);
|
||||
tick_do_broadcast(to_cpumask(tmpmask));
|
||||
|
||||
/*
|
||||
* Two reasons for reprogram:
|
||||
@@ -476,15 +476,16 @@ void tick_broadcast_oneshot_control(unsigned long reason)
|
||||
goto out;
|
||||
|
||||
if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
|
||||
if (!cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
|
||||
cpu_set(cpu, tick_broadcast_oneshot_mask);
|
||||
if (!cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) {
|
||||
cpumask_set_cpu(cpu, tick_get_broadcast_oneshot_mask());
|
||||
clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
|
||||
if (dev->next_event.tv64 < bc->next_event.tv64)
|
||||
tick_broadcast_set_event(dev->next_event, 1);
|
||||
}
|
||||
} else {
|
||||
if (cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
|
||||
cpu_clear(cpu, tick_broadcast_oneshot_mask);
|
||||
if (cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) {
|
||||
cpumask_clear_cpu(cpu,
|
||||
tick_get_broadcast_oneshot_mask());
|
||||
clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
|
||||
if (dev->next_event.tv64 != KTIME_MAX)
|
||||
tick_program_event(dev->next_event, 1);
|
||||
@@ -502,15 +503,16 @@ out:
|
||||
*/
|
||||
static void tick_broadcast_clear_oneshot(int cpu)
|
||||
{
|
||||
cpu_clear(cpu, tick_broadcast_oneshot_mask);
|
||||
cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask());
|
||||
}
|
||||
|
||||
static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
|
||||
static void tick_broadcast_init_next_event(struct cpumask *mask,
|
||||
ktime_t expires)
|
||||
{
|
||||
struct tick_device *td;
|
||||
int cpu;
|
||||
|
||||
for_each_cpu_mask_nr(cpu, *mask) {
|
||||
for_each_cpu(cpu, mask) {
|
||||
td = &per_cpu(tick_cpu_device, cpu);
|
||||
if (td->evtdev)
|
||||
td->evtdev->next_event = expires;
|
||||
@@ -526,7 +528,6 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
|
||||
if (bc->event_handler != tick_handle_oneshot_broadcast) {
|
||||
int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
|
||||
int cpu = smp_processor_id();
|
||||
cpumask_t mask;
|
||||
|
||||
bc->event_handler = tick_handle_oneshot_broadcast;
|
||||
clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
|
||||
@@ -540,13 +541,15 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
|
||||
* oneshot_mask bits for those and program the
|
||||
* broadcast device to fire.
|
||||
*/
|
||||
mask = tick_broadcast_mask;
|
||||
cpu_clear(cpu, mask);
|
||||
cpus_or(tick_broadcast_oneshot_mask,
|
||||
tick_broadcast_oneshot_mask, mask);
|
||||
cpumask_copy(to_cpumask(tmpmask), tick_get_broadcast_mask());
|
||||
cpumask_clear_cpu(cpu, to_cpumask(tmpmask));
|
||||
cpumask_or(tick_get_broadcast_oneshot_mask(),
|
||||
tick_get_broadcast_oneshot_mask(),
|
||||
to_cpumask(tmpmask));
|
||||
|
||||
if (was_periodic && !cpus_empty(mask)) {
|
||||
tick_broadcast_init_next_event(&mask, tick_next_period);
|
||||
if (was_periodic && !cpumask_empty(to_cpumask(tmpmask))) {
|
||||
tick_broadcast_init_next_event(to_cpumask(tmpmask),
|
||||
tick_next_period);
|
||||
tick_broadcast_set_event(tick_next_period, 1);
|
||||
} else
|
||||
bc->next_event.tv64 = KTIME_MAX;
|
||||
@@ -585,7 +588,7 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
|
||||
* Clear the broadcast mask flag for the dead cpu, but do not
|
||||
* stop the broadcast device!
|
||||
*/
|
||||
cpu_clear(cpu, tick_broadcast_oneshot_mask);
|
||||
cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask());
|
||||
|
||||
spin_unlock_irqrestore(&tick_broadcast_lock, flags);
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
|
||||
*/
|
||||
static void tick_setup_device(struct tick_device *td,
|
||||
struct clock_event_device *newdev, int cpu,
|
||||
const cpumask_t *cpumask)
|
||||
const struct cpumask *cpumask)
|
||||
{
|
||||
ktime_t next_event;
|
||||
void (*handler)(struct clock_event_device *) = NULL;
|
||||
@@ -171,8 +171,8 @@ static void tick_setup_device(struct tick_device *td,
|
||||
* When the device is not per cpu, pin the interrupt to the
|
||||
* current cpu:
|
||||
*/
|
||||
if (!cpus_equal(newdev->cpumask, *cpumask))
|
||||
irq_set_affinity(newdev->irq, *cpumask);
|
||||
if (!cpumask_equal(newdev->cpumask, cpumask))
|
||||
irq_set_affinity(newdev->irq, cpumask);
|
||||
|
||||
/*
|
||||
* When global broadcasting is active, check if the current
|
||||
@@ -202,14 +202,14 @@ static int tick_check_new_device(struct clock_event_device *newdev)
|
||||
spin_lock_irqsave(&tick_device_lock, flags);
|
||||
|
||||
cpu = smp_processor_id();
|
||||
if (!cpu_isset(cpu, newdev->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, newdev->cpumask))
|
||||
goto out_bc;
|
||||
|
||||
td = &per_cpu(tick_cpu_device, cpu);
|
||||
curdev = td->evtdev;
|
||||
|
||||
/* cpu local device ? */
|
||||
if (!cpus_equal(newdev->cpumask, cpumask_of_cpu(cpu))) {
|
||||
if (!cpumask_equal(newdev->cpumask, cpumask_of(cpu))) {
|
||||
|
||||
/*
|
||||
* If the cpu affinity of the device interrupt can not
|
||||
@@ -222,7 +222,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
|
||||
* If we have a cpu local device already, do not replace it
|
||||
* by a non cpu local device
|
||||
*/
|
||||
if (curdev && cpus_equal(curdev->cpumask, cpumask_of_cpu(cpu)))
|
||||
if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu)))
|
||||
goto out_bc;
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
|
||||
curdev = NULL;
|
||||
}
|
||||
clockevents_exchange_device(curdev, newdev);
|
||||
tick_setup_device(td, newdev, cpu, &cpumask_of_cpu(cpu));
|
||||
tick_setup_device(td, newdev, cpu, cpumask_of(cpu));
|
||||
if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
|
||||
tick_oneshot_notify();
|
||||
|
||||
@@ -299,9 +299,9 @@ static void tick_shutdown(unsigned int *cpup)
|
||||
}
|
||||
/* Transfer the do_timer job away from this cpu */
|
||||
if (*cpup == tick_do_timer_cpu) {
|
||||
int cpu = first_cpu(cpu_online_map);
|
||||
int cpu = cpumask_first(cpu_online_mask);
|
||||
|
||||
tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu :
|
||||
tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu :
|
||||
TICK_DO_TIMER_NONE;
|
||||
}
|
||||
spin_unlock_irqrestore(&tick_device_lock, flags);
|
||||
|
||||
+11
-11
@@ -144,7 +144,7 @@ void tick_nohz_update_jiffies(void)
|
||||
if (!ts->tick_stopped)
|
||||
return;
|
||||
|
||||
cpu_clear(cpu, nohz_cpu_mask);
|
||||
cpumask_clear_cpu(cpu, nohz_cpu_mask);
|
||||
now = ktime_get();
|
||||
ts->idle_waketime = now;
|
||||
|
||||
@@ -301,7 +301,7 @@ void tick_nohz_stop_sched_tick(int inidle)
|
||||
tick_do_timer_cpu = TICK_DO_TIMER_NONE;
|
||||
|
||||
if (delta_jiffies > 1)
|
||||
cpu_set(cpu, nohz_cpu_mask);
|
||||
cpumask_set_cpu(cpu, nohz_cpu_mask);
|
||||
|
||||
/* Skip reprogram of event if its not changed */
|
||||
if (ts->tick_stopped && ktime_equal(expires, dev->next_event))
|
||||
@@ -319,7 +319,7 @@ void tick_nohz_stop_sched_tick(int inidle)
|
||||
/*
|
||||
* sched tick not stopped!
|
||||
*/
|
||||
cpu_clear(cpu, nohz_cpu_mask);
|
||||
cpumask_clear_cpu(cpu, nohz_cpu_mask);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ void tick_nohz_stop_sched_tick(int inidle)
|
||||
* softirq.
|
||||
*/
|
||||
tick_do_update_jiffies64(ktime_get());
|
||||
cpu_clear(cpu, nohz_cpu_mask);
|
||||
cpumask_clear_cpu(cpu, nohz_cpu_mask);
|
||||
}
|
||||
raise_softirq_irqoff(TIMER_SOFTIRQ);
|
||||
out:
|
||||
@@ -419,7 +419,9 @@ void tick_nohz_restart_sched_tick(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
|
||||
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
unsigned long ticks;
|
||||
#endif
|
||||
ktime_t now;
|
||||
|
||||
local_irq_disable();
|
||||
@@ -439,8 +441,9 @@ void tick_nohz_restart_sched_tick(void)
|
||||
select_nohz_load_balancer(0);
|
||||
now = ktime_get();
|
||||
tick_do_update_jiffies64(now);
|
||||
cpu_clear(cpu, nohz_cpu_mask);
|
||||
cpumask_clear_cpu(cpu, nohz_cpu_mask);
|
||||
|
||||
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
/*
|
||||
* We stopped the tick in idle. Update process times would miss the
|
||||
* time we slept as update_process_times does only a 1 tick
|
||||
@@ -450,12 +453,9 @@ void tick_nohz_restart_sched_tick(void)
|
||||
/*
|
||||
* We might be one off. Do not randomly account a huge number of ticks!
|
||||
*/
|
||||
if (ticks && ticks < LONG_MAX) {
|
||||
add_preempt_count(HARDIRQ_OFFSET);
|
||||
account_system_time(current, HARDIRQ_OFFSET,
|
||||
jiffies_to_cputime(ticks));
|
||||
sub_preempt_count(HARDIRQ_OFFSET);
|
||||
}
|
||||
if (ticks && ticks < LONG_MAX)
|
||||
account_idle_ticks(ticks);
|
||||
#endif
|
||||
|
||||
touch_softlockup_watchdog();
|
||||
/*
|
||||
|
||||
@@ -1018,21 +1018,6 @@ unsigned long get_next_timer_interrupt(unsigned long now)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
void account_process_tick(struct task_struct *p, int user_tick)
|
||||
{
|
||||
cputime_t one_jiffy = jiffies_to_cputime(1);
|
||||
|
||||
if (user_tick) {
|
||||
account_user_time(p, one_jiffy);
|
||||
account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
|
||||
} else {
|
||||
account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
|
||||
account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called from the timer interrupt handler to charge one tick to the current
|
||||
* process. user_tick is 1 if the tick is user time, 0 for system.
|
||||
|
||||
+25
-17
@@ -195,7 +195,7 @@ void *ring_buffer_event_data(struct ring_buffer_event *event)
|
||||
EXPORT_SYMBOL_GPL(ring_buffer_event_data);
|
||||
|
||||
#define for_each_buffer_cpu(buffer, cpu) \
|
||||
for_each_cpu_mask(cpu, buffer->cpumask)
|
||||
for_each_cpu(cpu, buffer->cpumask)
|
||||
|
||||
#define TS_SHIFT 27
|
||||
#define TS_MASK ((1ULL << TS_SHIFT) - 1)
|
||||
@@ -267,7 +267,7 @@ struct ring_buffer {
|
||||
unsigned pages;
|
||||
unsigned flags;
|
||||
int cpus;
|
||||
cpumask_t cpumask;
|
||||
cpumask_var_t cpumask;
|
||||
atomic_t record_disabled;
|
||||
|
||||
struct mutex mutex;
|
||||
@@ -458,6 +458,9 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
if (!alloc_cpumask_var(&buffer->cpumask, GFP_KERNEL))
|
||||
goto fail_free_buffer;
|
||||
|
||||
buffer->pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
|
||||
buffer->flags = flags;
|
||||
|
||||
@@ -465,14 +468,14 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
|
||||
if (buffer->pages == 1)
|
||||
buffer->pages++;
|
||||
|
||||
buffer->cpumask = cpu_possible_map;
|
||||
cpumask_copy(buffer->cpumask, cpu_possible_mask);
|
||||
buffer->cpus = nr_cpu_ids;
|
||||
|
||||
bsize = sizeof(void *) * nr_cpu_ids;
|
||||
buffer->buffers = kzalloc(ALIGN(bsize, cache_line_size()),
|
||||
GFP_KERNEL);
|
||||
if (!buffer->buffers)
|
||||
goto fail_free_buffer;
|
||||
goto fail_free_cpumask;
|
||||
|
||||
for_each_buffer_cpu(buffer, cpu) {
|
||||
buffer->buffers[cpu] =
|
||||
@@ -492,6 +495,9 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
|
||||
}
|
||||
kfree(buffer->buffers);
|
||||
|
||||
fail_free_cpumask:
|
||||
free_cpumask_var(buffer->cpumask);
|
||||
|
||||
fail_free_buffer:
|
||||
kfree(buffer);
|
||||
return NULL;
|
||||
@@ -510,6 +516,8 @@ ring_buffer_free(struct ring_buffer *buffer)
|
||||
for_each_buffer_cpu(buffer, cpu)
|
||||
rb_free_cpu_buffer(buffer->buffers[cpu]);
|
||||
|
||||
free_cpumask_var(buffer->cpumask);
|
||||
|
||||
kfree(buffer);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ring_buffer_free);
|
||||
@@ -1283,7 +1291,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
|
||||
|
||||
cpu = raw_smp_processor_id();
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
goto out;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -1396,7 +1404,7 @@ int ring_buffer_write(struct ring_buffer *buffer,
|
||||
|
||||
cpu = raw_smp_processor_id();
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
goto out;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -1478,7 +1486,7 @@ void ring_buffer_record_disable_cpu(struct ring_buffer *buffer, int cpu)
|
||||
{
|
||||
struct ring_buffer_per_cpu *cpu_buffer;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -1498,7 +1506,7 @@ void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu)
|
||||
{
|
||||
struct ring_buffer_per_cpu *cpu_buffer;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -1515,7 +1523,7 @@ unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu)
|
||||
{
|
||||
struct ring_buffer_per_cpu *cpu_buffer;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return 0;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -1532,7 +1540,7 @@ unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu)
|
||||
{
|
||||
struct ring_buffer_per_cpu *cpu_buffer;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return 0;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -1850,7 +1858,7 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
|
||||
struct buffer_page *reader;
|
||||
int nr_loops = 0;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return NULL;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -2025,7 +2033,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts)
|
||||
struct ring_buffer_event *event;
|
||||
unsigned long flags;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
|
||||
@@ -2062,7 +2070,7 @@ ring_buffer_read_start(struct ring_buffer *buffer, int cpu)
|
||||
struct ring_buffer_iter *iter;
|
||||
unsigned long flags;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return NULL;
|
||||
|
||||
iter = kmalloc(sizeof(*iter), GFP_KERNEL);
|
||||
@@ -2172,7 +2180,7 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu)
|
||||
struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu];
|
||||
unsigned long flags;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
|
||||
@@ -2228,7 +2236,7 @@ int ring_buffer_empty_cpu(struct ring_buffer *buffer, int cpu)
|
||||
{
|
||||
struct ring_buffer_per_cpu *cpu_buffer;
|
||||
|
||||
if (!cpu_isset(cpu, buffer->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer->cpumask))
|
||||
return 1;
|
||||
|
||||
cpu_buffer = buffer->buffers[cpu];
|
||||
@@ -2252,8 +2260,8 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
|
||||
struct ring_buffer_per_cpu *cpu_buffer_a;
|
||||
struct ring_buffer_per_cpu *cpu_buffer_b;
|
||||
|
||||
if (!cpu_isset(cpu, buffer_a->cpumask) ||
|
||||
!cpu_isset(cpu, buffer_b->cpumask))
|
||||
if (!cpumask_test_cpu(cpu, buffer_a->cpumask) ||
|
||||
!cpumask_test_cpu(cpu, buffer_b->cpumask))
|
||||
return -EINVAL;
|
||||
|
||||
/* At least make sure the two buffers are somewhat the same */
|
||||
|
||||
+43
-25
@@ -89,10 +89,10 @@ static inline void ftrace_enable_cpu(void)
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static cpumask_t __read_mostly tracing_buffer_mask;
|
||||
static cpumask_var_t __read_mostly tracing_buffer_mask;
|
||||
|
||||
#define for_each_tracing_cpu(cpu) \
|
||||
for_each_cpu_mask(cpu, tracing_buffer_mask)
|
||||
for_each_cpu(cpu, tracing_buffer_mask)
|
||||
|
||||
/*
|
||||
* ftrace_dump_on_oops - variable to dump ftrace buffer on oops
|
||||
@@ -1811,10 +1811,10 @@ static void test_cpu_buff_start(struct trace_iterator *iter)
|
||||
if (!(iter->iter_flags & TRACE_FILE_ANNOTATE))
|
||||
return;
|
||||
|
||||
if (cpu_isset(iter->cpu, iter->started))
|
||||
if (cpumask_test_cpu(iter->cpu, iter->started))
|
||||
return;
|
||||
|
||||
cpu_set(iter->cpu, iter->started);
|
||||
cpumask_set_cpu(iter->cpu, iter->started);
|
||||
trace_seq_printf(s, "##### CPU %u buffer started ####\n", iter->cpu);
|
||||
}
|
||||
|
||||
@@ -2646,13 +2646,7 @@ static struct file_operations show_traces_fops = {
|
||||
/*
|
||||
* Only trace on a CPU if the bitmask is set:
|
||||
*/
|
||||
static cpumask_t tracing_cpumask = CPU_MASK_ALL;
|
||||
|
||||
/*
|
||||
* When tracing/tracing_cpu_mask is modified then this holds
|
||||
* the new bitmask we are about to install:
|
||||
*/
|
||||
static cpumask_t tracing_cpumask_new;
|
||||
static cpumask_var_t tracing_cpumask;
|
||||
|
||||
/*
|
||||
* The tracer itself will not take this lock, but still we want
|
||||
@@ -2693,6 +2687,10 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int err, cpu;
|
||||
cpumask_var_t tracing_cpumask_new;
|
||||
|
||||
if (!alloc_cpumask_var(&tracing_cpumask_new, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&tracing_cpumask_update_lock);
|
||||
err = cpumask_parse_user(ubuf, count, tracing_cpumask_new);
|
||||
@@ -2706,26 +2704,28 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
|
||||
* Increase/decrease the disabled counter if we are
|
||||
* about to flip a bit in the cpumask:
|
||||
*/
|
||||
if (cpu_isset(cpu, tracing_cpumask) &&
|
||||
!cpu_isset(cpu, tracing_cpumask_new)) {
|
||||
if (cpumask_test_cpu(cpu, tracing_cpumask) &&
|
||||
!cpumask_test_cpu(cpu, tracing_cpumask_new)) {
|
||||
atomic_inc(&global_trace.data[cpu]->disabled);
|
||||
}
|
||||
if (!cpu_isset(cpu, tracing_cpumask) &&
|
||||
cpu_isset(cpu, tracing_cpumask_new)) {
|
||||
if (!cpumask_test_cpu(cpu, tracing_cpumask) &&
|
||||
cpumask_test_cpu(cpu, tracing_cpumask_new)) {
|
||||
atomic_dec(&global_trace.data[cpu]->disabled);
|
||||
}
|
||||
}
|
||||
__raw_spin_unlock(&ftrace_max_lock);
|
||||
local_irq_enable();
|
||||
|
||||
tracing_cpumask = tracing_cpumask_new;
|
||||
cpumask_copy(tracing_cpumask, tracing_cpumask_new);
|
||||
|
||||
mutex_unlock(&tracing_cpumask_update_lock);
|
||||
free_cpumask_var(tracing_cpumask_new);
|
||||
|
||||
return count;
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&tracing_cpumask_update_lock);
|
||||
free_cpumask_var(tracing_cpumask);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -3114,10 +3114,15 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
|
||||
if (!iter)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!alloc_cpumask_var(&iter->started, GFP_KERNEL)) {
|
||||
kfree(iter);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&trace_types_lock);
|
||||
|
||||
/* trace pipe does not show start of buffer */
|
||||
cpus_setall(iter->started);
|
||||
cpumask_setall(iter->started);
|
||||
|
||||
iter->tr = &global_trace;
|
||||
iter->trace = current_trace;
|
||||
@@ -3134,6 +3139,7 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct trace_iterator *iter = file->private_data;
|
||||
|
||||
free_cpumask_var(iter->started);
|
||||
kfree(iter);
|
||||
atomic_dec(&tracing_reader);
|
||||
|
||||
@@ -3752,7 +3758,6 @@ void ftrace_dump(void)
|
||||
static DEFINE_SPINLOCK(ftrace_dump_lock);
|
||||
/* use static because iter can be a bit big for the stack */
|
||||
static struct trace_iterator iter;
|
||||
static cpumask_t mask;
|
||||
static int dump_ran;
|
||||
unsigned long flags;
|
||||
int cnt = 0, cpu;
|
||||
@@ -3786,8 +3791,6 @@ void ftrace_dump(void)
|
||||
* and then release the locks again.
|
||||
*/
|
||||
|
||||
cpus_clear(mask);
|
||||
|
||||
while (!trace_empty(&iter)) {
|
||||
|
||||
if (!cnt)
|
||||
@@ -3823,19 +3826,28 @@ __init static int tracer_alloc_buffers(void)
|
||||
{
|
||||
struct trace_array_cpu *data;
|
||||
int i;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
|
||||
goto out;
|
||||
|
||||
if (!alloc_cpumask_var(&tracing_cpumask, GFP_KERNEL))
|
||||
goto out_free_buffer_mask;
|
||||
|
||||
cpumask_copy(tracing_buffer_mask, cpu_possible_mask);
|
||||
cpumask_copy(tracing_cpumask, cpu_all_mask);
|
||||
|
||||
/* TODO: make the number of buffers hot pluggable with CPUS */
|
||||
tracing_buffer_mask = cpu_possible_map;
|
||||
|
||||
global_trace.buffer = ring_buffer_alloc(trace_buf_size,
|
||||
TRACE_BUFFER_FLAGS);
|
||||
if (!global_trace.buffer) {
|
||||
printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
goto out_free_cpumask;
|
||||
}
|
||||
global_trace.entries = ring_buffer_size(global_trace.buffer);
|
||||
|
||||
|
||||
#ifdef CONFIG_TRACER_MAX_TRACE
|
||||
max_tr.buffer = ring_buffer_alloc(trace_buf_size,
|
||||
TRACE_BUFFER_FLAGS);
|
||||
@@ -3843,7 +3855,7 @@ __init static int tracer_alloc_buffers(void)
|
||||
printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n");
|
||||
WARN_ON(1);
|
||||
ring_buffer_free(global_trace.buffer);
|
||||
return 0;
|
||||
goto out_free_cpumask;
|
||||
}
|
||||
max_tr.entries = ring_buffer_size(max_tr.buffer);
|
||||
WARN_ON(max_tr.entries != global_trace.entries);
|
||||
@@ -3873,8 +3885,14 @@ __init static int tracer_alloc_buffers(void)
|
||||
&trace_panic_notifier);
|
||||
|
||||
register_die_notifier(&trace_die_notifier);
|
||||
ret = 0;
|
||||
|
||||
return 0;
|
||||
out_free_cpumask:
|
||||
free_cpumask_var(tracing_cpumask);
|
||||
out_free_buffer_mask:
|
||||
free_cpumask_var(tracing_buffer_mask);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
early_initcall(tracer_alloc_buffers);
|
||||
fs_initcall(tracer_init_debugfs);
|
||||
|
||||
@@ -368,7 +368,7 @@ struct trace_iterator {
|
||||
loff_t pos;
|
||||
long idx;
|
||||
|
||||
cpumask_t started;
|
||||
cpumask_var_t started;
|
||||
};
|
||||
|
||||
int tracing_is_enabled(void);
|
||||
|
||||
@@ -42,7 +42,7 @@ static int boot_trace_init(struct trace_array *tr)
|
||||
int cpu;
|
||||
boot_trace = tr;
|
||||
|
||||
for_each_cpu_mask(cpu, cpu_possible_map)
|
||||
for_each_cpu(cpu, cpu_possible_mask)
|
||||
tracing_reset(tr, cpu);
|
||||
|
||||
tracing_sched_switch_assign_trace(tr);
|
||||
|
||||
@@ -79,7 +79,7 @@ print_graph_cpu(struct trace_seq *s, int cpu)
|
||||
int i;
|
||||
int ret;
|
||||
int log10_this = log10_cpu(cpu);
|
||||
int log10_all = log10_cpu(cpus_weight_nr(cpu_online_map));
|
||||
int log10_all = log10_cpu(cpumask_weight(cpu_online_mask));
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -46,7 +46,7 @@ static void bts_trace_start(struct trace_array *tr)
|
||||
|
||||
tracing_reset_online_cpus(tr);
|
||||
|
||||
for_each_cpu_mask(cpu, cpu_possible_map)
|
||||
for_each_cpu(cpu, cpu_possible_mask)
|
||||
smp_call_function_single(cpu, bts_trace_start_cpu, NULL, 1);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ static void bts_trace_stop(struct trace_array *tr)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_cpu_mask(cpu, cpu_possible_map)
|
||||
for_each_cpu(cpu, cpu_possible_mask)
|
||||
smp_call_function_single(cpu, bts_trace_stop_cpu, NULL, 1);
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ static void trace_bts_prepare(struct trace_iterator *iter)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_cpu_mask(cpu, cpu_possible_map)
|
||||
for_each_cpu(cpu, cpu_possible_mask)
|
||||
smp_call_function_single(cpu, trace_bts_cpu, iter->tr, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ static int power_trace_init(struct trace_array *tr)
|
||||
|
||||
trace_power_enabled = 1;
|
||||
|
||||
for_each_cpu_mask(cpu, cpu_possible_map)
|
||||
for_each_cpu(cpu, cpu_possible_mask)
|
||||
tracing_reset(tr, cpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -196,9 +196,9 @@ static enum hrtimer_restart stack_trace_timer_fn(struct hrtimer *hrtimer)
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
static void start_stack_timer(int cpu)
|
||||
static void start_stack_timer(void *unused)
|
||||
{
|
||||
struct hrtimer *hrtimer = &per_cpu(stack_trace_hrtimer, cpu);
|
||||
struct hrtimer *hrtimer = &__get_cpu_var(stack_trace_hrtimer);
|
||||
|
||||
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
hrtimer->function = stack_trace_timer_fn;
|
||||
@@ -208,14 +208,7 @@ static void start_stack_timer(int cpu)
|
||||
|
||||
static void start_stack_timers(void)
|
||||
{
|
||||
cpumask_t saved_mask = current->cpus_allowed;
|
||||
int cpu;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
|
||||
start_stack_timer(cpu);
|
||||
}
|
||||
set_cpus_allowed_ptr(current, &saved_mask);
|
||||
on_each_cpu(start_stack_timer, NULL, 1);
|
||||
}
|
||||
|
||||
static void stop_stack_timer(int cpu)
|
||||
|
||||
+14
-12
@@ -73,7 +73,7 @@ static DEFINE_SPINLOCK(workqueue_lock);
|
||||
static LIST_HEAD(workqueues);
|
||||
|
||||
static int singlethread_cpu __read_mostly;
|
||||
static cpumask_t cpu_singlethread_map __read_mostly;
|
||||
static const struct cpumask *cpu_singlethread_map __read_mostly;
|
||||
/*
|
||||
* _cpu_down() first removes CPU from cpu_online_map, then CPU_DEAD
|
||||
* flushes cwq->worklist. This means that flush_workqueue/wait_on_work
|
||||
@@ -81,7 +81,7 @@ static cpumask_t cpu_singlethread_map __read_mostly;
|
||||
* use cpu_possible_map, the cpumask below is more a documentation
|
||||
* than optimization.
|
||||
*/
|
||||
static cpumask_t cpu_populated_map __read_mostly;
|
||||
static cpumask_var_t cpu_populated_map __read_mostly;
|
||||
|
||||
/* If it's single threaded, it isn't in the list of workqueues. */
|
||||
static inline int is_wq_single_threaded(struct workqueue_struct *wq)
|
||||
@@ -89,10 +89,10 @@ static inline int is_wq_single_threaded(struct workqueue_struct *wq)
|
||||
return wq->singlethread;
|
||||
}
|
||||
|
||||
static const cpumask_t *wq_cpu_map(struct workqueue_struct *wq)
|
||||
static const struct cpumask *wq_cpu_map(struct workqueue_struct *wq)
|
||||
{
|
||||
return is_wq_single_threaded(wq)
|
||||
? &cpu_singlethread_map : &cpu_populated_map;
|
||||
? cpu_singlethread_map : cpu_populated_map;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -410,7 +410,7 @@ static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
|
||||
*/
|
||||
void flush_workqueue(struct workqueue_struct *wq)
|
||||
{
|
||||
const cpumask_t *cpu_map = wq_cpu_map(wq);
|
||||
const struct cpumask *cpu_map = wq_cpu_map(wq);
|
||||
int cpu;
|
||||
|
||||
might_sleep();
|
||||
@@ -532,7 +532,7 @@ static void wait_on_work(struct work_struct *work)
|
||||
{
|
||||
struct cpu_workqueue_struct *cwq;
|
||||
struct workqueue_struct *wq;
|
||||
const cpumask_t *cpu_map;
|
||||
const struct cpumask *cpu_map;
|
||||
int cpu;
|
||||
|
||||
might_sleep();
|
||||
@@ -903,7 +903,7 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
|
||||
*/
|
||||
void destroy_workqueue(struct workqueue_struct *wq)
|
||||
{
|
||||
const cpumask_t *cpu_map = wq_cpu_map(wq);
|
||||
const struct cpumask *cpu_map = wq_cpu_map(wq);
|
||||
int cpu;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
@@ -933,7 +933,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
|
||||
|
||||
switch (action) {
|
||||
case CPU_UP_PREPARE:
|
||||
cpu_set(cpu, cpu_populated_map);
|
||||
cpumask_set_cpu(cpu, cpu_populated_map);
|
||||
}
|
||||
undo:
|
||||
list_for_each_entry(wq, &workqueues, list) {
|
||||
@@ -964,7 +964,7 @@ undo:
|
||||
switch (action) {
|
||||
case CPU_UP_CANCELED:
|
||||
case CPU_POST_DEAD:
|
||||
cpu_clear(cpu, cpu_populated_map);
|
||||
cpumask_clear_cpu(cpu, cpu_populated_map);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1017,9 +1017,11 @@ EXPORT_SYMBOL_GPL(work_on_cpu);
|
||||
|
||||
void __init init_workqueues(void)
|
||||
{
|
||||
cpu_populated_map = cpu_online_map;
|
||||
singlethread_cpu = first_cpu(cpu_possible_map);
|
||||
cpu_singlethread_map = cpumask_of_cpu(singlethread_cpu);
|
||||
alloc_cpumask_var(&cpu_populated_map, GFP_KERNEL);
|
||||
|
||||
cpumask_copy(cpu_populated_map, cpu_online_mask);
|
||||
singlethread_cpu = cpumask_first(cpu_possible_mask);
|
||||
cpu_singlethread_map = cpumask_of(singlethread_cpu);
|
||||
hotcpu_notifier(workqueue_cpu_callback, 0);
|
||||
keventd_wq = create_workqueue("events");
|
||||
BUG_ON(!keventd_wq);
|
||||
|
||||
Reference in New Issue
Block a user