Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1675592 > unrolled thread
| Started by | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| First post | 2017-06-27 13:50 +0200 |
| Last post | 2017-06-27 22:50 +0200 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/5] v2 mm subsystem refcounter conversions Elena Reshetova <elena.reshetova@intel.com> - 2017-06-27 13:50 +0200
[PATCH 5/5] mm: convert mm_struct.mm_count from atomic_t to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-06-27 14:00 +0200
[PATCH 1/5] mm: convert bdi_writeback_congested.refcnt from atomic_t to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-06-27 14:00 +0200
Re: [PATCH 0/5] v2 mm subsystem refcounter conversions Andrew Morton <akpm@linux-foundation.org> - 2017-06-27 22:50 +0200
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-06-27 13:50 +0200 |
| Subject | [PATCH 0/5] v2 mm subsystem refcounter conversions |
| Message-ID | <tWXai-8mt-7@gated-at.bofh.it> |
Changes in v2: No changes in patches apart from trivial rebases, but now by default refcount_t = atomic_t and uses all atomic standard operations unless CONFIG_REFCOUNT_FULL is enabled. This is a compromize for the systems that are critical on performance and cannot accept even slight delay on the refcounter operations. Elena Reshetova (5): mm: convert bdi_writeback_congested.refcnt from atomic_t to refcount_t mm: convert anon_vma.refcount from atomic_t to refcount_t mm: convert kmemleak_object.use_count from atomic_t to refcount_t mm: convert mm_struct.mm_users from atomic_t to refcount_t mm: convert mm_struct.mm_count from atomic_t to refcount_t arch/alpha/kernel/smp.c | 6 +++--- arch/arc/mm/tlb.c | 2 +- arch/blackfin/mach-common/smp.c | 4 ++-- arch/ia64/include/asm/tlbflush.h | 2 +- arch/ia64/kernel/smp.c | 2 +- arch/ia64/sn/kernel/sn2/sn2_smp.c | 4 ++-- arch/mips/kernel/process.c | 2 +- arch/mips/kernel/smp.c | 6 +++--- arch/parisc/include/asm/mmu_context.h | 2 +- arch/powerpc/mm/hugetlbpage.c | 2 +- arch/powerpc/mm/icswx.c | 4 ++-- arch/sh/kernel/smp.c | 6 +++--- arch/sparc/kernel/smp_64.c | 6 +++--- arch/sparc/mm/srmmu.c | 2 +- arch/um/kernel/tlb.c | 2 +- arch/x86/kernel/tboot.c | 4 ++-- drivers/firmware/efi/arm-runtime.c | 4 ++-- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 2 +- fs/coredump.c | 2 +- fs/proc/base.c | 2 +- fs/proc/task_nommu.c | 4 ++-- fs/userfaultfd.c | 3 +-- include/linux/backing-dev-defs.h | 3 ++- include/linux/backing-dev.h | 4 ++-- include/linux/mm_types.h | 5 +++-- include/linux/rmap.h | 7 ++++--- include/linux/sched/mm.h | 10 +++++----- kernel/events/uprobes.c | 2 +- kernel/exit.c | 2 +- kernel/fork.c | 12 ++++++------ kernel/sched/core.c | 2 +- lib/is_single_threaded.c | 2 +- mm/backing-dev.c | 13 +++++++------ mm/debug.c | 4 ++-- mm/init-mm.c | 4 ++-- mm/khugepaged.c | 2 +- mm/kmemleak.c | 16 ++++++++-------- mm/ksm.c | 2 +- mm/memory.c | 2 +- mm/mmu_notifier.c | 10 +++++----- mm/mprotect.c | 2 +- mm/oom_kill.c | 2 +- mm/rmap.c | 14 +++++++------- mm/swapfile.c | 2 +- mm/vmacache.c | 2 +- 45 files changed, 100 insertions(+), 97 deletions(-) -- 2.7.4
[toc] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-06-27 14:00 +0200 |
| Subject | [PATCH 5/5] mm: convert mm_struct.mm_count from atomic_t to refcount_t |
| Message-ID | <tWXjX-8qo-3@gated-at.bofh.it> |
| In reply to | #1675592 |
refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
---
arch/blackfin/mach-common/smp.c | 2 +-
arch/x86/kernel/tboot.c | 2 +-
drivers/firmware/efi/arm-runtime.c | 2 +-
drivers/gpu/drm/amd/amdkfd/kfd_process.c | 2 +-
fs/proc/task_nommu.c | 4 ++--
fs/userfaultfd.c | 3 +--
include/linux/mm_types.h | 2 +-
include/linux/sched/mm.h | 6 +++---
kernel/fork.c | 2 +-
mm/debug.c | 2 +-
mm/init-mm.c | 2 +-
mm/mmu_notifier.c | 6 +++---
12 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index ed69b4f..f288f66 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -424,7 +424,7 @@ void cpu_die(void)
(void)cpu_report_death();
refcount_dec(&init_mm.mm_users);
- atomic_dec(&init_mm.mm_count);
+ refcount_dec(&init_mm.mm_count);
local_irq_disable();
platform_cpu_die();
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 39aaca5..fdbae72 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -103,7 +103,7 @@ static struct mm_struct tboot_mm = {
.mm_rb = RB_ROOT,
.pgd = swapper_pg_dir,
.mm_users = REFCOUNT_INIT(2),
- .mm_count = ATOMIC_INIT(1),
+ .mm_count = REFCOUNT_INIT(1),
.mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem),
.page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(init_mm.mmlist),
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index a9c41e2..24aeaef 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -33,7 +33,7 @@ extern u64 efi_system_table;
static struct mm_struct efi_mm = {
.mm_rb = RB_ROOT,
.mm_users = REFCOUNT_INIT(2),
- .mm_count = ATOMIC_INIT(1),
+ .mm_count = REFCOUNT_INIT(1),
.mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
.page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 84d1ffd..ba63d26 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -205,7 +205,7 @@ static void kfd_process_destroy_delayed(struct rcu_head *rcu)
BUG_ON(!kfd_process_wq);
p = container_of(rcu, struct kfd_process, rcu);
- BUG_ON(atomic_read(&p->mm->mm_count) <= 0);
+ BUG_ON(refcount_read(&p->mm->mm_count) == 0);
mmdrop(p->mm);
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index e969e79..eea6b91 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -38,7 +38,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
size = vma->vm_end - vma->vm_start;
}
- if (atomic_read(&mm->mm_count) > 1 ||
+ if (refcount_read(&mm->mm_count) > 1 ||
vma->vm_flags & VM_MAYSHARE) {
sbytes += size;
} else {
@@ -48,7 +48,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
}
}
- if (atomic_read(&mm->mm_count) > 1)
+ if (refcount_read(&mm->mm_count) > 1)
sbytes += kobjsize(mm);
else
bytes += kobjsize(mm);
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index f7555fc..a5d5015 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -624,7 +624,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
ctx->features = octx->features;
ctx->released = false;
ctx->mm = vma->vm_mm;
- atomic_inc(&ctx->mm->mm_count);
+ mmgrab(ctx->mm);
userfaultfd_ctx_get(octx);
fctx->orig = octx;
@@ -1826,7 +1826,6 @@ static struct file *userfaultfd_file_create(int flags)
ctx->mm = current->mm;
/* prevent the mm struct to be freed */
mmgrab(ctx->mm);
-
file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, ctx,
O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
if (IS_ERR(file)) {
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index e87b5fe..a29f66d 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -390,7 +390,7 @@ struct mm_struct {
* Use mmgrab()/mmdrop() to modify. When this drops to 0, the
* &struct mm_struct is freed.
*/
- atomic_t mm_count;
+ refcount_t mm_count;
atomic_long_t nr_ptes; /* PTE page table pages */
#if CONFIG_PGTABLE_LEVELS > 2
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index 1a15aa9d1..5e80e9e 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -31,14 +31,14 @@ extern struct mm_struct * mm_alloc(void);
*/
static inline void mmgrab(struct mm_struct *mm)
{
- atomic_inc(&mm->mm_count);
+ refcount_inc(&mm->mm_count);
}
/* mmdrop drops the mm and the page tables */
extern void __mmdrop(struct mm_struct *);
static inline void mmdrop(struct mm_struct *mm)
{
- if (unlikely(atomic_dec_and_test(&mm->mm_count)))
+ if (unlikely(refcount_dec_and_test(&mm->mm_count)))
__mmdrop(mm);
}
@@ -50,7 +50,7 @@ static inline void mmdrop_async_fn(struct work_struct *work)
static inline void mmdrop_async(struct mm_struct *mm)
{
- if (unlikely(atomic_dec_and_test(&mm->mm_count))) {
+ if (unlikely(refcount_dec_and_test(&mm->mm_count))) {
INIT_WORK(&mm->async_put_work, mmdrop_async_fn);
schedule_work(&mm->async_put_work);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index 3bbfe0e..0334742 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -770,7 +770,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
mm->mm_rb = RB_ROOT;
mm->vmacache_seqnum = 0;
refcount_set(&mm->mm_users, 1);
- atomic_set(&mm->mm_count, 1);
+ refcount_set(&mm->mm_count, 1);
init_rwsem(&mm->mmap_sem);
INIT_LIST_HEAD(&mm->mmlist);
mm->core_state = NULL;
diff --git a/mm/debug.c b/mm/debug.c
index 0866505..eebbd15 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -135,7 +135,7 @@ void dump_mm(const struct mm_struct *mm)
#endif
mm->mmap_base, mm->mmap_legacy_base, mm->highest_vm_end,
mm->pgd, refcount_read(&mm->mm_users),
- atomic_read(&mm->mm_count),
+ refcount_read(&mm->mm_count),
atomic_long_read((atomic_long_t *)&mm->nr_ptes),
mm_nr_pmds((struct mm_struct *)mm),
mm->map_count,
diff --git a/mm/init-mm.c b/mm/init-mm.c
index 6927a72..8de5267 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -18,7 +18,7 @@ struct mm_struct init_mm = {
.mm_rb = RB_ROOT,
.pgd = swapper_pg_dir,
.mm_users = REFCOUNT_INIT(2),
- .mm_count = ATOMIC_INIT(1),
+ .mm_count = REFCOUNT_INIT(1),
.mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem),
.page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(init_mm.mmlist),
diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
index b8c3dda..21fae87 100644
--- a/mm/mmu_notifier.c
+++ b/mm/mmu_notifier.c
@@ -349,7 +349,7 @@ void __mmu_notifier_mm_destroy(struct mm_struct *mm)
*/
void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
{
- BUG_ON(atomic_read(&mm->mm_count) <= 0);
+ BUG_ON(refcount_read(&mm->mm_count) == 0);
if (!hlist_unhashed(&mn->hlist)) {
/*
@@ -382,7 +382,7 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
*/
synchronize_srcu(&srcu);
- BUG_ON(atomic_read(&mm->mm_count) <= 0);
+ BUG_ON(refcount_read(&mm->mm_count) == 0);
mmdrop(mm);
}
@@ -402,7 +402,7 @@ void mmu_notifier_unregister_no_release(struct mmu_notifier *mn,
hlist_del_init_rcu(&mn->hlist);
spin_unlock(&mm->mmu_notifier_mm->lock);
- BUG_ON(atomic_read(&mm->mm_count) <= 0);
+ BUG_ON(refcount_read(&mm->mm_count) == 0);
mmdrop(mm);
}
EXPORT_SYMBOL_GPL(mmu_notifier_unregister_no_release);
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-06-27 14:00 +0200 |
| Subject | [PATCH 1/5] mm: convert bdi_writeback_congested.refcnt from atomic_t to refcount_t |
| Message-ID | <tWXjY-8qo-31@gated-at.bofh.it> |
| In reply to | #1675592 |
refcount_t type and corresponding API should be used instead of
atomic_t when the variable is used as a reference counter.
This allows to avoid accidental refcounter overflows that might
lead to use-after-free situations.
Switch bdi_writeback_congested.refcnt from atomic_t to refcount_t and
increment initial value by 1. The incrementation affecs the function
wb_congested_get_create which previously incremented both found and
created objects. After this patch the function will increment only found
objects and instead set the refcount of new objects to 1. Note that
new_congested is initially NULL, and will be discarded unless exiting
via the 'if (new_congested)' section.
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
---
include/linux/backing-dev-defs.h | 3 ++-
include/linux/backing-dev.h | 4 ++--
mm/backing-dev.c | 13 +++++++------
3 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index ad95581..609ee6f 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -4,6 +4,7 @@
#include <linux/list.h>
#include <linux/radix-tree.h>
#include <linux/rbtree.h>
+#include <linux/refcount.h>
#include <linux/spinlock.h>
#include <linux/percpu_counter.h>
#include <linux/percpu-refcount.h>
@@ -51,7 +52,7 @@ enum wb_stat_item {
*/
struct bdi_writeback_congested {
unsigned long state; /* WB_[a]sync_congested flags */
- atomic_t refcnt; /* nr of attached wb's and blkg */
+ refcount_t refcnt; /* nr of attached wb's and blkg */
#ifdef CONFIG_CGROUP_WRITEBACK
struct backing_dev_info *bdi; /* the associated bdi */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index c52a48c..4726d81 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -430,13 +430,13 @@ static inline bool inode_cgwb_enabled(struct inode *inode)
static inline struct bdi_writeback_congested *
wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
{
- atomic_inc(&bdi->wb_congested->refcnt);
+ refcount_inc(&bdi->wb_congested->refcnt);
return bdi->wb_congested;
}
static inline void wb_congested_put(struct bdi_writeback_congested *congested)
{
- if (atomic_dec_and_test(&congested->refcnt))
+ if (refcount_dec_and_test(&congested->refcnt))
kfree(congested);
}
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index c6f2a37..1799930 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -417,14 +417,17 @@ wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
node = &parent->rb_left;
else if (congested->blkcg_id > blkcg_id)
node = &parent->rb_right;
- else
- goto found;
+ else {
+ refcount_inc(&congested->refcnt);
+ goto found;
+ }
}
if (new_congested) {
/* !found and storage for new one already allocated, insert */
congested = new_congested;
new_congested = NULL;
+ refcount_set(&congested->refcnt, 1);
rb_link_node(&congested->rb_node, parent, node);
rb_insert_color(&congested->rb_node, &bdi->cgwb_congested_tree);
goto found;
@@ -437,13 +440,11 @@ wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
if (!new_congested)
return NULL;
- atomic_set(&new_congested->refcnt, 0);
new_congested->bdi = bdi;
new_congested->blkcg_id = blkcg_id;
goto retry;
found:
- atomic_inc(&congested->refcnt);
spin_unlock_irqrestore(&cgwb_lock, flags);
kfree(new_congested);
return congested;
@@ -460,7 +461,7 @@ void wb_congested_put(struct bdi_writeback_congested *congested)
unsigned long flags;
local_irq_save(flags);
- if (!atomic_dec_and_lock(&congested->refcnt, &cgwb_lock)) {
+ if (!refcount_dec_and_lock(&congested->refcnt, &cgwb_lock)) {
local_irq_restore(flags);
return;
}
@@ -767,7 +768,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
if (!bdi->wb_congested)
return -ENOMEM;
- atomic_set(&bdi->wb_congested->refcnt, 1);
+ refcount_set(&bdi->wb_congested->refcnt, 1);
err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
if (err) {
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Andrew Morton <akpm@linux-foundation.org> |
|---|---|
| Date | 2017-06-27 22:50 +0200 |
| Message-ID | <tX5AR-5JN-3@gated-at.bofh.it> |
| In reply to | #1675592 |
On Tue, 27 Jun 2017 14:48:42 +0300 Elena Reshetova <elena.reshetova@intel.com> wrote: > No changes in patches apart from trivial rebases, but now by > default refcount_t = atomic_t and uses all atomic standard operations > unless CONFIG_REFCOUNT_FULL is enabled. This is a compromize for the > systems that are critical on performance and cannot accept even > slight delay on the refcounter operations. OK, thanks - I'll save these up for consideration after the 4.12 release.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web