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/six.c | |
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/six.c')
-rw-r--r-- | fs/bcachefs/six.c | 86 |
1 files changed, 17 insertions, 69 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) |