Commit 648e46b5 authored by Lars Ellenberg's avatar Lars Ellenberg Committed by Philipp Reisner

drbd: complete_conflicting_writes() should not care about connections

complete_conflicting_writes() should not cause -EIO.
It should not timeout either, or care for connection states.

Connection timeout is detected elsewhere, and it's cleanup path is
supposed to remove any pending requests or peer_requests from the
write_requests tree.
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 4439c400
...@@ -800,21 +800,33 @@ static bool remote_due_to_read_balancing(struct drbd_conf *mdev, sector_t sector ...@@ -800,21 +800,33 @@ static bool remote_due_to_read_balancing(struct drbd_conf *mdev, sector_t sector
* The write_requests tree contains all active write requests which we * The write_requests tree contains all active write requests which we
* currently know about. Wait for any requests to complete which conflict with * currently know about. Wait for any requests to complete which conflict with
* the new one. * the new one.
*
* Only way out: remove the conflicting intervals from the tree.
*/ */
static int complete_conflicting_writes(struct drbd_conf *mdev, static void complete_conflicting_writes(struct drbd_request *req)
sector_t sector, int size)
{ {
for(;;) { DEFINE_WAIT(wait);
struct drbd_interval *i; struct drbd_conf *mdev = req->w.mdev;
int err; struct drbd_interval *i;
sector_t sector = req->i.sector;
int size = req->i.size;
i = drbd_find_overlap(&mdev->write_requests, sector, size);
if (!i)
return;
for (;;) {
prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
i = drbd_find_overlap(&mdev->write_requests, sector, size); i = drbd_find_overlap(&mdev->write_requests, sector, size);
if (!i) if (!i)
return 0; break;
err = drbd_wait_misc(mdev, i); /* Indicate to wake up device->misc_wait on progress. */
if (err) i->waiting = true;
return err; spin_unlock_irq(&mdev->tconn->req_lock);
schedule();
spin_lock_irq(&mdev->tconn->req_lock);
} }
finish_wait(&mdev->misc_wait, &wait);
} }
int __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) int __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
...@@ -826,7 +838,7 @@ int __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long s ...@@ -826,7 +838,7 @@ int __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long s
struct drbd_request *req; struct drbd_request *req;
struct net_conf *nc; struct net_conf *nc;
int local, remote, send_oos = 0; int local, remote, send_oos = 0;
int err; int err = 0;
int ret = 0; int ret = 0;
union drbd_dev_state s; union drbd_dev_state s;
...@@ -925,16 +937,10 @@ int __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long s ...@@ -925,16 +937,10 @@ int __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long s
spin_lock_irq(&mdev->tconn->req_lock); spin_lock_irq(&mdev->tconn->req_lock);
if (rw == WRITE) { if (rw == WRITE) {
err = complete_conflicting_writes(mdev, sector, size); /* This may temporarily give up the req_lock,
if (err) { * but will re-aquire it before it returns here.
if (err != -ERESTARTSYS) * Needs to be before the check on drbd_suspended() */
_conn_request_state(mdev->tconn, complete_conflicting_writes(req);
NS(conn, C_TIMEOUT),
CS_HARD);
spin_unlock_irq(&mdev->tconn->req_lock);
err = -EIO;
goto fail_free_complete;
}
} }
if (drbd_suspended(mdev)) { if (drbd_suspended(mdev)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment