Commit 1eb0b69c authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://gkernel.bkbits.net/libata-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 8904925c bf2efbc5
...@@ -127,7 +127,9 @@ static void set_brk(unsigned long start, unsigned long end) ...@@ -127,7 +127,9 @@ static void set_brk(unsigned long start, unsigned long end)
end = PAGE_ALIGN(end); end = PAGE_ALIGN(end);
if (end <= start) if (end <= start)
return; return;
down_write(&current->mm->mmap_sem);
do_brk(start, end - start); do_brk(start, end - start);
up_write(&current->mm->mmap_sem);
} }
...@@ -375,7 +377,9 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, ...@@ -375,7 +377,9 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
/* Map the last of the bss segment */ /* Map the last of the bss segment */
if (last_bss > len) { if (last_bss > len) {
down_write(&current->mm->mmap_sem);
do_brk(len, (last_bss - len)); do_brk(len, (last_bss - len));
up_write(&current->mm->mmap_sem);
} }
kfree(elf_phdata); kfree(elf_phdata);
...@@ -562,7 +566,9 @@ void irix_map_prda_page (void) ...@@ -562,7 +566,9 @@ void irix_map_prda_page (void)
unsigned long v; unsigned long v;
struct prda *pp; struct prda *pp;
down_write(&current->mm->mmap_sem);
v = do_brk (PRDA_ADDRESS, PAGE_SIZE); v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
up_write(&current->mm->mmap_sem);
if (v < 0) if (v < 0)
return; return;
...@@ -852,8 +858,11 @@ static int load_irix_library(struct file *file) ...@@ -852,8 +858,11 @@ static int load_irix_library(struct file *file)
len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
if (bss > len) if (bss > len) {
down_write(&current->mm->mmap_sem);
do_brk(len, bss-len); do_brk(len, bss-len);
up_write(&current->mm->mmap_sem);
}
kfree(elf_phdata); kfree(elf_phdata);
return 0; return 0;
} }
......
...@@ -49,7 +49,9 @@ static void set_brk(unsigned long start, unsigned long end) ...@@ -49,7 +49,9 @@ static void set_brk(unsigned long start, unsigned long end)
end = PAGE_ALIGN(end); end = PAGE_ALIGN(end);
if (end <= start) if (end <= start)
return; return;
down_write(&current->mm->mmap_sem);
do_brk(start, end - start); do_brk(start, end - start);
up_write(&current->mm->mmap_sem);
} }
/* /*
...@@ -246,10 +248,14 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -246,10 +248,14 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (N_MAGIC(ex) == NMAGIC) { if (N_MAGIC(ex) == NMAGIC) {
loff_t pos = fd_offset; loff_t pos = fd_offset;
/* Fuck me plenty... */ /* Fuck me plenty... */
down_write(&current->mm->mmap_sem);
error = do_brk(N_TXTADDR(ex), ex.a_text); error = do_brk(N_TXTADDR(ex), ex.a_text);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
ex.a_text, &pos); ex.a_text, &pos);
down_write(&current->mm->mmap_sem);
error = do_brk(N_DATADDR(ex), ex.a_data); error = do_brk(N_DATADDR(ex), ex.a_data);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex), bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
ex.a_data, &pos); ex.a_data, &pos);
goto beyond_if; goto beyond_if;
...@@ -257,8 +263,10 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -257,8 +263,10 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (N_MAGIC(ex) == OMAGIC) { if (N_MAGIC(ex) == OMAGIC) {
loff_t pos = fd_offset; loff_t pos = fd_offset;
down_write(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex) & PAGE_MASK, do_brk(N_TXTADDR(ex) & PAGE_MASK,
ex.a_text+ex.a_data + PAGE_SIZE - 1); ex.a_text+ex.a_data + PAGE_SIZE - 1);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos); ex.a_text+ex.a_data, &pos);
} else { } else {
...@@ -272,7 +280,9 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -272,7 +280,9 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!bprm->file->f_op->mmap) { if (!bprm->file->f_op->mmap) {
loff_t pos = fd_offset; loff_t pos = fd_offset;
down_write(&current->mm->mmap_sem);
do_brk(0, ex.a_text+ex.a_data); do_brk(0, ex.a_text+ex.a_data);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, bprm->file->f_op->read(bprm->file,
(char __user *)N_TXTADDR(ex), (char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos); ex.a_text+ex.a_data, &pos);
...@@ -389,7 +399,9 @@ static int load_aout32_library(struct file *file) ...@@ -389,7 +399,9 @@ static int load_aout32_library(struct file *file)
len = PAGE_ALIGN(ex.a_text + ex.a_data); len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss; bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) { if (bss > len) {
down_write(&current->mm->mmap_sem);
error = do_brk(start_addr + len, bss - len); error = do_brk(start_addr + len, bss - len);
up_write(&current->mm->mmap_sem);
retval = error; retval = error;
if (error != start_addr + len) if (error != start_addr + len)
goto out; goto out;
......
...@@ -115,7 +115,9 @@ static void set_brk(unsigned long start, unsigned long end) ...@@ -115,7 +115,9 @@ static void set_brk(unsigned long start, unsigned long end)
end = PAGE_ALIGN(end); end = PAGE_ALIGN(end);
if (end <= start) if (end <= start)
return; return;
down_write(&current->mm->mmap_sem);
do_brk(start, end - start); do_brk(start, end - start);
up_write(&current->mm->mmap_sem);
} }
#if CORE_DUMP #if CORE_DUMP
...@@ -325,7 +327,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -325,7 +327,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
pos = 32; pos = 32;
map_size = ex.a_text+ex.a_data; map_size = ex.a_text+ex.a_data;
down_write(&current->mm->mmap_sem);
error = do_brk(text_addr & PAGE_MASK, map_size); error = do_brk(text_addr & PAGE_MASK, map_size);
up_write(&current->mm->mmap_sem);
if (error != (text_addr & PAGE_MASK)) { if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0); send_sig(SIGKILL, current, 0);
return error; return error;
...@@ -361,7 +366,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -361,7 +366,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
loff_t pos = fd_offset; loff_t pos = fd_offset;
down_write(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex), bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos); ex.a_text+ex.a_data, &pos);
flush_icache_range((unsigned long) N_TXTADDR(ex), flush_icache_range((unsigned long) N_TXTADDR(ex),
...@@ -469,8 +476,9 @@ static int load_aout_library(struct file *file) ...@@ -469,8 +476,9 @@ static int load_aout_library(struct file *file)
error_time = jiffies; error_time = jiffies;
} }
#endif #endif
down_write(&current->mm->mmap_sem);
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
up_write(&current->mm->mmap_sem);
file->f_op->read(file, (char *)start_addr, file->f_op->read(file, (char *)start_addr,
ex.a_text + ex.a_data, &pos); ex.a_text + ex.a_data, &pos);
...@@ -494,7 +502,9 @@ static int load_aout_library(struct file *file) ...@@ -494,7 +502,9 @@ static int load_aout_library(struct file *file)
len = PAGE_ALIGN(ex.a_text + ex.a_data); len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss; bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) { if (bss > len) {
down_write(&current->mm->mmap_sem);
error = do_brk(start_addr + len, bss - len); error = do_brk(start_addr + len, bss - len);
up_write(&current->mm->mmap_sem);
retval = error; retval = error;
if (error != start_addr + len) if (error != start_addr + len)
goto out; goto out;
......
...@@ -47,6 +47,10 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) ...@@ -47,6 +47,10 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
int nodeid, i, nb; int nodeid, i, nb;
int found = 0; int found = 0;
u32 reg; u32 reg;
unsigned numnodes;
nodemask_t nodes_parsed;
nodes_clear(nodes_parsed);
nb = find_northbridge(); nb = find_northbridge();
if (nb < 0) if (nb < 0)
...@@ -55,10 +59,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) ...@@ -55,10 +59,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb); printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb);
reg = read_pci_config(0, nb, 0, 0x60); reg = read_pci_config(0, nb, 0, 0x60);
for (i = 0; i <= ((reg >> 4) & 7); i++) numnodes = ((reg >> 4) & 7) + 1;
node_set_online(i);
printk(KERN_INFO "Number of nodes %d (%x)\n", num_online_nodes(), reg); printk(KERN_INFO "Number of nodes %d\n", numnodes);
memset(&nodes,0,sizeof(nodes)); memset(&nodes,0,sizeof(nodes));
prevbase = 0; prevbase = 0;
...@@ -70,11 +73,11 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) ...@@ -70,11 +73,11 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodeid = limit & 7; nodeid = limit & 7;
if ((base & 3) == 0) { if ((base & 3) == 0) {
if (i < num_online_nodes()) if (i < numnodes)
printk("Skipping disabled node %d\n", i); printk("Skipping disabled node %d\n", i);
continue; continue;
} }
if (nodeid >= num_online_nodes()) { if (nodeid >= numnodes) {
printk("Ignoring excess node %d (%lx:%lx)\n", nodeid, printk("Ignoring excess node %d (%lx:%lx)\n", nodeid,
base, limit); base, limit);
continue; continue;
...@@ -90,7 +93,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) ...@@ -90,7 +93,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodeid, (base>>8)&3, (limit>>8) & 3); nodeid, (base>>8)&3, (limit>>8) & 3);
return -1; return -1;
} }
if (node_online(nodeid)) { if (node_isset(nodeid, nodes_parsed)) {
printk(KERN_INFO "Node %d already present. Skipping\n", printk(KERN_INFO "Node %d already present. Skipping\n",
nodeid); nodeid);
continue; continue;
...@@ -138,12 +141,14 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) ...@@ -138,12 +141,14 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodes[nodeid].end = limit; nodes[nodeid].end = limit;
prevbase = base; prevbase = base;
node_set(nodeid, nodes_parsed);
} }
if (!found) if (!found)
return -1; return -1;
memnode_shift = compute_hash_shift(nodes); memnode_shift = compute_hash_shift(nodes, numnodes);
if (memnode_shift < 0) { if (memnode_shift < 0) {
printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n"); printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n");
return -1; return -1;
......
...@@ -34,9 +34,7 @@ cpumask_t node_to_cpumask[MAX_NUMNODES]; ...@@ -34,9 +34,7 @@ cpumask_t node_to_cpumask[MAX_NUMNODES];
int numa_off __initdata; int numa_off __initdata;
unsigned long nodes_present; int __init compute_hash_shift(struct node *nodes, int numnodes)
int __init compute_hash_shift(struct node *nodes)
{ {
int i; int i;
int shift = 24; int shift = 24;
...@@ -45,7 +43,7 @@ int __init compute_hash_shift(struct node *nodes) ...@@ -45,7 +43,7 @@ int __init compute_hash_shift(struct node *nodes)
/* When in doubt use brute force. */ /* When in doubt use brute force. */
while (shift < 48) { while (shift < 48) {
memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE);
for_each_online_node(i) { for (i = 0; i < numnodes; i++) {
if (nodes[i].start == nodes[i].end) if (nodes[i].start == nodes[i].end)
continue; continue;
for (addr = nodes[i].start; for (addr = nodes[i].start;
...@@ -197,7 +195,7 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) ...@@ -197,7 +195,7 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
(nodes[i].end - nodes[i].start) >> 20); (nodes[i].end - nodes[i].start) >> 20);
node_set_online(i); node_set_online(i);
} }
memnode_shift = compute_hash_shift(nodes); memnode_shift = compute_hash_shift(nodes, numa_fake);
if (memnode_shift < 0) { if (memnode_shift < 0) {
memnode_shift = 0; memnode_shift = 0;
printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n"); printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
...@@ -274,7 +272,7 @@ void __init paging_init(void) ...@@ -274,7 +272,7 @@ void __init paging_init(void)
/* [numa=off] */ /* [numa=off] */
__init int numa_setup(char *opt) __init int numa_setup(char *opt)
{ {
if (!strcmp(opt,"off")) if (!strncmp(opt,"off",3))
numa_off = 1; numa_off = 1;
#ifdef CONFIG_NUMA_EMU #ifdef CONFIG_NUMA_EMU
if(!strncmp(opt, "fake=", 5)) { if(!strncmp(opt, "fake=", 5)) {
......
...@@ -20,17 +20,20 @@ ...@@ -20,17 +20,20 @@
static struct acpi_table_slit *acpi_slit; static struct acpi_table_slit *acpi_slit;
static DECLARE_BITMAP(nodes_parsed, MAX_NUMNODES) __initdata; static nodemask_t nodes_parsed __initdata;
static nodemask_t nodes_found __initdata;
static struct node nodes[MAX_NUMNODES] __initdata; static struct node nodes[MAX_NUMNODES] __initdata;
static __u8 pxm2node[256] __initdata = { [0 ... 255] = 0xff }; static __u8 pxm2node[256] __initdata = { [0 ... 255] = 0xff };
static __init int setup_node(int pxm) static __init int setup_node(int pxm)
{ {
if (pxm2node[pxm] == 0xff) { unsigned node = pxm2node[pxm];
if (num_online_nodes() >= MAX_NUMNODES) if (node == 0xff) {
if (nodes_weight(nodes_found) >= MAX_NUMNODES)
return -1; return -1;
pxm2node[pxm] = num_online_nodes(); node = first_unset_node(nodes_found);
node_set_online(num_online_nodes()); node_set(node, nodes_found);
pxm2node[pxm] = node;
} }
return pxm2node[pxm]; return pxm2node[pxm];
} }
...@@ -140,7 +143,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) ...@@ -140,7 +143,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
return; return;
} }
nd = &nodes[node]; nd = &nodes[node];
if (!test_and_set_bit(node, &nodes_parsed)) { if (!node_test_and_set(node, nodes_parsed)) {
nd->start = start; nd->start = start;
nd->end = end; nd->end = end;
} else { } else {
...@@ -163,7 +166,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) ...@@ -163,7 +166,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
int i; int i;
if (acpi_numa <= 0) if (acpi_numa <= 0)
return -1; return -1;
memnode_shift = compute_hash_shift(nodes); memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed));
if (memnode_shift < 0) { if (memnode_shift < 0) {
printk(KERN_ERR printk(KERN_ERR
"SRAT: No NUMA node hash function found. Contact maintainer\n"); "SRAT: No NUMA node hash function found. Contact maintainer\n");
...@@ -171,7 +174,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) ...@@ -171,7 +174,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
return -1; return -1;
} }
for (i = 0; i < MAX_NUMNODES; i++) { for (i = 0; i < MAX_NUMNODES; i++) {
if (!test_bit(i, &nodes_parsed)) if (!node_isset(i, nodes_parsed))
continue; continue;
cutoff_node(i, start, end); cutoff_node(i, start, end);
if (nodes[i].start == nodes[i].end) if (nodes[i].start == nodes[i].end)
......
...@@ -50,7 +50,10 @@ static int set_brk(unsigned long start, unsigned long end) ...@@ -50,7 +50,10 @@ static int set_brk(unsigned long start, unsigned long end)
start = PAGE_ALIGN(start); start = PAGE_ALIGN(start);
end = PAGE_ALIGN(end); end = PAGE_ALIGN(end);
if (end > start) { if (end > start) {
unsigned long addr = do_brk(start, end - start); unsigned long addr;
down_write(&current->mm->mmap_sem);
addr = do_brk(start, end - start);
up_write(&current->mm->mmap_sem);
if (BAD_ADDR(addr)) if (BAD_ADDR(addr))
return addr; return addr;
} }
...@@ -323,10 +326,14 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -323,10 +326,14 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
loff_t pos = fd_offset; loff_t pos = fd_offset;
/* Fuck me plenty... */ /* Fuck me plenty... */
/* <AOL></AOL> */ /* <AOL></AOL> */
down_write(&current->mm->mmap_sem);
error = do_brk(N_TXTADDR(ex), ex.a_text); error = do_brk(N_TXTADDR(ex), ex.a_text);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex), bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
ex.a_text, &pos); ex.a_text, &pos);
down_write(&current->mm->mmap_sem);
error = do_brk(N_DATADDR(ex), ex.a_data); error = do_brk(N_DATADDR(ex), ex.a_data);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex), bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
ex.a_data, &pos); ex.a_data, &pos);
goto beyond_if; goto beyond_if;
...@@ -346,8 +353,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -346,8 +353,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
pos = 32; pos = 32;
map_size = ex.a_text+ex.a_data; map_size = ex.a_text+ex.a_data;
#endif #endif
down_write(&current->mm->mmap_sem);
error = do_brk(text_addr & PAGE_MASK, map_size); error = do_brk(text_addr & PAGE_MASK, map_size);
up_write(&current->mm->mmap_sem);
if (error != (text_addr & PAGE_MASK)) { if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0); send_sig(SIGKILL, current, 0);
return error; return error;
...@@ -382,7 +390,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -382,7 +390,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
loff_t pos = fd_offset; loff_t pos = fd_offset;
down_write(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, bprm->file->f_op->read(bprm->file,
(char __user *)N_TXTADDR(ex), (char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos); ex.a_text+ex.a_data, &pos);
...@@ -487,8 +497,9 @@ static int load_aout_library(struct file *file) ...@@ -487,8 +497,9 @@ static int load_aout_library(struct file *file)
file->f_dentry->d_name.name); file->f_dentry->d_name.name);
error_time = jiffies; error_time = jiffies;
} }
down_write(&current->mm->mmap_sem);
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
up_write(&current->mm->mmap_sem);
file->f_op->read(file, (char __user *)start_addr, file->f_op->read(file, (char __user *)start_addr,
ex.a_text + ex.a_data, &pos); ex.a_text + ex.a_data, &pos);
......
...@@ -88,7 +88,10 @@ static int set_brk(unsigned long start, unsigned long end) ...@@ -88,7 +88,10 @@ static int set_brk(unsigned long start, unsigned long end)
start = ELF_PAGEALIGN(start); start = ELF_PAGEALIGN(start);
end = ELF_PAGEALIGN(end); end = ELF_PAGEALIGN(end);
if (end > start) { if (end > start) {
unsigned long addr = do_brk(start, end - start); unsigned long addr;
down_write(&current->mm->mmap_sem);
addr = do_brk(start, end - start);
up_write(&current->mm->mmap_sem);
if (BAD_ADDR(addr)) if (BAD_ADDR(addr))
return addr; return addr;
} }
...@@ -409,7 +412,9 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, ...@@ -409,7 +412,9 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
/* Map the last of the bss segment */ /* Map the last of the bss segment */
if (last_bss > elf_bss) { if (last_bss > elf_bss) {
down_write(&current->mm->mmap_sem);
error = do_brk(elf_bss, last_bss - elf_bss); error = do_brk(elf_bss, last_bss - elf_bss);
up_write(&current->mm->mmap_sem);
if (BAD_ADDR(error)) if (BAD_ADDR(error))
goto out_close; goto out_close;
} }
...@@ -449,7 +454,9 @@ static unsigned long load_aout_interp(struct exec * interp_ex, ...@@ -449,7 +454,9 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
goto out; goto out;
} }
down_write(&current->mm->mmap_sem);
do_brk(0, text_data); do_brk(0, text_data);
up_write(&current->mm->mmap_sem);
if (!interpreter->f_op || !interpreter->f_op->read) if (!interpreter->f_op || !interpreter->f_op->read)
goto out; goto out;
if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0) if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
...@@ -457,8 +464,11 @@ static unsigned long load_aout_interp(struct exec * interp_ex, ...@@ -457,8 +464,11 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
flush_icache_range((unsigned long)addr, flush_icache_range((unsigned long)addr,
(unsigned long)addr + text_data); (unsigned long)addr + text_data);
down_write(&current->mm->mmap_sem);
do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
interp_ex->a_bss); interp_ex->a_bss);
up_write(&current->mm->mmap_sem);
elf_entry = interp_ex->a_entry; elf_entry = interp_ex->a_entry;
out: out:
......
...@@ -8,7 +8,7 @@ struct node { ...@@ -8,7 +8,7 @@ struct node {
u64 start,end; u64 start,end;
}; };
extern int compute_hash_shift(struct node *nodes); extern int compute_hash_shift(struct node *nodes, int numnodes);
#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT)) #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
* *
* int first_node(mask) Number lowest set bit, or MAX_NUMNODES * int first_node(mask) Number lowest set bit, or MAX_NUMNODES
* int next_node(node, mask) Next node past 'node', or MAX_NUMNODES * int next_node(node, mask) Next node past 'node', or MAX_NUMNODES
* int first_unset_node(mask) First node not set in mask, or
* MAX_NUMNODES.
* *
* nodemask_t nodemask_of_node(node) Return nodemask with bit 'node' set * nodemask_t nodemask_of_node(node) Return nodemask with bit 'node' set
* NODE_MASK_ALL Initializer - all bits set * NODE_MASK_ALL Initializer - all bits set
...@@ -235,6 +237,13 @@ static inline int __next_node(int n, const nodemask_t *srcp, int nbits) ...@@ -235,6 +237,13 @@ static inline int __next_node(int n, const nodemask_t *srcp, int nbits)
m; \ m; \
}) })
#define first_unset_node(mask) __first_unset_node(&(mask))
static inline int __first_unset_node(const nodemask_t *maskp)
{
return min_t(int,MAX_NUMNODES,
find_first_zero_bit(maskp->bits, MAX_NUMNODES));
}
#define NODE_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(MAX_NUMNODES) #define NODE_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(MAX_NUMNODES)
#if MAX_NUMNODES <= BITS_PER_LONG #if MAX_NUMNODES <= BITS_PER_LONG
......
...@@ -1475,7 +1475,6 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un ...@@ -1475,7 +1475,6 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
int expand_stack(struct vm_area_struct * vma, unsigned long address) int expand_stack(struct vm_area_struct * vma, unsigned long address)
{ {
int error; int error;
unsigned long size, grow;
if (!(vma->vm_flags & VM_GROWSUP)) if (!(vma->vm_flags & VM_GROWSUP))
return -EFAULT; return -EFAULT;
...@@ -1495,12 +1494,19 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address) ...@@ -1495,12 +1494,19 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
*/ */
address += 4 + PAGE_SIZE - 1; address += 4 + PAGE_SIZE - 1;
address &= PAGE_MASK; address &= PAGE_MASK;
error = 0;
/* Somebody else might have raced and expanded it already */
if (address > vma->vm_end) {
unsigned long size, grow;
size = address - vma->vm_start; size = address - vma->vm_start;
grow = (address - vma->vm_end) >> PAGE_SHIFT; grow = (address - vma->vm_end) >> PAGE_SHIFT;
error = acct_stack_growth(vma, size, grow); error = acct_stack_growth(vma, size, grow);
if (!error) if (!error)
vma->vm_end = address; vma->vm_end = address;
}
anon_vma_unlock(vma); anon_vma_unlock(vma);
return error; return error;
} }
...@@ -1528,7 +1534,6 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr) ...@@ -1528,7 +1534,6 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
int expand_stack(struct vm_area_struct *vma, unsigned long address) int expand_stack(struct vm_area_struct *vma, unsigned long address)
{ {
int error; int error;
unsigned long size, grow;
/* /*
* We must make sure the anon_vma is allocated * We must make sure the anon_vma is allocated
...@@ -1544,6 +1549,12 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address) ...@@ -1544,6 +1549,12 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address)
* anon_vma lock to serialize against concurrent expand_stacks. * anon_vma lock to serialize against concurrent expand_stacks.
*/ */
address &= PAGE_MASK; address &= PAGE_MASK;
error = 0;
/* Somebody else might have raced and expanded it already */
if (address < vma->vm_start) {
unsigned long size, grow;
size = vma->vm_end - address; size = vma->vm_end - address;
grow = (vma->vm_start - address) >> PAGE_SHIFT; grow = (vma->vm_start - address) >> PAGE_SHIFT;
...@@ -1552,6 +1563,7 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address) ...@@ -1552,6 +1563,7 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address)
vma->vm_start = address; vma->vm_start = address;
vma->vm_pgoff -= grow; vma->vm_pgoff -= grow;
} }
}
anon_vma_unlock(vma); anon_vma_unlock(vma);
return error; return error;
} }
...@@ -1858,6 +1870,16 @@ asmlinkage long sys_munmap(unsigned long addr, size_t len) ...@@ -1858,6 +1870,16 @@ asmlinkage long sys_munmap(unsigned long addr, size_t len)
return ret; return ret;
} }
static inline void verify_mm_writelocked(struct mm_struct *mm)
{
#ifdef CONFIG_DEBUG_KERNEL
if (unlikely(down_read_trylock(&mm->mmap_sem))) {
WARN_ON(1);
up_read(&mm->mmap_sem);
}
#endif
}
/* /*
* this is really a simplified "do_mmap". it only handles * this is really a simplified "do_mmap". it only handles
* anonymous maps. eventually we may be able to do some * anonymous maps. eventually we may be able to do some
...@@ -1890,6 +1912,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) ...@@ -1890,6 +1912,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
return -EAGAIN; return -EAGAIN;
} }
/*
* mm->mmap_sem is required to protect against another thread
* changing the mappings in case we sleep.
*/
verify_mm_writelocked(mm);
/* /*
* Clear old maps. this also does some error checking for us * Clear old maps. this also does some error checking for us
*/ */
......
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