summaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_receiver.c
diff options
context:
space:
mode:
authorAndreas Gruenbacher2011-01-28 10:31:04 +0100
committerPhilipp Reisner2011-09-28 10:26:31 +0200
commit53840641bb1feff8c08acdba9de4c0f8b8674df5 (patch)
tree4a0eb7966272182b417a9a94f1c5423bcb1fd663 /drivers/block/drbd/drbd_receiver.c
parentdrbd: Remove redundant check from drbd_contains_interval() (diff)
downloadkernel-qcow2-linux-53840641bb1feff8c08acdba9de4c0f8b8674df5.tar.gz
kernel-qcow2-linux-53840641bb1feff8c08acdba9de4c0f8b8674df5.tar.xz
kernel-qcow2-linux-53840641bb1feff8c08acdba9de4c0f8b8674df5.zip
drbd: Allow to wait for the completion of an epoch entry as well
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_receiver.c')
-rw-r--r--drivers/block/drbd/drbd_receiver.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index d9f3f7fd9bb2..b84a9c9fd3f8 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -334,13 +334,15 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
goto fail;
drbd_clear_interval(&e->i);
+ e->i.size = data_size;
+ e->i.sector = sector;
+ e->i.waiting = false;
+
e->epoch = NULL;
e->mdev = mdev;
e->pages = page;
atomic_set(&e->pending_bios, 0);
- e->i.size = data_size;
e->flags = 0;
- e->i.sector = sector;
/*
* The block_id is opaque to the receiver. It is not endianness
* converted, and sent back to the sender unchanged.
@@ -1172,6 +1174,19 @@ fail:
return err;
}
+static void drbd_remove_epoch_entry_interval(struct drbd_conf *mdev,
+ struct drbd_epoch_entry *e)
+{
+ struct drbd_interval *i = &e->i;
+
+ drbd_remove_interval(&mdev->write_requests, i);
+ drbd_clear_interval(i);
+
+ /* Wake up any processes waiting for this epoch entry to complete. */
+ if (i->waiting)
+ wake_up(&mdev->misc_wait);
+}
+
static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packet cmd,
unsigned int data_size)
{
@@ -1591,8 +1606,7 @@ static int e_end_block(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
if (mdev->tconn->net_conf->two_primaries) {
spin_lock_irq(&mdev->tconn->req_lock);
D_ASSERT(!drbd_interval_empty(&e->i));
- drbd_remove_interval(&mdev->epoch_entries, &e->i);
- drbd_clear_interval(&e->i);
+ drbd_remove_epoch_entry_interval(mdev, e);
spin_unlock_irq(&mdev->tconn->req_lock);
} else
D_ASSERT(drbd_interval_empty(&e->i));
@@ -1612,8 +1626,7 @@ static int e_send_discard_ack(struct drbd_conf *mdev, struct drbd_work *w, int u
spin_lock_irq(&mdev->tconn->req_lock);
D_ASSERT(!drbd_interval_empty(&e->i));
- drbd_remove_interval(&mdev->epoch_entries, &e->i);
- drbd_clear_interval(&e->i);
+ drbd_remove_epoch_entry_interval(mdev, e);
spin_unlock_irq(&mdev->tconn->req_lock);
dec_unacked(mdev);
@@ -1860,17 +1873,14 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
}
if (signal_pending(current)) {
- drbd_remove_interval(&mdev->epoch_entries, &e->i);
- drbd_clear_interval(&e->i);
-
+ drbd_remove_epoch_entry_interval(mdev, e);
spin_unlock_irq(&mdev->tconn->req_lock);
-
finish_wait(&mdev->misc_wait, &wait);
goto out_interrupted;
}
/* Indicate to wake up mdev->misc_wait upon completion. */
- req2->rq_state |= RQ_COLLISION;
+ i->waiting = true;
spin_unlock_irq(&mdev->tconn->req_lock);
if (first) {
@@ -1922,8 +1932,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
dev_err(DEV, "submit failed, triggering re-connect\n");
spin_lock_irq(&mdev->tconn->req_lock);
list_del(&e->w.list);
- drbd_remove_interval(&mdev->epoch_entries, &e->i);
- drbd_clear_interval(&e->i);
+ drbd_remove_epoch_entry_interval(mdev, e);
spin_unlock_irq(&mdev->tconn->req_lock);
if (e->flags & EE_CALL_AL_COMPLETE_IO)
drbd_al_complete_io(mdev, e->i.sector);