Merge branch 'akpm' (patches from Andrew)

Merge misc fixes from Andrew Morton:
 "A lot of stuff, sorry about that. A week on a beach, then a bunch of
  time catching up then more time letting it bake in -next. Shan't do
  that again!"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (51 commits)
  include/linux/fs.h: fix comment about struct address_space
  checkpatch: fix ignoring cover-letter logic
  m32r: fix build failure
  lib/ratelimit.c: use deferred printk() version
  kernel/params.c: improve STANDARD_PARAM_DEF readability
  kernel/params.c: fix an overflow in param_attr_show
  kernel/params.c: fix the maximum length in param_get_string
  mm/memory_hotplug: define find_{smallest|biggest}_section_pfn as unsigned long
  mm/memory_hotplug: change pfn_to_section_nr/section_nr_to_pfn macro to inline function
  kernel/kcmp.c: drop branch leftover typo
  memremap: add scheduling point to devm_memremap_pages
  mm, page_alloc: add scheduling point to memmap_init_zone
  mm, memory_hotplug: add scheduling point to __add_pages
  lib/idr.c: fix comment for idr_replace()
  mm: memcontrol: use vmalloc fallback for large kmem memcg arrays
  kernel/sysctl.c: remove duplicate UINT_MAX check on do_proc_douintvec_conv()
  include/linux/bitfield.h: remove 32bit from FIELD_GET comment block
  lib/lz4: make arrays static const, reduces object code size
  exec: binfmt_misc: kill the onstack iname[BINPRM_BUF_SIZE] array
  exec: binfmt_misc: fix race between load_misc_binary() and kill_node()
  ...
This commit is contained in:
Linus Torvalds 2017-10-04 09:30:50 -07:00
commit b7e1416441
49 changed files with 381 additions and 205 deletions

View File

@ -8,6 +8,7 @@
*/ */
#include <linux/mm_types.h> #include <linux/mm_types.h>
#include <linux/sched.h>
#include <asm/machvec.h> #include <asm/machvec.h>
#include <asm/compiler.h> #include <asm/compiler.h>

View File

@ -194,6 +194,10 @@ config TIMER_DIVIDE
int "Timer divider (integer)" int "Timer divider (integer)"
default "128" default "128"
config CPU_BIG_ENDIAN
bool "Generate big endian code"
default n
config CPU_LITTLE_ENDIAN config CPU_LITTLE_ENDIAN
bool "Generate little endian code" bool "Generate little endian code"
default n default n

View File

@ -114,6 +114,15 @@ static void set_eit_vector_entries(void)
_flush_cache_copyback_all(); _flush_cache_copyback_all();
} }
void abort(void)
{
BUG();
/* if that doesn't kill us, halt */
panic("Oops failed to kill thread");
}
EXPORT_SYMBOL(abort);
void __init trap_init(void) void __init trap_init(void)
{ {
set_eit_vector_entries(); set_eit_vector_entries();

View File

@ -71,6 +71,8 @@
#define RIWAR_WRTYP_ALLOC 0x00006000 #define RIWAR_WRTYP_ALLOC 0x00006000
#define RIWAR_SIZE_MASK 0x0000003F #define RIWAR_SIZE_MASK 0x0000003F
static DEFINE_SPINLOCK(fsl_rio_config_lock);
#define __fsl_read_rio_config(x, addr, err, op) \ #define __fsl_read_rio_config(x, addr, err, op) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: "op" %1,0(%2)\n" \ "1: "op" %1,0(%2)\n" \
@ -184,6 +186,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
u8 hopcount, u32 offset, int len, u32 *val) u8 hopcount, u32 offset, int len, u32 *val)
{ {
struct rio_priv *priv = mport->priv; struct rio_priv *priv = mport->priv;
unsigned long flags;
u8 *data; u8 *data;
u32 rval, err = 0; u32 rval, err = 0;
@ -197,6 +200,8 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&fsl_rio_config_lock, flags);
out_be32(&priv->maint_atmu_regs->rowtar, out_be32(&priv->maint_atmu_regs->rowtar,
(destid << 22) | (hopcount << 12) | (offset >> 12)); (destid << 22) | (hopcount << 12) | (offset >> 12));
out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
@ -213,6 +218,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
__fsl_read_rio_config(rval, data, err, "lwz"); __fsl_read_rio_config(rval, data, err, "lwz");
break; break;
default: default:
spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
return -EINVAL; return -EINVAL;
} }
@ -221,6 +227,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
err, destid, hopcount, offset); err, destid, hopcount, offset);
} }
spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
*val = rval; *val = rval;
return err; return err;
@ -244,7 +251,10 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
u8 hopcount, u32 offset, int len, u32 val) u8 hopcount, u32 offset, int len, u32 val)
{ {
struct rio_priv *priv = mport->priv; struct rio_priv *priv = mport->priv;
unsigned long flags;
u8 *data; u8 *data;
int ret = 0;
pr_debug pr_debug
("fsl_rio_config_write:" ("fsl_rio_config_write:"
" index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", " index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
@ -255,6 +265,8 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&fsl_rio_config_lock, flags);
out_be32(&priv->maint_atmu_regs->rowtar, out_be32(&priv->maint_atmu_regs->rowtar,
(destid << 22) | (hopcount << 12) | (offset >> 12)); (destid << 22) | (hopcount << 12) | (offset >> 12));
out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
@ -271,10 +283,11 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
out_be32((u32 *) data, val); out_be32((u32 *) data, val);
break; break;
default: default:
return -EINVAL; ret = -EINVAL;
} }
spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
return 0; return ret;
} }
static void fsl_rio_inbound_mem_init(struct rio_priv *priv) static void fsl_rio_inbound_mem_init(struct rio_priv *priv)

View File

@ -104,6 +104,8 @@
#define DOORBELL_MESSAGE_SIZE 0x08 #define DOORBELL_MESSAGE_SIZE 0x08
static DEFINE_SPINLOCK(fsl_rio_doorbell_lock);
struct rio_msg_regs { struct rio_msg_regs {
u32 omr; u32 omr;
u32 osr; u32 osr;
@ -626,9 +628,13 @@ err_out:
int fsl_rio_doorbell_send(struct rio_mport *mport, int fsl_rio_doorbell_send(struct rio_mport *mport,
int index, u16 destid, u16 data) int index, u16 destid, u16 data)
{ {
unsigned long flags;
pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
index, destid, data); index, destid, data);
spin_lock_irqsave(&fsl_rio_doorbell_lock, flags);
/* In the serial version silicons, such as MPC8548, MPC8641, /* In the serial version silicons, such as MPC8548, MPC8641,
* below operations is must be. * below operations is must be.
*/ */
@ -638,6 +644,8 @@ int fsl_rio_doorbell_send(struct rio_mport *mport,
out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data); out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data);
out_be32(&dbell->dbell_regs->odmr, 0x00000001); out_be32(&dbell->dbell_regs->odmr, 0x00000001);
spin_unlock_irqrestore(&fsl_rio_doorbell_lock, flags);
return 0; return 0;
} }

View File

@ -43,9 +43,7 @@ enum {
GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4, GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0, GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
/* Port H */ /* Port H - Port H does not have a Data Register */
GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4,
GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
/* Port I - not on device */ /* Port I - not on device */

View File

@ -45,9 +45,7 @@ enum {
GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4, GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0, GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
/* Port H */ /* Port H - Port H does not have a Data Register */
GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4,
GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
/* Port I - not on device */ /* Port I - not on device */

View File

@ -67,7 +67,7 @@ enum {
GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0, GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
/* PTQ */ /* PTQ */
GPIO_PTQ7, GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4, GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0, GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
/* PTR */ /* PTR */

View File

@ -40,7 +40,7 @@ enum {
/* PTJ */ /* PTJ */
GPIO_PTJ0, GPIO_PTJ1, GPIO_PTJ2, GPIO_PTJ3, GPIO_PTJ0, GPIO_PTJ1, GPIO_PTJ2, GPIO_PTJ3,
GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6, GPIO_PTJ7_RESV, GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6,
/* PTK */ /* PTK */
GPIO_PTK0, GPIO_PTK1, GPIO_PTK2, GPIO_PTK3, GPIO_PTK0, GPIO_PTK1, GPIO_PTK2, GPIO_PTK3,
@ -48,7 +48,7 @@ enum {
/* PTL */ /* PTL */
GPIO_PTL0, GPIO_PTL1, GPIO_PTL2, GPIO_PTL3, GPIO_PTL0, GPIO_PTL1, GPIO_PTL2, GPIO_PTL3,
GPIO_PTL4, GPIO_PTL5, GPIO_PTL6, GPIO_PTL7_RESV, GPIO_PTL4, GPIO_PTL5, GPIO_PTL6,
/* PTM */ /* PTM */
GPIO_PTM0, GPIO_PTM1, GPIO_PTM2, GPIO_PTM3, GPIO_PTM0, GPIO_PTM1, GPIO_PTM2, GPIO_PTM3,
@ -56,7 +56,7 @@ enum {
/* PTN */ /* PTN */
GPIO_PTN0, GPIO_PTN1, GPIO_PTN2, GPIO_PTN3, GPIO_PTN0, GPIO_PTN1, GPIO_PTN2, GPIO_PTN3,
GPIO_PTN4, GPIO_PTN5, GPIO_PTN6, GPIO_PTN7_RESV, GPIO_PTN4, GPIO_PTN5, GPIO_PTN6,
/* PTO */ /* PTO */
GPIO_PTO0, GPIO_PTO1, GPIO_PTO2, GPIO_PTO3, GPIO_PTO0, GPIO_PTO1, GPIO_PTO2, GPIO_PTO3,
@ -68,7 +68,7 @@ enum {
/* PTQ */ /* PTQ */
GPIO_PTQ0, GPIO_PTQ1, GPIO_PTQ2, GPIO_PTQ3, GPIO_PTQ0, GPIO_PTQ1, GPIO_PTQ2, GPIO_PTQ3,
GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6, GPIO_PTQ7_RESV, GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6,
/* PTR */ /* PTR */
GPIO_PTR0, GPIO_PTR1, GPIO_PTR2, GPIO_PTR3, GPIO_PTR0, GPIO_PTR1, GPIO_PTR2, GPIO_PTR3,

View File

@ -913,6 +913,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
struct binder_alloc *alloc; struct binder_alloc *alloc;
uintptr_t page_addr; uintptr_t page_addr;
size_t index; size_t index;
struct vm_area_struct *vma;
alloc = page->alloc; alloc = page->alloc;
if (!mutex_trylock(&alloc->mutex)) if (!mutex_trylock(&alloc->mutex))
@ -923,16 +924,22 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
index = page - alloc->pages; index = page - alloc->pages;
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
if (alloc->vma) { vma = alloc->vma;
if (vma) {
mm = get_task_mm(alloc->tsk); mm = get_task_mm(alloc->tsk);
if (!mm) if (!mm)
goto err_get_task_mm_failed; goto err_get_task_mm_failed;
if (!down_write_trylock(&mm->mmap_sem)) if (!down_write_trylock(&mm->mmap_sem))
goto err_down_write_mmap_sem_failed; goto err_down_write_mmap_sem_failed;
}
list_lru_isolate(lru, item);
spin_unlock(lock);
if (vma) {
trace_binder_unmap_user_start(alloc, index); trace_binder_unmap_user_start(alloc, index);
zap_page_range(alloc->vma, zap_page_range(vma,
page_addr + alloc->user_buffer_offset, page_addr + alloc->user_buffer_offset,
PAGE_SIZE); PAGE_SIZE);
@ -950,13 +957,12 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
trace_binder_unmap_kernel_end(alloc, index); trace_binder_unmap_kernel_end(alloc, index);
list_lru_isolate(lru, item); spin_lock(lock);
mutex_unlock(&alloc->mutex); mutex_unlock(&alloc->mutex);
return LRU_REMOVED; return LRU_REMOVED_RETRY;
err_down_write_mmap_sem_failed: err_down_write_mmap_sem_failed:
mmput(mm); mmput_async(mm);
err_get_task_mm_failed: err_get_task_mm_failed:
err_page_already_freed: err_page_already_freed:
mutex_unlock(&alloc->mutex); mutex_unlock(&alloc->mutex);

View File

@ -766,27 +766,6 @@ static void zram_slot_unlock(struct zram *zram, u32 index)
bit_spin_unlock(ZRAM_ACCESS, &zram->table[index].value); bit_spin_unlock(ZRAM_ACCESS, &zram->table[index].value);
} }
static bool zram_same_page_read(struct zram *zram, u32 index,
struct page *page,
unsigned int offset, unsigned int len)
{
zram_slot_lock(zram, index);
if (unlikely(!zram_get_handle(zram, index) ||
zram_test_flag(zram, index, ZRAM_SAME))) {
void *mem;
zram_slot_unlock(zram, index);
mem = kmap_atomic(page);
zram_fill_page(mem + offset, len,
zram_get_element(zram, index));
kunmap_atomic(mem);
return true;
}
zram_slot_unlock(zram, index);
return false;
}
static void zram_meta_free(struct zram *zram, u64 disksize) static void zram_meta_free(struct zram *zram, u64 disksize)
{ {
size_t num_pages = disksize >> PAGE_SHIFT; size_t num_pages = disksize >> PAGE_SHIFT;
@ -884,11 +863,20 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
zram_slot_unlock(zram, index); zram_slot_unlock(zram, index);
} }
if (zram_same_page_read(zram, index, page, 0, PAGE_SIZE))
return 0;
zram_slot_lock(zram, index); zram_slot_lock(zram, index);
handle = zram_get_handle(zram, index); handle = zram_get_handle(zram, index);
if (!handle || zram_test_flag(zram, index, ZRAM_SAME)) {
unsigned long value;
void *mem;
value = handle ? zram_get_element(zram, index) : 0;
mem = kmap_atomic(page);
zram_fill_page(mem, PAGE_SIZE, value);
kunmap_atomic(mem);
zram_slot_unlock(zram, index);
return 0;
}
size = zram_get_obj_size(zram, index); size = zram_get_obj_size(zram, index);
src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);

View File

@ -51,6 +51,8 @@ module_param(mbox_sel, byte, S_IRUGO);
MODULE_PARM_DESC(mbox_sel, MODULE_PARM_DESC(mbox_sel,
"RIO Messaging MBOX Selection Mask (default: 0x0f = all)"); "RIO Messaging MBOX Selection Mask (default: 0x0f = all)");
static DEFINE_SPINLOCK(tsi721_maint_lock);
static void tsi721_omsg_handler(struct tsi721_device *priv, int ch); static void tsi721_omsg_handler(struct tsi721_device *priv, int ch);
static void tsi721_imsg_handler(struct tsi721_device *priv, int ch); static void tsi721_imsg_handler(struct tsi721_device *priv, int ch);
@ -124,12 +126,15 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id); void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id);
struct tsi721_dma_desc *bd_ptr; struct tsi721_dma_desc *bd_ptr;
u32 rd_count, swr_ptr, ch_stat; u32 rd_count, swr_ptr, ch_stat;
unsigned long flags;
int i, err = 0; int i, err = 0;
u32 op = do_wr ? MAINT_WR : MAINT_RD; u32 op = do_wr ? MAINT_WR : MAINT_RD;
if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32))) if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32)))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&tsi721_maint_lock, flags);
bd_ptr = priv->mdma.bd_base; bd_ptr = priv->mdma.bd_base;
rd_count = ioread32(regs + TSI721_DMAC_DRDCNT); rd_count = ioread32(regs + TSI721_DMAC_DRDCNT);
@ -197,7 +202,9 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
*/ */
swr_ptr = ioread32(regs + TSI721_DMAC_DSWP); swr_ptr = ioread32(regs + TSI721_DMAC_DSWP);
iowrite32(swr_ptr, regs + TSI721_DMAC_DSRP); iowrite32(swr_ptr, regs + TSI721_DMAC_DSRP);
err_out: err_out:
spin_unlock_irqrestore(&tsi721_maint_lock, flags);
return err; return err;
} }

View File

@ -13,17 +13,9 @@
#include <linux/rio.h> #include <linux/rio.h>
#include <linux/module.h> #include <linux/module.h>
/*
* These interrupt-safe spinlocks protect all accesses to RIO
* configuration space and doorbell access.
*/
static DEFINE_SPINLOCK(rio_config_lock);
static DEFINE_SPINLOCK(rio_doorbell_lock);
/* /*
* Wrappers for all RIO configuration access functions. They just check * Wrappers for all RIO configuration access functions. They just check
* alignment, do locking and call the low-level functions pointed to * alignment and call the low-level functions pointed to by rio_mport->ops.
* by rio_mport->ops.
*/ */
#define RIO_8_BAD 0 #define RIO_8_BAD 0
@ -44,13 +36,10 @@ int __rio_local_read_config_##size \
(struct rio_mport *mport, u32 offset, type *value) \ (struct rio_mport *mport, u32 offset, type *value) \
{ \ { \
int res; \ int res; \
unsigned long flags; \
u32 data = 0; \ u32 data = 0; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \
res = mport->ops->lcread(mport, mport->id, offset, len, &data); \ res = mport->ops->lcread(mport, mport->id, offset, len, &data); \
*value = (type)data; \ *value = (type)data; \
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \ return res; \
} }
@ -67,13 +56,8 @@ int __rio_local_read_config_##size \
int __rio_local_write_config_##size \ int __rio_local_write_config_##size \
(struct rio_mport *mport, u32 offset, type value) \ (struct rio_mport *mport, u32 offset, type value) \
{ \ { \
int res; \
unsigned long flags; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \ return mport->ops->lcwrite(mport, mport->id, offset, len, value);\
res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \
} }
RIO_LOP_READ(8, u8, 1) RIO_LOP_READ(8, u8, 1)
@ -104,13 +88,10 @@ int rio_mport_read_config_##size \
(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \ (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \
{ \ { \
int res; \ int res; \
unsigned long flags; \
u32 data = 0; \ u32 data = 0; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \
res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \ res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
*value = (type)data; \ *value = (type)data; \
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \ return res; \
} }
@ -127,13 +108,9 @@ int rio_mport_read_config_##size \
int rio_mport_write_config_##size \ int rio_mport_write_config_##size \
(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \ (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \
{ \ { \
int res; \
unsigned long flags; \
if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
spin_lock_irqsave(&rio_config_lock, flags); \ return mport->ops->cwrite(mport, mport->id, destid, hopcount, \
res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \ offset, len, value); \
spin_unlock_irqrestore(&rio_config_lock, flags); \
return res; \
} }
RIO_OP_READ(8, u8, 1) RIO_OP_READ(8, u8, 1)
@ -162,14 +139,7 @@ EXPORT_SYMBOL_GPL(rio_mport_write_config_32);
*/ */
int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data) int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
{ {
int res; return mport->ops->dsend(mport, mport->id, destid, data);
unsigned long flags;
spin_lock_irqsave(&rio_doorbell_lock, flags);
res = mport->ops->dsend(mport, mport->id, destid, data);
spin_unlock_irqrestore(&rio_doorbell_lock, flags);
return res;
} }
EXPORT_SYMBOL_GPL(rio_mport_send_doorbell); EXPORT_SYMBOL_GPL(rio_mport_send_doorbell);

View File

@ -54,7 +54,7 @@ typedef struct {
int size; /* size of magic/mask */ int size; /* size of magic/mask */
char *magic; /* magic or filename extension */ char *magic; /* magic or filename extension */
char *mask; /* mask, NULL for exact match */ char *mask; /* mask, NULL for exact match */
char *interpreter; /* filename of interpreter */ const char *interpreter; /* filename of interpreter */
char *name; char *name;
struct dentry *dentry; struct dentry *dentry;
struct file *interp_file; struct file *interp_file;
@ -131,27 +131,26 @@ static int load_misc_binary(struct linux_binprm *bprm)
{ {
Node *fmt; Node *fmt;
struct file *interp_file = NULL; struct file *interp_file = NULL;
char iname[BINPRM_BUF_SIZE];
const char *iname_addr = iname;
int retval; int retval;
int fd_binary = -1; int fd_binary = -1;
retval = -ENOEXEC; retval = -ENOEXEC;
if (!enabled) if (!enabled)
goto ret; return retval;
/* to keep locking time low, we copy the interpreter string */ /* to keep locking time low, we copy the interpreter string */
read_lock(&entries_lock); read_lock(&entries_lock);
fmt = check_file(bprm); fmt = check_file(bprm);
if (fmt) if (fmt)
strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE); dget(fmt->dentry);
read_unlock(&entries_lock); read_unlock(&entries_lock);
if (!fmt) if (!fmt)
goto ret; return retval;
/* Need to be able to load the file after exec */ /* Need to be able to load the file after exec */
retval = -ENOENT;
if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE) if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
return -ENOENT; goto ret;
if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
retval = remove_arg_zero(bprm); retval = remove_arg_zero(bprm);
@ -195,22 +194,22 @@ static int load_misc_binary(struct linux_binprm *bprm)
bprm->argc++; bprm->argc++;
/* add the interp as argv[0] */ /* add the interp as argv[0] */
retval = copy_strings_kernel(1, &iname_addr, bprm); retval = copy_strings_kernel(1, &fmt->interpreter, bprm);
if (retval < 0) if (retval < 0)
goto error; goto error;
bprm->argc++; bprm->argc++;
/* Update interp in case binfmt_script needs it. */ /* Update interp in case binfmt_script needs it. */
retval = bprm_change_interp(iname, bprm); retval = bprm_change_interp(fmt->interpreter, bprm);
if (retval < 0) if (retval < 0)
goto error; goto error;
if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) { if (fmt->flags & MISC_FMT_OPEN_FILE) {
interp_file = filp_clone_open(fmt->interp_file); interp_file = filp_clone_open(fmt->interp_file);
if (!IS_ERR(interp_file)) if (!IS_ERR(interp_file))
deny_write_access(interp_file); deny_write_access(interp_file);
} else { } else {
interp_file = open_exec(iname); interp_file = open_exec(fmt->interpreter);
} }
retval = PTR_ERR(interp_file); retval = PTR_ERR(interp_file);
if (IS_ERR(interp_file)) if (IS_ERR(interp_file))
@ -238,6 +237,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
goto error; goto error;
ret: ret:
dput(fmt->dentry);
return retval; return retval;
error: error:
if (fd_binary > 0) if (fd_binary > 0)
@ -594,8 +594,13 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
static void bm_evict_inode(struct inode *inode) static void bm_evict_inode(struct inode *inode)
{ {
Node *e = inode->i_private;
if (e->flags & MISC_FMT_OPEN_FILE)
filp_close(e->interp_file, NULL);
clear_inode(inode); clear_inode(inode);
kfree(inode->i_private); kfree(e);
} }
static void kill_node(Node *e) static void kill_node(Node *e)
@ -603,24 +608,14 @@ static void kill_node(Node *e)
struct dentry *dentry; struct dentry *dentry;
write_lock(&entries_lock); write_lock(&entries_lock);
dentry = e->dentry; list_del_init(&e->list);
if (dentry) {
list_del_init(&e->list);
e->dentry = NULL;
}
write_unlock(&entries_lock); write_unlock(&entries_lock);
if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) { dentry = e->dentry;
filp_close(e->interp_file, NULL); drop_nlink(d_inode(dentry));
e->interp_file = NULL; d_drop(dentry);
} dput(dentry);
simple_release_fs(&bm_mnt, &entry_count);
if (dentry) {
drop_nlink(d_inode(dentry));
d_drop(dentry);
dput(dentry);
simple_release_fs(&bm_mnt, &entry_count);
}
} }
/* /<entry> */ /* /<entry> */
@ -665,7 +660,8 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
root = file_inode(file)->i_sb->s_root; root = file_inode(file)->i_sb->s_root;
inode_lock(d_inode(root)); inode_lock(d_inode(root));
kill_node(e); if (!list_empty(&e->list))
kill_node(e);
inode_unlock(d_inode(root)); inode_unlock(d_inode(root));
break; break;
@ -794,7 +790,7 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
inode_lock(d_inode(root)); inode_lock(d_inode(root));
while (!list_empty(&entries)) while (!list_empty(&entries))
kill_node(list_entry(entries.next, Node, list)); kill_node(list_first_entry(&entries, Node, list));
inode_unlock(d_inode(root)); inode_unlock(d_inode(root));
break; break;

View File

@ -19,7 +19,6 @@ static int load_script(struct linux_binprm *bprm)
const char *i_arg, *i_name; const char *i_arg, *i_name;
char *cp; char *cp;
struct file *file; struct file *file;
char interp[BINPRM_BUF_SIZE];
int retval; int retval;
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
@ -55,7 +54,7 @@ static int load_script(struct linux_binprm *bprm)
break; break;
} }
for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++); for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
if (*cp == '\0') if (*cp == '\0')
return -ENOEXEC; /* No interpreter name found */ return -ENOEXEC; /* No interpreter name found */
i_name = cp; i_name = cp;
i_arg = NULL; i_arg = NULL;
@ -65,7 +64,6 @@ static int load_script(struct linux_binprm *bprm)
*cp++ = '\0'; *cp++ = '\0';
if (*cp) if (*cp)
i_arg = cp; i_arg = cp;
strcpy (interp, i_name);
/* /*
* OK, we've parsed out the interpreter name and * OK, we've parsed out the interpreter name and
* (optional) argument. * (optional) argument.
@ -80,24 +78,27 @@ static int load_script(struct linux_binprm *bprm)
if (retval) if (retval)
return retval; return retval;
retval = copy_strings_kernel(1, &bprm->interp, bprm); retval = copy_strings_kernel(1, &bprm->interp, bprm);
if (retval < 0) return retval; if (retval < 0)
return retval;
bprm->argc++; bprm->argc++;
if (i_arg) { if (i_arg) {
retval = copy_strings_kernel(1, &i_arg, bprm); retval = copy_strings_kernel(1, &i_arg, bprm);
if (retval < 0) return retval; if (retval < 0)
return retval;
bprm->argc++; bprm->argc++;
} }
retval = copy_strings_kernel(1, &i_name, bprm); retval = copy_strings_kernel(1, &i_name, bprm);
if (retval) return retval; if (retval)
return retval;
bprm->argc++; bprm->argc++;
retval = bprm_change_interp(interp, bprm); retval = bprm_change_interp(i_name, bprm);
if (retval < 0) if (retval < 0)
return retval; return retval;
/* /*
* OK, now restart the process with the interpreter's dentry. * OK, now restart the process with the interpreter's dentry.
*/ */
file = open_exec(interp); file = open_exec(i_name);
if (IS_ERR(file)) if (IS_ERR(file))
return PTR_ERR(file); return PTR_ERR(file);

View File

@ -1410,7 +1410,7 @@ static void free_bprm(struct linux_binprm *bprm)
kfree(bprm); kfree(bprm);
} }
int bprm_change_interp(char *interp, struct linux_binprm *bprm) int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
{ {
/* If a binfmt changed the interp, free it first. */ /* If a binfmt changed the interp, free it first. */
if (bprm->interp != bprm->filename) if (bprm->interp != bprm->filename)

View File

@ -588,6 +588,12 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
break; break;
if (ACCESS_ONCE(ctx->released) || if (ACCESS_ONCE(ctx->released) ||
fatal_signal_pending(current)) { fatal_signal_pending(current)) {
/*
* &ewq->wq may be queued in fork_event, but
* __remove_wait_queue ignores the head
* parameter. It would be a problem if it
* didn't.
*/
__remove_wait_queue(&ctx->event_wqh, &ewq->wq); __remove_wait_queue(&ctx->event_wqh, &ewq->wq);
if (ewq->msg.event == UFFD_EVENT_FORK) { if (ewq->msg.event == UFFD_EVENT_FORK) {
struct userfaultfd_ctx *new; struct userfaultfd_ctx *new;
@ -1061,6 +1067,12 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
(unsigned long) (unsigned long)
uwq->msg.arg.reserved.reserved1; uwq->msg.arg.reserved.reserved1;
list_move(&uwq->wq.entry, &fork_event); list_move(&uwq->wq.entry, &fork_event);
/*
* fork_nctx can be freed as soon as
* we drop the lock, unless we take a
* reference on it.
*/
userfaultfd_ctx_get(fork_nctx);
spin_unlock(&ctx->event_wqh.lock); spin_unlock(&ctx->event_wqh.lock);
ret = 0; ret = 0;
break; break;
@ -1091,19 +1103,53 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
if (!ret && msg->event == UFFD_EVENT_FORK) { if (!ret && msg->event == UFFD_EVENT_FORK) {
ret = resolve_userfault_fork(ctx, fork_nctx, msg); ret = resolve_userfault_fork(ctx, fork_nctx, msg);
spin_lock(&ctx->event_wqh.lock);
if (!list_empty(&fork_event)) {
/*
* The fork thread didn't abort, so we can
* drop the temporary refcount.
*/
userfaultfd_ctx_put(fork_nctx);
if (!ret) { uwq = list_first_entry(&fork_event,
spin_lock(&ctx->event_wqh.lock); typeof(*uwq),
if (!list_empty(&fork_event)) { wq.entry);
uwq = list_first_entry(&fork_event, /*
typeof(*uwq), * If fork_event list wasn't empty and in turn
wq.entry); * the event wasn't already released by fork
list_del(&uwq->wq.entry); * (the event is allocated on fork kernel
__add_wait_queue(&ctx->event_wqh, &uwq->wq); * stack), put the event back to its place in
* the event_wq. fork_event head will be freed
* as soon as we return so the event cannot
* stay queued there no matter the current
* "ret" value.
*/
list_del(&uwq->wq.entry);
__add_wait_queue(&ctx->event_wqh, &uwq->wq);
/*
* Leave the event in the waitqueue and report
* error to userland if we failed to resolve
* the userfault fork.
*/
if (likely(!ret))
userfaultfd_event_complete(ctx, uwq); userfaultfd_event_complete(ctx, uwq);
} } else {
spin_unlock(&ctx->event_wqh.lock); /*
* Here the fork thread aborted and the
* refcount from the fork thread on fork_nctx
* has already been released. We still hold
* the reference we took before releasing the
* lock above. If resolve_userfault_fork
* failed we've to drop it because the
* fork_nctx has to be freed in such case. If
* it succeeded we'll hold it because the new
* uffd references it.
*/
if (ret)
userfaultfd_ctx_put(fork_nctx);
} }
spin_unlock(&ctx->event_wqh.lock);
} }
return ret; return ret;

View File

@ -131,7 +131,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm,
int executable_stack); int executable_stack);
extern int transfer_args_to_stack(struct linux_binprm *bprm, extern int transfer_args_to_stack(struct linux_binprm *bprm,
unsigned long *sp_location); unsigned long *sp_location);
extern int bprm_change_interp(char *interp, struct linux_binprm *bprm); extern int bprm_change_interp(const char *interp, struct linux_binprm *bprm);
extern int copy_strings_kernel(int argc, const char *const *argv, extern int copy_strings_kernel(int argc, const char *const *argv,
struct linux_binprm *bprm); struct linux_binprm *bprm);
extern int prepare_bprm_creds(struct linux_binprm *bprm); extern int prepare_bprm_creds(struct linux_binprm *bprm);

View File

@ -92,7 +92,7 @@
/** /**
* FIELD_GET() - extract a bitfield element * FIELD_GET() - extract a bitfield element
* @_mask: shifted mask defining the field's length and position * @_mask: shifted mask defining the field's length and position
* @_reg: 32bit value of entire bitfield * @_reg: value of entire bitfield
* *
* FIELD_GET() extracts the field specified by @_mask from the * FIELD_GET() extracts the field specified by @_mask from the
* bitfield passed in as @_reg by masking and shifting it down. * bitfield passed in as @_reg by masking and shifting it down.

View File

@ -403,7 +403,7 @@ struct address_space {
unsigned long flags; /* error bits */ unsigned long flags; /* error bits */
spinlock_t private_lock; /* for use by the address_space */ spinlock_t private_lock; /* for use by the address_space */
gfp_t gfp_mask; /* implicit gfp mask for allocations */ gfp_t gfp_mask; /* implicit gfp mask for allocations */
struct list_head private_list; /* ditto */ struct list_head private_list; /* for use by the address_space */
void *private_data; /* ditto */ void *private_data; /* ditto */
errseq_t wb_err; errseq_t wb_err;
} __attribute__((aligned(sizeof(long)))) __randomize_layout; } __attribute__((aligned(sizeof(long)))) __randomize_layout;

View File

@ -240,7 +240,7 @@ extern unsigned int kobjsize(const void *objp);
#if defined(CONFIG_X86_INTEL_MPX) #if defined(CONFIG_X86_INTEL_MPX)
/* MPX specific bounds table or bounds directory */ /* MPX specific bounds table or bounds directory */
# define VM_MPX VM_HIGH_ARCH_BIT_4 # define VM_MPX VM_HIGH_ARCH_4
#else #else
# define VM_MPX VM_NONE # define VM_MPX VM_NONE
#endif #endif

View File

@ -400,6 +400,11 @@ extern void mmu_notifier_synchronize(void);
#else /* CONFIG_MMU_NOTIFIER */ #else /* CONFIG_MMU_NOTIFIER */
static inline int mm_has_notifiers(struct mm_struct *mm)
{
return 0;
}
static inline void mmu_notifier_release(struct mm_struct *mm) static inline void mmu_notifier_release(struct mm_struct *mm)
{ {
} }

View File

@ -1094,8 +1094,14 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
#error Allocator MAX_ORDER exceeds SECTION_SIZE #error Allocator MAX_ORDER exceeds SECTION_SIZE
#endif #endif
#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT) static inline unsigned long pfn_to_section_nr(unsigned long pfn)
#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT) {
return pfn >> PFN_SECTION_SHIFT;
}
static inline unsigned long section_nr_to_pfn(unsigned long sec)
{
return sec << PFN_SECTION_SHIFT;
}
#define SECTION_ALIGN_UP(pfn) (((pfn) + PAGES_PER_SECTION - 1) & PAGE_SECTION_MASK) #define SECTION_ALIGN_UP(pfn) (((pfn) + PAGES_PER_SECTION - 1) & PAGE_SECTION_MASK)
#define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK) #define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK)

View File

@ -84,6 +84,12 @@ static inline bool mmget_not_zero(struct mm_struct *mm)
/* mmput gets rid of the mappings and all user-space */ /* mmput gets rid of the mappings and all user-space */
extern void mmput(struct mm_struct *); extern void mmput(struct mm_struct *);
#ifdef CONFIG_MMU
/* same as above but performs the slow path from the async context. Can
* be called from the atomic context as well
*/
void mmput_async(struct mm_struct *);
#endif
/* Grab a reference to a task's mm, if it is not already going away */ /* Grab a reference to a task's mm, if it is not already going away */
extern struct mm_struct *get_task_mm(struct task_struct *task); extern struct mm_struct *get_task_mm(struct task_struct *task);

View File

@ -946,6 +946,24 @@ void mmput(struct mm_struct *mm)
} }
EXPORT_SYMBOL_GPL(mmput); EXPORT_SYMBOL_GPL(mmput);
#ifdef CONFIG_MMU
static void mmput_async_fn(struct work_struct *work)
{
struct mm_struct *mm = container_of(work, struct mm_struct,
async_put_work);
__mmput(mm);
}
void mmput_async(struct mm_struct *mm)
{
if (atomic_dec_and_test(&mm->mm_users)) {
INIT_WORK(&mm->async_put_work, mmput_async_fn);
schedule_work(&mm->async_put_work);
}
}
#endif
/** /**
* set_mm_exe_file - change a reference to the mm's executable file * set_mm_exe_file - change a reference to the mm's executable file
* *

View File

@ -131,7 +131,7 @@ static int kcmp_epoll_target(struct task_struct *task1,
if (filp_epoll) { if (filp_epoll) {
filp_tgt = get_epoll_tfile_raw_ptr(filp_epoll, slot.tfd, slot.toff); filp_tgt = get_epoll_tfile_raw_ptr(filp_epoll, slot.tfd, slot.toff);
fput(filp_epoll); fput(filp_epoll);
} else }
if (IS_ERR(filp_tgt)) if (IS_ERR(filp_tgt))
return PTR_ERR(filp_tgt); return PTR_ERR(filp_tgt);

View File

@ -350,7 +350,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
pgprot_t pgprot = PAGE_KERNEL; pgprot_t pgprot = PAGE_KERNEL;
struct dev_pagemap *pgmap; struct dev_pagemap *pgmap;
struct page_map *page_map; struct page_map *page_map;
int error, nid, is_ram; int error, nid, is_ram, i = 0;
align_start = res->start & ~(SECTION_SIZE - 1); align_start = res->start & ~(SECTION_SIZE - 1);
align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE) align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
@ -448,6 +448,8 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
list_del(&page->lru); list_del(&page->lru);
page->pgmap = pgmap; page->pgmap = pgmap;
percpu_ref_get(ref); percpu_ref_get(ref);
if (!(++i % 1024))
cond_resched();
} }
devres_add(dev, page_map); devres_add(dev, page_map);
return __va(res->start); return __va(res->start);

View File

@ -224,7 +224,7 @@ char *parse_args(const char *doing,
} \ } \
int param_get_##name(char *buffer, const struct kernel_param *kp) \ int param_get_##name(char *buffer, const struct kernel_param *kp) \
{ \ { \
return scnprintf(buffer, PAGE_SIZE, format, \ return scnprintf(buffer, PAGE_SIZE, format "\n", \
*((type *)kp->arg)); \ *((type *)kp->arg)); \
} \ } \
const struct kernel_param_ops param_ops_##name = { \ const struct kernel_param_ops param_ops_##name = { \
@ -236,14 +236,14 @@ char *parse_args(const char *doing,
EXPORT_SYMBOL(param_ops_##name) EXPORT_SYMBOL(param_ops_##name)
STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8); STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8);
STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16); STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16);
STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16); STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16);
STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); STANDARD_PARAM_DEF(int, int, "%i", kstrtoint);
STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint);
STANDARD_PARAM_DEF(long, long, "%li", kstrtol); STANDARD_PARAM_DEF(long, long, "%li", kstrtol);
STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul);
STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull);
int param_set_charp(const char *val, const struct kernel_param *kp) int param_set_charp(const char *val, const struct kernel_param *kp)
{ {
@ -270,7 +270,7 @@ EXPORT_SYMBOL(param_set_charp);
int param_get_charp(char *buffer, const struct kernel_param *kp) int param_get_charp(char *buffer, const struct kernel_param *kp)
{ {
return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg)); return scnprintf(buffer, PAGE_SIZE, "%s\n", *((char **)kp->arg));
} }
EXPORT_SYMBOL(param_get_charp); EXPORT_SYMBOL(param_get_charp);
@ -301,7 +301,7 @@ EXPORT_SYMBOL(param_set_bool);
int param_get_bool(char *buffer, const struct kernel_param *kp) int param_get_bool(char *buffer, const struct kernel_param *kp)
{ {
/* Y and N chosen as being relatively non-coder friendly */ /* Y and N chosen as being relatively non-coder friendly */
return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N'); return sprintf(buffer, "%c\n", *(bool *)kp->arg ? 'Y' : 'N');
} }
EXPORT_SYMBOL(param_get_bool); EXPORT_SYMBOL(param_get_bool);
@ -360,7 +360,7 @@ EXPORT_SYMBOL(param_set_invbool);
int param_get_invbool(char *buffer, const struct kernel_param *kp) int param_get_invbool(char *buffer, const struct kernel_param *kp)
{ {
return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); return sprintf(buffer, "%c\n", (*(bool *)kp->arg) ? 'N' : 'Y');
} }
EXPORT_SYMBOL(param_get_invbool); EXPORT_SYMBOL(param_get_invbool);
@ -460,8 +460,9 @@ static int param_array_get(char *buffer, const struct kernel_param *kp)
struct kernel_param p = *kp; struct kernel_param p = *kp;
for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) { for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
/* Replace \n with comma */
if (i) if (i)
buffer[off++] = ','; buffer[off - 1] = ',';
p.arg = arr->elem + arr->elemsize * i; p.arg = arr->elem + arr->elemsize * i;
check_kparam_locked(p.mod); check_kparam_locked(p.mod);
ret = arr->ops->get(buffer + off, &p); ret = arr->ops->get(buffer + off, &p);
@ -507,7 +508,7 @@ EXPORT_SYMBOL(param_set_copystring);
int param_get_string(char *buffer, const struct kernel_param *kp) int param_get_string(char *buffer, const struct kernel_param *kp)
{ {
const struct kparam_string *kps = kp->str; const struct kparam_string *kps = kp->str;
return strlcpy(buffer, kps->string, kps->maxlen); return scnprintf(buffer, PAGE_SIZE, "%s\n", kps->string);
} }
EXPORT_SYMBOL(param_get_string); EXPORT_SYMBOL(param_get_string);
@ -549,10 +550,6 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
kernel_param_lock(mk->mod); kernel_param_lock(mk->mod);
count = attribute->param->ops->get(buf, attribute->param); count = attribute->param->ops->get(buf, attribute->param);
kernel_param_unlock(mk->mod); kernel_param_unlock(mk->mod);
if (count > 0) {
strcat(buf, "\n");
++count;
}
return count; return count;
} }
@ -600,7 +597,7 @@ EXPORT_SYMBOL(kernel_param_unlock);
/* /*
* add_sysfs_param - add a parameter to sysfs * add_sysfs_param - add a parameter to sysfs
* @mk: struct module_kobject * @mk: struct module_kobject
* @kparam: the actual parameter definition to add to sysfs * @kp: the actual parameter definition to add to sysfs
* @name: name of parameter * @name: name of parameter
* *
* Create a kobject if for a (per-module) parameter if mp NULL, and * Create a kobject if for a (per-module) parameter if mp NULL, and

View File

@ -2186,8 +2186,6 @@ static int do_proc_douintvec_conv(unsigned long *lvalp,
int write, void *data) int write, void *data)
{ {
if (write) { if (write) {
if (*lvalp > UINT_MAX)
return -EINVAL;
if (*lvalp > UINT_MAX) if (*lvalp > UINT_MAX)
return -EINVAL; return -EINVAL;
*valp = *lvalp; *valp = *lvalp;

View File

@ -146,8 +146,8 @@ EXPORT_SYMBOL(idr_get_next_ext);
* idr_alloc() and idr_remove() (as long as the ID being removed is not * idr_alloc() and idr_remove() (as long as the ID being removed is not
* the one being replaced!). * the one being replaced!).
* *
* Returns: 0 on success. %-ENOENT indicates that @id was not found. * Returns: the old value on success. %-ENOENT indicates that @id was not
* %-EINVAL indicates that @id or @ptr were not valid. * found. %-EINVAL indicates that @id or @ptr were not valid.
*/ */
void *idr_replace(struct idr *idr, void *ptr, int id) void *idr_replace(struct idr *idr, void *ptr, int id)
{ {

View File

@ -85,8 +85,8 @@ static FORCE_INLINE int LZ4_decompress_generic(
const BYTE * const lowLimit = lowPrefix - dictSize; const BYTE * const lowLimit = lowPrefix - dictSize;
const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize; const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
const unsigned int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; static const unsigned int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };
const int dec64table[] = { 0, 0, 0, -1, 0, 1, 2, 3 }; static const int dec64table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
const int safeDecode = (endOnInput == endOnInputSize); const int safeDecode = (endOnInput == endOnInputSize);
const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB))); const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));

View File

@ -48,7 +48,9 @@ int ___ratelimit(struct ratelimit_state *rs, const char *func)
if (time_is_before_jiffies(rs->begin + rs->interval)) { if (time_is_before_jiffies(rs->begin + rs->interval)) {
if (rs->missed) { if (rs->missed) {
if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) { if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
pr_warn("%s: %d callbacks suppressed\n", func, rs->missed); printk_deferred(KERN_WARNING
"%s: %d callbacks suppressed\n",
func, rs->missed);
rs->missed = 0; rs->missed = 0;
} }
} }

View File

@ -1999,17 +1999,14 @@ void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx)
if (pgdat->kcompactd_max_order < order) if (pgdat->kcompactd_max_order < order)
pgdat->kcompactd_max_order = order; pgdat->kcompactd_max_order = order;
/*
* Pairs with implicit barrier in wait_event_freezable()
* such that wakeups are not missed in the lockless
* waitqueue_active() call.
*/
smp_acquire__after_ctrl_dep();
if (pgdat->kcompactd_classzone_idx > classzone_idx) if (pgdat->kcompactd_classzone_idx > classzone_idx)
pgdat->kcompactd_classzone_idx = classzone_idx; pgdat->kcompactd_classzone_idx = classzone_idx;
if (!waitqueue_active(&pgdat->kcompactd_wait)) /*
* Pairs with implicit barrier in wait_event_freezable()
* such that wakeups are not missed.
*/
if (!wq_has_sleeper(&pgdat->kcompactd_wait))
return; return;
if (!kcompactd_node_suitable(pgdat)) if (!kcompactd_node_suitable(pgdat))

View File

@ -620,6 +620,14 @@ int file_check_and_advance_wb_err(struct file *file)
trace_file_check_and_advance_wb_err(file, old); trace_file_check_and_advance_wb_err(file, old);
spin_unlock(&file->f_lock); spin_unlock(&file->f_lock);
} }
/*
* We're mostly using this function as a drop in replacement for
* filemap_check_errors. Clear AS_EIO/AS_ENOSPC to emulate the effect
* that the legacy code would have had on these flags.
*/
clear_bit(AS_EIO, &mapping->flags);
clear_bit(AS_ENOSPC, &mapping->flags);
return err; return err;
} }
EXPORT_SYMBOL(file_check_and_advance_wb_err); EXPORT_SYMBOL(file_check_and_advance_wb_err);

View File

@ -1990,6 +1990,7 @@ static void stable_tree_append(struct rmap_item *rmap_item,
*/ */
static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item) static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
{ {
struct mm_struct *mm = rmap_item->mm;
struct rmap_item *tree_rmap_item; struct rmap_item *tree_rmap_item;
struct page *tree_page = NULL; struct page *tree_page = NULL;
struct stable_node *stable_node; struct stable_node *stable_node;
@ -2062,9 +2063,11 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
if (ksm_use_zero_pages && (checksum == zero_checksum)) { if (ksm_use_zero_pages && (checksum == zero_checksum)) {
struct vm_area_struct *vma; struct vm_area_struct *vma;
vma = find_mergeable_vma(rmap_item->mm, rmap_item->address); down_read(&mm->mmap_sem);
vma = find_mergeable_vma(mm, rmap_item->address);
err = try_to_merge_one_page(vma, page, err = try_to_merge_one_page(vma, page,
ZERO_PAGE(rmap_item->address)); ZERO_PAGE(rmap_item->address));
up_read(&mm->mmap_sem);
/* /*
* In case of failure, the page was not really empty, so we * In case of failure, the page was not really empty, so we
* need to continue. Otherwise we're done. * need to continue. Otherwise we're done.

View File

@ -325,12 +325,12 @@ static int memcg_init_list_lru_node(struct list_lru_node *nlru)
{ {
int size = memcg_nr_cache_ids; int size = memcg_nr_cache_ids;
nlru->memcg_lrus = kmalloc(size * sizeof(void *), GFP_KERNEL); nlru->memcg_lrus = kvmalloc(size * sizeof(void *), GFP_KERNEL);
if (!nlru->memcg_lrus) if (!nlru->memcg_lrus)
return -ENOMEM; return -ENOMEM;
if (__memcg_init_list_lru_node(nlru->memcg_lrus, 0, size)) { if (__memcg_init_list_lru_node(nlru->memcg_lrus, 0, size)) {
kfree(nlru->memcg_lrus); kvfree(nlru->memcg_lrus);
return -ENOMEM; return -ENOMEM;
} }
@ -340,7 +340,7 @@ static int memcg_init_list_lru_node(struct list_lru_node *nlru)
static void memcg_destroy_list_lru_node(struct list_lru_node *nlru) static void memcg_destroy_list_lru_node(struct list_lru_node *nlru)
{ {
__memcg_destroy_list_lru_node(nlru->memcg_lrus, 0, memcg_nr_cache_ids); __memcg_destroy_list_lru_node(nlru->memcg_lrus, 0, memcg_nr_cache_ids);
kfree(nlru->memcg_lrus); kvfree(nlru->memcg_lrus);
} }
static int memcg_update_list_lru_node(struct list_lru_node *nlru, static int memcg_update_list_lru_node(struct list_lru_node *nlru,
@ -351,12 +351,12 @@ static int memcg_update_list_lru_node(struct list_lru_node *nlru,
BUG_ON(old_size > new_size); BUG_ON(old_size > new_size);
old = nlru->memcg_lrus; old = nlru->memcg_lrus;
new = kmalloc(new_size * sizeof(void *), GFP_KERNEL); new = kvmalloc(new_size * sizeof(void *), GFP_KERNEL);
if (!new) if (!new)
return -ENOMEM; return -ENOMEM;
if (__memcg_init_list_lru_node(new, old_size, new_size)) { if (__memcg_init_list_lru_node(new, old_size, new_size)) {
kfree(new); kvfree(new);
return -ENOMEM; return -ENOMEM;
} }
@ -373,7 +373,7 @@ static int memcg_update_list_lru_node(struct list_lru_node *nlru,
nlru->memcg_lrus = new; nlru->memcg_lrus = new;
spin_unlock_irq(&nlru->lock); spin_unlock_irq(&nlru->lock);
kfree(old); kvfree(old);
return 0; return 0;
} }

View File

@ -625,18 +625,26 @@ static int madvise_inject_error(int behavior,
{ {
struct page *page; struct page *page;
struct zone *zone; struct zone *zone;
unsigned int order;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
for (; start < end; start += PAGE_SIZE <<
compound_order(compound_head(page))) { for (; start < end; start += PAGE_SIZE << order) {
int ret; int ret;
ret = get_user_pages_fast(start, 1, 0, &page); ret = get_user_pages_fast(start, 1, 0, &page);
if (ret != 1) if (ret != 1)
return ret; return ret;
/*
* When soft offlining hugepages, after migrating the page
* we dissolve it, therefore in the second loop "page" will
* no longer be a compound page, and order will be 0.
*/
order = compound_order(compound_head(page));
if (PageHWPoison(page)) { if (PageHWPoison(page)) {
put_page(page); put_page(page);
continue; continue;

View File

@ -1777,6 +1777,10 @@ static void drain_local_stock(struct work_struct *dummy)
struct memcg_stock_pcp *stock; struct memcg_stock_pcp *stock;
unsigned long flags; unsigned long flags;
/*
* The only protection from memory hotplug vs. drain_stock races is
* that we always operate on local CPU stock here with IRQ disabled
*/
local_irq_save(flags); local_irq_save(flags);
stock = this_cpu_ptr(&memcg_stock); stock = this_cpu_ptr(&memcg_stock);
@ -1821,27 +1825,33 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
/* If someone's already draining, avoid adding running more workers. */ /* If someone's already draining, avoid adding running more workers. */
if (!mutex_trylock(&percpu_charge_mutex)) if (!mutex_trylock(&percpu_charge_mutex))
return; return;
/* Notify other cpus that system-wide "drain" is running */ /*
get_online_cpus(); * Notify other cpus that system-wide "drain" is running
* We do not care about races with the cpu hotplug because cpu down
* as well as workers from this path always operate on the local
* per-cpu data. CPU up doesn't touch memcg_stock at all.
*/
curcpu = get_cpu(); curcpu = get_cpu();
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
struct mem_cgroup *memcg; struct mem_cgroup *memcg;
memcg = stock->cached; memcg = stock->cached;
if (!memcg || !stock->nr_pages) if (!memcg || !stock->nr_pages || !css_tryget(&memcg->css))
continue; continue;
if (!mem_cgroup_is_descendant(memcg, root_memcg)) if (!mem_cgroup_is_descendant(memcg, root_memcg)) {
css_put(&memcg->css);
continue; continue;
}
if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) { if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
if (cpu == curcpu) if (cpu == curcpu)
drain_local_stock(&stock->work); drain_local_stock(&stock->work);
else else
schedule_work_on(cpu, &stock->work); schedule_work_on(cpu, &stock->work);
} }
css_put(&memcg->css);
} }
put_cpu(); put_cpu();
put_online_cpus();
mutex_unlock(&percpu_charge_mutex); mutex_unlock(&percpu_charge_mutex);
} }
@ -5648,7 +5658,8 @@ static void uncharge_batch(const struct uncharge_gather *ug)
static void uncharge_page(struct page *page, struct uncharge_gather *ug) static void uncharge_page(struct page *page, struct uncharge_gather *ug)
{ {
VM_BUG_ON_PAGE(PageLRU(page), page); VM_BUG_ON_PAGE(PageLRU(page), page);
VM_BUG_ON_PAGE(!PageHWPoison(page) && page_count(page), page); VM_BUG_ON_PAGE(page_count(page) && !is_zone_device_page(page) &&
!PageHWPoison(page) , page);
if (!page->mem_cgroup) if (!page->mem_cgroup)
return; return;

View File

@ -845,7 +845,7 @@ struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
* vm_normal_page() so that we do not have to special case all * vm_normal_page() so that we do not have to special case all
* call site of vm_normal_page(). * call site of vm_normal_page().
*/ */
if (likely(pfn < highest_memmap_pfn)) { if (likely(pfn <= highest_memmap_pfn)) {
struct page *page = pfn_to_page(pfn); struct page *page = pfn_to_page(pfn);
if (is_device_public_page(page)) { if (is_device_public_page(page)) {

View File

@ -328,6 +328,7 @@ int __ref __add_pages(int nid, unsigned long phys_start_pfn,
if (err && (err != -EEXIST)) if (err && (err != -EEXIST))
break; break;
err = 0; err = 0;
cond_resched();
} }
vmemmap_populate_print_last(); vmemmap_populate_print_last();
out: out:
@ -337,7 +338,7 @@ EXPORT_SYMBOL_GPL(__add_pages);
#ifdef CONFIG_MEMORY_HOTREMOVE #ifdef CONFIG_MEMORY_HOTREMOVE
/* find the smallest valid pfn in the range [start_pfn, end_pfn) */ /* find the smallest valid pfn in the range [start_pfn, end_pfn) */
static int find_smallest_section_pfn(int nid, struct zone *zone, static unsigned long find_smallest_section_pfn(int nid, struct zone *zone,
unsigned long start_pfn, unsigned long start_pfn,
unsigned long end_pfn) unsigned long end_pfn)
{ {
@ -362,7 +363,7 @@ static int find_smallest_section_pfn(int nid, struct zone *zone,
} }
/* find the biggest valid pfn in the range [start_pfn, end_pfn). */ /* find the biggest valid pfn in the range [start_pfn, end_pfn). */
static int find_biggest_section_pfn(int nid, struct zone *zone, static unsigned long find_biggest_section_pfn(int nid, struct zone *zone,
unsigned long start_pfn, unsigned long start_pfn,
unsigned long end_pfn) unsigned long end_pfn)
{ {
@ -550,7 +551,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms,
return ret; return ret;
scn_nr = __section_nr(ms); scn_nr = __section_nr(ms);
start_pfn = section_nr_to_pfn(scn_nr); start_pfn = section_nr_to_pfn((unsigned long)scn_nr);
__remove_zone(zone, start_pfn); __remove_zone(zone, start_pfn);
sparse_remove_one_section(zone, ms, map_offset); sparse_remove_one_section(zone, ms, map_offset);

View File

@ -40,6 +40,7 @@
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mmu_notifier.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include "internal.h" #include "internal.h"
@ -494,6 +495,21 @@ static bool __oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm)
goto unlock_oom; goto unlock_oom;
} }
/*
* If the mm has notifiers then we would need to invalidate them around
* unmap_page_range and that is risky because notifiers can sleep and
* what they do is basically undeterministic. So let's have a short
* sleep to give the oom victim some more time.
* TODO: we really want to get rid of this ugly hack and make sure that
* notifiers cannot block for unbounded amount of time and add
* mmu_notifier_invalidate_range_{start,end} around unmap_page_range
*/
if (mm_has_notifiers(mm)) {
up_read(&mm->mmap_sem);
schedule_timeout_idle(HZ);
goto unlock_oom;
}
/* /*
* MMF_OOM_SKIP is set by exit_mmap when the OOM reaper can't * MMF_OOM_SKIP is set by exit_mmap when the OOM reaper can't
* work on the mm anymore. The check for MMF_OOM_SKIP must run * work on the mm anymore. The check for MMF_OOM_SKIP must run

View File

@ -1190,7 +1190,7 @@ static void __meminit __init_single_pfn(unsigned long pfn, unsigned long zone,
} }
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
static void init_reserved_page(unsigned long pfn) static void __meminit init_reserved_page(unsigned long pfn)
{ {
pg_data_t *pgdat; pg_data_t *pgdat;
int nid, zid; int nid, zid;
@ -5367,6 +5367,7 @@ not_early:
__init_single_page(page, pfn, zone, nid); __init_single_page(page, pfn, zone, nid);
set_pageblock_migratetype(page, MIGRATE_MOVABLE); set_pageblock_migratetype(page, MIGRATE_MOVABLE);
cond_resched();
} else { } else {
__init_single_pfn(pfn, zone, nid); __init_single_pfn(pfn, zone, nid);
} }

View File

@ -14,7 +14,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/sections.h> #include <asm/sections.h>
const int rodata_test_data = 0xC3; static const int rodata_test_data = 0xC3;
void rodata_test(void) void rodata_test(void)
{ {

View File

@ -165,9 +165,9 @@ static int init_memcg_params(struct kmem_cache *s,
if (!memcg_nr_cache_ids) if (!memcg_nr_cache_ids)
return 0; return 0;
arr = kzalloc(sizeof(struct memcg_cache_array) + arr = kvzalloc(sizeof(struct memcg_cache_array) +
memcg_nr_cache_ids * sizeof(void *), memcg_nr_cache_ids * sizeof(void *),
GFP_KERNEL); GFP_KERNEL);
if (!arr) if (!arr)
return -ENOMEM; return -ENOMEM;
@ -178,15 +178,23 @@ static int init_memcg_params(struct kmem_cache *s,
static void destroy_memcg_params(struct kmem_cache *s) static void destroy_memcg_params(struct kmem_cache *s)
{ {
if (is_root_cache(s)) if (is_root_cache(s))
kfree(rcu_access_pointer(s->memcg_params.memcg_caches)); kvfree(rcu_access_pointer(s->memcg_params.memcg_caches));
}
static void free_memcg_params(struct rcu_head *rcu)
{
struct memcg_cache_array *old;
old = container_of(rcu, struct memcg_cache_array, rcu);
kvfree(old);
} }
static int update_memcg_params(struct kmem_cache *s, int new_array_size) static int update_memcg_params(struct kmem_cache *s, int new_array_size)
{ {
struct memcg_cache_array *old, *new; struct memcg_cache_array *old, *new;
new = kzalloc(sizeof(struct memcg_cache_array) + new = kvzalloc(sizeof(struct memcg_cache_array) +
new_array_size * sizeof(void *), GFP_KERNEL); new_array_size * sizeof(void *), GFP_KERNEL);
if (!new) if (!new)
return -ENOMEM; return -ENOMEM;
@ -198,7 +206,7 @@ static int update_memcg_params(struct kmem_cache *s, int new_array_size)
rcu_assign_pointer(s->memcg_params.memcg_caches, new); rcu_assign_pointer(s->memcg_params.memcg_caches, new);
if (old) if (old)
kfree_rcu(old, rcu); call_rcu(&old->rcu, free_memcg_params);
return 0; return 0;
} }

View File

@ -575,7 +575,7 @@ static void lru_lazyfree_fn(struct page *page, struct lruvec *lruvec,
void *arg) void *arg)
{ {
if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) && if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) &&
!PageUnevictable(page)) { !PageSwapCache(page) && !PageUnevictable(page)) {
bool active = PageActive(page); bool active = PageActive(page);
del_page_from_lru_list(page, lruvec, del_page_from_lru_list(page, lruvec,
@ -665,7 +665,7 @@ void deactivate_file_page(struct page *page)
void mark_page_lazyfree(struct page *page) void mark_page_lazyfree(struct page *page)
{ {
if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) && if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) &&
!PageUnevictable(page)) { !PageSwapCache(page) && !PageUnevictable(page)) {
struct pagevec *pvec = &get_cpu_var(lru_lazyfree_pvecs); struct pagevec *pvec = &get_cpu_var(lru_lazyfree_pvecs);
get_page(page); get_page(page);

View File

@ -242,6 +242,17 @@ int add_to_swap(struct page *page)
* clear SWAP_HAS_CACHE flag. * clear SWAP_HAS_CACHE flag.
*/ */
goto fail; goto fail;
/*
* Normally the page will be dirtied in unmap because its pte should be
* dirty. A special case is MADV_FREE page. The page'e pte could have
* dirty bit cleared but the page's SwapBacked bit is still set because
* clearing the dirty bit and SwapBacked bit has no lock protected. For
* such page, unmap will not set dirty bit for it, so page reclaim will
* not write the page out. This can cause data corruption when the page
* is swap in later. Always setting the dirty bit for the page solves
* the problem.
*/
set_page_dirty(page);
return 1; return 1;

View File

@ -250,6 +250,7 @@ static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked)
WARN_ON(!list_empty(&zhdr->buddy)); WARN_ON(!list_empty(&zhdr->buddy));
set_bit(PAGE_STALE, &page->private); set_bit(PAGE_STALE, &page->private);
clear_bit(NEEDS_COMPACTING, &page->private);
spin_lock(&pool->lock); spin_lock(&pool->lock);
if (!list_empty(&page->lru)) if (!list_empty(&page->lru))
list_del(&page->lru); list_del(&page->lru);
@ -303,7 +304,6 @@ static void free_pages_work(struct work_struct *w)
list_del(&zhdr->buddy); list_del(&zhdr->buddy);
if (WARN_ON(!test_bit(PAGE_STALE, &page->private))) if (WARN_ON(!test_bit(PAGE_STALE, &page->private)))
continue; continue;
clear_bit(NEEDS_COMPACTING, &page->private);
spin_unlock(&pool->stale_lock); spin_unlock(&pool->stale_lock);
cancel_work_sync(&zhdr->work); cancel_work_sync(&zhdr->work);
free_z3fold_page(page); free_z3fold_page(page);
@ -624,10 +624,8 @@ lookup:
* stale pages list. cancel_work_sync() can sleep so we must make * stale pages list. cancel_work_sync() can sleep so we must make
* sure it won't be called in case we're in atomic context. * sure it won't be called in case we're in atomic context.
*/ */
if (zhdr && (can_sleep || !work_pending(&zhdr->work) || if (zhdr && (can_sleep || !work_pending(&zhdr->work))) {
!unlikely(work_busy(&zhdr->work)))) {
list_del(&zhdr->buddy); list_del(&zhdr->buddy);
clear_bit(NEEDS_COMPACTING, &page->private);
spin_unlock(&pool->stale_lock); spin_unlock(&pool->stale_lock);
if (can_sleep) if (can_sleep)
cancel_work_sync(&zhdr->work); cancel_work_sync(&zhdr->work);
@ -875,16 +873,18 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
goto next; goto next;
} }
next: next:
spin_lock(&pool->lock);
if (test_bit(PAGE_HEADLESS, &page->private)) { if (test_bit(PAGE_HEADLESS, &page->private)) {
if (ret == 0) { if (ret == 0) {
spin_unlock(&pool->lock);
free_z3fold_page(page); free_z3fold_page(page);
return 0; return 0;
} }
} else if (kref_put(&zhdr->refcount, release_z3fold_page)) { } else if (kref_put(&zhdr->refcount, release_z3fold_page)) {
atomic64_dec(&pool->pages_nr); atomic64_dec(&pool->pages_nr);
spin_unlock(&pool->lock);
return 0; return 0;
} }
spin_lock(&pool->lock);
/* /*
* Add to the beginning of LRU. * Add to the beginning of LRU.

View File

@ -6390,7 +6390,7 @@ sub process {
exit(0); exit(0);
} }
if (!$is_patch && $file !~ /cover-letter\.patch$/) { if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
ERROR("NOT_UNIFIED_DIFF", ERROR("NOT_UNIFIED_DIFF",
"Does not appear to be a unified-diff format patch\n"); "Does not appear to be a unified-diff format patch\n");
} }

View File

@ -53,6 +53,7 @@ acumulator||accumulator
adapater||adapter adapater||adapter
addional||additional addional||additional
additionaly||additionally additionaly||additionally
additonal||additional
addres||address addres||address
adddress||address adddress||address
addreses||addresses addreses||addresses
@ -67,6 +68,8 @@ adviced||advised
afecting||affecting afecting||affecting
againt||against againt||against
agaist||against agaist||against
aggreataon||aggregation
aggreation||aggregation
albumns||albums albumns||albums
alegorical||allegorical alegorical||allegorical
algined||aligned algined||aligned
@ -80,6 +83,8 @@ aligment||alignment
alignement||alignment alignement||alignment
allign||align allign||align
alligned||aligned alligned||aligned
alllocate||allocate
alloated||allocated
allocatote||allocate allocatote||allocate
allocatrd||allocated allocatrd||allocated
allocte||allocate allocte||allocate
@ -171,6 +176,7 @@ availale||available
availavility||availability availavility||availability
availble||available availble||available
availiable||available availiable||available
availible||available
avalable||available avalable||available
avaliable||available avaliable||available
aysnc||async aysnc||async
@ -203,6 +209,7 @@ broadcat||broadcast
cacluated||calculated cacluated||calculated
caculation||calculation caculation||calculation
calender||calendar calender||calendar
calescing||coalescing
calle||called calle||called
callibration||calibration callibration||calibration
calucate||calculate calucate||calculate
@ -210,6 +217,7 @@ calulate||calculate
cancelation||cancellation cancelation||cancellation
cancle||cancel cancle||cancel
capabilites||capabilities capabilites||capabilities
capabilty||capability
capabitilies||capabilities capabitilies||capabilities
capatibilities||capabilities capatibilities||capabilities
capapbilities||capabilities capapbilities||capabilities
@ -302,6 +310,7 @@ containts||contains
contaisn||contains contaisn||contains
contant||contact contant||contact
contence||contents contence||contents
continious||continuous
continous||continuous continous||continuous
continously||continuously continously||continuously
continueing||continuing continueing||continuing
@ -393,6 +402,7 @@ differrence||difference
diffrent||different diffrent||different
diffrentiate||differentiate diffrentiate||differentiate
difinition||definition difinition||definition
dimesions||dimensions
diplay||display diplay||display
direectly||directly direectly||directly
disassocation||disassociation disassocation||disassociation
@ -449,6 +459,7 @@ equiped||equipped
equivelant||equivalent equivelant||equivalent
equivilant||equivalent equivilant||equivalent
eror||error eror||error
errorr||error
estbalishment||establishment estbalishment||establishment
etsablishment||establishment etsablishment||establishment
etsbalishment||establishment etsbalishment||establishment
@ -481,6 +492,7 @@ failied||failed
faillure||failure faillure||failure
failue||failure failue||failure
failuer||failure failuer||failure
failng||failing
faireness||fairness faireness||fairness
falied||failed falied||failed
faliure||failure faliure||failure
@ -493,6 +505,7 @@ fetaure||feature
fetaures||features fetaures||features
fileystem||filesystem fileystem||filesystem
fimware||firmware fimware||firmware
firware||firmware
finanize||finalize finanize||finalize
findn||find findn||find
finilizes||finalizes finilizes||finalizes
@ -502,6 +515,7 @@ folloing||following
followign||following followign||following
followings||following followings||following
follwing||following follwing||following
fonud||found
forseeable||foreseeable forseeable||foreseeable
forse||force forse||force
fortan||fortran fortan||fortran
@ -532,6 +546,7 @@ grabing||grabbing
grahical||graphical grahical||graphical
grahpical||graphical grahpical||graphical
grapic||graphic grapic||graphic
grranted||granted
guage||gauge guage||gauge
guarenteed||guaranteed guarenteed||guaranteed
guarentee||guarantee guarentee||guarantee
@ -543,6 +558,7 @@ happend||happened
harware||hardware harware||hardware
heirarchically||hierarchically heirarchically||hierarchically
helpfull||helpful helpfull||helpful
hybernate||hibernate
hierachy||hierarchy hierachy||hierarchy
hierarchie||hierarchy hierarchie||hierarchy
howver||however howver||however
@ -565,16 +581,19 @@ implemenation||implementation
implementaiton||implementation implementaiton||implementation
implementated||implemented implementated||implemented
implemention||implementation implemention||implementation
implementd||implemented
implemetation||implementation implemetation||implementation
implemntation||implementation implemntation||implementation
implentation||implementation implentation||implementation
implmentation||implementation implmentation||implementation
implmenting||implementing implmenting||implementing
incative||inactive
incomming||incoming incomming||incoming
incompatabilities||incompatibilities incompatabilities||incompatibilities
incompatable||incompatible incompatable||incompatible
inconsistant||inconsistent inconsistant||inconsistent
increas||increase increas||increase
incremeted||incremented
incrment||increment incrment||increment
indendation||indentation indendation||indentation
indended||intended indended||intended
@ -619,6 +638,7 @@ interger||integer
intermittant||intermittent intermittant||intermittent
internel||internal internel||internal
interoprability||interoperability interoprability||interoperability
interuupt||interrupt
interrface||interface interrface||interface
interrrupt||interrupt interrrupt||interrupt
interrup||interrupt interrup||interrupt
@ -638,8 +658,10 @@ intrrupt||interrupt
intterrupt||interrupt intterrupt||interrupt
intuative||intuitive intuative||intuitive
invaid||invalid invaid||invalid
invald||invalid
invalde||invalid invalde||invalid
invalide||invalid invalide||invalid
invalidiate||invalidate
invalud||invalid invalud||invalid
invididual||individual invididual||individual
invokation||invocation invokation||invocation
@ -713,6 +735,7 @@ misformed||malformed
mispelled||misspelled mispelled||misspelled
mispelt||misspelt mispelt||misspelt
mising||missing mising||missing
mismactch||mismatch
missmanaged||mismanaged missmanaged||mismanaged
missmatch||mismatch missmatch||mismatch
miximum||maximum miximum||maximum
@ -731,6 +754,7 @@ multidimensionnal||multidimensional
multple||multiple multple||multiple
mumber||number mumber||number
muticast||multicast muticast||multicast
mutilcast||multicast
mutiple||multiple mutiple||multiple
mutli||multi mutli||multi
nams||names nams||names
@ -834,6 +858,7 @@ posible||possible
positon||position positon||position
possibilites||possibilities possibilites||possibilities
powerfull||powerful powerfull||powerful
preample||preamble
preapre||prepare preapre||prepare
preceeded||preceded preceeded||preceded
preceeding||preceding preceeding||preceding
@ -1059,6 +1084,7 @@ sturcture||structure
subdirectoires||subdirectories subdirectoires||subdirectories
suble||subtle suble||subtle
substract||subtract substract||subtract
submition||submission
succesfully||successfully succesfully||successfully
succesful||successful succesful||successful
successed||succeeded successed||succeeded
@ -1078,6 +1104,7 @@ suppoted||supported
suppported||supported suppported||supported
suppport||support suppport||support
supress||suppress supress||suppress
surpressed||suppressed
surpresses||suppresses surpresses||suppresses
susbsystem||subsystem susbsystem||subsystem
suspeneded||suspended suspeneded||suspended
@ -1091,6 +1118,7 @@ swithced||switched
swithcing||switching swithcing||switching
swithed||switched swithed||switched
swithing||switching swithing||switching
swtich||switch
symetric||symmetric symetric||symmetric
synax||syntax synax||syntax
synchonized||synchronized synchonized||synchronized
@ -1111,7 +1139,9 @@ therfore||therefore
thier||their thier||their
threds||threads threds||threads
threshhold||threshold threshhold||threshold
thresold||threshold
throught||through throught||through
troughput||throughput
thses||these thses||these
tiggered||triggered tiggered||triggered
tipically||typically tipically||typically
@ -1120,6 +1150,7 @@ tmis||this
torerable||tolerable torerable||tolerable
tramsmitted||transmitted tramsmitted||transmitted
tramsmit||transmit tramsmit||transmit
tranasction||transaction
tranfer||transfer tranfer||transfer
transciever||transceiver transciever||transceiver
transferd||transferred transferd||transferred
@ -1133,6 +1164,7 @@ trasmission||transmission
treshold||threshold treshold||threshold
trigerring||triggering trigerring||triggering
trun||turn trun||turn
tunning||tuning
ture||true ture||true
tyep||type tyep||type
udpate||update udpate||update
@ -1199,6 +1231,7 @@ visiters||visitors
vitual||virtual vitual||virtual
wakeus||wakeups wakeus||wakeups
wating||waiting wating||waiting
wiat||wait
wether||whether wether||whether
whataver||whatever whataver||whatever
whcih||which whcih||which