diff options
author | Matthew Wilcox <mawilcox@microsoft.com> | 2018-04-10 19:36:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-11 13:28:39 -0400 |
commit | f6bb2a2c0b81c47282ddb7883f92e65a063c27dd (patch) | |
tree | 74eb6dece48af9baee664a3abe1d70b5798f8b0d | |
parent | e5a955419642e0842fd26e1ada6ab3328018ca16 (diff) |
xarray: add the xa_lock to the radix_tree_root
This results in no change in structure size on 64-bit machines as it
fits in the padding between the gfp_t and the void *. 32-bit machines
will grow the structure from 8 to 12 bytes. Almost all radix trees are
protected with (at least) a spinlock, so as they are converted from
radix trees to xarrays, the data structures will shrink again.
Initialising the spinlock requires a name for the benefit of lockdep, so
RADIX_TREE_INIT() now needs to know the name of the radix tree it's
initialising, and so do IDR_INIT() and IDA_INIT().
Also add the xa_lock() and xa_unlock() family of wrappers to make it
easier to use the lock. If we could rely on -fplan9-extensions in the
compiler, we could avoid all of this syntactic sugar, but that wasn't
added until gcc 4.6.
Link: http://lkml.kernel.org/r/20180313132639.17387-8-willy@infradead.org
Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Cc: Darrick J. Wong <darrick.wong@oracle.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/f2fs/gc.c | 2 | ||||
-rw-r--r-- | include/linux/idr.h | 19 | ||||
-rw-r--r-- | include/linux/radix-tree.h | 7 | ||||
-rw-r--r-- | include/linux/xarray.h | 24 | ||||
-rw-r--r-- | kernel/pid.c | 2 | ||||
-rw-r--r-- | tools/include/linux/spinlock.h | 1 |
6 files changed, 42 insertions, 13 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index bfb7a4a3a929..9327411fd93b 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -1015,7 +1015,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, | |||
1015 | unsigned int init_segno = segno; | 1015 | unsigned int init_segno = segno; |
1016 | struct gc_inode_list gc_list = { | 1016 | struct gc_inode_list gc_list = { |
1017 | .ilist = LIST_HEAD_INIT(gc_list.ilist), | 1017 | .ilist = LIST_HEAD_INIT(gc_list.ilist), |
1018 | .iroot = RADIX_TREE_INIT(GFP_NOFS), | 1018 | .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), |
1019 | }; | 1019 | }; |
1020 | 1020 | ||
1021 | trace_f2fs_gc_begin(sbi->sb, sync, background, | 1021 | trace_f2fs_gc_begin(sbi->sb, sync, background, |
diff --git a/include/linux/idr.h b/include/linux/idr.h index 913c335054f0..e856f4e0ab35 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h | |||
@@ -32,27 +32,28 @@ struct idr { | |||
32 | #define IDR_RT_MARKER (ROOT_IS_IDR | (__force gfp_t) \ | 32 | #define IDR_RT_MARKER (ROOT_IS_IDR | (__force gfp_t) \ |
33 | (1 << (ROOT_TAG_SHIFT + IDR_FREE))) | 33 | (1 << (ROOT_TAG_SHIFT + IDR_FREE))) |
34 | 34 | ||
35 | #define IDR_INIT_BASE(base) { \ | 35 | #define IDR_INIT_BASE(name, base) { \ |
36 | .idr_rt = RADIX_TREE_INIT(IDR_RT_MARKER), \ | 36 | .idr_rt = RADIX_TREE_INIT(name, IDR_RT_MARKER), \ |
37 | .idr_base = (base), \ | 37 | .idr_base = (base), \ |
38 | .idr_next = 0, \ | 38 | .idr_next = 0, \ |
39 | } | 39 | } |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * IDR_INIT() - Initialise an IDR. | 42 | * IDR_INIT() - Initialise an IDR. |
43 | * @name: Name of IDR. | ||
43 | * | 44 | * |
44 | * A freshly-initialised IDR contains no IDs. | 45 | * A freshly-initialised IDR contains no IDs. |
45 | */ | 46 | */ |
46 | #define IDR_INIT IDR_INIT_BASE(0) | 47 | #define IDR_INIT(name) IDR_INIT_BASE(name, 0) |
47 | 48 | ||
48 | /** | 49 | /** |
49 | * DEFINE_IDR() - Define a statically-allocated IDR | 50 | * DEFINE_IDR() - Define a statically-allocated IDR. |
50 | * @name: Name of IDR | 51 | * @name: Name of IDR. |
51 | * | 52 | * |
52 | * An IDR defined using this macro is ready for use with no additional | 53 | * An IDR defined using this macro is ready for use with no additional |
53 | * initialisation required. It contains no IDs. | 54 | * initialisation required. It contains no IDs. |
54 | */ | 55 | */ |
55 | #define DEFINE_IDR(name) struct idr name = IDR_INIT | 56 | #define DEFINE_IDR(name) struct idr name = IDR_INIT(name) |
56 | 57 | ||
57 | /** | 58 | /** |
58 | * idr_get_cursor - Return the current position of the cyclic allocator | 59 | * idr_get_cursor - Return the current position of the cyclic allocator |
@@ -219,10 +220,10 @@ struct ida { | |||
219 | struct radix_tree_root ida_rt; | 220 | struct radix_tree_root ida_rt; |
220 | }; | 221 | }; |
221 | 222 | ||
222 | #define IDA_INIT { \ | 223 | #define IDA_INIT(name) { \ |
223 | .ida_rt = RADIX_TREE_INIT(IDR_RT_MARKER | GFP_NOWAIT), \ | 224 | .ida_rt = RADIX_TREE_INIT(name, IDR_RT_MARKER | GFP_NOWAIT), \ |
224 | } | 225 | } |
225 | #define DEFINE_IDA(name) struct ida name = IDA_INIT | 226 | #define DEFINE_IDA(name) struct ida name = IDA_INIT(name) |
226 | 227 | ||
227 | int ida_pre_get(struct ida *ida, gfp_t gfp_mask); | 228 | int ida_pre_get(struct ida *ida, gfp_t gfp_mask); |
228 | int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); | 229 | int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); |
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 6c4e2e716dac..34149e8b5f73 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h | |||
@@ -110,20 +110,23 @@ struct radix_tree_node { | |||
110 | #define ROOT_TAG_SHIFT (__GFP_BITS_SHIFT) | 110 | #define ROOT_TAG_SHIFT (__GFP_BITS_SHIFT) |
111 | 111 | ||
112 | struct radix_tree_root { | 112 | struct radix_tree_root { |
113 | spinlock_t xa_lock; | ||
113 | gfp_t gfp_mask; | 114 | gfp_t gfp_mask; |
114 | struct radix_tree_node __rcu *rnode; | 115 | struct radix_tree_node __rcu *rnode; |
115 | }; | 116 | }; |
116 | 117 | ||
117 | #define RADIX_TREE_INIT(mask) { \ | 118 | #define RADIX_TREE_INIT(name, mask) { \ |
119 | .xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock), \ | ||
118 | .gfp_mask = (mask), \ | 120 | .gfp_mask = (mask), \ |
119 | .rnode = NULL, \ | 121 | .rnode = NULL, \ |
120 | } | 122 | } |
121 | 123 | ||
122 | #define RADIX_TREE(name, mask) \ | 124 | #define RADIX_TREE(name, mask) \ |
123 | struct radix_tree_root name = RADIX_TREE_INIT(mask) | 125 | struct radix_tree_root name = RADIX_TREE_INIT(name, mask) |
124 | 126 | ||
125 | #define INIT_RADIX_TREE(root, mask) \ | 127 | #define INIT_RADIX_TREE(root, mask) \ |
126 | do { \ | 128 | do { \ |
129 | spin_lock_init(&(root)->xa_lock); \ | ||
127 | (root)->gfp_mask = (mask); \ | 130 | (root)->gfp_mask = (mask); \ |
128 | (root)->rnode = NULL; \ | 131 | (root)->rnode = NULL; \ |
129 | } while (0) | 132 | } while (0) |
diff --git a/include/linux/xarray.h b/include/linux/xarray.h new file mode 100644 index 000000000000..2dfc8006fe64 --- /dev/null +++ b/include/linux/xarray.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
2 | #ifndef _LINUX_XARRAY_H | ||
3 | #define _LINUX_XARRAY_H | ||
4 | /* | ||
5 | * eXtensible Arrays | ||
6 | * Copyright (c) 2017 Microsoft Corporation | ||
7 | * Author: Matthew Wilcox <mawilcox@microsoft.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/spinlock.h> | ||
11 | |||
12 | #define xa_trylock(xa) spin_trylock(&(xa)->xa_lock) | ||
13 | #define xa_lock(xa) spin_lock(&(xa)->xa_lock) | ||
14 | #define xa_unlock(xa) spin_unlock(&(xa)->xa_lock) | ||
15 | #define xa_lock_bh(xa) spin_lock_bh(&(xa)->xa_lock) | ||
16 | #define xa_unlock_bh(xa) spin_unlock_bh(&(xa)->xa_lock) | ||
17 | #define xa_lock_irq(xa) spin_lock_irq(&(xa)->xa_lock) | ||
18 | #define xa_unlock_irq(xa) spin_unlock_irq(&(xa)->xa_lock) | ||
19 | #define xa_lock_irqsave(xa, flags) \ | ||
20 | spin_lock_irqsave(&(xa)->xa_lock, flags) | ||
21 | #define xa_unlock_irqrestore(xa, flags) \ | ||
22 | spin_unlock_irqrestore(&(xa)->xa_lock, flags) | ||
23 | |||
24 | #endif /* _LINUX_XARRAY_H */ | ||
diff --git a/kernel/pid.c b/kernel/pid.c index ed6c343fe50d..157fe4b19971 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -70,7 +70,7 @@ int pid_max_max = PID_MAX_LIMIT; | |||
70 | */ | 70 | */ |
71 | struct pid_namespace init_pid_ns = { | 71 | struct pid_namespace init_pid_ns = { |
72 | .kref = KREF_INIT(2), | 72 | .kref = KREF_INIT(2), |
73 | .idr = IDR_INIT, | 73 | .idr = IDR_INIT(init_pid_ns.idr), |
74 | .pid_allocated = PIDNS_ADDING, | 74 | .pid_allocated = PIDNS_ADDING, |
75 | .level = 0, | 75 | .level = 0, |
76 | .child_reaper = &init_task, | 76 | .child_reaper = &init_task, |
diff --git a/tools/include/linux/spinlock.h b/tools/include/linux/spinlock.h index 4ed569fcb139..b21b586b9854 100644 --- a/tools/include/linux/spinlock.h +++ b/tools/include/linux/spinlock.h | |||
@@ -7,6 +7,7 @@ | |||
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 | 11 | ||
11 | #define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x) | 12 | #define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x) |
12 | #define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x) | 13 | #define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x) |