diff options
| -rw-r--r-- | drivers/block/drbd/drbd_req.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 773f4e2d3c1b..8e93a6ac9bb6 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
| @@ -770,6 +770,40 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s | |||
| 770 | return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); | 770 | return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | static void maybe_pull_ahead(struct drbd_conf *mdev) | ||
| 774 | { | ||
| 775 | int congested = 0; | ||
| 776 | |||
| 777 | /* If I don't even have good local storage, we can not reasonably try | ||
| 778 | * to pull ahead of the peer. We also need the local reference to make | ||
| 779 | * sure mdev->act_log is there. | ||
| 780 | * Note: caller has to make sure that net_conf is there. | ||
| 781 | */ | ||
| 782 | if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) | ||
| 783 | return; | ||
| 784 | |||
| 785 | if (mdev->net_conf->cong_fill && | ||
| 786 | atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) { | ||
| 787 | dev_info(DEV, "Congestion-fill threshold reached\n"); | ||
| 788 | congested = 1; | ||
| 789 | } | ||
| 790 | |||
| 791 | if (mdev->act_log->used >= mdev->net_conf->cong_extents) { | ||
| 792 | dev_info(DEV, "Congestion-extents threshold reached\n"); | ||
| 793 | congested = 1; | ||
| 794 | } | ||
| 795 | |||
| 796 | if (congested) { | ||
| 797 | queue_barrier(mdev); /* last barrier, after mirrored writes */ | ||
| 798 | |||
| 799 | if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) | ||
| 800 | _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); | ||
| 801 | else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ | ||
| 802 | _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL); | ||
| 803 | } | ||
| 804 | put_ldev(mdev); | ||
| 805 | } | ||
| 806 | |||
| 773 | static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) | 807 | static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) |
| 774 | { | 808 | { |
| 775 | const int rw = bio_rw(bio); | 809 | const int rw = bio_rw(bio); |
| @@ -977,29 +1011,8 @@ allocate_barrier: | |||
| 977 | _req_mod(req, queue_for_send_oos); | 1011 | _req_mod(req, queue_for_send_oos); |
| 978 | 1012 | ||
| 979 | if (remote && | 1013 | if (remote && |
| 980 | mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) { | 1014 | mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) |
| 981 | int congested = 0; | 1015 | maybe_pull_ahead(mdev); |
| 982 | |||
| 983 | if (mdev->net_conf->cong_fill && | ||
| 984 | atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) { | ||
| 985 | dev_info(DEV, "Congestion-fill threshold reached\n"); | ||
| 986 | congested = 1; | ||
| 987 | } | ||
| 988 | |||
| 989 | if (mdev->act_log->used >= mdev->net_conf->cong_extents) { | ||
| 990 | dev_info(DEV, "Congestion-extents threshold reached\n"); | ||
| 991 | congested = 1; | ||
| 992 | } | ||
| 993 | |||
| 994 | if (congested) { | ||
| 995 | queue_barrier(mdev); /* last barrier, after mirrored writes */ | ||
| 996 | |||
| 997 | if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) | ||
| 998 | _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); | ||
| 999 | else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ | ||
| 1000 | _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL); | ||
| 1001 | } | ||
| 1002 | } | ||
| 1003 | 1016 | ||
| 1004 | spin_unlock_irq(&mdev->req_lock); | 1017 | spin_unlock_irq(&mdev->req_lock); |
| 1005 | kfree(b); /* if someone else has beaten us to it... */ | 1018 | kfree(b); /* if someone else has beaten us to it... */ |
