Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP5:Update
drbd
bsc-1189995-01_drbd-Improve-the-resync-controll...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File bsc-1189995-01_drbd-Improve-the-resync-controller-for-fast-back-end.patch of Package drbd
From f571cabed0e2955cc3b3bf5ba89fb371780bf0c6 Mon Sep 17 00:00:00 2001 From: Philipp Reisner <philipp.reisner@linbit.com> Date: Tue, 29 Jan 2019 12:45:31 +0100 Subject: [PATCH] drbd: Improve the resync controller for fast back end devices and network So far we had the issue that the resync controller was not able to scale to resync speeds possible with recent storage devices like NVMe drives. In order to deal with such scenarios more gracefully, reschedule the rs_make_request() function early in case the resync source fulfilled all resync requests before the resync timer expired (rs_sect_in reaches the value of rs_in_flight). We scale the sect_in value with the "earliness". I.e. if it took only half of the time, sect_in is multiplied by 2. But it still consumes a whole slot from the the fifo. With that we narrow the timing characteristics of the controller a bit, but no problem since the data flows faster than expected anyways. --- drbd/drbd_int.h | 1 + drbd/drbd_receiver.c | 21 ++++++++++++++++----- drbd/drbd_sender.c | 21 +++++++++++++++++---- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/drbd/drbd_int.h b/drbd/drbd_int.h index 3e437a2681e4..026b9aa253f8 100644 --- a/drbd/drbd_int.h +++ b/drbd/drbd_int.h @@ -1172,6 +1172,7 @@ struct drbd_peer_device { int rs_last_events; /* counter of read or write "events" (unit sectors) * on the lower level device when we last looked. */ int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */ + unsigned long rs_last_mk_req_jif; unsigned long ov_left; /* in bits */ unsigned long ov_skipped; /* in bits */ diff --git a/drbd/drbd_receiver.c b/drbd/drbd_receiver.c index de1fb9f36cdd..f031d9cb90fb 100644 --- a/drbd/drbd_receiver.c +++ b/drbd/drbd_receiver.c @@ -218,6 +218,17 @@ static struct page *__drbd_alloc_pages(unsigned int number, gfp_t gfp_mask) return NULL; } +static void rs_sectors_came_in(struct drbd_peer_device *peer_device, int size) +{ + int rs_sect_in = atomic_add_return(size >> 9, &peer_device->rs_sect_in); + + /* In case resync runs faster than anticipated, run the resync_work early */ + if (rs_sect_in >= peer_device->rs_in_flight) + drbd_queue_work_if_unqueued( + &peer_device->connection->sender_work, + &peer_device->resync_work); +} + /* kick lower level device, if we have more than (arbitrary number) * reference counts on it, which typically are locally submitted io * requests. don't use unacked_cnt, so we speed up proto A and B, too. */ @@ -2273,7 +2284,7 @@ static int receive_RSDataReply(struct drbd_connection *connection, struct packet drbd_send_ack_dp(peer_device, P_NEG_ACK, &d); } - atomic_add(d.bi_size >> 9, &peer_device->rs_sect_in); + rs_sectors_came_in(peer_device, d.bi_size); return err; } @@ -3286,7 +3297,7 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet peer_device->use_csums = true; } else if (pi->cmd == P_OV_REPLY) { /* track progress, we may need to throttle */ - atomic_add(size >> 9, &peer_device->rs_sect_in); + rs_sectors_came_in(peer_device, size); peer_req->w.cb = w_e_end_ov_reply; dec_rs_pending(peer_device); /* drbd_rs_begin_io done when we sent this request, @@ -7520,7 +7531,7 @@ static int receive_rs_deallocated(struct drbd_connection *connection, struct pac drbd_send_ack_ex(peer_device, P_NEG_ACK, sector, size, ID_SYNCER); } - atomic_add(size >> 9, &peer_device->rs_sect_in); + rs_sectors_came_in(peer_device, size); return err; } @@ -8382,7 +8393,7 @@ static int got_IsInSync(struct drbd_connection *connection, struct packet_info * put_ldev(device); } dec_rs_pending(peer_device); - atomic_add(blksize >> 9, &peer_device->rs_sect_in); + rs_sectors_came_in(peer_device, blksize); return 0; } @@ -8555,7 +8566,7 @@ static int got_NegRSDReply(struct drbd_connection *connection, struct packet_inf mutex_unlock(&device->bm_resync_fo_mutex); } - atomic_add(size >> 9, &peer_device->rs_sect_in); + rs_sectors_came_in(peer_device, size); mod_timer(&peer_device->resync_timer, jiffies + RS_MAKE_REQS_INTV); break; default: diff --git a/drbd/drbd_sender.c b/drbd/drbd_sender.c index 17f25299bf87..ec8be16e28aa 100644 --- a/drbd/drbd_sender.c +++ b/drbd/drbd_sender.c @@ -554,7 +554,7 @@ struct fifo_buffer *fifo_alloc(int fifo_size) return fb; } -static int drbd_rs_controller(struct drbd_peer_device *peer_device, unsigned int sect_in) +static int drbd_rs_controller(struct drbd_peer_device *peer_device, unsigned int sect_in, unsigned long duration) { struct peer_device_conf *pdc; unsigned int want; /* The number of sectors we want in-flight */ @@ -566,6 +566,13 @@ static int drbd_rs_controller(struct drbd_peer_device *peer_device, unsigned int int max_sect; struct fifo_buffer *plan; + if (duration == 0) + duration = 1; + else if (duration > RS_MAKE_REQS_INTV * 10) + duration = RS_MAKE_REQS_INTV * 10; + + sect_in = (u64)sect_in * RS_MAKE_REQS_INTV / duration; + pdc = rcu_dereference(peer_device->conf); plan = rcu_dereference(peer_device->rs_plan_s); @@ -575,7 +582,7 @@ static int drbd_rs_controller(struct drbd_peer_device *peer_device, unsigned int want = ((pdc->resync_rate * 2 * RS_MAKE_REQS_INTV) / HZ) * steps; } else { /* normal path */ want = pdc->c_fill_target ? pdc->c_fill_target : - sect_in * pdc->c_delay_target * HZ / (RS_MAKE_REQS_INTV * 10); + sect_in * pdc->c_delay_target * HZ / (duration * 10); } correction = want - peer_device->rs_in_flight - plan->total; @@ -593,7 +600,7 @@ static int drbd_rs_controller(struct drbd_peer_device *peer_device, unsigned int if (req_sect < 0) req_sect = 0; - max_sect = (pdc->c_max_rate * 2 * RS_MAKE_REQS_INTV) / HZ; + max_sect = (pdc->c_max_rate * 2 * duration) / HZ; if (req_sect > max_sect) req_sect = max_sect; @@ -609,17 +616,22 @@ static int drbd_rs_controller(struct drbd_peer_device *peer_device, unsigned int static int drbd_rs_number_requests(struct drbd_peer_device *peer_device) { struct net_conf *nc; + unsigned long duration, now; unsigned int sect_in; /* Number of sectors that came in since the last turn */ int number, mxb; sect_in = atomic_xchg(&peer_device->rs_sect_in, 0); peer_device->rs_in_flight -= sect_in; + now = jiffies; + duration = now - peer_device->rs_last_mk_req_jif; + peer_device->rs_last_mk_req_jif = now; + rcu_read_lock(); nc = rcu_dereference(peer_device->connection->transport.net_conf); mxb = nc ? nc->max_buffers : 0; if (rcu_dereference(peer_device->rs_plan_s)->size) { - number = drbd_rs_controller(peer_device, sect_in) >> (BM_BLOCK_SHIFT - 9); + number = drbd_rs_controller(peer_device, sect_in, duration) >> (BM_BLOCK_SHIFT - 9); peer_device->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / RS_MAKE_REQS_INTV; } else { peer_device->c_sync_rate = rcu_dereference(peer_device->conf)->resync_rate; @@ -1816,6 +1828,7 @@ void drbd_rs_controller_reset(struct drbd_peer_device *peer_device) atomic_set(&peer_device->rs_sect_in, 0); atomic_set(&peer_device->device->rs_sect_ev, 0); /* FIXME: ??? */ + peer_device->rs_last_mk_req_jif = jiffies; peer_device->rs_in_flight = 0; peer_device->rs_last_events = drbd_backing_bdev_events(peer_device->device->ldev->backing_bdev->bd_contains->bd_disk); -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor