Commit 80a40e43 authored by Lars Ellenberg's avatar Lars Ellenberg Committed by Philipp Reisner

drbd: reduce code duplication when receiving data requests

also canonicalize the return values of read_for_csum
and drbd_rs_begin_io to return -ESOMETHING, or 0 for success.
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 1d7734a0
......@@ -1119,7 +1119,7 @@ static int _is_in_al(struct drbd_conf *mdev, unsigned int enr)
* @mdev: DRBD device.
* @sector: The sector number.
*
* This functions sleeps on al_wait. Returns 1 on success, 0 if interrupted.
* This functions sleeps on al_wait. Returns 0 on success, -EINTR if interrupted.
*/
int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
{
......@@ -1130,10 +1130,10 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
sig = wait_event_interruptible(mdev->al_wait,
(bm_ext = _bme_get(mdev, enr)));
if (sig)
return 0;
return -EINTR;
if (test_bit(BME_LOCKED, &bm_ext->flags))
return 1;
return 0;
for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
sig = wait_event_interruptible(mdev->al_wait,
......@@ -1146,13 +1146,11 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
wake_up(&mdev->al_wait);
}
spin_unlock_irq(&mdev->al_lock);
return 0;
return -EINTR;
}
}
set_bit(BME_LOCKED, &bm_ext->flags);
return 1;
return 0;
}
/**
......
......@@ -2068,21 +2068,12 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
case P_DATA_REQUEST:
e->w.cb = w_e_end_data_req;
fault_type = DRBD_FAULT_DT_RD;
break;
/* application IO, don't drbd_rs_begin_io */
goto submit;
case P_RS_DATA_REQUEST:
e->w.cb = w_e_end_rsdata_req;
fault_type = DRBD_FAULT_RS_RD;
/* Eventually this should become asynchronously. Currently it
* blocks the whole receiver just to delay the reading of a
* resync data block.
* the drbd_work_queue mechanism is made for this...
*/
if (!drbd_rs_begin_io(mdev, sector)) {
/* we have been interrupted,
* probably connection lost! */
D_ASSERT(signal_pending(current));
goto out_free_e;
}
break;
case P_OV_REPLY:
......@@ -2108,13 +2099,8 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
} else if (h->command == P_OV_REPLY) {
e->w.cb = w_e_end_ov_reply;
dec_rs_pending(mdev);
break;
}
if (!drbd_rs_begin_io(mdev, sector)) {
/* we have been interrupted, probably connection lost! */
D_ASSERT(signal_pending(current));
goto out_free_e;
/* drbd_rs_begin_io done when we sent this request */
goto submit;
}
break;
......@@ -2133,31 +2119,23 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
}
e->w.cb = w_e_end_ov_req;
fault_type = DRBD_FAULT_RS_RD;
/* Eventually this should become asynchronous. Currently it
* blocks the whole receiver just to delay the reading of a
* resync data block.
* the drbd_work_queue mechanism is made for this...
*/
if (!drbd_rs_begin_io(mdev, sector)) {
/* we have been interrupted,
* probably connection lost! */
D_ASSERT(signal_pending(current));
goto out_free_e;
}
break;
default:
dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
cmdname(h->command));
fault_type = DRBD_FAULT_MAX;
goto out_free_e;
}
spin_lock_irq(&mdev->req_lock);
list_add(&e->w.list, &mdev->read_ee);
spin_unlock_irq(&mdev->req_lock);
if (drbd_rs_begin_io(mdev, e->sector))
goto out_free_e;
submit:
inc_unacked(mdev);
spin_lock_irq(&mdev->req_lock);
list_add_tail(&e->w.list, &mdev->read_ee);
spin_unlock_irq(&mdev->req_lock);
if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
return TRUE;
......
......@@ -374,26 +374,26 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
struct drbd_epoch_entry *e;
if (!get_ldev(mdev))
return 0;
return -EIO;
/* GFP_TRY, because if there is no memory available right now, this may
* be rescheduled for later. It is "only" background resync, after all. */
e = drbd_alloc_ee(mdev, DRBD_MAGIC+0xbeef, sector, size, GFP_TRY);
if (!e)
goto fail;
goto defer;
e->w.cb = w_e_send_csum;
spin_lock_irq(&mdev->req_lock);
list_add(&e->w.list, &mdev->read_ee);
spin_unlock_irq(&mdev->req_lock);
e->w.cb = w_e_send_csum;
if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
return 1;
return 0;
drbd_free_ee(mdev, e);
fail:
defer:
put_ldev(mdev);
return 2;
return -EAGAIN;
}
void resync_timer_fn(unsigned long data)
......@@ -649,15 +649,19 @@ int w_make_resync_request(struct drbd_conf *mdev,
size = (capacity-sector)<<9;
if (mdev->agreed_pro_version >= 89 && mdev->csums_tfm) {
switch (read_for_csum(mdev, sector, size)) {
case 0: /* Disk failure*/
case -EIO: /* Disk failure */
put_ldev(mdev);
return 0;
case 2: /* Allocation failed */
case -EAGAIN: /* allocation failed, or ldev busy */
drbd_rs_complete_io(mdev, sector);
mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
i = rollback_i;
goto requeue;
/* case 1: everything ok */
case 0:
/* everything ok */
break;
default:
BUG();
}
} else {
inc_rs_pending(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