Commit 53840641 authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Philipp Reisner
Browse files

drbd: Allow to wait for the completion of an epoch entry as well

parent 3e05146f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ struct drbd_interval {
	sector_t sector;	/* start sector of the interval */
	unsigned int size;	/* size in bytes */
	sector_t end;		/* highest interval end in subtree */
	int waiting:1;
};

static inline void drbd_clear_interval(struct drbd_interval *i)
+22 −13
Original line number Diff line number Diff line
@@ -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 @@ int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
	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);
+18 −5
Original line number Diff line number Diff line
@@ -70,9 +70,12 @@ static struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
	req->mdev        = mdev;
	req->master_bio  = bio_src;
	req->epoch       = 0;

	drbd_clear_interval(&req->i);
	req->i.sector     = bio_src->bi_sector;
	req->i.size      = bio_src->bi_size;
	req->i.waiting = false;

	INIT_LIST_HEAD(&req->tl_requests);
	INIT_LIST_HEAD(&req->w.list);

@@ -175,10 +178,6 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev,
	    (s & RQ_NET_SENT) != 0 &&
	    req->epoch == mdev->tconn->newest_tle->br_number)
		queue_barrier(mdev);

	/* Wake up any processes waiting for this request to complete.  */
	if ((s & RQ_NET_DONE) && (s & RQ_COLLISION))
		wake_up(&mdev->misc_wait);
}

void complete_master_bio(struct drbd_conf *mdev,
@@ -188,6 +187,20 @@ void complete_master_bio(struct drbd_conf *mdev,
	dec_ap_bio(mdev);
}


static void drbd_remove_request_interval(struct rb_root *root,
					 struct drbd_request *req)
{
	struct drbd_conf *mdev = req->mdev;
	struct drbd_interval *i = &req->i;

	drbd_remove_interval(root, i);

	/* Wake up any processes waiting for this request to complete.  */
	if (i->waiting)
		wake_up(&mdev->misc_wait);
}

/* Helper for __req_mod().
 * Set m->bio to the master bio, if it is fit to be completed,
 * or leave it alone (it is initialized to NULL in __req_mod),
@@ -251,7 +264,7 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m)
				root = &mdev->write_requests;
			else
				root = &mdev->read_requests;
			drbd_remove_interval(root, &req->i);
			drbd_remove_request_interval(root, req);
		} else
			D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0);

+0 −7
Original line number Diff line number Diff line
@@ -194,12 +194,6 @@ enum drbd_req_state_bits {

	/* Should call drbd_al_complete_io() for this request... */
	__RQ_IN_ACT_LOG,

	/*
	 * Set when a processes puts itself to sleep to wait for this request
	 * to complete.
	 */
	__RQ_COLLISION,
};

#define RQ_LOCAL_PENDING   (1UL << __RQ_LOCAL_PENDING)
@@ -220,7 +214,6 @@ enum drbd_req_state_bits {

#define RQ_WRITE           (1UL << __RQ_WRITE)
#define RQ_IN_ACT_LOG      (1UL << __RQ_IN_ACT_LOG)
#define RQ_COLLISION	   (1UL << __RQ_COLLISION)

/* For waking up the frozen transfer log mod_req() has to return if the request
   should be counted in the epoch object*/