Commit 129827e3 authored by David Sterba's avatar David Sterba

btrfs: dev-replace: swich locking to rw semaphore

This is the first part of removing the custom locking and waiting scheme
used for device replace. It was probably copied from extent buffer
locking, but there's nothing that would require more than is provided by
the common locking primitives.

The rw spinlock protects waiting tasks counter in case of incompatible
locks and the waitqueue. Same as rw semaphore.

This patch only switches the locking primitive, for better
bisectability.  There should be no functional change other than the
overhead of the locking and potential sleeping instead of spinning when
the lock is contended.
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent ceb21a8d
...@@ -378,7 +378,7 @@ struct btrfs_dev_replace { ...@@ -378,7 +378,7 @@ struct btrfs_dev_replace {
struct btrfs_device *tgtdev; struct btrfs_device *tgtdev;
struct mutex lock_finishing_cancel_unmount; struct mutex lock_finishing_cancel_unmount;
rwlock_t lock; struct rw_semaphore rwsem;
atomic_t blocking_readers; atomic_t blocking_readers;
wait_queue_head_t read_lock_wq; wait_queue_head_t read_lock_wq;
......
...@@ -1002,12 +1002,12 @@ int btrfs_dev_replace_is_ongoing(struct btrfs_dev_replace *dev_replace) ...@@ -1002,12 +1002,12 @@ int btrfs_dev_replace_is_ongoing(struct btrfs_dev_replace *dev_replace)
void btrfs_dev_replace_read_lock(struct btrfs_dev_replace *dev_replace) void btrfs_dev_replace_read_lock(struct btrfs_dev_replace *dev_replace)
{ {
read_lock(&dev_replace->lock); down_read(&dev_replace->rwsem);
} }
void btrfs_dev_replace_read_unlock(struct btrfs_dev_replace *dev_replace) void btrfs_dev_replace_read_unlock(struct btrfs_dev_replace *dev_replace)
{ {
read_unlock(&dev_replace->lock); up_read(&dev_replace->rwsem);
} }
void btrfs_dev_replace_write_lock(struct btrfs_dev_replace *dev_replace) void btrfs_dev_replace_write_lock(struct btrfs_dev_replace *dev_replace)
...@@ -1015,16 +1015,16 @@ void btrfs_dev_replace_write_lock(struct btrfs_dev_replace *dev_replace) ...@@ -1015,16 +1015,16 @@ void btrfs_dev_replace_write_lock(struct btrfs_dev_replace *dev_replace)
again: again:
wait_event(dev_replace->read_lock_wq, wait_event(dev_replace->read_lock_wq,
atomic_read(&dev_replace->blocking_readers) == 0); atomic_read(&dev_replace->blocking_readers) == 0);
write_lock(&dev_replace->lock); down_write(&dev_replace->rwsem);
if (atomic_read(&dev_replace->blocking_readers)) { if (atomic_read(&dev_replace->blocking_readers)) {
write_unlock(&dev_replace->lock); up_write(&dev_replace->rwsem);
goto again; goto again;
} }
} }
void btrfs_dev_replace_write_unlock(struct btrfs_dev_replace *dev_replace) void btrfs_dev_replace_write_unlock(struct btrfs_dev_replace *dev_replace)
{ {
write_unlock(&dev_replace->lock); up_write(&dev_replace->rwsem);
} }
/* inc blocking cnt and release read lock */ /* inc blocking cnt and release read lock */
...@@ -1033,7 +1033,7 @@ void btrfs_dev_replace_set_lock_blocking( ...@@ -1033,7 +1033,7 @@ void btrfs_dev_replace_set_lock_blocking(
{ {
/* only set blocking for read lock */ /* only set blocking for read lock */
atomic_inc(&dev_replace->blocking_readers); atomic_inc(&dev_replace->blocking_readers);
read_unlock(&dev_replace->lock); up_read(&dev_replace->rwsem);
} }
void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info) void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)
......
...@@ -2141,7 +2141,7 @@ static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info) ...@@ -2141,7 +2141,7 @@ static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info)
static void btrfs_init_dev_replace_locks(struct btrfs_fs_info *fs_info) static void btrfs_init_dev_replace_locks(struct btrfs_fs_info *fs_info)
{ {
mutex_init(&fs_info->dev_replace.lock_finishing_cancel_unmount); mutex_init(&fs_info->dev_replace.lock_finishing_cancel_unmount);
rwlock_init(&fs_info->dev_replace.lock); init_rwsem(&fs_info->dev_replace.rwsem);
atomic_set(&fs_info->dev_replace.blocking_readers, 0); atomic_set(&fs_info->dev_replace.blocking_readers, 0);
init_waitqueue_head(&fs_info->dev_replace.replace_wait); init_waitqueue_head(&fs_info->dev_replace.replace_wait);
init_waitqueue_head(&fs_info->dev_replace.read_lock_wq); init_waitqueue_head(&fs_info->dev_replace.read_lock_wq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment