Commit 9c8e30d1 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'akpm' (patches from Andrew)

Merge misc fixes from Andrew Morton:
 "15 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  mm: numa: mark huge PTEs young when clearing NUMA hinting faults
  mm: numa: slow PTE scan rate if migration failures occur
  mm: numa: preserve PTE write permissions across a NUMA hinting fault
  mm: numa: group related processes based on VMA flags instead of page table flags
  hfsplus: fix B-tree corruption after insertion at position 0
  MAINTAINERS: add Jan as DMI/SMBIOS support maintainer
  fs/affs/file.c: unlock/release page on error
  mm/page_alloc.c: call kernel_map_pages in unset_migrateype_isolate
  mm/slub: fix lockups on PREEMPT && !SMP kernels
  mm/memory hotplug: postpone the reset of obsolete pgdat
  MAINTAINERS: correct rtc armada38x pattern entry
  mm/pagewalk.c: prevent positive return value of walk_page_test() from being passed to callers
  mm: fix anon_vma->degree underflow in anon_vma endless growing prevention
  drivers/rtc/rtc-mrst: fix suspend/resume
  aoe: update aoe maintainer information
parents b8517e98 b7b04004
...@@ -1186,7 +1186,7 @@ M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> ...@@ -1186,7 +1186,7 @@ M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/mach-mvebu/ F: arch/arm/mach-mvebu/
F: drivers/rtc/armada38x-rtc F: drivers/rtc/rtc-armada38x.c
ARM/Marvell Berlin SoC support ARM/Marvell Berlin SoC support
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
...@@ -1675,8 +1675,8 @@ F: drivers/misc/eeprom/at24.c ...@@ -1675,8 +1675,8 @@ F: drivers/misc/eeprom/at24.c
F: include/linux/platform_data/at24.h F: include/linux/platform_data/at24.h
ATA OVER ETHERNET (AOE) DRIVER ATA OVER ETHERNET (AOE) DRIVER
M: "Ed L. Cashin" <ecashin@coraid.com> M: "Ed L. Cashin" <ed.cashin@acm.org>
W: http://support.coraid.com/support/linux W: http://www.openaoe.org/
S: Supported S: Supported
F: Documentation/aoe/ F: Documentation/aoe/
F: drivers/block/aoe/ F: drivers/block/aoe/
...@@ -3252,6 +3252,13 @@ S: Maintained ...@@ -3252,6 +3252,13 @@ S: Maintained
F: Documentation/hwmon/dme1737 F: Documentation/hwmon/dme1737
F: drivers/hwmon/dme1737.c F: drivers/hwmon/dme1737.c
DMI/SMBIOS SUPPORT
M: Jean Delvare <jdelvare@suse.de>
S: Maintained
F: drivers/firmware/dmi-id.c
F: drivers/firmware/dmi_scan.c
F: include/linux/dmi.h
DOCKING STATION DRIVER DOCKING STATION DRIVER
M: Shaohua Li <shaohua.li@intel.com> M: Shaohua Li <shaohua.li@intel.com>
L: linux-acpi@vger.kernel.org L: linux-acpi@vger.kernel.org
......
...@@ -413,8 +413,8 @@ static void rtc_mrst_do_remove(struct device *dev) ...@@ -413,8 +413,8 @@ static void rtc_mrst_do_remove(struct device *dev)
mrst->dev = NULL; mrst->dev = NULL;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int mrst_suspend(struct device *dev, pm_message_t mesg) static int mrst_suspend(struct device *dev)
{ {
struct mrst_rtc *mrst = dev_get_drvdata(dev); struct mrst_rtc *mrst = dev_get_drvdata(dev);
unsigned char tmp; unsigned char tmp;
...@@ -453,7 +453,7 @@ static int mrst_suspend(struct device *dev, pm_message_t mesg) ...@@ -453,7 +453,7 @@ static int mrst_suspend(struct device *dev, pm_message_t mesg)
*/ */
static inline int mrst_poweroff(struct device *dev) static inline int mrst_poweroff(struct device *dev)
{ {
return mrst_suspend(dev, PMSG_HIBERNATE); return mrst_suspend(dev);
} }
static int mrst_resume(struct device *dev) static int mrst_resume(struct device *dev)
...@@ -490,9 +490,11 @@ static int mrst_resume(struct device *dev) ...@@ -490,9 +490,11 @@ static int mrst_resume(struct device *dev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(mrst_pm_ops, mrst_suspend, mrst_resume);
#define MRST_PM_OPS (&mrst_pm_ops)
#else #else
#define mrst_suspend NULL #define MRST_PM_OPS NULL
#define mrst_resume NULL
static inline int mrst_poweroff(struct device *dev) static inline int mrst_poweroff(struct device *dev)
{ {
...@@ -529,9 +531,8 @@ static struct platform_driver vrtc_mrst_platform_driver = { ...@@ -529,9 +531,8 @@ static struct platform_driver vrtc_mrst_platform_driver = {
.remove = vrtc_mrst_platform_remove, .remove = vrtc_mrst_platform_remove,
.shutdown = vrtc_mrst_platform_shutdown, .shutdown = vrtc_mrst_platform_shutdown,
.driver = { .driver = {
.name = (char *) driver_name, .name = driver_name,
.suspend = mrst_suspend, .pm = MRST_PM_OPS,
.resume = mrst_resume,
} }
}; };
......
...@@ -699,8 +699,10 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, ...@@ -699,8 +699,10 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
boff = tmp % bsize; boff = tmp % bsize;
if (boff) { if (boff) {
bh = affs_bread_ino(inode, bidx, 0); bh = affs_bread_ino(inode, bidx, 0);
if (IS_ERR(bh)) if (IS_ERR(bh)) {
return PTR_ERR(bh); written = PTR_ERR(bh);
goto err_first_bh;
}
tmp = min(bsize - boff, to - from); tmp = min(bsize - boff, to - from);
BUG_ON(boff + tmp > bsize || tmp > bsize); BUG_ON(boff + tmp > bsize || tmp > bsize);
memcpy(AFFS_DATA(bh) + boff, data + from, tmp); memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
...@@ -712,14 +714,16 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, ...@@ -712,14 +714,16 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
bidx++; bidx++;
} else if (bidx) { } else if (bidx) {
bh = affs_bread_ino(inode, bidx - 1, 0); bh = affs_bread_ino(inode, bidx - 1, 0);
if (IS_ERR(bh)) if (IS_ERR(bh)) {
return PTR_ERR(bh); written = PTR_ERR(bh);
goto err_first_bh;
}
} }
while (from + bsize <= to) { while (from + bsize <= to) {
prev_bh = bh; prev_bh = bh;
bh = affs_getemptyblk_ino(inode, bidx); bh = affs_getemptyblk_ino(inode, bidx);
if (IS_ERR(bh)) if (IS_ERR(bh))
goto out; goto err_bh;
memcpy(AFFS_DATA(bh), data + from, bsize); memcpy(AFFS_DATA(bh), data + from, bsize);
if (buffer_new(bh)) { if (buffer_new(bh)) {
AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
...@@ -751,7 +755,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, ...@@ -751,7 +755,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
prev_bh = bh; prev_bh = bh;
bh = affs_bread_ino(inode, bidx, 1); bh = affs_bread_ino(inode, bidx, 1);
if (IS_ERR(bh)) if (IS_ERR(bh))
goto out; goto err_bh;
tmp = min(bsize, to - from); tmp = min(bsize, to - from);
BUG_ON(tmp > bsize); BUG_ON(tmp > bsize);
memcpy(AFFS_DATA(bh), data + from, tmp); memcpy(AFFS_DATA(bh), data + from, tmp);
...@@ -790,12 +794,13 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, ...@@ -790,12 +794,13 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
if (tmp > inode->i_size) if (tmp > inode->i_size)
inode->i_size = AFFS_I(inode)->mmu_private = tmp; inode->i_size = AFFS_I(inode)->mmu_private = tmp;
err_first_bh:
unlock_page(page); unlock_page(page);
page_cache_release(page); page_cache_release(page);
return written; return written;
out: err_bh:
bh = prev_bh; bh = prev_bh;
if (!written) if (!written)
written = PTR_ERR(bh); written = PTR_ERR(bh);
......
...@@ -131,13 +131,16 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len) ...@@ -131,13 +131,16 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
hfs_bnode_write(node, entry, data_off + key_len, entry_len); hfs_bnode_write(node, entry, data_off + key_len, entry_len);
hfs_bnode_dump(node); hfs_bnode_dump(node);
if (new_node) { /*
/* update parent key if we inserted a key * update parent key if we inserted a key
* at the start of the first node * at the start of the node and it is not the new node
*/ */
if (!rec && new_node != node) if (!rec && new_node != node) {
hfs_brec_update_parent(fd); hfs_bnode_read_key(node, fd->search_key, data_off + size);
hfs_brec_update_parent(fd);
}
if (new_node) {
hfs_bnode_put(fd->bnode); hfs_bnode_put(fd->bnode);
if (!new_node->parent) { if (!new_node->parent) {
hfs_btree_inc_height(tree); hfs_btree_inc_height(tree);
...@@ -168,9 +171,6 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len) ...@@ -168,9 +171,6 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
goto again; goto again;
} }
if (!rec)
hfs_brec_update_parent(fd);
return 0; return 0;
} }
...@@ -370,6 +370,8 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd) ...@@ -370,6 +370,8 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd)
if (IS_ERR(parent)) if (IS_ERR(parent))
return PTR_ERR(parent); return PTR_ERR(parent);
__hfs_brec_find(parent, fd, hfs_find_rec_by_key); __hfs_brec_find(parent, fd, hfs_find_rec_by_key);
if (fd->record < 0)
return -ENOENT;
hfs_bnode_dump(parent); hfs_bnode_dump(parent);
rec = fd->record; rec = fd->record;
......
...@@ -1625,11 +1625,11 @@ struct task_struct { ...@@ -1625,11 +1625,11 @@ struct task_struct {
/* /*
* numa_faults_locality tracks if faults recorded during the last * numa_faults_locality tracks if faults recorded during the last
* scan window were remote/local. The task scan period is adapted * scan window were remote/local or failed to migrate. The task scan
* based on the locality of the faults with different weights * period is adapted based on the locality of the faults with different
* depending on whether they were shared or private faults * weights depending on whether they were shared or private faults
*/ */
unsigned long numa_faults_locality[2]; unsigned long numa_faults_locality[3];
unsigned long numa_pages_migrated; unsigned long numa_pages_migrated;
#endif /* CONFIG_NUMA_BALANCING */ #endif /* CONFIG_NUMA_BALANCING */
...@@ -1719,6 +1719,7 @@ struct task_struct { ...@@ -1719,6 +1719,7 @@ struct task_struct {
#define TNF_NO_GROUP 0x02 #define TNF_NO_GROUP 0x02
#define TNF_SHARED 0x04 #define TNF_SHARED 0x04
#define TNF_FAULT_LOCAL 0x08 #define TNF_FAULT_LOCAL 0x08
#define TNF_MIGRATE_FAIL 0x10
#ifdef CONFIG_NUMA_BALANCING #ifdef CONFIG_NUMA_BALANCING
extern void task_numa_fault(int last_node, int node, int pages, int flags); extern void task_numa_fault(int last_node, int node, int pages, int flags);
......
...@@ -1609,9 +1609,11 @@ static void update_task_scan_period(struct task_struct *p, ...@@ -1609,9 +1609,11 @@ static void update_task_scan_period(struct task_struct *p,
/* /*
* If there were no record hinting faults then either the task is * If there were no record hinting faults then either the task is
* completely idle or all activity is areas that are not of interest * completely idle or all activity is areas that are not of interest
* to automatic numa balancing. Scan slower * to automatic numa balancing. Related to that, if there were failed
* migration then it implies we are migrating too quickly or the local
* node is overloaded. In either case, scan slower
*/ */
if (local + shared == 0) { if (local + shared == 0 || p->numa_faults_locality[2]) {
p->numa_scan_period = min(p->numa_scan_period_max, p->numa_scan_period = min(p->numa_scan_period_max,
p->numa_scan_period << 1); p->numa_scan_period << 1);
...@@ -2080,6 +2082,8 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags) ...@@ -2080,6 +2082,8 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
if (migrated) if (migrated)
p->numa_pages_migrated += pages; p->numa_pages_migrated += pages;
if (flags & TNF_MIGRATE_FAIL)
p->numa_faults_locality[2] += pages;
p->numa_faults[task_faults_idx(NUMA_MEMBUF, mem_node, priv)] += pages; p->numa_faults[task_faults_idx(NUMA_MEMBUF, mem_node, priv)] += pages;
p->numa_faults[task_faults_idx(NUMA_CPUBUF, cpu_node, priv)] += pages; p->numa_faults[task_faults_idx(NUMA_CPUBUF, cpu_node, priv)] += pages;
......
...@@ -1260,6 +1260,7 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -1260,6 +1260,7 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
int target_nid, last_cpupid = -1; int target_nid, last_cpupid = -1;
bool page_locked; bool page_locked;
bool migrated = false; bool migrated = false;
bool was_writable;
int flags = 0; int flags = 0;
/* A PROT_NONE fault should not end up here */ /* A PROT_NONE fault should not end up here */
...@@ -1291,17 +1292,8 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -1291,17 +1292,8 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
flags |= TNF_FAULT_LOCAL; flags |= TNF_FAULT_LOCAL;
} }
/* /* See similar comment in do_numa_page for explanation */
* Avoid grouping on DSO/COW pages in specific and RO pages if (!(vma->vm_flags & VM_WRITE))
* in general, RO pages shouldn't hurt as much anyway since
* they can be in shared cache state.
*
* FIXME! This checks "pmd_dirty()" as an approximation of
* "is this a read-only page", since checking "pmd_write()"
* is even more broken. We haven't actually turned this into
* a writable page, so pmd_write() will always be false.
*/
if (!pmd_dirty(pmd))
flags |= TNF_NO_GROUP; flags |= TNF_NO_GROUP;
/* /*
...@@ -1358,12 +1350,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -1358,12 +1350,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (migrated) { if (migrated) {
flags |= TNF_MIGRATED; flags |= TNF_MIGRATED;
page_nid = target_nid; page_nid = target_nid;
} } else
flags |= TNF_MIGRATE_FAIL;
goto out; goto out;
clear_pmdnuma: clear_pmdnuma:
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
was_writable = pmd_write(pmd);
pmd = pmd_modify(pmd, vma->vm_page_prot); pmd = pmd_modify(pmd, vma->vm_page_prot);
pmd = pmd_mkyoung(pmd);
if (was_writable)
pmd = pmd_mkwrite(pmd);
set_pmd_at(mm, haddr, pmdp, pmd); set_pmd_at(mm, haddr, pmdp, pmd);
update_mmu_cache_pmd(vma, addr, pmdp); update_mmu_cache_pmd(vma, addr, pmdp);
unlock_page(page); unlock_page(page);
...@@ -1487,6 +1484,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, ...@@ -1487,6 +1484,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
pmd_t entry; pmd_t entry;
bool preserve_write = prot_numa && pmd_write(*pmd);
ret = 1; ret = 1;
/* /*
...@@ -1502,9 +1500,11 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, ...@@ -1502,9 +1500,11 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
if (!prot_numa || !pmd_protnone(*pmd)) { if (!prot_numa || !pmd_protnone(*pmd)) {
entry = pmdp_get_and_clear_notify(mm, addr, pmd); entry = pmdp_get_and_clear_notify(mm, addr, pmd);
entry = pmd_modify(entry, newprot); entry = pmd_modify(entry, newprot);
if (preserve_write)
entry = pmd_mkwrite(entry);
ret = HPAGE_PMD_NR; ret = HPAGE_PMD_NR;
set_pmd_at(mm, addr, pmd, entry); set_pmd_at(mm, addr, pmd, entry);
BUG_ON(pmd_write(entry)); BUG_ON(!preserve_write && pmd_write(entry));
} }
spin_unlock(ptl); spin_unlock(ptl);
} }
......
...@@ -3035,6 +3035,7 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -3035,6 +3035,7 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
int last_cpupid; int last_cpupid;
int target_nid; int target_nid;
bool migrated = false; bool migrated = false;
bool was_writable = pte_write(pte);
int flags = 0; int flags = 0;
/* A PROT_NONE fault should not end up here */ /* A PROT_NONE fault should not end up here */
...@@ -3059,6 +3060,8 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -3059,6 +3060,8 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
/* Make it present again */ /* Make it present again */
pte = pte_modify(pte, vma->vm_page_prot); pte = pte_modify(pte, vma->vm_page_prot);
pte = pte_mkyoung(pte); pte = pte_mkyoung(pte);
if (was_writable)
pte = pte_mkwrite(pte);
set_pte_at(mm, addr, ptep, pte); set_pte_at(mm, addr, ptep, pte);
update_mmu_cache(vma, addr, ptep); update_mmu_cache(vma, addr, ptep);
...@@ -3069,16 +3072,14 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -3069,16 +3072,14 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
} }
/* /*
* Avoid grouping on DSO/COW pages in specific and RO pages * Avoid grouping on RO pages in general. RO pages shouldn't hurt as
* in general, RO pages shouldn't hurt as much anyway since * much anyway since they can be in shared cache state. This misses
* they can be in shared cache state. * the case where a mapping is writable but the process never writes
* * to it but pte_write gets cleared during protection updates and
* FIXME! This checks "pmd_dirty()" as an approximation of * pte_dirty has unpredictable behaviour between PTE scan updates,
* "is this a read-only page", since checking "pmd_write()" * background writeback, dirty balancing and application behaviour.
* is even more broken. We haven't actually turned this into
* a writable page, so pmd_write() will always be false.
*/ */
if (!pte_dirty(pte)) if (!(vma->vm_flags & VM_WRITE))
flags |= TNF_NO_GROUP; flags |= TNF_NO_GROUP;
/* /*
...@@ -3102,7 +3103,8 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, ...@@ -3102,7 +3103,8 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (migrated) { if (migrated) {
page_nid = target_nid; page_nid = target_nid;
flags |= TNF_MIGRATED; flags |= TNF_MIGRATED;
} } else
flags |= TNF_MIGRATE_FAIL;
out: out:
if (page_nid != -1) if (page_nid != -1)
......
...@@ -1092,6 +1092,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) ...@@ -1092,6 +1092,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
return NULL; return NULL;
arch_refresh_nodedata(nid, pgdat); arch_refresh_nodedata(nid, pgdat);
} else {
/* Reset the nr_zones and classzone_idx to 0 before reuse */
pgdat->nr_zones = 0;
pgdat->classzone_idx = 0;
} }
/* we can use NODE_DATA(nid) from here */ /* we can use NODE_DATA(nid) from here */
...@@ -1977,15 +1981,6 @@ void try_offline_node(int nid) ...@@ -1977,15 +1981,6 @@ void try_offline_node(int nid)
if (is_vmalloc_addr(zone->wait_table)) if (is_vmalloc_addr(zone->wait_table))
vfree(zone->wait_table); vfree(zone->wait_table);
} }
/*
* Since there is no way to guarentee the address of pgdat/zone is not
* on stack of any kernel threads or used by other kernel objects
* without reference counting or other symchronizing method, do not
* reset node_data and free pgdat here. Just reset it to 0 and reuse
* the memory when the node is online again.
*/
memset(pgdat, 0, sizeof(*pgdat));
} }
EXPORT_SYMBOL(try_offline_node); EXPORT_SYMBOL(try_offline_node);
......
...@@ -774,10 +774,8 @@ again: remove_next = 1 + (end > next->vm_end); ...@@ -774,10 +774,8 @@ again: remove_next = 1 + (end > next->vm_end);
importer->anon_vma = exporter->anon_vma; importer->anon_vma = exporter->anon_vma;
error = anon_vma_clone(importer, exporter); error = anon_vma_clone(importer, exporter);
if (error) { if (error)
importer->anon_vma = NULL;
return error; return error;
}
} }
} }
......
...@@ -75,6 +75,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, ...@@ -75,6 +75,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
oldpte = *pte; oldpte = *pte;
if (pte_present(oldpte)) { if (pte_present(oldpte)) {
pte_t ptent; pte_t ptent;
bool preserve_write = prot_numa && pte_write(oldpte);
/* /*
* Avoid trapping faults against the zero or KSM * Avoid trapping faults against the zero or KSM
...@@ -94,6 +95,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, ...@@ -94,6 +95,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
ptent = ptep_modify_prot_start(mm, addr, pte); ptent = ptep_modify_prot_start(mm, addr, pte);
ptent = pte_modify(ptent, newprot); ptent = pte_modify(ptent, newprot);
if (preserve_write)
ptent = pte_mkwrite(ptent);
/* Avoid taking write faults for known dirty pages */ /* Avoid taking write faults for known dirty pages */
if (dirty_accountable && pte_dirty(ptent) && if (dirty_accountable && pte_dirty(ptent) &&
......
...@@ -103,6 +103,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype) ...@@ -103,6 +103,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
if (!is_migrate_isolate_page(buddy)) { if (!is_migrate_isolate_page(buddy)) {
__isolate_free_page(page, order); __isolate_free_page(page, order);
kernel_map_pages(page, (1 << order), 1);
set_page_refcounted(page); set_page_refcounted(page);
isolated_page = page; isolated_page = page;
} }
......
...@@ -265,8 +265,15 @@ int walk_page_range(unsigned long start, unsigned long end, ...@@ -265,8 +265,15 @@ int walk_page_range(unsigned long start, unsigned long end,
vma = vma->vm_next; vma = vma->vm_next;
err = walk_page_test(start, next, walk); err = walk_page_test(start, next, walk);
if (err > 0) if (err > 0) {
/*
* positive return values are purely for
* controlling the pagewalk, so should never
* be passed to the callers.
*/
err = 0;
continue; continue;
}
if (err < 0) if (err < 0)
break; break;
} }
......
...@@ -287,6 +287,13 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) ...@@ -287,6 +287,13 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
return 0; return 0;
enomem_failure: enomem_failure:
/*
* dst->anon_vma is dropped here otherwise its degree can be incorrectly
* decremented in unlink_anon_vmas().
* We can safely do this because callers of anon_vma_clone() don't care
* about dst->anon_vma if anon_vma_clone() failed.
*/
dst->anon_vma = NULL;
unlink_anon_vmas(dst); unlink_anon_vmas(dst);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -2449,7 +2449,8 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, ...@@ -2449,7 +2449,8 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
do { do {
tid = this_cpu_read(s->cpu_slab->tid); tid = this_cpu_read(s->cpu_slab->tid);
c = raw_cpu_ptr(s->cpu_slab); c = raw_cpu_ptr(s->cpu_slab);
} while (IS_ENABLED(CONFIG_PREEMPT) && unlikely(tid != c->tid)); } while (IS_ENABLED(CONFIG_PREEMPT) &&
unlikely(tid != READ_ONCE(c->tid)));
/* /*
* Irqless object alloc/free algorithm used here depends on sequence * Irqless object alloc/free algorithm used here depends on sequence
...@@ -2718,7 +2719,8 @@ static __always_inline void slab_free(struct kmem_cache *s, ...@@ -2718,7 +2719,8 @@ static __always_inline void slab_free(struct kmem_cache *s,
do { do {
tid = this_cpu_read(s->cpu_slab->tid); tid = this_cpu_read(s->cpu_slab->tid);
c = raw_cpu_ptr(s->cpu_slab); c = raw_cpu_ptr(s->cpu_slab);
} while (IS_ENABLED(CONFIG_PREEMPT) && unlikely(tid != c->tid)); } while (IS_ENABLED(CONFIG_PREEMPT) &&
unlikely(tid != READ_ONCE(c->tid)));
/* Same with comment on barrier() in slab_alloc_node() */ /* Same with comment on barrier() in slab_alloc_node() */
barrier(); barrier();
......
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