summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2012-08-03 02:19:09 +0200
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-09 14:05:46 +0100
commit519b6d3eac823e4ceec10484bc06f239047cebbf (patch)
treee3aeff3d85e0b75cf474bd717fd184c4b50e4cf4 /drivers
parent80c6eed49d5da3ba97cff4dc316ff051486cd1fc (diff)
drbd: fix drbd wire compatibility for empty flushes
DRBD has a concept of request epochs or reorder-domains, which are separated on the wire by P_BARRIER packets. Older DRBD is not able to handle zero-sized requests at all, so we need to map empty flushes to these drbd barriers. These are the equivalent of empty flushes, and by default trigger flushes on the receiving side anyways (unless not supported or explicitly disabled), so there is no need to handle this differently in newer drbd either. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/drbd/drbd_req.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 8323449fbba..a9111b68fe2 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -935,6 +935,20 @@ static int drbd_process_write_request(struct drbd_request *req)
send_oos = drbd_should_send_out_of_sync(mdev->state);
rcu_read_unlock();
+ /* Need to replicate writes. Unless it is an empty flush,
+ * which is better mapped to a DRBD P_BARRIER packet,
+ * also for drbd wire protocol compatibility reasons.
+ * If this was a flush, just start a new epoch.
+ * Unless the current epoch was empty anyways, or we are not currently
+ * replicating, in which case there is no point. */
+ if (unlikely(req->i.size == 0)) {
+ /* The only size==0 bios we expect are empty flushes. */
+ D_ASSERT(req->master_bio->bi_rw & REQ_FLUSH);
+ if (remote && mdev->tconn->current_tle_writes)
+ start_new_tl_epoch(mdev->tconn);
+ return 0;
+ }
+
if (!remote && !send_oos)
return 0;
@@ -1004,8 +1018,10 @@ void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long
* extent. This waits for any resync activity in the corresponding
* resync extent to finish, and, if necessary, pulls in the target
* extent into the activity log, which involves further disk io because
- * of transactional on-disk meta data updates. */
- if (rw == WRITE && req->private_bio
+ * of transactional on-disk meta data updates.
+ * Empty flushes don't need to go into the activity log, they can only
+ * flush data for pending writes which are already in there. */
+ if (rw == WRITE && req->private_bio && req->i.size
&& !test_bit(AL_SUSPENDED, &mdev->flags)) {
req->rq_state |= RQ_IN_ACT_LOG;
drbd_al_begin_io(mdev, &req->i);
@@ -1047,7 +1063,10 @@ void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long
if (rw == WRITE)
mdev->tconn->current_tle_writes++;
- list_add_tail(&req->tl_requests, &mdev->tconn->transfer_log);
+ /* no point in adding empty flushes to the transfer log,
+ * they are mapped to drbd barriers already. */
+ if (likely(req->i.size!=0))
+ list_add_tail(&req->tl_requests, &mdev->tconn->transfer_log);
if (rw == WRITE) {
if (!drbd_process_write_request(req))