aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_receiver.c
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2010-04-30 09:26:20 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-05-17 19:22:11 -0400
commit0ced55a3bed25b0e30dcb3c7dce9634ce3c60cf2 (patch)
tree7c5770c396588432619ecd2af5793a04ca7080b5 /drivers/block/drbd/drbd_receiver.c
parent5223671bb0315d83f9ad7becbbb9e703aa735bbe (diff)
drbd: Receiving of delay_probes
Delay_probes are new packets in the DRBD protocol, which allow DRBD to know the current delay packets have on the data socket. (relative to the meta data socket) 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.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index b27f4dd36f89..fee0d249adf7 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -3501,6 +3501,92 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, struct p_header *h)
3501 return TRUE; 3501 return TRUE;
3502} 3502}
3503 3503
3504static void timeval_sub_us(struct timeval* tv, unsigned int us)
3505{
3506 tv->tv_sec -= us / 1000000;
3507 us = us % 1000000;
3508 if (tv->tv_usec > us) {
3509 tv->tv_usec += 1000000;
3510 tv->tv_sec--;
3511 }
3512 tv->tv_usec -= us;
3513}
3514
3515static void got_delay_probe(struct drbd_conf *mdev, int from, struct p_delay_probe *p)
3516{
3517 struct delay_probe *dp;
3518 struct list_head *le;
3519 struct timeval now;
3520 int seq_num;
3521 int offset;
3522 int data_delay;
3523
3524 seq_num = be32_to_cpu(p->seq_num);
3525 offset = be32_to_cpu(p->offset);
3526
3527 spin_lock(&mdev->peer_seq_lock);
3528 if (!list_empty(&mdev->delay_probes)) {
3529 if (from == USE_DATA_SOCKET)
3530 le = mdev->delay_probes.next;
3531 else
3532 le = mdev->delay_probes.prev;
3533
3534 dp = list_entry(le, struct delay_probe, list);
3535
3536 if (dp->seq_num == seq_num) {
3537 list_del(le);
3538 spin_unlock(&mdev->peer_seq_lock);
3539 do_gettimeofday(&now);
3540 timeval_sub_us(&now, offset);
3541 data_delay =
3542 now.tv_usec - dp->time.tv_usec +
3543 (now.tv_sec - dp->time.tv_sec) * 1000000;
3544
3545 if (data_delay > 0)
3546 mdev->data_delay = data_delay;
3547
3548 kfree(dp);
3549 return;
3550 }
3551
3552 if (dp->seq_num > seq_num) {
3553 spin_unlock(&mdev->peer_seq_lock);
3554 dev_warn(DEV, "Previous allocation failure of struct delay_probe?\n");
3555 return; /* Do not alloca a struct delay_probe.... */
3556 }
3557 }
3558 spin_unlock(&mdev->peer_seq_lock);
3559
3560 dp = kmalloc(sizeof(struct delay_probe), GFP_NOIO);
3561 if (!dp) {
3562 dev_warn(DEV, "Failed to allocate a struct delay_probe, do not worry.\n");
3563 return;
3564 }
3565
3566 dp->seq_num = seq_num;
3567 do_gettimeofday(&dp->time);
3568 timeval_sub_us(&dp->time, offset);
3569
3570 spin_lock(&mdev->peer_seq_lock);
3571 if (from == USE_DATA_SOCKET)
3572 list_add(&dp->list, &mdev->delay_probes);
3573 else
3574 list_add_tail(&dp->list, &mdev->delay_probes);
3575 spin_unlock(&mdev->peer_seq_lock);
3576}
3577
3578static int receive_delay_probe(struct drbd_conf *mdev, struct p_header *h)
3579{
3580 struct p_delay_probe *p = (struct p_delay_probe *)h;
3581
3582 ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
3583 if (drbd_recv(mdev, h->payload, h->length) != h->length)
3584 return FALSE;
3585
3586 got_delay_probe(mdev, USE_DATA_SOCKET, p);
3587 return TRUE;
3588}
3589
3504typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, struct p_header *); 3590typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, struct p_header *);
3505 3591
3506static drbd_cmd_handler_f drbd_default_handler[] = { 3592static drbd_cmd_handler_f drbd_default_handler[] = {
@@ -3524,6 +3610,7 @@ static drbd_cmd_handler_f drbd_default_handler[] = {
3524 [P_OV_REQUEST] = receive_DataRequest, 3610 [P_OV_REQUEST] = receive_DataRequest,
3525 [P_OV_REPLY] = receive_DataRequest, 3611 [P_OV_REPLY] = receive_DataRequest,
3526 [P_CSUM_RS_REQUEST] = receive_DataRequest, 3612 [P_CSUM_RS_REQUEST] = receive_DataRequest,
3613 [P_DELAY_PROBE] = receive_delay_probe,
3527 /* anything missing from this table is in 3614 /* anything missing from this table is in
3528 * the asender_tbl, see get_asender_cmd */ 3615 * the asender_tbl, see get_asender_cmd */
3529 [P_MAX_CMD] = NULL, 3616 [P_MAX_CMD] = NULL,
@@ -4300,6 +4387,14 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header *h)
4300 return TRUE; 4387 return TRUE;
4301} 4388}
4302 4389
4390static int got_delay_probe_m(struct drbd_conf *mdev, struct p_header *h)
4391{
4392 struct p_delay_probe *p = (struct p_delay_probe *)h;
4393
4394 got_delay_probe(mdev, USE_META_SOCKET, p);
4395 return TRUE;
4396}
4397
4303struct asender_cmd { 4398struct asender_cmd {
4304 size_t pkt_size; 4399 size_t pkt_size;
4305 int (*process)(struct drbd_conf *mdev, struct p_header *h); 4400 int (*process)(struct drbd_conf *mdev, struct p_header *h);
@@ -4324,6 +4419,7 @@ static struct asender_cmd *get_asender_cmd(int cmd)
4324 [P_BARRIER_ACK] = { sizeof(struct p_barrier_ack), got_BarrierAck }, 4419 [P_BARRIER_ACK] = { sizeof(struct p_barrier_ack), got_BarrierAck },
4325 [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply }, 4420 [P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
4326 [P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), got_IsInSync }, 4421 [P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), got_IsInSync },
4422 [P_DELAY_PROBE] = { sizeof(struct p_delay_probe), got_delay_probe_m },
4327 [P_MAX_CMD] = { 0, NULL }, 4423 [P_MAX_CMD] = { 0, NULL },
4328 }; 4424 };
4329 if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL) 4425 if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL)