aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid1.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-06-28 00:44:04 -0400
committerDan Williams <dan.j.williams@intel.com>2008-06-30 20:18:19 -0400
commitb5470dc5fc18a8ff6517c3bb538d1479e58ecb02 (patch)
tree37b0eb3a4691bdbe58dc5c6c73b2dc8d3925b332 /drivers/md/raid1.c
parent1fe797e67fb07d605b82300934d0de67068a0aca (diff)
md: resolve external metadata handling deadlock in md_allow_write
md_allow_write() marks the metadata dirty while holding mddev->lock and then waits for the write to complete. For externally managed metadata this causes a deadlock as userspace needs to take the lock to communicate that the metadata update has completed. Change md_allow_write() in the 'external' case to start the 'mark active' operation and then return -EAGAIN. The expected side effects while waiting for userspace to write 'active' to 'array_state' are holding off reshape (code currently handles -ENOMEM), cause some 'stripe_cache_size' change requests to fail, cause some GET_BITMAP_FILE ioctl requests to fall back to GFP_NOIO, and cause updates to 'raid_disks' to fail. Except for 'stripe_cache_size' changes these failures can be mitigated by coordinating with mdmon. md_write_start() still prevents writes from occurring until the metadata handler has had a chance to take action as it unconditionally waits for MD_CHANGE_CLEAN to be cleared. [neilb@suse.de: return -EAGAIN, try GFP_NOIO] Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r--drivers/md/raid1.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f05d5983efb6..491dc2d4ad5f 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2136,7 +2136,7 @@ static int raid1_reshape(mddev_t *mddev)
2136 conf_t *conf = mddev_to_conf(mddev); 2136 conf_t *conf = mddev_to_conf(mddev);
2137 int cnt, raid_disks; 2137 int cnt, raid_disks;
2138 unsigned long flags; 2138 unsigned long flags;
2139 int d, d2; 2139 int d, d2, err;
2140 2140
2141 /* Cannot change chunk_size, layout, or level */ 2141 /* Cannot change chunk_size, layout, or level */
2142 if (mddev->chunk_size != mddev->new_chunk || 2142 if (mddev->chunk_size != mddev->new_chunk ||
@@ -2148,7 +2148,9 @@ static int raid1_reshape(mddev_t *mddev)
2148 return -EINVAL; 2148 return -EINVAL;
2149 } 2149 }
2150 2150
2151 md_allow_write(mddev); 2151 err = md_allow_write(mddev);
2152 if (err)
2153 return err;
2152 2154
2153 raid_disks = mddev->raid_disks + mddev->delta_disks; 2155 raid_disks = mddev->raid_disks + mddev->delta_disks;
2154 2156