Commit 2214c260 authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by 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: default avatarArtur Paszkiewicz <>
Signed-off-by: default avatarShaohua Li <>
parent 3d05f3ae
......@@ -8022,18 +8022,15 @@ EXPORT_SYMBOL(md_write_end);
* may proceed without blocking. It is important to call this before
* attempting a GFP_KERNEL allocation while holding the mddev lock.
* 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)
return 0;
if (mddev->ro)
return 0;
if (!mddev->pers->sync_request)
return 0;
if (mddev->in_sync) {
......@@ -8046,13 +8043,12 @@ int md_allow_write(struct mddev *mddev)
md_update_sb(mddev, 0);
/* wait for the dirty state to be recorded in the metadata */
!test_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags) &&
!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
} else
if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
return -EAGAIN;
return 0;
......@@ -665,7 +665,7 @@ extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
bool metadata_op);
extern void md_do_sync(struct md_thread *thread);
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_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
extern int md_check_no_bitmap(struct mddev *mddev);
......@@ -3197,7 +3197,7 @@ static int raid1_reshape(struct mddev *mddev)
struct r1conf *conf = mddev->private;
int cnt, raid_disks;
unsigned long flags;
int d, d2, err;
int d, d2;
/* Cannot change chunk_size, layout, or level */
if (mddev->chunk_sectors != mddev->new_chunk_sectors ||
......@@ -3209,11 +3209,8 @@ static int raid1_reshape(struct mddev *mddev)
return -EINVAL;
if (!mddev_is_clustered(mddev)) {
err = md_allow_write(mddev);
if (err)
return err;
if (!mddev_is_clustered(mddev))
raid_disks = mddev->raid_disks + mddev->delta_disks;
......@@ -2309,14 +2309,12 @@ static int resize_stripes(struct r5conf *conf, int newsize)
struct stripe_head *osh, *nsh;
struct disk_info *ndisks;
int err;
int err = 0;
struct kmem_cache *sc;
int i;
int hash, cnt;
err = md_allow_write(conf->mddev);
if (err)
return err;
/* Step 1 */
sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
......@@ -6310,7 +6308,6 @@ int
raid5_set_cache_size(struct mddev *mddev, int size)
struct r5conf *conf = mddev->private;
int err;
if (size <= 16 || size > 32768)
return -EINVAL;
......@@ -6322,10 +6319,7 @@ raid5_set_cache_size(struct mddev *mddev, int size)
err = md_allow_write(mddev);
if (err)
return err;
while (size > conf->max_nr_stripes)
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment