Lines Matching +full:lock +full:- +full:- +full:- +full:-
1 // SPDX-License-Identifier: GPL-2.0-only
7 #include "dm-block-manager.h"
8 #include "dm-persistent-data-internal.h"
10 #include <linux/dm-bufio.h>
15 #include <linux/device-mapper.h>
21 /*----------------------------------------------------------------*/
32 * trace is also emitted for the previous lock acquisition.
45 spinlock_t lock; member
61 static unsigned int __find_holder(struct block_lock *lock, in __find_holder() argument
67 if (lock->holders[i] == task) in __find_holder()
74 /* call this *after* you increment lock->count */
75 static void __add_holder(struct block_lock *lock, struct task_struct *task) in __add_holder() argument
77 unsigned int h = __find_holder(lock, NULL); in __add_holder()
83 lock->holders[h] = task; in __add_holder()
86 t = lock->traces + h; in __add_holder()
87 t->nr_entries = stack_trace_save(t->entries, MAX_STACK, 2); in __add_holder()
91 /* call this *before* you decrement lock->count */
92 static void __del_holder(struct block_lock *lock, struct task_struct *task) in __del_holder() argument
94 unsigned int h = __find_holder(lock, task); in __del_holder()
96 lock->holders[h] = NULL; in __del_holder()
100 static int __check_holder(struct block_lock *lock) in __check_holder() argument
105 if (lock->holders[i] == current) { in __check_holder()
106 DMERR("recursive lock detected in metadata"); in __check_holder()
109 stack_trace_print(lock->traces[i].entries, in __check_holder()
110 lock->traces[i].nr_entries, 4); in __check_holder()
115 return -EINVAL; in __check_holder()
127 if (!w->task) in __wait()
140 list_del(&w->list); in __wake_waiter()
141 task = w->task; in __wake_waiter()
143 w->task = NULL; in __wake_waiter()
150 static void __wake_many(struct block_lock *lock) in __wake_many() argument
154 BUG_ON(lock->count < 0); in __wake_many()
155 list_for_each_entry_safe(w, tmp, &lock->waiters, list) { in __wake_many()
156 if (lock->count >= MAX_HOLDERS) in __wake_many()
159 if (w->wants_write) { in __wake_many()
160 if (lock->count > 0) in __wake_many()
163 lock->count = -1; in __wake_many()
164 __add_holder(lock, w->task); in __wake_many()
169 lock->count++; in __wake_many()
170 __add_holder(lock, w->task); in __wake_many()
175 static void bl_init(struct block_lock *lock) in bl_init() argument
179 spin_lock_init(&lock->lock); in bl_init()
180 lock->count = 0; in bl_init()
181 INIT_LIST_HEAD(&lock->waiters); in bl_init()
183 lock->holders[i] = NULL; in bl_init()
186 static int __available_for_read(struct block_lock *lock) in __available_for_read() argument
188 return lock->count >= 0 && in __available_for_read()
189 lock->count < MAX_HOLDERS && in __available_for_read()
190 list_empty(&lock->waiters); in __available_for_read()
193 static int bl_down_read(struct block_lock *lock) in bl_down_read() argument
198 spin_lock(&lock->lock); in bl_down_read()
199 r = __check_holder(lock); in bl_down_read()
201 spin_unlock(&lock->lock); in bl_down_read()
205 if (__available_for_read(lock)) { in bl_down_read()
206 lock->count++; in bl_down_read()
207 __add_holder(lock, current); in bl_down_read()
208 spin_unlock(&lock->lock); in bl_down_read()
216 list_add_tail(&w.list, &lock->waiters); in bl_down_read()
217 spin_unlock(&lock->lock); in bl_down_read()
224 static int bl_down_read_nonblock(struct block_lock *lock) in bl_down_read_nonblock() argument
228 spin_lock(&lock->lock); in bl_down_read_nonblock()
229 r = __check_holder(lock); in bl_down_read_nonblock()
233 if (__available_for_read(lock)) { in bl_down_read_nonblock()
234 lock->count++; in bl_down_read_nonblock()
235 __add_holder(lock, current); in bl_down_read_nonblock()
238 r = -EWOULDBLOCK; in bl_down_read_nonblock()
241 spin_unlock(&lock->lock); in bl_down_read_nonblock()
245 static void bl_up_read(struct block_lock *lock) in bl_up_read() argument
247 spin_lock(&lock->lock); in bl_up_read()
248 BUG_ON(lock->count <= 0); in bl_up_read()
249 __del_holder(lock, current); in bl_up_read()
250 --lock->count; in bl_up_read()
251 if (!list_empty(&lock->waiters)) in bl_up_read()
252 __wake_many(lock); in bl_up_read()
253 spin_unlock(&lock->lock); in bl_up_read()
256 static int bl_down_write(struct block_lock *lock) in bl_down_write() argument
261 spin_lock(&lock->lock); in bl_down_write()
262 r = __check_holder(lock); in bl_down_write()
264 spin_unlock(&lock->lock); in bl_down_write()
268 if (lock->count == 0 && list_empty(&lock->waiters)) { in bl_down_write()
269 lock->count = -1; in bl_down_write()
270 __add_holder(lock, current); in bl_down_write()
271 spin_unlock(&lock->lock); in bl_down_write()
283 list_add(&w.list, &lock->waiters); in bl_down_write()
284 spin_unlock(&lock->lock); in bl_down_write()
292 static void bl_up_write(struct block_lock *lock) in bl_up_write() argument
294 spin_lock(&lock->lock); in bl_up_write()
295 __del_holder(lock, current); in bl_up_write()
296 lock->count = 0; in bl_up_write()
297 if (!list_empty(&lock->waiters)) in bl_up_write()
298 __wake_many(lock); in bl_up_write()
299 spin_unlock(&lock->lock); in bl_up_write()
304 if (r == -EINVAL) in report_recursive_bug()
321 /*----------------------------------------------------------------*/
324 * Block manager is currently implemented using dm-bufio. struct
352 struct block_lock lock; member
360 aux->validator = NULL; in dm_block_manager_alloc_callback()
361 bl_init(&aux->lock); in dm_block_manager_alloc_callback()
368 if (aux->validator) { in dm_block_manager_write_callback()
369 aux->validator->prepare_for_write(aux->validator, (struct dm_block *) buf, in dm_block_manager_write_callback()
375 * -------------------------------------------------------------
377 *--------------------------------------------------------------
393 r = -ENOMEM; in dm_block_manager_create()
397 bm->bufio = dm_bufio_client_create(bdev, block_size, max_held_per_thread, in dm_block_manager_create()
402 if (IS_ERR(bm->bufio)) { in dm_block_manager_create()
403 r = PTR_ERR(bm->bufio); in dm_block_manager_create()
408 bm->read_only = false; in dm_block_manager_create()
419 dm_bufio_client_destroy(bm->bufio); in dm_block_manager_destroy()
426 dm_bufio_client_reset(bm->bufio); in dm_block_manager_reset()
432 return dm_bufio_get_block_size(bm->bufio); in dm_bm_block_size()
438 return dm_bufio_get_device_size(bm->bufio); in dm_bm_nr_blocks()
446 if (unlikely(!aux->validator)) { in dm_bm_validate_buffer()
451 r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(bm->bufio)); in dm_bm_validate_buffer()
453 DMERR_LIMIT("%s validator check failed for block %llu", v->name, in dm_bm_validate_buffer()
457 aux->validator = v; in dm_bm_validate_buffer()
459 if (unlikely(aux->validator != v)) { in dm_bm_validate_buffer()
461 aux->validator->name, v ? v->name : "NULL", in dm_bm_validate_buffer()
463 return -EINVAL; in dm_bm_validate_buffer()
477 p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result); in dm_bm_read_lock()
482 r = bl_down_read(&aux->lock); in dm_bm_read_lock()
489 aux->write_locked = 0; in dm_bm_read_lock()
493 bl_up_read(&aux->lock); in dm_bm_read_lock()
511 return -EPERM; in dm_bm_write_lock()
513 p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result); in dm_bm_write_lock()
518 r = bl_down_write(&aux->lock); in dm_bm_write_lock()
525 aux->write_locked = 1; in dm_bm_write_lock()
529 bl_up_write(&aux->lock); in dm_bm_write_lock()
546 p = dm_bufio_get(bm->bufio, b, (struct dm_buffer **) result); in dm_bm_read_try_lock()
550 return -EWOULDBLOCK; in dm_bm_read_try_lock()
553 r = bl_down_read_nonblock(&aux->lock); in dm_bm_read_try_lock()
559 aux->write_locked = 0; in dm_bm_read_try_lock()
563 bl_up_read(&aux->lock); in dm_bm_read_try_lock()
580 return -EPERM; in dm_bm_write_lock_zero()
582 p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result); in dm_bm_write_lock_zero()
589 r = bl_down_write(&aux->lock); in dm_bm_write_lock_zero()
595 aux->write_locked = 1; in dm_bm_write_lock_zero()
596 aux->validator = v; in dm_bm_write_lock_zero()
606 if (aux->write_locked) { in dm_bm_unlock()
608 bl_up_write(&aux->lock); in dm_bm_unlock()
610 bl_up_read(&aux->lock); in dm_bm_unlock()
619 return -EPERM; in dm_bm_flush()
621 return dm_bufio_write_dirty_buffers(bm->bufio); in dm_bm_flush()
627 dm_bufio_prefetch(bm->bufio, b, 1); in dm_bm_prefetch()
632 return bm ? bm->read_only : true; in dm_bm_is_read_only()
639 bm->read_only = true; in dm_bm_set_read_only()
646 bm->read_only = false; in dm_bm_set_read_write()
656 /*----------------------------------------------------------------*/
659 MODULE_AUTHOR("Joe Thornber <dm-devel@lists.linux.dev>");
662 /*----------------------------------------------------------------*/