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;
* 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);
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))