aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/block/drbd/drbd_int.h20
-rw-r--r--drivers/block/drbd/drbd_main.c3
-rw-r--r--drivers/block/drbd/drbd_receiver.c96
3 files changed, 118 insertions, 1 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 2409de12f013..fd7615f1e526 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -209,8 +209,11 @@ enum drbd_packets {
209 P_RS_IS_IN_SYNC = 0x22, /* meta socket */ 209 P_RS_IS_IN_SYNC = 0x22, /* meta socket */
210 P_SYNC_PARAM89 = 0x23, /* data socket, protocol version 89 replacement for P_SYNC_PARAM */ 210 P_SYNC_PARAM89 = 0x23, /* data socket, protocol version 89 replacement for P_SYNC_PARAM */
211 P_COMPRESSED_BITMAP = 0x24, /* compressed or otherwise encoded bitmap transfer */ 211 P_COMPRESSED_BITMAP = 0x24, /* compressed or otherwise encoded bitmap transfer */
212 /* P_CKPT_FENCE_REQ = 0x25, * currently reserved for protocol D */
213 /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */
214 P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */
212 215
213 P_MAX_CMD = 0x25, 216 P_MAX_CMD = 0x28,
214 P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ 217 P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */
215 P_MAX_OPT_CMD = 0x101, 218 P_MAX_OPT_CMD = 0x101,
216 219
@@ -540,6 +543,18 @@ struct p_compressed_bm {
540 u8 code[0]; 543 u8 code[0];
541} __packed; 544} __packed;
542 545
546struct p_delay_probe {
547 struct p_header head;
548 u32 seq_num; /* sequence number to match the two probe packets */
549 u32 offset; /* usecs the probe got sent after the reference time point */
550} __packed;
551
552struct delay_probe {
553 struct list_head list;
554 int seq_num;
555 struct timeval time;
556};
557
543/* DCBP: Drbd Compressed Bitmap Packet ... */ 558/* DCBP: Drbd Compressed Bitmap Packet ... */
544static inline enum drbd_bitmap_code 559static inline enum drbd_bitmap_code
545DCBP_get_code(struct p_compressed_bm *p) 560DCBP_get_code(struct p_compressed_bm *p)
@@ -1028,6 +1043,9 @@ struct drbd_conf {
1028 u64 ed_uuid; /* UUID of the exposed data */ 1043 u64 ed_uuid; /* UUID of the exposed data */
1029 struct mutex state_mutex; 1044 struct mutex state_mutex;
1030 char congestion_reason; /* Why we where congested... */ 1045 char congestion_reason; /* Why we where congested... */
1046 struct list_head delay_probes; /* protected by peer_seq_lock */
1047 int data_delay; /* Delay of packets on the data-sock behind meta-sock */
1048 atomic_t delay_seq; /* To generate sequence numbers of delay probes */
1031}; 1049};
1032 1050
1033static inline struct drbd_conf *minor_to_mdev(unsigned int minor) 1051static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 7468d2ce7347..3d5fe307a19d 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2608,6 +2608,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
2608 atomic_set(&mdev->net_cnt, 0); 2608 atomic_set(&mdev->net_cnt, 0);
2609 atomic_set(&mdev->packet_seq, 0); 2609 atomic_set(&mdev->packet_seq, 0);
2610 atomic_set(&mdev->pp_in_use, 0); 2610 atomic_set(&mdev->pp_in_use, 0);
2611 atomic_set(&mdev->delay_seq, 0);
2611 2612
2612 mutex_init(&mdev->md_io_mutex); 2613 mutex_init(&mdev->md_io_mutex);
2613 mutex_init(&mdev->data.mutex); 2614 mutex_init(&mdev->data.mutex);
@@ -2636,6 +2637,8 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
2636 INIT_LIST_HEAD(&mdev->unplug_work.list); 2637 INIT_LIST_HEAD(&mdev->unplug_work.list);
2637 INIT_LIST_HEAD(&mdev->md_sync_work.list); 2638 INIT_LIST_HEAD(&mdev->md_sync_work.list);
2638 INIT_LIST_HEAD(&mdev->bm_io_work.w.list); 2639 INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
2640 INIT_LIST_HEAD(&mdev->delay_probes);
2641
2639 mdev->resync_work.cb = w_resync_inactive; 2642 mdev->resync_work.cb = w_resync_inactive;
2640 mdev->unplug_work.cb = w_send_write_hint; 2643 mdev->unplug_work.cb = w_send_write_hint;
2641 mdev->md_sync_work.cb = w_md_sync; 2644 mdev->md_sync_work.cb = w_md_sync;
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)