All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] Add split_lock
@ 2021-04-08  5:23 Matthew Wilcox (Oracle)
  2021-04-08  7:00 ` kernel test robot
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-04-08  5:23 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Will Deacon, Waiman Long,
	Boqun Feng, linux-kernel, Thomas Gleixner,
	Sebastian Andrzej Siewior
  Cc: Matthew Wilcox (Oracle)

bit_spinlocks are horrible on RT because there's absolutely nowhere
to put the mutex to sleep on.  They also do not participate in lockdep
because there's nowhere to put the map.

Most (all?) bit spinlocks are actually a split lock; logically they
could be treated as a single spinlock, but for performance, we want to
split the lock over many objects.  Introduce the split_lock as somewhere
to store the lockdep map and as somewhere that the RT kernel can put
a mutex.  It may also let us store a ticket lock for better performance
on non-RT kernels in the future, but I have left the current cpu_relax()
implementation intact for now.

The API change breaks all users except for the two which have been
converted.  This is an RFC, and I'm willing to fix all the rest.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/dcache.c                  | 25 ++++++++++----------
 include/linux/bit_spinlock.h | 36 ++++++++++++++---------------
 include/linux/list_bl.h      |  9 ++++----
 include/linux/split_lock.h   | 45 ++++++++++++++++++++++++++++++++++++
 mm/slub.c                    |  6 +++--
 5 files changed, 84 insertions(+), 37 deletions(-)
 create mode 100644 include/linux/split_lock.h

diff --git a/fs/dcache.c b/fs/dcache.c
index 7d24ff7eb206..a3861d330001 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -96,6 +96,7 @@ EXPORT_SYMBOL(slash_name);
 
 static unsigned int d_hash_shift __read_mostly;
 
+static DEFINE_SPLIT_LOCK(d_hash_lock);
 static struct hlist_bl_head *dentry_hashtable __read_mostly;
 
 static inline struct hlist_bl_head *d_hash(unsigned int hash)
@@ -469,9 +470,9 @@ static void ___d_drop(struct dentry *dentry)
 	else
 		b = d_hash(dentry->d_name.hash);
 
-	hlist_bl_lock(b);
+	hlist_bl_lock(b, &d_hash_lock);
 	__hlist_bl_del(&dentry->d_hash);
-	hlist_bl_unlock(b);
+	hlist_bl_unlock(b, &d_hash_lock);
 }
 
 void __d_drop(struct dentry *dentry)
@@ -2074,9 +2075,9 @@ static struct dentry *__d_instantiate_anon(struct dentry *dentry,
 	__d_set_inode_and_type(dentry, inode, add_flags);
 	hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
 	if (!disconnected) {
-		hlist_bl_lock(&dentry->d_sb->s_roots);
+		hlist_bl_lock(&dentry->d_sb->s_roots, &d_hash_lock);
 		hlist_bl_add_head(&dentry->d_hash, &dentry->d_sb->s_roots);
-		hlist_bl_unlock(&dentry->d_sb->s_roots);
+		hlist_bl_unlock(&dentry->d_sb->s_roots, &d_hash_lock);
 	}
 	spin_unlock(&dentry->d_lock);
 	spin_unlock(&inode->i_lock);
@@ -2513,9 +2514,9 @@ static void __d_rehash(struct dentry *entry)
 {
 	struct hlist_bl_head *b = d_hash(entry->d_name.hash);
 
-	hlist_bl_lock(b);
+	hlist_bl_lock(b, &d_hash_lock);
 	hlist_bl_add_head_rcu(&entry->d_hash, b);
-	hlist_bl_unlock(b);
+	hlist_bl_unlock(b, &d_hash_lock);
 }
 
 /**
@@ -2606,9 +2607,9 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
 		goto retry;
 	}
 
-	hlist_bl_lock(b);
+	hlist_bl_lock(b, &d_hash_lock);
 	if (unlikely(READ_ONCE(parent->d_inode->i_dir_seq) != seq)) {
-		hlist_bl_unlock(b);
+		hlist_bl_unlock(b, &d_hash_lock);
 		rcu_read_unlock();
 		goto retry;
 	}
@@ -2626,7 +2627,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
 			continue;
 		if (!d_same_name(dentry, parent, name))
 			continue;
-		hlist_bl_unlock(b);
+		hlist_bl_unlock(b, &d_hash_lock);
 		/* now we can try to grab a reference */
 		if (!lockref_get_not_dead(&dentry->d_lockref)) {
 			rcu_read_unlock();
@@ -2664,7 +2665,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
 	new->d_flags |= DCACHE_PAR_LOOKUP;
 	new->d_wait = wq;
 	hlist_bl_add_head_rcu(&new->d_u.d_in_lookup_hash, b);
-	hlist_bl_unlock(b);
+	hlist_bl_unlock(b, &d_hash_lock);
 	return new;
 mismatch:
 	spin_unlock(&dentry->d_lock);
@@ -2677,12 +2678,12 @@ void __d_lookup_done(struct dentry *dentry)
 {
 	struct hlist_bl_head *b = in_lookup_hash(dentry->d_parent,
 						 dentry->d_name.hash);
-	hlist_bl_lock(b);
+	hlist_bl_lock(b, &d_hash_lock);
 	dentry->d_flags &= ~DCACHE_PAR_LOOKUP;
 	__hlist_bl_del(&dentry->d_u.d_in_lookup_hash);
 	wake_up_all(dentry->d_wait);
 	dentry->d_wait = NULL;
-	hlist_bl_unlock(b);
+	hlist_bl_unlock(b, &d_hash_lock);
 	INIT_HLIST_NODE(&dentry->d_u.d_alias);
 	INIT_LIST_HEAD(&dentry->d_lru);
 }
diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h
index bbc4730a6505..641623d471b0 100644
--- a/include/linux/bit_spinlock.h
+++ b/include/linux/bit_spinlock.h
@@ -2,6 +2,7 @@
 #ifndef __LINUX_BIT_SPINLOCK_H
 #define __LINUX_BIT_SPINLOCK_H
 
+#include <linux/split_lock.h>
 #include <linux/kernel.h>
 #include <linux/preempt.h>
 #include <linux/atomic.h>
@@ -13,32 +14,23 @@
  * Don't use this unless you really need to: spin_lock() and spin_unlock()
  * are significantly faster.
  */
-static inline void bit_spin_lock(int bitnum, unsigned long *addr)
+static inline void bit_spin_lock(int bitnum, unsigned long *addr,
+		struct split_lock *lock)
 {
-	/*
-	 * Assuming the lock is uncontended, this never enters
-	 * the body of the outer loop. If it is contended, then
-	 * within the inner loop a non-atomic test is used to
-	 * busywait with less bus contention for a good time to
-	 * attempt to acquire the lock bit.
-	 */
 	preempt_disable();
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-	while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
-		preempt_enable();
-		do {
-			cpu_relax();
-		} while (test_bit(bitnum, addr));
-		preempt_disable();
-	}
+	while (unlikely(test_and_set_bit_lock(bitnum, addr)))
+		split_lock_spin(lock, bitnum, addr);
 #endif
+	spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
 	__acquire(bitlock);
 }
 
 /*
  * Return true if it was acquired
  */
-static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
+static inline int bit_spin_trylock(int bitnum, unsigned long *addr,
+		struct split_lock *lock)
 {
 	preempt_disable();
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
@@ -47,6 +39,7 @@ static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
 		return 0;
 	}
 #endif
+	spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
 	__acquire(bitlock);
 	return 1;
 }
@@ -54,13 +47,16 @@ static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
 /*
  *  bit-based spin_unlock()
  */
-static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
+static inline void bit_spin_unlock(int bitnum, unsigned long *addr,
+		struct split_lock *lock)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
 	BUG_ON(!test_bit(bitnum, addr));
 #endif
+	spin_release(&lock->dep_map, _RET_IP_);
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
 	clear_bit_unlock(bitnum, addr);
+	split_lock_unlock(lock, bitnum, addr);
 #endif
 	preempt_enable();
 	__release(bitlock);
@@ -71,13 +67,16 @@ static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
  *  non-atomic version, which can be used eg. if the bit lock itself is
  *  protecting the rest of the flags in the word.
  */
-static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
+static inline void __bit_spin_unlock(int bitnum, unsigned long *addr,
+		struct split_lock *lock)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
 	BUG_ON(!test_bit(bitnum, addr));
 #endif
+	spin_release(&lock->dep_map, _RET_IP_);
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
 	__clear_bit_unlock(bitnum, addr);
+	split_lock_unlock(lock, bitnum, addr);
 #endif
 	preempt_enable();
 	__release(bitlock);
@@ -98,4 +97,3 @@ static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
 }
 
 #endif /* __LINUX_BIT_SPINLOCK_H */
-
diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h
index ae1b541446c9..e6c57c670358 100644
--- a/include/linux/list_bl.h
+++ b/include/linux/list_bl.h
@@ -143,14 +143,15 @@ static inline void hlist_bl_del_init(struct hlist_bl_node *n)
 	}
 }
 
-static inline void hlist_bl_lock(struct hlist_bl_head *b)
+static inline void hlist_bl_lock(struct hlist_bl_head *b, struct split_lock *sl)
 {
-	bit_spin_lock(0, (unsigned long *)b);
+	bit_spin_lock(0, (unsigned long *)b, sl);
 }
 
-static inline void hlist_bl_unlock(struct hlist_bl_head *b)
+static inline void hlist_bl_unlock(struct hlist_bl_head *b,
+		struct split_lock *sl)
 {
-	__bit_spin_unlock(0, (unsigned long *)b);
+	__bit_spin_unlock(0, (unsigned long *)b, sl);
 }
 
 static inline bool hlist_bl_is_locked(struct hlist_bl_head *b)
diff --git a/include/linux/split_lock.h b/include/linux/split_lock.h
new file mode 100644
index 000000000000..d9c7816fb73c
--- /dev/null
+++ b/include/linux/split_lock.h
@@ -0,0 +1,45 @@
+#ifndef _LINUX_SPLIT_LOCK_H
+#define _LINUX_SPLIT_LOCK_H
+
+#include <linux/lockdep_types.h>
+
+struct split_lock {
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lockdep_map dep_map;
+#endif
+};
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#define SPLIT_DEP_MAP_INIT(lockname)					\
+	.dep_map = {							\
+		.name = #lockname,					\
+		.wait_type_inner = LD_WAIT_SPIN,			\
+	}
+#else
+#define SPLIT_DEP_MAP_INIT(lockname)
+#endif
+
+#define DEFINE_SPLIT_LOCK(name)						\
+struct split_lock name = {						\
+	SPLIT_DEP_MAP_INIT(name)					\
+};
+
+/*
+ * This is only called if we're contended.  We use a non-atomic test
+ * to reduce contention on the cacheline while we wait.
+ */
+static inline void split_lock_spin(struct split_lock *lock, int bitnum,
+		unsigned long *addr)
+{
+	preempt_enable();
+	do {
+		cpu_relax();
+	} while (test_bit(bitnum, addr));
+	preempt_disable();
+}
+
+static inline void split_lock_unlock(struct split_lock *lock, int bitnum,
+		unsigned long *addr)
+{
+}
+#endif /* _LINUX_SPLIT_LOCK_H */
diff --git a/mm/slub.c b/mm/slub.c
index 9c0e26ddf300..eb7c22fbc8fc 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -346,19 +346,21 @@ static inline unsigned int oo_objects(struct kmem_cache_order_objects x)
 	return x.x & OO_MASK;
 }
 
+static DEFINE_SPLIT_LOCK(slab_split_lock);
+
 /*
  * Per slab locking using the pagelock
  */
 static __always_inline void slab_lock(struct page *page)
 {
 	VM_BUG_ON_PAGE(PageTail(page), page);
-	bit_spin_lock(PG_locked, &page->flags);
+	bit_spin_lock(PG_locked, &page->flags, &slab_split_lock);
 }
 
 static __always_inline void slab_unlock(struct page *page)
 {
 	VM_BUG_ON_PAGE(PageTail(page), page);
-	__bit_spin_unlock(PG_locked, &page->flags);
+	__bit_spin_unlock(PG_locked, &page->flags, &slab_split_lock);
 }
 
 /* Interrupts must be disabled (for the fallback code to work right) */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] Add split_lock
  2021-04-08  5:23 [RFC PATCH] Add split_lock Matthew Wilcox (Oracle)
@ 2021-04-08  7:00 ` kernel test robot
  2021-04-08 10:18 ` Peter Zijlstra
  2021-04-08 10:50 ` kernel test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2021-04-08  7:00 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 4518 bytes --]

Hi "Matthew,

[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on linux/master]
[also build test ERROR on linus/master hnaz-linux-mm/master v5.12-rc6 next-20210407]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Matthew-Wilcox-Oracle/Add-split_lock/20210408-132535
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5e46d1b78a03d52306f21f77a4e4a144b6d31486
config: s390-randconfig-r016-20210407 (attached as .config)
compiler: s390-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/31f96279760e4e4a2abf1d397e5c85fca955d908
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matthew-Wilcox-Oracle/Add-split_lock/20210408-132535
        git checkout 31f96279760e4e4a2abf1d397e5c85fca955d908
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=s390 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from drivers/s390/cio/airq.c:21:
   arch/s390/include/asm/airq.h: In function 'airq_iv_lock':
>> arch/s390/include/asm/airq.h:75:2: error: too few arguments to function 'bit_spin_lock'
      75 |  bit_spin_lock(bit ^ be_to_le, iv->bitlock);
         |  ^~~~~~~~~~~~~
   In file included from include/linux/mm.h:22,
                    from include/linux/scatterlist.h:8,
                    from include/linux/iommu.h:10,
                    from arch/s390/include/asm/pci.h:7,
                    from include/linux/pci.h:1823,
                    from arch/s390/include/asm/hw_irq.h:6,
                    from include/linux/irq.h:589,
                    from drivers/s390/cio/airq.c:13:
   include/linux/bit_spinlock.h:17:20: note: declared here
      17 | static inline void bit_spin_lock(int bitnum, unsigned long *addr,
         |                    ^~~~~~~~~~~~~
   In file included from drivers/s390/cio/airq.c:21:
   arch/s390/include/asm/airq.h: In function 'airq_iv_unlock':
>> arch/s390/include/asm/airq.h:81:2: error: too few arguments to function 'bit_spin_unlock'
      81 |  bit_spin_unlock(bit ^ be_to_le, iv->bitlock);
         |  ^~~~~~~~~~~~~~~
   In file included from include/linux/mm.h:22,
                    from include/linux/scatterlist.h:8,
                    from include/linux/iommu.h:10,
                    from arch/s390/include/asm/pci.h:7,
                    from include/linux/pci.h:1823,
                    from arch/s390/include/asm/hw_irq.h:6,
                    from include/linux/irq.h:589,
                    from drivers/s390/cio/airq.c:13:
   include/linux/bit_spinlock.h:50:20: note: declared here
      50 | static inline void bit_spin_unlock(int bitnum, unsigned long *addr,
         |                    ^~~~~~~~~~~~~~~


vim +/bit_spin_lock +75 arch/s390/include/asm/airq.h

a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  71  
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  72  static inline void airq_iv_lock(struct airq_iv *iv, unsigned long bit)
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  73  {
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  74  	const unsigned long be_to_le = BITS_PER_LONG - 1;
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25 @75  	bit_spin_lock(bit ^ be_to_le, iv->bitlock);
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  76  }
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  77  
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  78  static inline void airq_iv_unlock(struct airq_iv *iv, unsigned long bit)
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  79  {
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  80  	const unsigned long be_to_le = BITS_PER_LONG - 1;
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25 @81  	bit_spin_unlock(bit ^ be_to_le, iv->bitlock);
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  82  }
a9a6f0341df9a6 Martin Schwidefsky 2013-06-25  83  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 14799 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] Add split_lock
  2021-04-08  5:23 [RFC PATCH] Add split_lock Matthew Wilcox (Oracle)
  2021-04-08  7:00 ` kernel test robot
@ 2021-04-08 10:18 ` Peter Zijlstra
  2021-04-09 13:42   ` Thomas Gleixner
  2021-04-08 10:50 ` kernel test robot
  2 siblings, 1 reply; 5+ messages in thread
From: Peter Zijlstra @ 2021-04-08 10:18 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: Ingo Molnar, Will Deacon, Waiman Long, Boqun Feng, linux-kernel,
	Thomas Gleixner, Sebastian Andrzej Siewior

On Thu, Apr 08, 2021 at 06:23:38AM +0100, Matthew Wilcox (Oracle) wrote:
> bit_spinlocks are horrible on RT because there's absolutely nowhere
> to put the mutex to sleep on.  They also do not participate in lockdep
> because there's nowhere to put the map.
> 
> Most (all?) bit spinlocks are actually a split lock; logically they
> could be treated as a single spinlock, but for performance, we want to
> split the lock over many objects.  Introduce the split_lock as somewhere
> to store the lockdep map and as somewhere that the RT kernel can put
> a mutex.  It may also let us store a ticket lock for better performance
> on non-RT kernels in the future, but I have left the current cpu_relax()
> implementation intact for now.

I think I like it, but I'm not sure it'll work for RT as is. It's a bit
like qrwlock in that it only uses the internal (split) lock for
contention, but that doesn't work for PI.

I've not recently looked at RT, but I think they simply used to bloat a
number of the data structures with a real lock. Sebastian and Thomas
will know better.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] Add split_lock
  2021-04-08  5:23 [RFC PATCH] Add split_lock Matthew Wilcox (Oracle)
  2021-04-08  7:00 ` kernel test robot
  2021-04-08 10:18 ` Peter Zijlstra
@ 2021-04-08 10:50 ` kernel test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2021-04-08 10:50 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 11652 bytes --]

Hi "Matthew,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on linux/master]
[also build test WARNING on linus/master hnaz-linux-mm/master v5.12-rc6 next-20210407]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Matthew-Wilcox-Oracle/Add-split_lock/20210408-132535
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5e46d1b78a03d52306f21f77a4e4a144b6d31486
config: x86_64-randconfig-a011-20210408 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 56ea2e2fdd691136d5e6631fa0e447173694b82c)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/31f96279760e4e4a2abf1d397e5c85fca955d908
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matthew-Wilcox-Oracle/Add-split_lock/20210408-132535
        git checkout 31f96279760e4e4a2abf1d397e5c85fca955d908
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/infiniband/hw/hfi1/pcie.c:55:
   In file included from drivers/infiniband/hw/hfi1/hfi.h:71:
   include/linux/rhashtable.h:330:39: error: too few arguments to function call, expected 3, have 2
           bit_spin_lock(0, (unsigned long *)bkt);
           ~~~~~~~~~~~~~                        ^
   include/linux/bit_spinlock.h:17:20: note: 'bit_spin_lock' declared here
   static inline void bit_spin_lock(int bitnum, unsigned long *addr,
                      ^
   In file included from drivers/infiniband/hw/hfi1/pcie.c:55:
   In file included from drivers/infiniband/hw/hfi1/hfi.h:71:
   include/linux/rhashtable.h:339:42: error: too few arguments to function call, expected 3, have 2
           bit_spin_lock(0, (unsigned long *)bucket);
           ~~~~~~~~~~~~~                           ^
   include/linux/bit_spinlock.h:17:20: note: 'bit_spin_lock' declared here
   static inline void bit_spin_lock(int bitnum, unsigned long *addr,
                      ^
   In file included from drivers/infiniband/hw/hfi1/pcie.c:55:
   In file included from drivers/infiniband/hw/hfi1/hfi.h:71:
   include/linux/rhashtable.h:347:41: error: too few arguments to function call, expected 3, have 2
           bit_spin_unlock(0, (unsigned long *)bkt);
           ~~~~~~~~~~~~~~~                        ^
   include/linux/bit_spinlock.h:50:20: note: 'bit_spin_unlock' declared here
   static inline void bit_spin_unlock(int bitnum, unsigned long *addr,
                      ^
>> drivers/infiniband/hw/hfi1/pcie.c:95:31: warning: shift count >= width of type [-Wshift-count-overflow]
           ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
                                        ^~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^ ~~~
   drivers/infiniband/hw/hfi1/pcie.c:109:43: warning: shift count >= width of type [-Wshift-count-overflow]
                   ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
                                                           ^~~~~~~~~~~~~~~~
   include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
   #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
                                                        ^ ~~~
   2 warnings and 3 errors generated.


vim +95 drivers/infiniband/hw/hfi1/pcie.c

7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   58  
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   59  /*
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   60   * This file contains PCIe utility routines.
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   61   */
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   62  
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   63  /*
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   64   * Do all the common PCIe setup and initialization.
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   65   */
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15   66  int hfi1_pcie_init(struct hfi1_devdata *dd)
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   67  {
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   68  	int ret;
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15   69  	struct pci_dev *pdev = dd->pcidev;
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   70  
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   71  	ret = pci_enable_device(pdev);
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   72  	if (ret) {
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   73  		/*
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   74  		 * This can happen (in theory) iff:
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   75  		 * We did a chip reset, and then failed to reprogram the
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   76  		 * BAR, or the chip reset due to an internal error.  We then
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   77  		 * unloaded the driver and reloaded it.
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   78  		 *
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   79  		 * Both reset cases set the BAR back to initial state.  For
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   80  		 * the latter case, the AER sticky error bit at offset 0x718
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   81  		 * should be set, but the Linux kernel doesn't yet know
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   82  		 * about that, it appears.  If the original BAR was retained
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   83  		 * in the kernel data structures, this may be OK.
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   84  		 */
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15   85  		dd_dev_err(dd, "pci enable failed: error %d\n", -ret);
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15   86  		return ret;
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   87  	}
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   88  
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   89  	ret = pci_request_regions(pdev, DRIVER_NAME);
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   90  	if (ret) {
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15   91  		dd_dev_err(dd, "pci_request_regions fails: err %d\n", -ret);
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   92  		goto bail;
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   93  	}
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   94  
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  @95  	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   96  	if (ret) {
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   97  		/*
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   98  		 * If the 64 bit setup fails, try 32 bit.  Some systems
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30   99  		 * do not setup 64 bit maps on systems with 2GB or less
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  100  		 * memory installed.
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  101  		 */
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  102  		ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  103  		if (ret) {
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15  104  			dd_dev_err(dd, "Unable to set DMA mask: %d\n", ret);
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  105  			goto bail;
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  106  		}
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  107  		ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
e490974e675e8d drivers/staging/rdma/hfi1/pcie.c  Jubin John       2016-02-14  108  	} else {
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  109  		ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
e490974e675e8d drivers/staging/rdma/hfi1/pcie.c  Jubin John       2016-02-14  110  	}
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  111  	if (ret) {
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15  112  		dd_dev_err(dd, "Unable to set DMA consistent mask: %d\n", ret);
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  113  		goto bail;
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  114  	}
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  115  
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  116  	pci_set_master(pdev);
0096765be01926 drivers/staging/rdma/hfi1/pcie.c  Dean Luick       2016-02-03  117  	(void)pci_enable_pcie_error_reporting(pdev);
57f97e96625fe8 drivers/infiniband/hw/hfi1/pcie.c Michael J. Ruhl  2018-08-15  118  	return 0;
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  119  
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  120  bail:
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  121  	hfi1_pcie_cleanup(pdev);
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  122  	return ret;
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  123  }
7724105686e718 drivers/staging/rdma/hfi1/pcie.c  Mike Marciniszyn 2015-07-30  124  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 30821 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH] Add split_lock
  2021-04-08 10:18 ` Peter Zijlstra
@ 2021-04-09 13:42   ` Thomas Gleixner
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Gleixner @ 2021-04-09 13:42 UTC (permalink / raw)
  To: Peter Zijlstra, Matthew Wilcox (Oracle)
  Cc: Ingo Molnar, Will Deacon, Waiman Long, Boqun Feng, linux-kernel,
	Sebastian Andrzej Siewior

On Thu, Apr 08 2021 at 12:18, Peter Zijlstra wrote:
> On Thu, Apr 08, 2021 at 06:23:38AM +0100, Matthew Wilcox (Oracle) wrote:
>> bit_spinlocks are horrible on RT because there's absolutely nowhere
>> to put the mutex to sleep on.  They also do not participate in lockdep
>> because there's nowhere to put the map.
>> 
>> Most (all?) bit spinlocks are actually a split lock; logically they
>> could be treated as a single spinlock, but for performance, we want to
>> split the lock over many objects.  Introduce the split_lock as somewhere
>> to store the lockdep map and as somewhere that the RT kernel can put
>> a mutex.  It may also let us store a ticket lock for better performance
>> on non-RT kernels in the future, but I have left the current cpu_relax()
>> implementation intact for now.
>
> I think I like it, but I'm not sure it'll work for RT as is. It's a bit
> like qrwlock in that it only uses the internal (split) lock for
> contention, but that doesn't work for PI.
>
> I've not recently looked at RT, but I think they simply used to bloat a
> number of the data structures with a real lock. Sebastian and Thomas
> will know better.

Correct, but it depends on the nature of the bit spinlock and the lock
held times. Some of them we just keep as is as it's not worth the
trouble.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-04-09 13:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-08  5:23 [RFC PATCH] Add split_lock Matthew Wilcox (Oracle)
2021-04-08  7:00 ` kernel test robot
2021-04-08 10:18 ` Peter Zijlstra
2021-04-09 13:42   ` Thomas Gleixner
2021-04-08 10:50 ` kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.