diff options
author | Sebastian Riemer <sebastian.riemer@profitbricks.com> | 2013-02-20 21:28:09 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-02-20 21:28:09 -0500 |
commit | bbfa57c0f2243a7c31fd248d22e9861a2802cad5 (patch) | |
tree | a762bd442fe3799f3987881eb60526b4d9ea4952 /drivers/md/md.c | |
parent | 19f949f52599ba7c3f67a5897ac6be14bfcb1200 (diff) |
md: protect against crash upon fsync on ro array
If an fsync occurs on a read-only array, we need to send a
completion for the IO and may not increment the active IO count.
Otherwise, we hit a bug trace and can't stop the MD array anymore.
By advice of Christoph Hellwig we return success upon a flush
request but we return -EROFS for other writes.
We detect flush requests by checking if the bio has zero sectors.
This patch is suitable to any -stable kernel to which it applies.
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Ben Hutchings <ben@decadent.org.uk>
Cc: NeilBrown <neilb@suse.de>
Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Riemer <sebastian.riemer@profitbricks.com>
Reported-by: Ben Hutchings <ben@decadent.org.uk>
Acked-by: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 3db3d1b271f7..1e634a68541e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -307,6 +307,10 @@ static void md_make_request(struct request_queue *q, struct bio *bio) | |||
307 | bio_io_error(bio); | 307 | bio_io_error(bio); |
308 | return; | 308 | return; |
309 | } | 309 | } |
310 | if (mddev->ro == 1 && unlikely(rw == WRITE)) { | ||
311 | bio_endio(bio, bio_sectors(bio) == 0 ? 0 : -EROFS); | ||
312 | return; | ||
313 | } | ||
310 | smp_rmb(); /* Ensure implications of 'active' are visible */ | 314 | smp_rmb(); /* Ensure implications of 'active' are visible */ |
311 | rcu_read_lock(); | 315 | rcu_read_lock(); |
312 | if (mddev->suspended) { | 316 | if (mddev->suspended) { |