Skip to content

Commit 73fcb1a

Browse files
committed
Merge branch 'akpm' (patches from Andrew)
Merge misc fixes from Andrew Morton: "10 fixes" * emailed patches from Andrew Morton <[email protected]>: 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
2 parents 10a2f87 + 66072c2 commit 73fcb1a

File tree

11 files changed

+116
-15
lines changed

11 files changed

+116
-15
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7698,6 +7698,7 @@ KERNEL SELFTEST FRAMEWORK
76987698
M: Shuah Khan <[email protected]>
76997699
77007700
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
7701+
Q: https://patchwork.kernel.org/project/linux-kselftest/list/
77017702
S: Maintained
77027703
F: tools/testing/selftests/
77037704
F: Documentation/dev-tools/kselftest*

fs/hfsplus/super.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
588588
return 0;
589589

590590
out_put_hidden_dir:
591+
cancel_delayed_work_sync(&sbi->sync_work);
591592
iput(sbi->hidden_dir);
592593
out_put_root:
593594
dput(sb->s_root);

include/linux/mm.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2466,6 +2466,13 @@ static inline vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma,
24662466
return VM_FAULT_NOPAGE;
24672467
}
24682468

2469+
static 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+
24692476
struct page *follow_page_mask(struct vm_area_struct *vma,
24702477
unsigned long address, unsigned int foll_flags,
24712478
unsigned int *page_mask);

lib/radix-tree.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,11 +1612,9 @@ static void set_iter_tags(struct radix_tree_iter *iter,
16121612
static void __rcu **skip_siblings(struct radix_tree_node **nodep,
16131613
void __rcu **slot, struct radix_tree_iter *iter)
16141614
{
1615-
void *sib = node_to_entry(slot - 1);
1616-
16171615
while (iter->index < iter->next_index) {
16181616
*nodep = rcu_dereference_raw(*slot);
1619-
if (*nodep && *nodep != sib)
1617+
if (*nodep && !is_sibling_entry(iter->node, *nodep))
16201618
return slot;
16211619
slot++;
16221620
iter->index = __radix_tree_iter_add(iter, 1);
@@ -1631,7 +1629,7 @@ void __rcu **__radix_tree_next_slot(void __rcu **slot,
16311629
struct radix_tree_iter *iter, unsigned flags)
16321630
{
16331631
unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK;
1634-
struct radix_tree_node *node = rcu_dereference_raw(*slot);
1632+
struct radix_tree_node *node;
16351633

16361634
slot = skip_siblings(&node, slot, iter);
16371635

lib/test_bitmap.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,23 +331,32 @@ static void noinline __init test_mem_optimisations(void)
331331
unsigned int start, nbits;
332332

333333
for (start = 0; start < 1024; start += 8) {
334-
memset(bmap1, 0x5a, sizeof(bmap1));
335-
memset(bmap2, 0x5a, sizeof(bmap2));
336334
for (nbits = 0; nbits < 1024 - start; nbits += 8) {
335+
memset(bmap1, 0x5a, sizeof(bmap1));
336+
memset(bmap2, 0x5a, sizeof(bmap2));
337+
337338
bitmap_set(bmap1, start, nbits);
338339
__bitmap_set(bmap2, start, nbits);
339-
if (!bitmap_equal(bmap1, bmap2, 1024))
340+
if (!bitmap_equal(bmap1, bmap2, 1024)) {
340341
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)) {
342345
printk("set not __equal %d %d\n", start, nbits);
346+
failed_tests++;
347+
}
343348

344349
bitmap_clear(bmap1, start, nbits);
345350
__bitmap_clear(bmap2, start, nbits);
346-
if (!bitmap_equal(bmap1, bmap2, 1024))
351+
if (!bitmap_equal(bmap1, bmap2, 1024)) {
347352
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)) {
349356
printk("clear not __equal %d %d\n", start,
350357
nbits);
358+
failed_tests++;
359+
}
351360
}
352361
}
353362
}

mm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ config DEFERRED_STRUCT_PAGE_INIT
636636
default n
637637
depends on NO_BOOTMEM
638638
depends on !FLATMEM
639+
depends on !NEED_PER_CPU_KM
639640
help
640641
Ordinarily all struct pages are initialised during early boot in a
641642
single thread. On very large machines this can take a considerable

tools/include/linux/spinlock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
#include <stdbool.h>
77

88
#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
1010
#define __SPIN_LOCK_UNLOCKED(x) (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER
11+
#define spin_lock_init(x) pthread_mutex_init(x, NULL)
1112

1213
#define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x)
1314
#define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x)

tools/testing/radix-tree/Makefile

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ifeq ($(BUILD), 32)
1717
LDFLAGS += -m32
1818
endif
1919

20-
targets: mapshift $(TARGETS)
20+
targets: generated/map-shift.h $(TARGETS)
2121

2222
main: $(OFILES)
2323

@@ -42,9 +42,7 @@ radix-tree.c: ../../../lib/radix-tree.c
4242
idr.c: ../../../lib/idr.c
4343
sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
4444

45-
.PHONY: mapshift
46-
47-
mapshift:
45+
generated/map-shift.h:
4846
@if ! grep -qws $(SHIFT) generated/map-shift.h; then \
4947
echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \
5048
generated/map-shift.h; \

tools/testing/radix-tree/multiorder.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/radix-tree.h>
1717
#include <linux/slab.h>
1818
#include <linux/errno.h>
19+
#include <pthread.h>
1920

2021
#include "test.h"
2122

@@ -624,6 +625,67 @@ static void multiorder_account(void)
624625
item_kill_tree(&tree);
625626
}
626627

628+
bool stop_iteration = false;
629+
630+
static 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+
646+
static 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+
672+
static 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+
627689
void multiorder_checks(void)
628690
{
629691
int i;
@@ -644,6 +706,7 @@ void multiorder_checks(void)
644706
multiorder_join();
645707
multiorder_split();
646708
multiorder_account();
709+
multiorder_iteration_race();
647710

648711
radix_tree_cpu_dead(0);
649712
}

tools/testing/radix-tree/test.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,25 @@ int item_delete(struct radix_tree_root *root, unsigned long index)
7575
return 0;
7676
}
7777

78+
static 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+
85+
int 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+
7897
void item_check_present(struct radix_tree_root *root, unsigned long index)
7998
{
8099
struct item *item;

tools/testing/radix-tree/test.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@
55
#include <linux/rcupdate.h>
66

77
struct item {
8+
struct rcu_head rcu_head;
89
unsigned long index;
910
unsigned int order;
1011
};
1112

1213
struct item *item_create(unsigned long index, unsigned int order);
1314
int __item_insert(struct radix_tree_root *root, struct item *item);
1415
int item_insert(struct radix_tree_root *root, unsigned long index);
16+
void item_sanity(struct item *item, unsigned long index);
1517
int item_insert_order(struct radix_tree_root *root, unsigned long index,
1618
unsigned order);
1719
int item_delete(struct radix_tree_root *root, unsigned long index);
20+
int item_delete_rcu(struct radix_tree_root *root, unsigned long index);
1821
struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
1922

2023
void item_check_present(struct radix_tree_root *root, unsigned long index);

0 commit comments

Comments
 (0)