提交 2214c260 编写于 作者: A Artur Paszkiewicz 提交者: Shaohua Li

md: don't return -EAGAIN in md_allow_write for external metadata arrays

This essentially reverts commit b5470dc5 ("md: resolve external
metadata handling deadlock in md_allow_write") with some adjustments.

Since commit 6791875e ("md: make reconfig_mutex optional for writes
to md sysfs files.") changing array_state to 'active' does not use
mddev_lock() and will not cause a deadlock with md_allow_write(). This
revert simplifies userspace tools that write to sysfs attributes like
"stripe_cache_size" or "consistency_policy" because it removes the need
for special handling for external metadata arrays, checking for EAGAIN
and retrying the write.
Signed-off-by: NArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: NShaohua Li <shli@fb.com>
上级 3d05f3ae
...@@ -8022,18 +8022,15 @@ EXPORT_SYMBOL(md_write_end); ...@@ -8022,18 +8022,15 @@ EXPORT_SYMBOL(md_write_end);
* may proceed without blocking. It is important to call this before * may proceed without blocking. It is important to call this before
* attempting a GFP_KERNEL allocation while holding the mddev lock. * attempting a GFP_KERNEL allocation while holding the mddev lock.
* Must be called with mddev_lock held. * Must be called with mddev_lock held.
*
* In the ->external case MD_SB_CHANGE_PENDING can not be cleared until mddev->lock
* is dropped, so return -EAGAIN after notifying userspace.
*/ */
int md_allow_write(struct mddev *mddev) void md_allow_write(struct mddev *mddev)
{ {
if (!mddev->pers) if (!mddev->pers)
return 0; return;
if (mddev->ro) if (mddev->ro)
return 0; return;
if (!mddev->pers->sync_request) if (!mddev->pers->sync_request)
return 0; return;
spin_lock(&mddev->lock); spin_lock(&mddev->lock);
if (mddev->in_sync) { if (mddev->in_sync) {
...@@ -8046,13 +8043,12 @@ int md_allow_write(struct mddev *mddev) ...@@ -8046,13 +8043,12 @@ int md_allow_write(struct mddev *mddev)
spin_unlock(&mddev->lock); spin_unlock(&mddev->lock);
md_update_sb(mddev, 0); md_update_sb(mddev, 0);
sysfs_notify_dirent_safe(mddev->sysfs_state); sysfs_notify_dirent_safe(mddev->sysfs_state);
/* wait for the dirty state to be recorded in the metadata */
wait_event(mddev->sb_wait,
!test_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags) &&
!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
} else } else
spin_unlock(&mddev->lock); spin_unlock(&mddev->lock);
if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
return -EAGAIN;
else
return 0;
} }
EXPORT_SYMBOL_GPL(md_allow_write); EXPORT_SYMBOL_GPL(md_allow_write);
......
...@@ -665,7 +665,7 @@ extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, ...@@ -665,7 +665,7 @@ extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
bool metadata_op); bool metadata_op);
extern void md_do_sync(struct md_thread *thread); extern void md_do_sync(struct md_thread *thread);
extern void md_new_event(struct mddev *mddev); extern void md_new_event(struct mddev *mddev);
extern int md_allow_write(struct mddev *mddev); extern void md_allow_write(struct mddev *mddev);
extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev); extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors); extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
extern int md_check_no_bitmap(struct mddev *mddev); extern int md_check_no_bitmap(struct mddev *mddev);
......
...@@ -3197,7 +3197,7 @@ static int raid1_reshape(struct mddev *mddev) ...@@ -3197,7 +3197,7 @@ static int raid1_reshape(struct mddev *mddev)
struct r1conf *conf = mddev->private; struct r1conf *conf = mddev->private;
int cnt, raid_disks; int cnt, raid_disks;
unsigned long flags; unsigned long flags;
int d, d2, err; int d, d2;
/* Cannot change chunk_size, layout, or level */ /* Cannot change chunk_size, layout, or level */
if (mddev->chunk_sectors != mddev->new_chunk_sectors || if (mddev->chunk_sectors != mddev->new_chunk_sectors ||
...@@ -3209,11 +3209,8 @@ static int raid1_reshape(struct mddev *mddev) ...@@ -3209,11 +3209,8 @@ static int raid1_reshape(struct mddev *mddev)
return -EINVAL; return -EINVAL;
} }
if (!mddev_is_clustered(mddev)) { if (!mddev_is_clustered(mddev))
err = md_allow_write(mddev); md_allow_write(mddev);
if (err)
return err;
}
raid_disks = mddev->raid_disks + mddev->delta_disks; raid_disks = mddev->raid_disks + mddev->delta_disks;
......
...@@ -2309,14 +2309,12 @@ static int resize_stripes(struct r5conf *conf, int newsize) ...@@ -2309,14 +2309,12 @@ static int resize_stripes(struct r5conf *conf, int newsize)
struct stripe_head *osh, *nsh; struct stripe_head *osh, *nsh;
LIST_HEAD(newstripes); LIST_HEAD(newstripes);
struct disk_info *ndisks; struct disk_info *ndisks;
int err; int err = 0;
struct kmem_cache *sc; struct kmem_cache *sc;
int i; int i;
int hash, cnt; int hash, cnt;
err = md_allow_write(conf->mddev); md_allow_write(conf->mddev);
if (err)
return err;
/* Step 1 */ /* Step 1 */
sc = kmem_cache_create(conf->cache_name[1-conf->active_name], sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
...@@ -6310,7 +6308,6 @@ int ...@@ -6310,7 +6308,6 @@ int
raid5_set_cache_size(struct mddev *mddev, int size) raid5_set_cache_size(struct mddev *mddev, int size)
{ {
struct r5conf *conf = mddev->private; struct r5conf *conf = mddev->private;
int err;
if (size <= 16 || size > 32768) if (size <= 16 || size > 32768)
return -EINVAL; return -EINVAL;
...@@ -6322,10 +6319,7 @@ raid5_set_cache_size(struct mddev *mddev, int size) ...@@ -6322,10 +6319,7 @@ raid5_set_cache_size(struct mddev *mddev, int size)
; ;
mutex_unlock(&conf->cache_size_mutex); mutex_unlock(&conf->cache_size_mutex);
md_allow_write(mddev);
err = md_allow_write(mddev);
if (err)
return err;
mutex_lock(&conf->cache_size_mutex); mutex_lock(&conf->cache_size_mutex);
while (size > conf->max_nr_stripes) while (size > conf->max_nr_stripes)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册