On 29.01.2013 06:45, Ben Hutchings wrote:
> I'm slightly uneasy about returning 0 for all writes to a read-only
> deivce, because if someone ever fails to check the read-only flag
> elsewhere this could turn into silent data loss.  Does this work:
> 
>               BUG_ON(bio_segments(bio));
> 
> Or should it be:
> 
>               bio_endio(bio, bio_segments(bio) == 0 ? 0 : -EROFS);
> 
> to make the error survivable?

Good point. But it's better to use "bio_sectors" as bi_size is the
important information. I've seen that DRBD detects empty flushes the
same way.

For testing I've disabled the "set_disk_ro" in "md_set_readonly". Then,
I did direct IO writes on the read-only array and it worked - I've
received "Input/output error" in the user space.

I've attached version 4 of the patch.

Any further objection?
From adfac4df99edc1a83dced9c732464634d3381a9f Mon Sep 17 00:00:00 2001
From: Sebastian Riemer <sebastian.rie...@profitbricks.com>
Date: Fri, 25 Jan 2013 12:46:59 +0100
Subject: [PATCH v4] md: protect against crash upon fsync on ro array

If an fsync occurrs 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.

Cc: Christoph Hellwig <h...@infradead.org>
Cc: Ben Hutchings <b...@decadent.org.uk>
Cc: NeilBrown <ne...@suse.de>
Signed-off-by: Sebastian Riemer <sebastian.rie...@profitbricks.com>
Reported-by: Ben Hutchings <b...@decadent.org.uk>
---
 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 3db3d1b..1e634a6 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)
                bio_io_error(bio);
                return;
        }
+       if (mddev->ro == 1 && unlikely(rw == WRITE)) {
+               bio_endio(bio, bio_sectors(bio) == 0 ? 0 : -EROFS);
+               return;
+       }
        smp_rmb(); /* Ensure implications of  'active' are visible */
        rcu_read_lock();
        if (mddev->suspended) {
-- 
1.7.1

Reply via email to