aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-05-19 00:24:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-05-19 00:24:26 -0400
commit73fcb1a370c76b202d406e95d9dabb76eaccf484 (patch)
tree78997fee9c78677955d414a699ce965fb8a21065
parent10a2f87485b9fb7bec1a50305d4a3ec74aa8058c (diff)
parent66072c29328717072fd84aaff3e070e3f008ba77 (diff)
Merge branch 'akpm' (patches from Andrew)
Merge misc fixes from Andrew Morton: "10 fixes" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: hfsplus: stop workqueue when fill_super() failed mm: don't allow deferred pages with NEED_PER_CPU_KM MAINTAINERS: add Q: entry to kselftest for patchwork project radix tree: fix multi-order iteration race radix tree test suite: multi-order iteration race radix tree test suite: add item_delete_rcu() radix tree test suite: fix compilation issue radix tree test suite: fix mapshift build target include/linux/mm.h: add new inline function vmf_error() lib/test_bitmap.c: fix bitmap optimisation tests to report errors correctly
-rw-r--r--MAINTAINERS1
-rw-r--r--fs/hfsplus/super.c1
-rw-r--r--include/linux/mm.h7
-rw-r--r--lib/radix-tree.c6
-rw-r--r--lib/test_bitmap.c21
-rw-r--r--mm/Kconfig1
-rw-r--r--tools/include/linux/spinlock.h3
-rw-r--r--tools/testing/radix-tree/Makefile6
-rw-r--r--tools/testing/radix-tree/multiorder.c63
-rw-r--r--tools/testing/radix-tree/test.c19
-rw-r--r--tools/testing/radix-tree/test.h3
11 files changed, 116 insertions, 15 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 4de8a5d9ed91..d155d1e0dbc2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7698,6 +7698,7 @@ KERNEL SELFTEST FRAMEWORK
7698M: Shuah Khan <shuah@kernel.org> 7698M: Shuah Khan <shuah@kernel.org>
7699L: linux-kselftest@vger.kernel.org 7699L: linux-kselftest@vger.kernel.org
7700T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git 7700T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
7701Q: https://patchwork.kernel.org/project/linux-kselftest/list/
7701S: Maintained 7702S: Maintained
7702F: tools/testing/selftests/ 7703F: tools/testing/selftests/
7703F: Documentation/dev-tools/kselftest* 7704F: Documentation/dev-tools/kselftest*
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 513c357c734b..a6c0f54c48c3 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -588,6 +588,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
588 return 0; 588 return 0;
589 589
590out_put_hidden_dir: 590out_put_hidden_dir:
591 cancel_delayed_work_sync(&sbi->sync_work);
591 iput(sbi->hidden_dir); 592 iput(sbi->hidden_dir);
592out_put_root: 593out_put_root:
593 dput(sb->s_root); 594 dput(sb->s_root);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index c080af584ddd..c6fa9a255dbf 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2466,6 +2466,13 @@ static inline vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma,
2466 return VM_FAULT_NOPAGE; 2466 return VM_FAULT_NOPAGE;
2467} 2467}
2468 2468
2469static inline vm_fault_t vmf_error(int err)
2470{
2471 if (err == -ENOMEM)
2472 return VM_FAULT_OOM;
2473 return VM_FAULT_SIGBUS;
2474}
2475
2469struct page *follow_page_mask(struct vm_area_struct *vma, 2476struct page *follow_page_mask(struct vm_area_struct *vma,
2470 unsigned long address, unsigned int foll_flags, 2477 unsigned long address, unsigned int foll_flags,
2471 unsigned int *page_mask); 2478 unsigned int *page_mask);
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index da9e10c827df..43e0cbedc3a0 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -1612,11 +1612,9 @@ static void set_iter_tags(struct radix_tree_iter *iter,
1612static void __rcu **skip_siblings(struct radix_tree_node **nodep, 1612static void __rcu **skip_siblings(struct radix_tree_node **nodep,
1613 void __rcu **slot, struct radix_tree_iter *iter) 1613 void __rcu **slot, struct radix_tree_iter *iter)
1614{ 1614{
1615 void *sib = node_to_entry(slot - 1);
1616
1617 while (iter->index < iter->next_index) { 1615 while (iter->index < iter->next_index) {
1618 *nodep = rcu_dereference_raw(*slot); 1616 *nodep = rcu_dereference_raw(*slot);
1619 if (*nodep && *nodep != sib) 1617 if (*nodep && !is_sibling_entry(iter->node, *nodep))
1620 return slot; 1618 return slot;
1621 slot++; 1619 slot++;
1622 iter->index = __radix_tree_iter_add(iter, 1); 1620 iter->index = __radix_tree_iter_add(iter, 1);
@@ -1631,7 +1629,7 @@ void __rcu **__radix_tree_next_slot(void __rcu **slot,
1631 struct radix_tree_iter *iter, unsigned flags) 1629 struct radix_tree_iter *iter, unsigned flags)
1632{ 1630{
1633 unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK; 1631 unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK;
1634 struct radix_tree_node *node = rcu_dereference_raw(*slot); 1632 struct radix_tree_node *node;
1635 1633
1636 slot = skip_siblings(&node, slot, iter); 1634 slot = skip_siblings(&node, slot, iter);
1637 1635
diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
index de16f7869fb1..6cd7d0740005 100644
--- a/lib/test_bitmap.c
+++ b/lib/test_bitmap.c
@@ -331,23 +331,32 @@ static void noinline __init test_mem_optimisations(void)
331 unsigned int start, nbits; 331 unsigned int start, nbits;
332 332
333 for (start = 0; start < 1024; start += 8) { 333 for (start = 0; start < 1024; start += 8) {
334 memset(bmap1, 0x5a, sizeof(bmap1));
335 memset(bmap2, 0x5a, sizeof(bmap2));
336 for (nbits = 0; nbits < 1024 - start; nbits += 8) { 334 for (nbits = 0; nbits < 1024 - start; nbits += 8) {
335 memset(bmap1, 0x5a, sizeof(bmap1));
336 memset(bmap2, 0x5a, sizeof(bmap2));
337
337 bitmap_set(bmap1, start, nbits); 338 bitmap_set(bmap1, start, nbits);
338 __bitmap_set(bmap2, start, nbits); 339 __bitmap_set(bmap2, start, nbits);
339 if (!bitmap_equal(bmap1, bmap2, 1024)) 340 if (!bitmap_equal(bmap1, bmap2, 1024)) {
340 printk("set not equal %d %d\n", start, nbits); 341 printk("set not equal %d %d\n", start, nbits);
341 if (!__bitmap_equal(bmap1, bmap2, 1024)) 342 failed_tests++;
343 }
344 if (!__bitmap_equal(bmap1, bmap2, 1024)) {
342 printk("set not __equal %d %d\n", start, nbits); 345 printk("set not __equal %d %d\n", start, nbits);
346 failed_tests++;
347 }
343 348
344 bitmap_clear(bmap1, start, nbits); 349 bitmap_clear(bmap1, start, nbits);
345 __bitmap_clear(bmap2, start, nbits); 350 __bitmap_clear(bmap2, start, nbits);
346 if (!bitmap_equal(bmap1, bmap2, 1024)) 351 if (!bitmap_equal(bmap1, bmap2, 1024)) {
347 printk("clear not equal %d %d\n", start, nbits); 352 printk("clear not equal %d %d\n", start, nbits);
348 if (!__bitmap_equal(bmap1, bmap2, 1024)) 353 failed_tests++;
354 }
355 if (!__bitmap_equal(bmap1, bmap2, 1024)) {
349 printk("clear not __equal %d %d\n", start, 356 printk("clear not __equal %d %d\n", start,
350 nbits); 357 nbits);
358 failed_tests++;
359 }
351 } 360 }
352 } 361 }
353} 362}
diff --git a/mm/Kconfig b/mm/Kconfig
index d5004d82a1d6..e14c01513bfd 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -636,6 +636,7 @@ config DEFERRED_STRUCT_PAGE_INIT
636 default n 636 default n
637 depends on NO_BOOTMEM 637 depends on NO_BOOTMEM
638 depends on !FLATMEM 638 depends on !FLATMEM
639 depends on !NEED_PER_CPU_KM
639 help 640 help
640 Ordinarily all struct pages are initialised during early boot in a 641 Ordinarily all struct pages are initialised during early boot in a
641 single thread. On very large machines this can take a considerable 642 single thread. On very large machines this can take a considerable
diff --git a/tools/include/linux/spinlock.h b/tools/include/linux/spinlock.h
index b21b586b9854..1738c0391da4 100644
--- a/tools/include/linux/spinlock.h
+++ b/tools/include/linux/spinlock.h
@@ -6,8 +6,9 @@
6#include <stdbool.h> 6#include <stdbool.h>
7 7
8#define spinlock_t pthread_mutex_t 8#define spinlock_t pthread_mutex_t
9#define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; 9#define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER
10#define __SPIN_LOCK_UNLOCKED(x) (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER 10#define __SPIN_LOCK_UNLOCKED(x) (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER
11#define spin_lock_init(x) pthread_mutex_init(x, NULL)
11 12
12#define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x) 13#define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x)
13#define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x) 14#define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x)
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index fa7ee369b3c9..db66f8a0d4be 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -17,7 +17,7 @@ ifeq ($(BUILD), 32)
17 LDFLAGS += -m32 17 LDFLAGS += -m32
18endif 18endif
19 19
20targets: mapshift $(TARGETS) 20targets: generated/map-shift.h $(TARGETS)
21 21
22main: $(OFILES) 22main: $(OFILES)
23 23
@@ -42,9 +42,7 @@ radix-tree.c: ../../../lib/radix-tree.c
42idr.c: ../../../lib/idr.c 42idr.c: ../../../lib/idr.c
43 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ 43 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
44 44
45.PHONY: mapshift 45generated/map-shift.h:
46
47mapshift:
48 @if ! grep -qws $(SHIFT) generated/map-shift.h; then \ 46 @if ! grep -qws $(SHIFT) generated/map-shift.h; then \
49 echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \ 47 echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \
50 generated/map-shift.h; \ 48 generated/map-shift.h; \
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 59245b3d587c..7bf405638b0b 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -16,6 +16,7 @@
16#include <linux/radix-tree.h> 16#include <linux/radix-tree.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <pthread.h>
19 20
20#include "test.h" 21#include "test.h"
21 22
@@ -624,6 +625,67 @@ static void multiorder_account(void)
624 item_kill_tree(&tree); 625 item_kill_tree(&tree);
625} 626}
626 627
628bool stop_iteration = false;
629
630static void *creator_func(void *ptr)
631{
632 /* 'order' is set up to ensure we have sibling entries */
633 unsigned int order = RADIX_TREE_MAP_SHIFT - 1;
634 struct radix_tree_root *tree = ptr;
635 int i;
636
637 for (i = 0; i < 10000; i++) {
638 item_insert_order(tree, 0, order);
639 item_delete_rcu(tree, 0);
640 }
641
642 stop_iteration = true;
643 return NULL;
644}
645
646static void *iterator_func(void *ptr)
647{
648 struct radix_tree_root *tree = ptr;
649 struct radix_tree_iter iter;
650 struct item *item;
651 void **slot;
652
653 while (!stop_iteration) {
654 rcu_read_lock();
655 radix_tree_for_each_slot(slot, tree, &iter, 0) {
656 item = radix_tree_deref_slot(slot);
657
658 if (!item)
659 continue;
660 if (radix_tree_deref_retry(item)) {
661 slot = radix_tree_iter_retry(&iter);
662 continue;
663 }
664
665 item_sanity(item, iter.index);
666 }
667 rcu_read_unlock();
668 }
669 return NULL;
670}
671
672static void multiorder_iteration_race(void)
673{
674 const int num_threads = sysconf(_SC_NPROCESSORS_ONLN);
675 pthread_t worker_thread[num_threads];
676 RADIX_TREE(tree, GFP_KERNEL);
677 int i;
678
679 pthread_create(&worker_thread[0], NULL, &creator_func, &tree);
680 for (i = 1; i < num_threads; i++)
681 pthread_create(&worker_thread[i], NULL, &iterator_func, &tree);
682
683 for (i = 0; i < num_threads; i++)
684 pthread_join(worker_thread[i], NULL);
685
686 item_kill_tree(&tree);
687}
688
627void multiorder_checks(void) 689void multiorder_checks(void)
628{ 690{
629 int i; 691 int i;
@@ -644,6 +706,7 @@ void multiorder_checks(void)
644 multiorder_join(); 706 multiorder_join();
645 multiorder_split(); 707 multiorder_split();
646 multiorder_account(); 708 multiorder_account();
709 multiorder_iteration_race();
647 710
648 radix_tree_cpu_dead(0); 711 radix_tree_cpu_dead(0);
649} 712}
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index 5978ab1f403d..def6015570b2 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -75,6 +75,25 @@ int item_delete(struct radix_tree_root *root, unsigned long index)
75 return 0; 75 return 0;
76} 76}
77 77
78static void item_free_rcu(struct rcu_head *head)
79{
80 struct item *item = container_of(head, struct item, rcu_head);
81
82 free(item);
83}
84
85int item_delete_rcu(struct radix_tree_root *root, unsigned long index)
86{
87 struct item *item = radix_tree_delete(root, index);
88
89 if (item) {
90 item_sanity(item, index);
91 call_rcu(&item->rcu_head, item_free_rcu);
92 return 1;
93 }
94 return 0;
95}
96
78void item_check_present(struct radix_tree_root *root, unsigned long index) 97void item_check_present(struct radix_tree_root *root, unsigned long index)
79{ 98{
80 struct item *item; 99 struct item *item;
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index d9c031dbeb1a..31f1d9b6f506 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -5,6 +5,7 @@
5#include <linux/rcupdate.h> 5#include <linux/rcupdate.h>
6 6
7struct item { 7struct item {
8 struct rcu_head rcu_head;
8 unsigned long index; 9 unsigned long index;
9 unsigned int order; 10 unsigned int order;
10}; 11};
@@ -12,9 +13,11 @@ struct item {
12struct item *item_create(unsigned long index, unsigned int order); 13struct item *item_create(unsigned long index, unsigned int order);
13int __item_insert(struct radix_tree_root *root, struct item *item); 14int __item_insert(struct radix_tree_root *root, struct item *item);
14int item_insert(struct radix_tree_root *root, unsigned long index); 15int item_insert(struct radix_tree_root *root, unsigned long index);
16void item_sanity(struct item *item, unsigned long index);
15int item_insert_order(struct radix_tree_root *root, unsigned long index, 17int item_insert_order(struct radix_tree_root *root, unsigned long index,
16 unsigned order); 18 unsigned order);
17int item_delete(struct radix_tree_root *root, unsigned long index); 19int item_delete(struct radix_tree_root *root, unsigned long index);
20int item_delete_rcu(struct radix_tree_root *root, unsigned long index);
18struct item *item_lookup(struct radix_tree_root *root, unsigned long index); 21struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
19 22
20void item_check_present(struct radix_tree_root *root, unsigned long index); 23void item_check_present(struct radix_tree_root *root, unsigned long index);