Merge branch 'akpm' (patches from Andrew)
Merge fixes from Andrew Morton: "26 fixes" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (26 commits) userfaultfd: remove wrong comment from userfaultfd_ctx_get() fat: fix using uninitialized fields of fat_inode/fsinfo_inode sh: cayman: IDE support fix kasan: fix races in quarantine_remove_cache() kasan: resched in quarantine_remove_cache() mm: do not call mem_cgroup_free() from within mem_cgroup_alloc() thp: fix another corner case of munlock() vs. THPs rmap: fix NULL-pointer dereference on THP munlocking mm/memblock.c: fix memblock_next_valid_pfn() userfaultfd: selftest: vm: allow to build in vm/ directory userfaultfd: non-cooperative: userfaultfd_remove revalidate vma in MADV_DONTNEED userfaultfd: non-cooperative: fix fork fctx->new memleak mm/cgroup: avoid panic when init with low memory drivers/md/bcache/util.h: remove duplicate inclusion of blkdev.h mm/vmstats: add thp_split_pud event for clarity include/linux/fs.h: fix unsigned enum warning with gcc-4.2 userfaultfd: non-cooperative: release all ctx in dup_userfaultfd_complete userfaultfd: non-cooperative: robustness check userfaultfd: non-cooperative: rollback userfaultfd_exit x86, mm: unify exit paths in gup_pte_range() ...
This commit is contained in:
+12
-1
@@ -1359,6 +1359,16 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fat_dummy_inode_init(struct inode *inode)
|
||||
{
|
||||
/* Initialize this dummy inode to work as no-op. */
|
||||
MSDOS_I(inode)->mmu_private = 0;
|
||||
MSDOS_I(inode)->i_start = 0;
|
||||
MSDOS_I(inode)->i_logstart = 0;
|
||||
MSDOS_I(inode)->i_attrs = 0;
|
||||
MSDOS_I(inode)->i_pos = 0;
|
||||
}
|
||||
|
||||
static int fat_read_root(struct inode *inode)
|
||||
{
|
||||
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
|
||||
@@ -1803,12 +1813,13 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
fat_inode = new_inode(sb);
|
||||
if (!fat_inode)
|
||||
goto out_fail;
|
||||
MSDOS_I(fat_inode)->i_pos = 0;
|
||||
fat_dummy_inode_init(fat_inode);
|
||||
sbi->fat_inode = fat_inode;
|
||||
|
||||
fsinfo_inode = new_inode(sb);
|
||||
if (!fsinfo_inode)
|
||||
goto out_fail;
|
||||
fat_dummy_inode_init(fsinfo_inode);
|
||||
fsinfo_inode->i_ino = MSDOS_FSINFO_INO;
|
||||
sbi->fsinfo_inode = fsinfo_inode;
|
||||
insert_inode_hash(fsinfo_inode);
|
||||
|
||||
+21
-48
@@ -138,8 +138,6 @@ out:
|
||||
* userfaultfd_ctx_get - Acquires a reference to the internal userfaultfd
|
||||
* context.
|
||||
* @ctx: [in] Pointer to the userfaultfd context.
|
||||
*
|
||||
* Returns: In case of success, returns not zero.
|
||||
*/
|
||||
static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
|
||||
{
|
||||
@@ -490,7 +488,7 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
|
||||
* in such case.
|
||||
*/
|
||||
down_read(&mm->mmap_sem);
|
||||
ret = 0;
|
||||
ret = VM_FAULT_NOPAGE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,10 +525,11 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
|
||||
struct userfaultfd_wait_queue *ewq)
|
||||
static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
|
||||
struct userfaultfd_wait_queue *ewq)
|
||||
{
|
||||
int ret = 0;
|
||||
if (WARN_ON_ONCE(current->flags & PF_EXITING))
|
||||
goto out;
|
||||
|
||||
ewq->ctx = ctx;
|
||||
init_waitqueue_entry(&ewq->wq, current);
|
||||
@@ -547,8 +546,16 @@ static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
|
||||
break;
|
||||
if (ACCESS_ONCE(ctx->released) ||
|
||||
fatal_signal_pending(current)) {
|
||||
ret = -1;
|
||||
__remove_wait_queue(&ctx->event_wqh, &ewq->wq);
|
||||
if (ewq->msg.event == UFFD_EVENT_FORK) {
|
||||
struct userfaultfd_ctx *new;
|
||||
|
||||
new = (struct userfaultfd_ctx *)
|
||||
(unsigned long)
|
||||
ewq->msg.arg.reserved.reserved1;
|
||||
|
||||
userfaultfd_ctx_put(new);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -566,9 +573,8 @@ static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
|
||||
* ctx may go away after this if the userfault pseudo fd is
|
||||
* already released.
|
||||
*/
|
||||
|
||||
out:
|
||||
userfaultfd_ctx_put(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void userfaultfd_event_complete(struct userfaultfd_ctx *ctx,
|
||||
@@ -626,7 +632,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dup_fctx(struct userfaultfd_fork_ctx *fctx)
|
||||
static void dup_fctx(struct userfaultfd_fork_ctx *fctx)
|
||||
{
|
||||
struct userfaultfd_ctx *ctx = fctx->orig;
|
||||
struct userfaultfd_wait_queue ewq;
|
||||
@@ -636,17 +642,15 @@ static int dup_fctx(struct userfaultfd_fork_ctx *fctx)
|
||||
ewq.msg.event = UFFD_EVENT_FORK;
|
||||
ewq.msg.arg.reserved.reserved1 = (unsigned long)fctx->new;
|
||||
|
||||
return userfaultfd_event_wait_completion(ctx, &ewq);
|
||||
userfaultfd_event_wait_completion(ctx, &ewq);
|
||||
}
|
||||
|
||||
void dup_userfaultfd_complete(struct list_head *fcs)
|
||||
{
|
||||
int ret = 0;
|
||||
struct userfaultfd_fork_ctx *fctx, *n;
|
||||
|
||||
list_for_each_entry_safe(fctx, n, fcs, list) {
|
||||
if (!ret)
|
||||
ret = dup_fctx(fctx);
|
||||
dup_fctx(fctx);
|
||||
list_del(&fctx->list);
|
||||
kfree(fctx);
|
||||
}
|
||||
@@ -689,8 +693,7 @@ void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *vm_ctx,
|
||||
userfaultfd_event_wait_completion(ctx, &ewq);
|
||||
}
|
||||
|
||||
void userfaultfd_remove(struct vm_area_struct *vma,
|
||||
struct vm_area_struct **prev,
|
||||
bool userfaultfd_remove(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
@@ -699,13 +702,11 @@ void userfaultfd_remove(struct vm_area_struct *vma,
|
||||
|
||||
ctx = vma->vm_userfaultfd_ctx.ctx;
|
||||
if (!ctx || !(ctx->features & UFFD_FEATURE_EVENT_REMOVE))
|
||||
return;
|
||||
return true;
|
||||
|
||||
userfaultfd_ctx_get(ctx);
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
*prev = NULL; /* We wait for ACK w/o the mmap semaphore */
|
||||
|
||||
msg_init(&ewq.msg);
|
||||
|
||||
ewq.msg.event = UFFD_EVENT_REMOVE;
|
||||
@@ -714,7 +715,7 @@ void userfaultfd_remove(struct vm_area_struct *vma,
|
||||
|
||||
userfaultfd_event_wait_completion(ctx, &ewq);
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool has_unmap_ctx(struct userfaultfd_ctx *ctx, struct list_head *unmaps,
|
||||
@@ -775,34 +776,6 @@ void userfaultfd_unmap_complete(struct mm_struct *mm, struct list_head *uf)
|
||||
}
|
||||
}
|
||||
|
||||
void userfaultfd_exit(struct mm_struct *mm)
|
||||
{
|
||||
struct vm_area_struct *vma = mm->mmap;
|
||||
|
||||
/*
|
||||
* We can do the vma walk without locking because the caller
|
||||
* (exit_mm) knows it now has exclusive access
|
||||
*/
|
||||
while (vma) {
|
||||
struct userfaultfd_ctx *ctx = vma->vm_userfaultfd_ctx.ctx;
|
||||
|
||||
if (ctx && (ctx->features & UFFD_FEATURE_EVENT_EXIT)) {
|
||||
struct userfaultfd_wait_queue ewq;
|
||||
|
||||
userfaultfd_ctx_get(ctx);
|
||||
|
||||
msg_init(&ewq.msg);
|
||||
ewq.msg.event = UFFD_EVENT_EXIT;
|
||||
|
||||
userfaultfd_event_wait_completion(ctx, &ewq);
|
||||
|
||||
ctx->features &= ~UFFD_FEATURE_EVENT_EXIT;
|
||||
}
|
||||
|
||||
vma = vma->vm_next;
|
||||
}
|
||||
}
|
||||
|
||||
static int userfaultfd_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct userfaultfd_ctx *ctx = file->private_data;
|
||||
|
||||
Reference in New Issue
Block a user