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
This commit is contained in:
commit
9c8e30d12d
13
MAINTAINERS
13
MAINTAINERS
|
@ -1186,7 +1186,7 @@ M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
|||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: arch/arm/mach-mvebu/
|
||||
F: drivers/rtc/armada38x-rtc
|
||||
F: drivers/rtc/rtc-armada38x.c
|
||||
|
||||
ARM/Marvell Berlin SoC support
|
||||
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
|
@ -1675,8 +1675,8 @@ F: drivers/misc/eeprom/at24.c
|
|||
F: include/linux/platform_data/at24.h
|
||||
|
||||
ATA OVER ETHERNET (AOE) DRIVER
|
||||
M: "Ed L. Cashin" <ecashin@coraid.com>
|
||||
W: http://support.coraid.com/support/linux
|
||||
M: "Ed L. Cashin" <ed.cashin@acm.org>
|
||||
W: http://www.openaoe.org/
|
||||
S: Supported
|
||||
F: Documentation/aoe/
|
||||
F: drivers/block/aoe/
|
||||
|
@ -3252,6 +3252,13 @@ S: Maintained
|
|||
F: Documentation/hwmon/dme1737
|
||||
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
|
||||
M: Shaohua Li <shaohua.li@intel.com>
|
||||
L: linux-acpi@vger.kernel.org
|
||||
|
|
|
@ -413,8 +413,8 @@ static void rtc_mrst_do_remove(struct device *dev)
|
|||
mrst->dev = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mrst_suspend(struct device *dev, pm_message_t mesg)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mrst_suspend(struct device *dev)
|
||||
{
|
||||
struct mrst_rtc *mrst = dev_get_drvdata(dev);
|
||||
unsigned char tmp;
|
||||
|
@ -453,7 +453,7 @@ static int mrst_suspend(struct device *dev, pm_message_t mesg)
|
|||
*/
|
||||
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)
|
||||
|
@ -490,9 +490,11 @@ static int mrst_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(mrst_pm_ops, mrst_suspend, mrst_resume);
|
||||
#define MRST_PM_OPS (&mrst_pm_ops)
|
||||
|
||||
#else
|
||||
#define mrst_suspend NULL
|
||||
#define mrst_resume NULL
|
||||
#define MRST_PM_OPS NULL
|
||||
|
||||
static inline int mrst_poweroff(struct device *dev)
|
||||
{
|
||||
|
@ -529,9 +531,8 @@ static struct platform_driver vrtc_mrst_platform_driver = {
|
|||
.remove = vrtc_mrst_platform_remove,
|
||||
.shutdown = vrtc_mrst_platform_shutdown,
|
||||
.driver = {
|
||||
.name = (char *) driver_name,
|
||||
.suspend = mrst_suspend,
|
||||
.resume = mrst_resume,
|
||||
.name = driver_name,
|
||||
.pm = MRST_PM_OPS,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -699,8 +699,10 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
|
|||
boff = tmp % bsize;
|
||||
if (boff) {
|
||||
bh = affs_bread_ino(inode, bidx, 0);
|
||||
if (IS_ERR(bh))
|
||||
return PTR_ERR(bh);
|
||||
if (IS_ERR(bh)) {
|
||||
written = PTR_ERR(bh);
|
||||
goto err_first_bh;
|
||||
}
|
||||
tmp = min(bsize - boff, to - from);
|
||||
BUG_ON(boff + tmp > bsize || tmp > bsize);
|
||||
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,
|
|||
bidx++;
|
||||
} else if (bidx) {
|
||||
bh = affs_bread_ino(inode, bidx - 1, 0);
|
||||
if (IS_ERR(bh))
|
||||
return PTR_ERR(bh);
|
||||
if (IS_ERR(bh)) {
|
||||
written = PTR_ERR(bh);
|
||||
goto err_first_bh;
|
||||
}
|
||||
}
|
||||
while (from + bsize <= to) {
|
||||
prev_bh = bh;
|
||||
bh = affs_getemptyblk_ino(inode, bidx);
|
||||
if (IS_ERR(bh))
|
||||
goto out;
|
||||
goto err_bh;
|
||||
memcpy(AFFS_DATA(bh), data + from, bsize);
|
||||
if (buffer_new(bh)) {
|
||||
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,
|
|||
prev_bh = bh;
|
||||
bh = affs_bread_ino(inode, bidx, 1);
|
||||
if (IS_ERR(bh))
|
||||
goto out;
|
||||
goto err_bh;
|
||||
tmp = min(bsize, to - from);
|
||||
BUG_ON(tmp > bsize);
|
||||
memcpy(AFFS_DATA(bh), data + from, tmp);
|
||||
|
@ -790,12 +794,13 @@ done:
|
|||
if (tmp > inode->i_size)
|
||||
inode->i_size = AFFS_I(inode)->mmu_private = tmp;
|
||||
|
||||
err_first_bh:
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
|
||||
return written;
|
||||
|
||||
out:
|
||||
err_bh:
|
||||
bh = prev_bh;
|
||||
if (!written)
|
||||
written = PTR_ERR(bh);
|
||||
|
|
|
@ -131,13 +131,16 @@ skip:
|
|||
hfs_bnode_write(node, entry, data_off + key_len, entry_len);
|
||||
hfs_bnode_dump(node);
|
||||
|
||||
if (new_node) {
|
||||
/* update parent key if we inserted a key
|
||||
* at the start of the first node
|
||||
*/
|
||||
if (!rec && new_node != node)
|
||||
hfs_brec_update_parent(fd);
|
||||
/*
|
||||
* update parent key if we inserted a key
|
||||
* at the start of the node and it is not the new node
|
||||
*/
|
||||
if (!rec && new_node != node) {
|
||||
hfs_bnode_read_key(node, fd->search_key, data_off + size);
|
||||
hfs_brec_update_parent(fd);
|
||||
}
|
||||
|
||||
if (new_node) {
|
||||
hfs_bnode_put(fd->bnode);
|
||||
if (!new_node->parent) {
|
||||
hfs_btree_inc_height(tree);
|
||||
|
@ -168,9 +171,6 @@ skip:
|
|||
goto again;
|
||||
}
|
||||
|
||||
if (!rec)
|
||||
hfs_brec_update_parent(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -370,6 +370,8 @@ again:
|
|||
if (IS_ERR(parent))
|
||||
return PTR_ERR(parent);
|
||||
__hfs_brec_find(parent, fd, hfs_find_rec_by_key);
|
||||
if (fd->record < 0)
|
||||
return -ENOENT;
|
||||
hfs_bnode_dump(parent);
|
||||
rec = fd->record;
|
||||
|
||||
|
|
|
@ -1625,11 +1625,11 @@ struct task_struct {
|
|||
|
||||
/*
|
||||
* numa_faults_locality tracks if faults recorded during the last
|
||||
* scan window were remote/local. The task scan period is adapted
|
||||
* based on the locality of the faults with different weights
|
||||
* depending on whether they were shared or private faults
|
||||
* scan window were remote/local or failed to migrate. The task scan
|
||||
* period is adapted based on the locality of the faults with different
|
||||
* 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;
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
@ -1719,6 +1719,7 @@ struct task_struct {
|
|||
#define TNF_NO_GROUP 0x02
|
||||
#define TNF_SHARED 0x04
|
||||
#define TNF_FAULT_LOCAL 0x08
|
||||
#define TNF_MIGRATE_FAIL 0x10
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
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,
|
|||
/*
|
||||
* If there were no record hinting faults then either the task is
|
||||
* 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 << 1);
|
||||
|
||||
|
@ -2080,6 +2082,8 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
|
|||
|
||||
if (migrated)
|
||||
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_CPUBUF, cpu_node, priv)] += pages;
|
||||
|
|
|
@ -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;
|
||||
bool page_locked;
|
||||
bool migrated = false;
|
||||
bool was_writable;
|
||||
int flags = 0;
|
||||
|
||||
/* 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,
|
|||
flags |= TNF_FAULT_LOCAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid grouping on DSO/COW pages in specific and RO pages
|
||||
* 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))
|
||||
/* See similar comment in do_numa_page for explanation */
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
flags |= TNF_NO_GROUP;
|
||||
|
||||
/*
|
||||
|
@ -1358,12 +1350,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||
if (migrated) {
|
||||
flags |= TNF_MIGRATED;
|
||||
page_nid = target_nid;
|
||||
}
|
||||
} else
|
||||
flags |= TNF_MIGRATE_FAIL;
|
||||
|
||||
goto out;
|
||||
clear_pmdnuma:
|
||||
BUG_ON(!PageLocked(page));
|
||||
was_writable = pmd_write(pmd);
|
||||
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);
|
||||
update_mmu_cache_pmd(vma, addr, pmdp);
|
||||
unlock_page(page);
|
||||
|
@ -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) {
|
||||
pmd_t entry;
|
||||
bool preserve_write = prot_numa && pmd_write(*pmd);
|
||||
ret = 1;
|
||||
|
||||
/*
|
||||
|
@ -1502,9 +1500,11 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|||
if (!prot_numa || !pmd_protnone(*pmd)) {
|
||||
entry = pmdp_get_and_clear_notify(mm, addr, pmd);
|
||||
entry = pmd_modify(entry, newprot);
|
||||
if (preserve_write)
|
||||
entry = pmd_mkwrite(entry);
|
||||
ret = HPAGE_PMD_NR;
|
||||
set_pmd_at(mm, addr, pmd, entry);
|
||||
BUG_ON(pmd_write(entry));
|
||||
BUG_ON(!preserve_write && pmd_write(entry));
|
||||
}
|
||||
spin_unlock(ptl);
|
||||
}
|
||||
|
|
22
mm/memory.c
22
mm/memory.c
|
@ -3035,6 +3035,7 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||
int last_cpupid;
|
||||
int target_nid;
|
||||
bool migrated = false;
|
||||
bool was_writable = pte_write(pte);
|
||||
int flags = 0;
|
||||
|
||||
/* 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,
|
|||
/* Make it present again */
|
||||
pte = pte_modify(pte, vma->vm_page_prot);
|
||||
pte = pte_mkyoung(pte);
|
||||
if (was_writable)
|
||||
pte = pte_mkwrite(pte);
|
||||
set_pte_at(mm, addr, ptep, pte);
|
||||
update_mmu_cache(vma, addr, ptep);
|
||||
|
||||
|
@ -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
|
||||
* 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.
|
||||
* Avoid grouping on RO pages in general. RO pages shouldn't hurt as
|
||||
* much anyway since they can be in shared cache state. This misses
|
||||
* the case where a mapping is writable but the process never writes
|
||||
* to it but pte_write gets cleared during protection updates and
|
||||
* pte_dirty has unpredictable behaviour between PTE scan updates,
|
||||
* background writeback, dirty balancing and application behaviour.
|
||||
*/
|
||||
if (!pte_dirty(pte))
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
flags |= TNF_NO_GROUP;
|
||||
|
||||
/*
|
||||
|
@ -3102,7 +3103,8 @@ static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||
if (migrated) {
|
||||
page_nid = target_nid;
|
||||
flags |= TNF_MIGRATED;
|
||||
}
|
||||
} else
|
||||
flags |= TNF_MIGRATE_FAIL;
|
||||
|
||||
out:
|
||||
if (page_nid != -1)
|
||||
|
|
|
@ -1092,6 +1092,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
|
|||
return NULL;
|
||||
|
||||
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 */
|
||||
|
@ -1977,15 +1981,6 @@ void try_offline_node(int nid)
|
|||
if (is_vmalloc_addr(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);
|
||||
|
||||
|
|
|
@ -774,10 +774,8 @@ again: remove_next = 1 + (end > next->vm_end);
|
|||
|
||||
importer->anon_vma = exporter->anon_vma;
|
||||
error = anon_vma_clone(importer, exporter);
|
||||
if (error) {
|
||||
importer->anon_vma = NULL;
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
|
|||
oldpte = *pte;
|
||||
if (pte_present(oldpte)) {
|
||||
pte_t ptent;
|
||||
bool preserve_write = prot_numa && pte_write(oldpte);
|
||||
|
||||
/*
|
||||
* 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,
|
|||
|
||||
ptent = ptep_modify_prot_start(mm, addr, pte);
|
||||
ptent = pte_modify(ptent, newprot);
|
||||
if (preserve_write)
|
||||
ptent = pte_mkwrite(ptent);
|
||||
|
||||
/* Avoid taking write faults for known dirty pages */
|
||||
if (dirty_accountable && pte_dirty(ptent) &&
|
||||
|
|
|
@ -103,6 +103,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
|
|||
|
||||
if (!is_migrate_isolate_page(buddy)) {
|
||||
__isolate_free_page(page, order);
|
||||
kernel_map_pages(page, (1 << order), 1);
|
||||
set_page_refcounted(page);
|
||||
isolated_page = page;
|
||||
}
|
||||
|
|
|
@ -265,8 +265,15 @@ int walk_page_range(unsigned long start, unsigned long end,
|
|||
vma = vma->vm_next;
|
||||
|
||||
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;
|
||||
}
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -287,6 +287,13 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
|
|||
return 0;
|
||||
|
||||
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);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -2449,7 +2449,8 @@ redo:
|
|||
do {
|
||||
tid = this_cpu_read(s->cpu_slab->tid);
|
||||
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
|
||||
|
@ -2718,7 +2719,8 @@ redo:
|
|||
do {
|
||||
tid = this_cpu_read(s->cpu_slab->tid);
|
||||
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() */
|
||||
barrier();
|
||||
|
|
Loading…
Reference in New Issue