1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHEFS_NOCOW_LOCKING_H
3 #define _BCACHEFS_NOCOW_LOCKING_H
5 #include "bcachefs_format.h"
6 #include "two_state_shared_lock.h"
8 #include <linux/hash.h>
10 #define BUCKET_NOCOW_LOCKS_BITS 10
11 #define BUCKET_NOCOW_LOCKS (1U << BUCKET_NOCOW_LOCKS_BITS)
13 struct bucket_nocow_lock_table {
14 two_state_lock_t l[BUCKET_NOCOW_LOCKS];
17 #define BUCKET_NOCOW_LOCK_UPDATE (1 << 0)
19 static inline two_state_lock_t *bucket_nocow_lock(struct bucket_nocow_lock_table *t,
22 u64 dev_bucket = bucket.inode << 56 | bucket.offset;
23 unsigned h = hash_64(dev_bucket, BUCKET_NOCOW_LOCKS_BITS);
25 return t->l + (h & (BUCKET_NOCOW_LOCKS - 1));
28 static inline bool bch2_bucket_nocow_is_locked(struct bucket_nocow_lock_table *t,
31 two_state_lock_t *l = bucket_nocow_lock(t, bucket);
33 return atomic_long_read(&l->v) != 0;
36 static inline void bch2_bucket_nocow_unlock(struct bucket_nocow_lock_table *t,
37 struct bpos bucket, int flags)
39 two_state_lock_t *l = bucket_nocow_lock(t, bucket);
41 bch2_two_state_unlock(l, flags & BUCKET_NOCOW_LOCK_UPDATE);
44 void __bch2_bucket_nocow_lock(struct bucket_nocow_lock_table *, two_state_lock_t *, int);
46 static inline void bch2_bucket_nocow_lock(struct bucket_nocow_lock_table *t,
47 struct bpos bucket, int flags)
49 two_state_lock_t *l = bucket_nocow_lock(t, bucket);
51 if (!bch2_two_state_trylock(l, flags & BUCKET_NOCOW_LOCK_UPDATE))
52 __bch2_bucket_nocow_lock(t, l, flags);
55 #endif /* _BCACHEFS_NOCOW_LOCKING_H */