drbd: Actually send delay probes
authorPhilipp Reisner <philipp.reisner@linbit.com>
Tue, 4 May 2010 10:33:58 +0000 (12:33 +0200)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Mon, 17 May 2010 23:25:28 +0000 (01:25 +0200)
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_main.c

index 3e4d8b5..210870e 100644 (file)
@@ -925,9 +925,11 @@ struct drbd_conf {
        unsigned int ko_count;
        struct drbd_work  resync_work,
                          unplug_work,
-                         md_sync_work;
+                         md_sync_work,
+                         delay_probe_work;
        struct timer_list resync_timer;
        struct timer_list md_sync_timer;
+       struct timer_list delay_probe_timer;
 
        /* Used after attach while negotiating new disk state. */
        union drbd_state new_state_tmp;
@@ -1047,6 +1049,8 @@ struct drbd_conf {
        int data_delay;   /* Delay of packets on the data-sock behind meta-sock */
        atomic_t delay_seq; /* To generate sequence numbers of delay probes */
        struct timeval dps_time; /* delay-probes-start-time */
+       int dp_volume_last;  /* send_cnt of last delay probe */
+       int c_sync_rate; /* current resync rate after delay_probe magic */
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
index 710bfeb..98785d0 100644 (file)
@@ -2207,10 +2207,13 @@ static int drbd_send_delay_probe(struct drbd_conf *mdev, struct drbd_socket *ds)
        }
        mutex_unlock(&ds->mutex);
 
+       mdev->dp_volume_last = mdev->send_cnt;
+       mod_timer(&mdev->delay_probe_timer, jiffies + mdev->sync_conf.dp_interval * HZ / 10);
+
        return ok;
 }
 
-static int drbd_send_dalay_probes(struct drbd_conf *mdev)
+static int drbd_send_delay_probes(struct drbd_conf *mdev)
 {
        int ok;
        atomic_inc(&mdev->delay_seq);
@@ -2350,6 +2353,30 @@ static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
        return 1;
 }
 
+static void consider_delay_probes(struct drbd_conf *mdev)
+{
+       if (mdev->state.conn != C_SYNC_SOURCE)
+               return;
+
+       if (mdev->dp_volume_last + mdev->sync_conf.dp_volume * 2 < mdev->send_cnt)
+               drbd_send_delay_probes(mdev);
+}
+
+static int w_delay_probes(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+       if (!cancel && mdev->state.conn == C_SYNC_SOURCE)
+               drbd_send_delay_probes(mdev);
+
+       return 1;
+}
+
+static void delay_probe_timer_fn(unsigned long data)
+{
+       struct drbd_conf *mdev = (struct drbd_conf *) data;
+
+       drbd_queue_work(&mdev->data.work, &mdev->delay_probe_work);
+}
+
 /* Used to send write requests
  * R_PRIMARY -> Peer   (P_DATA)
  */
@@ -2412,6 +2439,10 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
        }
 
        drbd_put_data_sock(mdev);
+
+       if (ok)
+               consider_delay_probes(mdev);
+
        return ok;
 }
 
@@ -2457,6 +2488,10 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
                ok = _drbd_send_zc_bio(mdev, e->private_bio);
 
        drbd_put_data_sock(mdev);
+
+       if (ok)
+               consider_delay_probes(mdev);
+
        return ok;
 }
 
@@ -2671,17 +2706,23 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
        INIT_LIST_HEAD(&mdev->md_sync_work.list);
        INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
        INIT_LIST_HEAD(&mdev->delay_probes);
+       INIT_LIST_HEAD(&mdev->delay_probe_work.list);
 
        mdev->resync_work.cb  = w_resync_inactive;
        mdev->unplug_work.cb  = w_send_write_hint;
        mdev->md_sync_work.cb = w_md_sync;
        mdev->bm_io_work.w.cb = w_bitmap_io;
+       mdev->delay_probe_work.cb = w_delay_probes;
        init_timer(&mdev->resync_timer);
        init_timer(&mdev->md_sync_timer);
+       init_timer(&mdev->delay_probe_timer);
        mdev->resync_timer.function = resync_timer_fn;
        mdev->resync_timer.data = (unsigned long) mdev;
        mdev->md_sync_timer.function = md_sync_timer_fn;
        mdev->md_sync_timer.data = (unsigned long) mdev;
+       mdev->delay_probe_timer.function = delay_probe_timer_fn;
+       mdev->delay_probe_timer.data = (unsigned long) mdev;
+
 
        init_waitqueue_head(&mdev->misc_wait);
        init_waitqueue_head(&mdev->state_wait);