Skip to content

Commit

Permalink
Merge branch 'akpm' (patches from Andrew)
Browse files Browse the repository at this point in the history
Merge fixes from Andrew Morton:
 "21 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (21 commits)
  writeback: fix initial dirty limit
  mm/memory-failure: set PageHWPoison before migrate_pages()
  mm: check __PG_HWPOISON separately from PAGE_FLAGS_CHECK_AT_*
  mm/memory-failure: give up error handling for non-tail-refcounted thp
  mm/memory-failure: fix race in counting num_poisoned_pages
  mm/memory-failure: unlock_page before put_page
  ipc: use private shmem or hugetlbfs inodes for shm segments.
  mm: initialize hotplugged pages as reserved
  ocfs2: fix shift left overflow
  kthread: export kthread functions
  fsnotify: fix oops in fsnotify_clear_marks_by_group_flags()
  lib/iommu-common.c: do not use 0xffffffffffffffffl for computing align_mask
  mm/slub: allow merging when SLAB_DEBUG_FREE is set
  signalfd: fix information leak in signalfd_copyinfo
  signal: fix information leak in copy_siginfo_to_user
  signal: fix information leak in copy_siginfo_from_user32
  ocfs2: fix BUG in ocfs2_downconvert_thread_do_work()
  fs, file table: reinit files_stat.max_files after deferred memory initialisation
  mm, meminit: replace rwsem with completion
  mm, meminit: allow early_pfn_to_nid to be used during runtime
  ...
  • Loading branch information
Linus Torvalds committed Aug 7, 2015
2 parents a58997e + a50fcb5 commit 8664b90
Show file tree
Hide file tree
Showing 27 changed files with 153 additions and 102 deletions.
5 changes: 2 additions & 3 deletions arch/arm64/kernel/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
* Other callers might not initialize the si_lsb field,
* so check explicitely for the right codes here.
*/
if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
if (from->si_signo == SIGBUS &&
(from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
#endif
break;
Expand Down Expand Up @@ -201,8 +202,6 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
memset(to, 0, sizeof *to);

if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
copy_from_user(to->_sifields._pad,
from->_sifields._pad, SI_PAD_SIZE))
Expand Down
2 changes: 0 additions & 2 deletions arch/mips/kernel/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,6 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
memset(to, 0, sizeof *to);

if (copy_from_user(to, from, 3*sizeof(int)) ||
copy_from_user(to->_sifields._pad,
from->_sifields._pad, SI_PAD_SIZE32))
Expand Down
2 changes: 0 additions & 2 deletions arch/powerpc/kernel/signal_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,8 +966,6 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s)

int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
{
memset(to, 0, sizeof *to);

if (copy_from_user(to, from, 3*sizeof(int)) ||
copy_from_user(to->_sifields._pad,
from->_sifields._pad, SI_PAD_SIZE32))
Expand Down
2 changes: 0 additions & 2 deletions arch/tile/kernel/compat_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
return -EFAULT;

memset(to, 0, sizeof(*to));

err = __get_user(to->si_signo, &from->si_signo);
err |= __get_user(to->si_errno, &from->si_errno);
err |= __get_user(to->si_code, &from->si_code);
Expand Down
13 changes: 3 additions & 10 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -3442,22 +3442,15 @@ void __init vfs_caches_init_early(void)
inode_init_early();
}

void __init vfs_caches_init(unsigned long mempages)
void __init vfs_caches_init(void)
{
unsigned long reserve;

/* Base hash sizes on available memory, with a reserve equal to
150% of current kernel size */

reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
mempages -= reserve;

names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);

dcache_init();
inode_init();
files_init(mempages);
files_init();
files_maxfiles_init();
mnt_init();
bdev_cache_init();
chrdev_init();
Expand Down
24 changes: 15 additions & 9 deletions fs/file_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/hardirq.h>
#include <linux/task_work.h>
#include <linux/ima.h>
#include <linux/swap.h>

#include <linux/atomic.h>

Expand Down Expand Up @@ -308,19 +309,24 @@ void put_filp(struct file *file)
}
}

void __init files_init(unsigned long mempages)
void __init files_init(void)
{
unsigned long n;

filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
percpu_counter_init(&nr_files, 0, GFP_KERNEL);
}

/*
* One file with associated inode and dcache is very roughly 1K.
* Per default don't use more than 10% of our memory for files.
*/
/*
* One file with associated inode and dcache is very roughly 1K. Per default
* do not use more than 10% of our memory for files.
*/
void __init files_maxfiles_init(void)
{
unsigned long n;
unsigned long memreserve = (totalram_pages - nr_free_pages()) * 3/2;

memreserve = min(memreserve, totalram_pages - 1);
n = ((totalram_pages - memreserve) * (PAGE_SIZE / 1024)) / 10;

n = (mempages * (PAGE_SIZE / 1024)) / 10;
files_stat.max_files = max_t(unsigned long, n, NR_FILE);
percpu_counter_init(&nr_files, 0, GFP_KERNEL);
}
2 changes: 2 additions & 0 deletions fs/hugetlbfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
inode = hugetlbfs_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0);
if (!inode)
goto out_dentry;
if (creat_flags == HUGETLB_SHMFS_INODE)
inode->i_flags |= S_PRIVATE;

file = ERR_PTR(-ENOMEM);
if (hugetlb_reserve_pages(inode, 0,
Expand Down
30 changes: 25 additions & 5 deletions fs/notify/mark.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,16 +412,36 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
unsigned int flags)
{
struct fsnotify_mark *lmark, *mark;
LIST_HEAD(to_free);

/*
* We have to be really careful here. Anytime we drop mark_mutex, e.g.
* fsnotify_clear_marks_by_inode() can come and free marks. Even in our
* to_free list so we have to use mark_mutex even when accessing that
* list. And freeing mark requires us to drop mark_mutex. So we can
* reliably free only the first mark in the list. That's why we first
* move marks to free to to_free list in one go and then free marks in
* to_free list one by one.
*/
mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
if (mark->flags & flags) {
fsnotify_get_mark(mark);
fsnotify_destroy_mark_locked(mark, group);
fsnotify_put_mark(mark);
}
if (mark->flags & flags)
list_move(&mark->g_list, &to_free);
}
mutex_unlock(&group->mark_mutex);

while (1) {
mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
if (list_empty(&to_free)) {
mutex_unlock(&group->mark_mutex);
break;
}
mark = list_first_entry(&to_free, struct fsnotify_mark, g_list);
fsnotify_get_mark(mark);
fsnotify_destroy_mark_locked(mark, group);
mutex_unlock(&group->mark_mutex);
fsnotify_put_mark(mark);
}
}

/*
Expand Down
4 changes: 2 additions & 2 deletions fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ static int ocfs2_direct_IO_zero_extend(struct ocfs2_super *osb,

if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) {
u64 s = i_size_read(inode);
sector_t sector = (p_cpos << (osb->s_clustersize_bits - 9)) +
sector_t sector = ((u64)p_cpos << (osb->s_clustersize_bits - 9)) +
(do_div(s, osb->s_clustersize) >> 9);

ret = blkdev_issue_zeroout(osb->sb->s_bdev, sector,
Expand Down Expand Up @@ -910,7 +910,7 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
BUG_ON(!p_cpos || (ext_flags & OCFS2_EXT_UNWRITTEN));

ret = blkdev_issue_zeroout(osb->sb->s_bdev,
p_cpos << (osb->s_clustersize_bits - 9),
(u64)p_cpos << (osb->s_clustersize_bits - 9),
zero_len_head >> 9, GFP_NOFS, false);
if (ret < 0)
mlog_errno(ret);
Expand Down
10 changes: 7 additions & 3 deletions fs/ocfs2/dlmglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -4025,9 +4025,13 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
osb->dc_work_sequence = osb->dc_wake_sequence;

processed = osb->blocked_lock_count;
while (processed) {
BUG_ON(list_empty(&osb->blocked_lock_list));

/*
* blocked lock processing in this loop might call iput which can
* remove items off osb->blocked_lock_list. Downconvert up to
* 'processed' number of locks, but stop short if we had some
* removed in ocfs2_mark_lockres_freeing when downconverting.
*/
while (processed && !list_empty(&osb->blocked_lock_list)) {
lockres = list_entry(osb->blocked_lock_list.next,
struct ocfs2_lock_res, l_blocked_list);
list_del_init(&lockres->l_blocked_list);
Expand Down
5 changes: 3 additions & 2 deletions fs/signalfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
* Other callers might not initialize the si_lsb field,
* so check explicitly for the right codes here.
*/
if (kinfo->si_code == BUS_MCEERR_AR ||
kinfo->si_code == BUS_MCEERR_AO)
if (kinfo->si_signo == SIGBUS &&
(kinfo->si_code == BUS_MCEERR_AR ||
kinfo->si_code == BUS_MCEERR_AO))
err |= __put_user((short) kinfo->si_addr_lsb,
&uinfo->ssi_addr_lsb);
#endif
Expand Down
5 changes: 3 additions & 2 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ struct vm_fault;

extern void __init inode_init(void);
extern void __init inode_init_early(void);
extern void __init files_init(unsigned long);
extern void __init files_init(void);
extern void __init files_maxfiles_init(void);

extern struct files_stat_struct files_stat;
extern unsigned long get_max_files(void);
Expand Down Expand Up @@ -2245,7 +2246,7 @@ extern int ioctl_preallocate(struct file *filp, void __user *argp);

/* fs/dcache.c */
extern void __init vfs_caches_init_early(void);
extern void __init vfs_caches_init(unsigned long);
extern void __init vfs_caches_init(void);

extern struct kmem_cache *names_cachep;

Expand Down
10 changes: 7 additions & 3 deletions include/linux/page-flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,15 +631,19 @@ static inline void ClearPageSlabPfmemalloc(struct page *page)
1 << PG_private | 1 << PG_private_2 | \
1 << PG_writeback | 1 << PG_reserved | \
1 << PG_slab | 1 << PG_swapcache | 1 << PG_active | \
1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON | \
1 << PG_unevictable | __PG_MLOCKED | \
__PG_COMPOUND_LOCK)

/*
* Flags checked when a page is prepped for return by the page allocator.
* Pages being prepped should not have any flags set. It they are set,
* Pages being prepped should not have these flags set. It they are set,
* there has been a kernel bug or struct page corruption.
*
* __PG_HWPOISON is exceptional because it needs to be kept beyond page's
* alloc-free cycle to prevent from reusing the page.
*/
#define PAGE_FLAGS_CHECK_AT_PREP ((1 << NR_PAGEFLAGS) - 1)
#define PAGE_FLAGS_CHECK_AT_PREP \
(((1 << NR_PAGEFLAGS) - 1) & ~__PG_HWPOISON)

#define PAGE_FLAGS_PRIVATE \
(1 << PG_private | 1 << PG_private_2)
Expand Down
2 changes: 1 addition & 1 deletion init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ asmlinkage __visible void __init start_kernel(void)
key_init();
security_init();
dbg_late_init();
vfs_caches_init(totalram_pages);
vfs_caches_init();
signals_init();
/* rootfs populating might need page-writeback */
page_writeback_init();
Expand Down
5 changes: 0 additions & 5 deletions ipc/mqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info)
if (!leaf)
return -ENOMEM;
INIT_LIST_HEAD(&leaf->msg_list);
info->qsize += sizeof(*leaf);
}
leaf->priority = msg->m_type;
rb_link_node(&leaf->rb_node, parent, p);
Expand Down Expand Up @@ -187,7 +186,6 @@ static inline struct msg_msg *msg_get(struct mqueue_inode_info *info)
"lazy leaf delete!\n");
rb_erase(&leaf->rb_node, &info->msg_tree);
if (info->node_cache) {
info->qsize -= sizeof(*leaf);
kfree(leaf);
} else {
info->node_cache = leaf;
Expand All @@ -200,7 +198,6 @@ static inline struct msg_msg *msg_get(struct mqueue_inode_info *info)
if (list_empty(&leaf->msg_list)) {
rb_erase(&leaf->rb_node, &info->msg_tree);
if (info->node_cache) {
info->qsize -= sizeof(*leaf);
kfree(leaf);
} else {
info->node_cache = leaf;
Expand Down Expand Up @@ -1034,7 +1031,6 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
/* Save our speculative allocation into the cache */
INIT_LIST_HEAD(&new_leaf->msg_list);
info->node_cache = new_leaf;
info->qsize += sizeof(*new_leaf);
new_leaf = NULL;
} else {
kfree(new_leaf);
Expand Down Expand Up @@ -1142,7 +1138,6 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
/* Save our speculative allocation into the cache */
INIT_LIST_HEAD(&new_leaf->msg_list);
info->node_cache = new_leaf;
info->qsize += sizeof(*new_leaf);
} else {
kfree(new_leaf);
}
Expand Down
2 changes: 1 addition & 1 deletion ipc/shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
if ((shmflg & SHM_NORESERVE) &&
sysctl_overcommit_memory != OVERCOMMIT_NEVER)
acctflag = VM_NORESERVE;
file = shmem_file_setup(name, size, acctflag);
file = shmem_kernel_file_setup(name, size, acctflag);
}
error = PTR_ERR(file);
if (IS_ERR(file))
Expand Down
4 changes: 4 additions & 0 deletions kernel/kthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ bool kthread_should_park(void)
{
return test_bit(KTHREAD_SHOULD_PARK, &to_kthread(current)->flags);
}
EXPORT_SYMBOL_GPL(kthread_should_park);

/**
* kthread_freezable_should_stop - should this freezable kthread return now?
Expand Down Expand Up @@ -171,6 +172,7 @@ void kthread_parkme(void)
{
__kthread_parkme(to_kthread(current));
}
EXPORT_SYMBOL_GPL(kthread_parkme);

static int kthread(void *_create)
{
Expand Down Expand Up @@ -411,6 +413,7 @@ void kthread_unpark(struct task_struct *k)
if (kthread)
__kthread_unpark(k, kthread);
}
EXPORT_SYMBOL_GPL(kthread_unpark);

/**
* kthread_park - park a thread created by kthread_create().
Expand Down Expand Up @@ -441,6 +444,7 @@ int kthread_park(struct task_struct *k)
}
return ret;
}
EXPORT_SYMBOL_GPL(kthread_park);

/**
* kthread_stop - stop a thread created by kthread_create().
Expand Down
13 changes: 8 additions & 5 deletions kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2748,12 +2748,15 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
* Other callers might not initialize the si_lsb field,
* so check explicitly for the right codes here.
*/
if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
if (from->si_signo == SIGBUS &&
(from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
#endif
#ifdef SEGV_BNDERR
err |= __put_user(from->si_lower, &to->si_lower);
err |= __put_user(from->si_upper, &to->si_upper);
if (from->si_signo == SIGSEGV && from->si_code == SEGV_BNDERR) {
err |= __put_user(from->si_lower, &to->si_lower);
err |= __put_user(from->si_upper, &to->si_upper);
}
#endif
break;
case __SI_CHLD:
Expand Down Expand Up @@ -3017,7 +3020,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo,
int, sig,
struct compat_siginfo __user *, uinfo)
{
siginfo_t info;
siginfo_t info = {};
int ret = copy_siginfo_from_user32(&info, uinfo);
if (unlikely(ret))
return ret;
Expand Down Expand Up @@ -3061,7 +3064,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
int, sig,
struct compat_siginfo __user *, uinfo)
{
siginfo_t info;
siginfo_t info = {};

if (copy_siginfo_from_user32(&info, uinfo))
return -EFAULT;
Expand Down
2 changes: 1 addition & 1 deletion lib/iommu-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ unsigned long iommu_tbl_range_alloc(struct device *dev,
unsigned long align_mask = 0;

if (align_order > 0)
align_mask = 0xffffffffffffffffl >> (64 - align_order);
align_mask = ~0ul >> (BITS_PER_LONG - align_order);

/* Sanity check */
if (unlikely(npages == 0)) {
Expand Down
Loading

0 comments on commit 8664b90

Please sign in to comment.