aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2013-03-27 09:08:41 -0400
committerJens Axboe <axboe@kernel.dk>2013-03-28 12:10:25 -0400
commit7074e4a745799d521b17775f6d076d84dc7f8c50 (patch)
treea45461e71c8aaab46b8322fbaeb55e6d8710d057
parent2bd5ed5d6713594eb2b4d234d01217d506279c7d (diff)
drbd: only fail empty flushes if no good data is reachable
We completed empty flushes (blkdev_issue_flush()) with IO error if we lost the local disk, even if we still have an established replication link to a healthy remote disk. Fix this to only report errors to upper layers, if neither local nor remote data is reachable. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/block/drbd/drbd_req.c12
-rw-r--r--drivers/block/drbd/drbd_req.h8
2 files changed, 16 insertions, 4 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 9f7ff1cb46ff..beefe65764ff 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -263,8 +263,7 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
263 else 263 else
264 root = &mdev->read_requests; 264 root = &mdev->read_requests;
265 drbd_remove_request_interval(root, req); 265 drbd_remove_request_interval(root, req);
266 } else if (!(s & RQ_POSTPONED)) 266 }
267 D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0);
268 267
269 /* Before we can signal completion to the upper layers, 268 /* Before we can signal completion to the upper layers,
270 * we may need to close the current transfer log epoch. 269 * we may need to close the current transfer log epoch.
@@ -755,6 +754,11 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
755 D_ASSERT(req->rq_state & RQ_NET_PENDING); 754 D_ASSERT(req->rq_state & RQ_NET_PENDING);
756 mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK|RQ_NET_DONE); 755 mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK|RQ_NET_DONE);
757 break; 756 break;
757
758 case QUEUE_AS_DRBD_BARRIER:
759 start_new_tl_epoch(mdev->tconn);
760 mod_rq_state(req, m, 0, RQ_NET_OK|RQ_NET_DONE);
761 break;
758 }; 762 };
759 763
760 return rv; 764 return rv;
@@ -975,8 +979,8 @@ static int drbd_process_write_request(struct drbd_request *req)
975 /* The only size==0 bios we expect are empty flushes. */ 979 /* The only size==0 bios we expect are empty flushes. */
976 D_ASSERT(req->master_bio->bi_rw & REQ_FLUSH); 980 D_ASSERT(req->master_bio->bi_rw & REQ_FLUSH);
977 if (remote) 981 if (remote)
978 start_new_tl_epoch(mdev->tconn); 982 _req_mod(req, QUEUE_AS_DRBD_BARRIER);
979 return 0; 983 return remote;
980 } 984 }
981 985
982 if (!remote && !send_oos) 986 if (!remote && !send_oos)
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index c08d22964d06..978cb1addc98 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -88,6 +88,14 @@ enum drbd_req_event {
88 QUEUE_FOR_NET_READ, 88 QUEUE_FOR_NET_READ,
89 QUEUE_FOR_SEND_OOS, 89 QUEUE_FOR_SEND_OOS,
90 90
91 /* An empty flush is queued as P_BARRIER,
92 * which will cause it to complete "successfully",
93 * even if the local disk flush failed.
94 *
95 * Just like "real" requests, empty flushes (blkdev_issue_flush()) will
96 * only see an error if neither local nor remote data is reachable. */
97 QUEUE_AS_DRBD_BARRIER,
98
91 SEND_CANCELED, 99 SEND_CANCELED,
92 SEND_FAILED, 100 SEND_FAILED,
93 HANDED_OVER_TO_NETWORK, 101 HANDED_OVER_TO_NETWORK,