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: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
This commit is contained in:
parent
4439c400ab
commit
648e46b531
|
@ -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_conf *mdev = req->w.mdev;
|
||||||
struct drbd_interval *i;
|
struct drbd_interval *i;
|
||||||
int err;
|
sector_t sector = req->i.sector;
|
||||||
|
int size = req->i.size;
|
||||||
|
|
||||||
i = drbd_find_overlap(&mdev->write_requests, sector, size);
|
i = drbd_find_overlap(&mdev->write_requests, sector, size);
|
||||||
if (!i)
|
if (!i)
|
||||||
return 0;
|
return;
|
||||||
err = drbd_wait_misc(mdev, i);
|
|
||||||
if (err)
|
for (;;) {
|
||||||
return err;
|
prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
|
||||||
|
i = drbd_find_overlap(&mdev->write_requests, sector, size);
|
||||||
|
if (!i)
|
||||||
|
break;
|
||||||
|
/* Indicate to wake up device->misc_wait on progress. */
|
||||||
|
i->waiting = true;
|
||||||
|
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
|
||||||
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 @@ allocate_barrier:
|
||||||
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)) {
|
||||||
|
|
Loading…
Reference in New Issue