Commit 706489d8 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] slab: extended cpu notifiers

Patch from Dipankar Sarma  <dipankar@in.ibm.com>

This is Manfred's patch which provides a CPU_UP_PREPARE cpu notifier to
allow initialization of per_cpu data just before the cpu becomes fully
functional.

It also provides a facility for the CPU_UP_PREPARE handler to return
NOTIFY_BAD to signify that the CPU is not permitted to come up.  If
that happens, a CPU_UP_CANCELLED message is passed to all the handlers.

The patch also fixes a bogus NOFITY_BAD return from the softirq setup
code.

Patch has been acked by Rusty.

We need this mechanism in slab for starting per-cpu timers and for
allocating the per-cpu slab hgead arrays *before* the CPU has come up
and started using slab.
parent c51fcfae
......@@ -60,7 +60,11 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi
#define NETLINK_URELEASE 0x0001 /* Unicast netlink socket released */
#define CPU_ONLINE 0x0002 /* CPU (unsigned)v coming up */
#define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */
#define CPU_UP_PREPARE 0x0003 /* CPU (unsigned)v coming up */
#define CPU_UP_CANCELED 0x0004 /* CPU (unsigned)v NOT coming up */
#define CPU_OFFLINE 0x0005 /* CPU (unsigned)v offline (still scheduling) */
#define CPU_DEAD 0x0006 /* CPU (unsigned)v dead */
#endif /* __KERNEL__ */
#endif /* _LINUX_NOTIFIER_H */
......@@ -29,6 +29,7 @@ void unregister_cpu_notifier(struct notifier_block *nb)
int __devinit cpu_up(unsigned int cpu)
{
int ret;
void *hcpu = (void *)(long)cpu;
if ((ret = down_interruptible(&cpucontrol)) != 0)
return ret;
......@@ -37,18 +38,29 @@ int __devinit cpu_up(unsigned int cpu)
ret = -EINVAL;
goto out;
}
ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
if (ret == NOTIFY_BAD) {
printk("%s: attempt to bring up CPU %u failed\n",
__FUNCTION__, cpu);
ret = -EINVAL;
goto out_notify;
}
/* Arch-specific enabling code. */
ret = __cpu_up(cpu);
if (ret != 0) goto out;
if (ret != 0)
goto out_notify;
if (!cpu_online(cpu))
BUG();
/* Now call notifier in preparation. */
printk("CPU %u IS NOW UP!\n", cpu);
notifier_call_chain(&cpu_chain, CPU_ONLINE, (void *)(long)cpu);
notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
out:
out_notify:
if (ret != 0)
notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu);
out:
up(&cpucontrol);
return ret;
}
......@@ -316,9 +316,8 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
while (!ksoftirqd_task(hotcpu))
yield();
return NOTIFY_OK;
}
return NOTIFY_BAD;
return NOTIFY_OK;
}
static struct notifier_block cpu_nfb = { &cpu_callback, NULL, 0 };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment