xarray: add the xa_lock to the radix_tree_root
authorMatthew Wilcox <mawilcox@microsoft.com>
Tue, 10 Apr 2018 23:36:52 +0000 (16:36 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 11 Apr 2018 17:28:39 +0000 (10:28 -0700)
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>
fs/f2fs/gc.c
include/linux/idr.h
include/linux/radix-tree.h
include/linux/xarray.h [new file with mode: 0644]
kernel/pid.c
tools/include/linux/spinlock.h

index bfb7a4a3a929793eae8b7c39dc71ac275e0776bf..9327411fd93b232bb18fc515d06e6122c7a608fa 100644 (file)
@@ -1015,7 +1015,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
        unsigned int init_segno = segno;
        struct gc_inode_list gc_list = {
                .ilist = LIST_HEAD_INIT(gc_list.ilist),
-               .iroot = RADIX_TREE_INIT(GFP_NOFS),
+               .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
        };
 
        trace_f2fs_gc_begin(sbi->sb, sync, background,
index 913c335054f0ab2e1ebfe59461c389c8d8680044..e856f4e0ab359d085d33266ca4505ea941df01af 100644 (file)
@@ -32,27 +32,28 @@ struct idr {
 #define IDR_RT_MARKER  (ROOT_IS_IDR | (__force gfp_t)                  \
                                        (1 << (ROOT_TAG_SHIFT + IDR_FREE)))
 
-#define IDR_INIT_BASE(base) {                                          \
-       .idr_rt = RADIX_TREE_INIT(IDR_RT_MARKER),                       \
+#define IDR_INIT_BASE(name, base) {                                    \
+       .idr_rt = RADIX_TREE_INIT(name, IDR_RT_MARKER),                 \
        .idr_base = (base),                                             \
        .idr_next = 0,                                                  \
 }
 
 /**
  * IDR_INIT() - Initialise an IDR.
+ * @name: Name of IDR.
  *
  * A freshly-initialised IDR contains no IDs.
  */
-#define IDR_INIT       IDR_INIT_BASE(0)
+#define IDR_INIT(name) IDR_INIT_BASE(name, 0)
 
 /**
- * DEFINE_IDR() - Define a statically-allocated IDR
- * @name: Name of IDR
+ * DEFINE_IDR() - Define a statically-allocated IDR.
+ * @name: Name of IDR.
  *
  * An IDR defined using this macro is ready for use with no additional
  * initialisation required.  It contains no IDs.
  */
-#define DEFINE_IDR(name)       struct idr name = IDR_INIT
+#define DEFINE_IDR(name)       struct idr name = IDR_INIT(name)
 
 /**
  * idr_get_cursor - Return the current position of the cyclic allocator
@@ -219,10 +220,10 @@ struct ida {
        struct radix_tree_root  ida_rt;
 };
 
-#define IDA_INIT       {                                               \
-       .ida_rt = RADIX_TREE_INIT(IDR_RT_MARKER | GFP_NOWAIT),          \
+#define IDA_INIT(name) {                                               \
+       .ida_rt = RADIX_TREE_INIT(name, IDR_RT_MARKER | GFP_NOWAIT),    \
 }
-#define DEFINE_IDA(name)       struct ida name = IDA_INIT
+#define DEFINE_IDA(name)       struct ida name = IDA_INIT(name)
 
 int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
 int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
index 6c4e2e716dacafcefdf2bf4bb9a3fd67b6f22a62..34149e8b5f73fe6cd821ba58c5196974d0adee2e 100644 (file)
@@ -110,20 +110,23 @@ struct radix_tree_node {
 #define ROOT_TAG_SHIFT (__GFP_BITS_SHIFT)
 
 struct radix_tree_root {
+       spinlock_t              xa_lock;
        gfp_t                   gfp_mask;
        struct radix_tree_node  __rcu *rnode;
 };
 
-#define RADIX_TREE_INIT(mask)  {                                       \
+#define RADIX_TREE_INIT(name, mask)    {                               \
+       .xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock),                  \
        .gfp_mask = (mask),                                             \
        .rnode = NULL,                                                  \
 }
 
 #define RADIX_TREE(name, mask) \
-       struct radix_tree_root name = RADIX_TREE_INIT(mask)
+       struct radix_tree_root name = RADIX_TREE_INIT(name, mask)
 
 #define INIT_RADIX_TREE(root, mask)                                    \
 do {                                                                   \
+       spin_lock_init(&(root)->xa_lock);                               \
        (root)->gfp_mask = (mask);                                      \
        (root)->rnode = NULL;                                           \
 } while (0)
diff --git a/include/linux/xarray.h b/include/linux/xarray.h
new file mode 100644 (file)
index 0000000..2dfc800
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef _LINUX_XARRAY_H
+#define _LINUX_XARRAY_H
+/*
+ * eXtensible Arrays
+ * Copyright (c) 2017 Microsoft Corporation
+ * Author: Matthew Wilcox <mawilcox@microsoft.com>
+ */
+
+#include <linux/spinlock.h>
+
+#define xa_trylock(xa)         spin_trylock(&(xa)->xa_lock)
+#define xa_lock(xa)            spin_lock(&(xa)->xa_lock)
+#define xa_unlock(xa)          spin_unlock(&(xa)->xa_lock)
+#define xa_lock_bh(xa)         spin_lock_bh(&(xa)->xa_lock)
+#define xa_unlock_bh(xa)       spin_unlock_bh(&(xa)->xa_lock)
+#define xa_lock_irq(xa)                spin_lock_irq(&(xa)->xa_lock)
+#define xa_unlock_irq(xa)      spin_unlock_irq(&(xa)->xa_lock)
+#define xa_lock_irqsave(xa, flags) \
+                               spin_lock_irqsave(&(xa)->xa_lock, flags)
+#define xa_unlock_irqrestore(xa, flags) \
+                               spin_unlock_irqrestore(&(xa)->xa_lock, flags)
+
+#endif /* _LINUX_XARRAY_H */
index ed6c343fe50dff7b546e43fd89102f43b898417e..157fe4b199713b65cb62c6d591225306cd5289f9 100644 (file)
@@ -70,7 +70,7 @@ int pid_max_max = PID_MAX_LIMIT;
  */
 struct pid_namespace init_pid_ns = {
        .kref = KREF_INIT(2),
-       .idr = IDR_INIT,
+       .idr = IDR_INIT(init_pid_ns.idr),
        .pid_allocated = PIDNS_ADDING,
        .level = 0,
        .child_reaper = &init_task,
index 4ed569fcb1390cea11b287aa4b34ef3b0851385e..b21b586b985424a03338023f96a3e9e3d996b2af 100644 (file)
@@ -7,6 +7,7 @@
 
 #define spinlock_t             pthread_mutex_t
 #define DEFINE_SPINLOCK(x)     pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
+#define __SPIN_LOCK_UNLOCKED(x)        (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER
 
 #define spin_lock_irqsave(x, f)                (void)f, pthread_mutex_lock(x)
 #define spin_unlock_irqrestore(x, f)   (void)f, pthread_mutex_unlock(x)