diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-05-21 04:44:30 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:10:02 +0300 |
commit | c4bd3491b1c0b335f63599ec96d1d4ab0d37a3c1 (patch) | |
tree | 4be0daffa01be52e7629c131bb43cbec38c943a3 /fs/bcachefs | |
parent | d2c86b77de5894bbe26ecbf5214227f61855aed7 (diff) | |
download | linux-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.c | 86 | ||||
-rw-r--r-- | fs/bcachefs/six.h | 148 |
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, |