summaryrefslogtreecommitdiff
path: root/fs/bcachefs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-05-21 04:44:30 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:10:02 +0300
commitc4bd3491b1c0b335f63599ec96d1d4ab0d37a3c1 (patch)
tree4be0daffa01be52e7629c131bb43cbec38c943a3 /fs/bcachefs
parentd2c86b77de5894bbe26ecbf5214227f61855aed7 (diff)
downloadlinux-c4bd3491b1c0b335f63599ec96d1d4ab0d37a3c1.tar.xz
six locks: Simplify dispatch
Originally, we used inlining/flattening to cause the compiler to generate different versions of lock/trylock/relock/unlock for each lock type - read, intent, and write. This made the individual functions smaller and let the compiler eliminate table lookups: however, as the code has gotten more complicated these optimizations have gotten less worthwhile, and all the tricky inlining and dispatching made the code less readable. Text size: 11015 bytes -> 7467 bytes, and benchmarks show no loss of performance. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r--fs/bcachefs/six.c86
-rw-r--r--fs/bcachefs/six.h148
2 files changed, 106 insertions, 128 deletions
diff --git a/fs/bcachefs/six.c b/fs/bcachefs/six.c
index d8f1d20f5ece..1a64b8a027a7 100644
--- a/fs/bcachefs/six.c
+++ b/fs/bcachefs/six.c
@@ -245,9 +245,10 @@ unlock:
}
}
-static inline void six_lock_wakeup(struct six_lock *lock,
- union six_lock_state state,
- enum six_lock_type lock_type)
+__always_inline
+static void six_lock_wakeup(struct six_lock *lock,
+ union six_lock_state state,
+ enum six_lock_type lock_type)
{
if (lock_type == SIX_LOCK_write && state.read_lock)
return;
@@ -258,6 +259,7 @@ static inline void six_lock_wakeup(struct six_lock *lock,
__six_lock_wakeup(lock, lock_type);
}
+__always_inline
static bool do_six_trylock_type(struct six_lock *lock,
enum six_lock_type type,
bool try)
@@ -271,9 +273,8 @@ static bool do_six_trylock_type(struct six_lock *lock,
return ret > 0;
}
-__always_inline __flatten
-static bool __six_trylock_type(struct six_lock *lock, enum six_lock_type type,
- unsigned long ip)
+bool six_trylock_ip_type(struct six_lock *lock, enum six_lock_type type,
+ unsigned long ip)
{
if (!do_six_trylock_type(lock, type, true))
return false;
@@ -283,9 +284,8 @@ static bool __six_trylock_type(struct six_lock *lock, enum six_lock_type type,
return true;
}
-__always_inline __flatten
-static bool __six_relock_type(struct six_lock *lock, enum six_lock_type type,
- unsigned seq, unsigned long ip)
+bool six_relock_ip_type(struct six_lock *lock, enum six_lock_type type,
+ unsigned seq, unsigned long ip)
{
const struct six_lock_vals l[] = LOCK_VALS;
union six_lock_state old;
@@ -335,6 +335,7 @@ static bool __six_relock_type(struct six_lock *lock, enum six_lock_type type,
six_acquire(&lock->dep_map, 1, type == SIX_LOCK_read, ip);
return true;
}
+EXPORT_SYMBOL_GPL(six_relock_ip_type);
#ifdef CONFIG_SIX_LOCK_SPIN_ON_OWNER
@@ -566,11 +567,10 @@ out:
return ret;
}
-__always_inline __flatten
-static int __six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type,
- struct six_lock_waiter *wait,
- six_lock_should_sleep_fn should_sleep_fn, void *p,
- unsigned long ip)
+int six_lock_type_ip_waiter(struct six_lock *lock, enum six_lock_type type,
+ struct six_lock_waiter *wait,
+ six_lock_should_sleep_fn should_sleep_fn, void *p,
+ unsigned long ip)
{
int ret;
@@ -589,18 +589,9 @@ static int __six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type
return ret;
}
+EXPORT_SYMBOL_GPL(six_lock_type_ip_waiter);
__always_inline
-static int __six_lock_type(struct six_lock *lock, enum six_lock_type type,
- six_lock_should_sleep_fn should_sleep_fn, void *p,
- unsigned long ip)
-{
- struct six_lock_waiter wait;
-
- return __six_lock_type_waiter(lock, type, &wait, should_sleep_fn, p, ip);
-}
-
-__always_inline __flatten
static void do_six_unlock_type(struct six_lock *lock, enum six_lock_type type)
{
const struct six_lock_vals l[] = LOCK_VALS;
@@ -628,9 +619,7 @@ static void do_six_unlock_type(struct six_lock *lock, enum six_lock_type type)
six_lock_wakeup(lock, state, l[type].unlock_wakeup);
}
-__always_inline __flatten
-static void __six_unlock_type(struct six_lock *lock, enum six_lock_type type,
- unsigned long ip)
+void six_unlock_ip_type(struct six_lock *lock, enum six_lock_type type, unsigned long ip)
{
EBUG_ON(type == SIX_LOCK_write &&
!(lock->state.v & __SIX_LOCK_HELD_intent));
@@ -649,48 +638,7 @@ static void __six_unlock_type(struct six_lock *lock, enum six_lock_type type,
do_six_unlock_type(lock, type);
}
-
-#define __SIX_LOCK(type) \
-bool six_trylock_ip_##type(struct six_lock *lock, unsigned long ip) \
-{ \
- return __six_trylock_type(lock, SIX_LOCK_##type, ip); \
-} \
-EXPORT_SYMBOL_GPL(six_trylock_ip_##type); \
- \
-bool six_relock_ip_##type(struct six_lock *lock, u32 seq, unsigned long ip)\
-{ \
- return __six_relock_type(lock, SIX_LOCK_##type, seq, ip); \
-} \
-EXPORT_SYMBOL_GPL(six_relock_ip_##type); \
- \
-int six_lock_ip_##type(struct six_lock *lock, \
- six_lock_should_sleep_fn should_sleep_fn, void *p, \
- unsigned long ip) \
-{ \
- return __six_lock_type(lock, SIX_LOCK_##type, should_sleep_fn, p, ip);\
-} \
-EXPORT_SYMBOL_GPL(six_lock_ip_##type); \
- \
-int six_lock_ip_waiter_##type(struct six_lock *lock, \
- struct six_lock_waiter *wait, \
- six_lock_should_sleep_fn should_sleep_fn, void *p,\
- unsigned long ip) \
-{ \
- return __six_lock_type_waiter(lock, SIX_LOCK_##type, wait, should_sleep_fn, p, ip);\
-} \
-EXPORT_SYMBOL_GPL(six_lock_ip_waiter_##type); \
- \
-void six_unlock_ip_##type(struct six_lock *lock, unsigned long ip) \
-{ \
- __six_unlock_type(lock, SIX_LOCK_##type, ip); \
-} \
-EXPORT_SYMBOL_GPL(six_unlock_ip_##type);
-
-__SIX_LOCK(read)
-__SIX_LOCK(intent)
-__SIX_LOCK(write)
-
-#undef __SIX_LOCK
+EXPORT_SYMBOL_GPL(six_unlock_ip_type);
/* Convert from intent to read: */
void six_lock_downgrade(struct six_lock *lock)
diff --git a/fs/bcachefs/six.h b/fs/bcachefs/six.h
index 2c8424bd7d2f..5ddabbfb8aba 100644
--- a/fs/bcachefs/six.h
+++ b/fs/bcachefs/six.h
@@ -148,37 +148,116 @@ do { \
__six_lock_init((lock), #lock, &__key, flags); \
} while (0)
+bool six_trylock_ip_type(struct six_lock *lock, enum six_lock_type type,
+ unsigned long ip);
+
+static inline bool six_trylock_type(struct six_lock *lock, enum six_lock_type type)
+{
+ return six_trylock_ip_type(lock, type, _THIS_IP_);
+}
+
+int six_lock_type_ip_waiter(struct six_lock *lock, enum six_lock_type type,
+ struct six_lock_waiter *wait,
+ six_lock_should_sleep_fn should_sleep_fn, void *p,
+ unsigned long ip);
+
+static inline int six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type,
+ struct six_lock_waiter *wait,
+ six_lock_should_sleep_fn should_sleep_fn, void *p)
+{
+ return six_lock_type_ip_waiter(lock, type, wait, should_sleep_fn, p, _THIS_IP_);
+}
+
+static inline int six_lock_ip_type(struct six_lock *lock, enum six_lock_type type,
+ six_lock_should_sleep_fn should_sleep_fn, void *p,
+ unsigned long ip)
+{
+ struct six_lock_waiter wait;
+
+ return six_lock_type_ip_waiter(lock, type, &wait, should_sleep_fn, p, ip);
+}
+
+static inline int six_lock_type(struct six_lock *lock, enum six_lock_type type,
+ six_lock_should_sleep_fn should_sleep_fn, void *p)
+{
+ struct six_lock_waiter wait;
+
+ return six_lock_type_ip_waiter(lock, type, &wait, should_sleep_fn, p, _THIS_IP_);
+}
+
+bool six_relock_ip_type(struct six_lock *lock, enum six_lock_type type,
+ unsigned seq, unsigned long ip);
+
+static inline bool six_relock_type(struct six_lock *lock, enum six_lock_type type,
+ unsigned seq)
+{
+ return six_relock_ip_type(lock, type, seq, _THIS_IP_);
+}
+
+void six_unlock_ip_type(struct six_lock *lock, enum six_lock_type type, unsigned long ip);
+
+static inline void six_unlock_type(struct six_lock *lock, enum six_lock_type type)
+{
+ six_unlock_ip_type(lock, type, _THIS_IP_);
+}
+
#define __SIX_LOCK(type) \
-bool six_trylock_ip_##type(struct six_lock *, unsigned long); \
-bool six_relock_ip_##type(struct six_lock *, u32, unsigned long); \
-int six_lock_ip_##type(struct six_lock *, six_lock_should_sleep_fn, \
- void *, unsigned long); \
-int six_lock_ip_waiter_##type(struct six_lock *, struct six_lock_waiter *,\
- six_lock_should_sleep_fn, void *, unsigned long);\
-void six_unlock_ip_##type(struct six_lock *, unsigned long); \
+static inline bool six_trylock_ip_##type(struct six_lock *lock, unsigned long ip)\
+{ \
+ return six_trylock_ip_type(lock, SIX_LOCK_##type, ip); \
+} \
\
static inline bool six_trylock_##type(struct six_lock *lock) \
{ \
- return six_trylock_ip_##type(lock, _THIS_IP_); \
+ return six_trylock_ip_type(lock, SIX_LOCK_##type, _THIS_IP_); \
+} \
+ \
+static inline int six_lock_ip_waiter_##type(struct six_lock *lock, \
+ struct six_lock_waiter *wait, \
+ six_lock_should_sleep_fn should_sleep_fn, void *p,\
+ unsigned long ip) \
+{ \
+ return six_lock_type_ip_waiter(lock, SIX_LOCK_##type, wait, should_sleep_fn, p, ip);\
+} \
+ \
+static inline int six_lock_ip_##type(struct six_lock *lock, \
+ six_lock_should_sleep_fn should_sleep_fn, void *p, \
+ unsigned long ip) \
+{ \
+ return six_lock_ip_type(lock, SIX_LOCK_##type, should_sleep_fn, p, ip);\
+} \
+ \
+static inline bool six_relock_ip_##type(struct six_lock *lock, u32 seq, unsigned long ip)\
+{ \
+ return six_relock_ip_type(lock, SIX_LOCK_##type, seq, ip); \
} \
+ \
static inline bool six_relock_##type(struct six_lock *lock, u32 seq) \
{ \
- return six_relock_ip_##type(lock, seq, _THIS_IP_); \
+ return six_relock_ip_type(lock, SIX_LOCK_##type, seq, _THIS_IP_);\
} \
+ \
static inline int six_lock_##type(struct six_lock *lock, \
six_lock_should_sleep_fn fn, void *p)\
{ \
return six_lock_ip_##type(lock, fn, p, _THIS_IP_); \
} \
+ \
static inline int six_lock_waiter_##type(struct six_lock *lock, \
struct six_lock_waiter *wait, \
six_lock_should_sleep_fn fn, void *p) \
{ \
return six_lock_ip_waiter_##type(lock, wait, fn, p, _THIS_IP_); \
} \
+ \
+static inline void six_unlock_ip_##type(struct six_lock *lock, unsigned long ip) \
+{ \
+ six_unlock_ip_type(lock, SIX_LOCK_##type, ip); \
+} \
+ \
static inline void six_unlock_##type(struct six_lock *lock) \
{ \
- return six_unlock_ip_##type(lock, _THIS_IP_); \
+ six_unlock_ip_type(lock, SIX_LOCK_##type, _THIS_IP_); \
}
__SIX_LOCK(read)
@@ -186,55 +265,6 @@ __SIX_LOCK(intent)
__SIX_LOCK(write)
#undef __SIX_LOCK
-#define SIX_LOCK_DISPATCH(type, fn, ...) \
- switch (type) { \
- case SIX_LOCK_read: \
- return fn##_read(__VA_ARGS__); \
- case SIX_LOCK_intent: \
- return fn##_intent(__VA_ARGS__); \
- case SIX_LOCK_write: \
- return fn##_write(__VA_ARGS__); \
- default: \
- BUG(); \
- }
-
-static inline bool six_trylock_type(struct six_lock *lock, enum six_lock_type type)
-{
- SIX_LOCK_DISPATCH(type, six_trylock, lock);
-}
-
-static inline bool six_relock_type(struct six_lock *lock, enum six_lock_type type,
- unsigned seq)
-{
- SIX_LOCK_DISPATCH(type, six_relock, lock, seq);
-}
-
-static inline int six_lock_type(struct six_lock *lock, enum six_lock_type type,
- six_lock_should_sleep_fn should_sleep_fn, void *p)
-{
- SIX_LOCK_DISPATCH(type, six_lock, lock, should_sleep_fn, p);
-}
-
-static inline int six_lock_type_ip_waiter(struct six_lock *lock, enum six_lock_type type,
- struct six_lock_waiter *wait,
- six_lock_should_sleep_fn should_sleep_fn, void *p,
- unsigned long ip)
-{
- SIX_LOCK_DISPATCH(type, six_lock_ip_waiter, lock, wait, should_sleep_fn, p, ip);
-}
-
-static inline int six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type,
- struct six_lock_waiter *wait,
- six_lock_should_sleep_fn should_sleep_fn, void *p)
-{
- SIX_LOCK_DISPATCH(type, six_lock_waiter, lock, wait, should_sleep_fn, p);
-}
-
-static inline void six_unlock_type(struct six_lock *lock, enum six_lock_type type)
-{
- SIX_LOCK_DISPATCH(type, six_unlock, lock);
-}
-
void six_lock_downgrade(struct six_lock *);
bool six_lock_tryupgrade(struct six_lock *);
bool six_trylock_convert(struct six_lock *, enum six_lock_type,