Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 346048
b: refs/heads/master
c: 813472c
h: refs/heads/master
v: v3
  • Loading branch information
Philipp Reisner committed Nov 8, 2012
1 parent 3eb87e1 commit c8f22ad
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 56 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d589a21e5d9099a6351862ae6a7f4ae5ec4103d4
refs/heads/master: 813472ced7fac734157fe5be1137ce2bac942902
2 changes: 1 addition & 1 deletion trunk/drivers/block/drbd/drbd_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ struct drbd_conf {
int rs_last_events; /* counter of read or write "events" (unit sectors)
* on the lower level device when we last looked. */
int c_sync_rate; /* current resync rate after syncer throttle magic */
struct fifo_buffer *rs_plan_s; /* correction values of resync planer */
struct fifo_buffer *rs_plan_s; /* correction values of resync planer (RCU, tconn->conn_update) */
int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */
int peer_max_bio_size;
Expand Down
18 changes: 8 additions & 10 deletions trunk/drivers/block/drbd/drbd_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
enum drbd_ret_code retcode;
struct drbd_conf *mdev;
struct disk_conf *new_disk_conf, *old_disk_conf;
struct fifo_buffer *rs_plan_s = NULL;
struct fifo_buffer *old_plan = NULL, *new_plan = NULL;
int err, fifo_size;

retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
Expand Down Expand Up @@ -1158,8 +1158,8 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)

fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
if (fifo_size != mdev->rs_plan_s->size) {
rs_plan_s = fifo_alloc(fifo_size);
if (!rs_plan_s) {
new_plan = fifo_alloc(fifo_size);
if (!new_plan) {
dev_err(DEV, "kmalloc of fifo_buffer failed");
retcode = ERR_NOMEM;
goto fail_unlock;
Expand Down Expand Up @@ -1188,13 +1188,10 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
if (retcode != NO_ERROR)
goto fail_unlock;

spin_lock(&mdev->peer_seq_lock);
if (rs_plan_s) {
kfree(mdev->rs_plan_s);
mdev->rs_plan_s = rs_plan_s;
rs_plan_s = NULL;
if (new_plan) {
old_plan = mdev->rs_plan_s;
rcu_assign_pointer(mdev->rs_plan_s, new_plan);
}
spin_unlock(&mdev->peer_seq_lock);

drbd_md_sync(mdev);

Expand All @@ -1204,13 +1201,14 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
mutex_unlock(&mdev->tconn->conf_update);
synchronize_rcu();
kfree(old_disk_conf);
kfree(old_plan);
goto success;

fail_unlock:
mutex_unlock(&mdev->tconn->conf_update);
fail:
kfree(new_disk_conf);
kfree(rs_plan_s);
kfree(new_plan);
success:
put_ldev(mdev);
out:
Expand Down
71 changes: 44 additions & 27 deletions trunk/drivers/block/drbd/drbd_receiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -3157,9 +3157,9 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
struct crypto_hash *verify_tfm = NULL;
struct crypto_hash *csums_tfm = NULL;
struct net_conf *old_net_conf, *new_net_conf = NULL;
struct disk_conf *old_disk_conf, *new_disk_conf = NULL;
struct disk_conf *old_disk_conf = NULL, *new_disk_conf = NULL;
const int apv = tconn->agreed_pro_version;
struct fifo_buffer *rs_plan_s = NULL;
struct fifo_buffer *old_plan = NULL, *new_plan = NULL;
int fifo_size = 0;
int err;

Expand Down Expand Up @@ -3200,34 +3200,36 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
if (err)
return err;

new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
if (!new_disk_conf) {
dev_err(DEV, "Allocation of new disk_conf failed\n");
return -ENOMEM;
}

mutex_lock(&mdev->tconn->conf_update);
old_net_conf = mdev->tconn->net_conf;
old_disk_conf = mdev->ldev->disk_conf;
*new_disk_conf = *old_disk_conf;
if (get_ldev(mdev)) {
new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
if (!new_disk_conf) {
put_ldev(mdev);
mutex_unlock(&mdev->tconn->conf_update);
dev_err(DEV, "Allocation of new disk_conf failed\n");
return -ENOMEM;
}

new_disk_conf->resync_rate = be32_to_cpu(p->rate);
old_disk_conf = mdev->ldev->disk_conf;
*new_disk_conf = *old_disk_conf;

new_disk_conf->resync_rate = be32_to_cpu(p->rate);
}

if (apv >= 88) {
if (apv == 88) {
if (data_size > SHARED_SECRET_MAX) {
dev_err(DEV, "verify-alg too long, "
"peer wants %u, accepting only %u byte\n",
data_size, SHARED_SECRET_MAX);
mutex_unlock(&mdev->tconn->conf_update);
return -EIO;
err = -EIO;
goto reconnect;
}

err = drbd_recv_all(mdev->tconn, p->verify_alg, data_size);
if (err) {
mutex_unlock(&mdev->tconn->conf_update);
return err;
}
if (err)
goto reconnect;
/* we expect NUL terminated string */
/* but just in case someone tries to be evil */
D_ASSERT(p->verify_alg[data_size-1] == 0);
Expand Down Expand Up @@ -3270,16 +3272,16 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
}
}

if (apv > 94) {
if (apv > 94 && new_disk_conf) {
new_disk_conf->c_plan_ahead = be32_to_cpu(p->c_plan_ahead);
new_disk_conf->c_delay_target = be32_to_cpu(p->c_delay_target);
new_disk_conf->c_fill_target = be32_to_cpu(p->c_fill_target);
new_disk_conf->c_max_rate = be32_to_cpu(p->c_max_rate);

fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
if (fifo_size != mdev->rs_plan_s->size) {
rs_plan_s = fifo_alloc(fifo_size);
if (!rs_plan_s) {
new_plan = fifo_alloc(fifo_size);
if (!new_plan) {
dev_err(DEV, "kmalloc of fifo_buffer failed");
put_ldev(mdev);
goto disconnect;
Expand Down Expand Up @@ -3314,24 +3316,39 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
}
}

rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
spin_lock(&mdev->peer_seq_lock);
if (rs_plan_s) {
kfree(mdev->rs_plan_s);
mdev->rs_plan_s = rs_plan_s;
if (new_disk_conf) {
rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
put_ldev(mdev);
}

if (new_plan) {
old_plan = mdev->rs_plan_s;
rcu_assign_pointer(mdev->rs_plan_s, new_plan);
}
spin_unlock(&mdev->peer_seq_lock);

mutex_unlock(&mdev->tconn->conf_update);
synchronize_rcu();
if (new_net_conf)
kfree(old_net_conf);
kfree(old_disk_conf);
kfree(old_plan);

return 0;

reconnect:
if (new_disk_conf) {
put_ldev(mdev);
kfree(new_disk_conf);
}
mutex_unlock(&mdev->tconn->conf_update);
return -EIO;

disconnect:
kfree(rs_plan_s);
kfree(new_plan);
if (new_disk_conf) {
put_ldev(mdev);
kfree(new_disk_conf);
}
mutex_unlock(&mdev->tconn->conf_update);
/* just for completeness: actually not needed,
* as this is not reached if csums_tfm was ok. */
Expand Down
41 changes: 24 additions & 17 deletions trunk/drivers/block/drbd/drbd_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,15 +460,15 @@ static int drbd_rs_controller(struct drbd_conf *mdev)
int steps; /* Number of time steps to plan ahead */
int curr_corr;
int max_sect;
struct fifo_buffer *plan;

sect_in = atomic_xchg(&mdev->rs_sect_in, 0); /* Number of sectors that came in */
mdev->rs_in_flight -= sect_in;

spin_lock(&mdev->peer_seq_lock); /* get an atomic view on mdev->rs_plan_s */
rcu_read_lock();
dc = rcu_dereference(mdev->ldev->disk_conf);
plan = rcu_dereference(mdev->rs_plan_s);

steps = mdev->rs_plan_s->size; /* (dc->c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
steps = plan->size; /* (dc->c_plan_ahead * 10 * SLEEP_TIME) / HZ; */

if (mdev->rs_in_flight + sect_in == 0) { /* At start of resync */
want = ((dc->resync_rate * 2 * SLEEP_TIME) / HZ) * steps;
Expand All @@ -477,16 +477,16 @@ static int drbd_rs_controller(struct drbd_conf *mdev)
sect_in * dc->c_delay_target * HZ / (SLEEP_TIME * 10);
}

correction = want - mdev->rs_in_flight - mdev->rs_plan_s->total;
correction = want - mdev->rs_in_flight - plan->total;

/* Plan ahead */
cps = correction / steps;
fifo_add_val(mdev->rs_plan_s, cps);
mdev->rs_plan_s->total += cps * steps;
fifo_add_val(plan, cps);
plan->total += cps * steps;

/* What we do in this step */
curr_corr = fifo_push(mdev->rs_plan_s, 0);
mdev->rs_plan_s->total -= curr_corr;
curr_corr = fifo_push(plan, 0);
plan->total -= curr_corr;

req_sect = sect_in + curr_corr;
if (req_sect < 0)
Expand All @@ -501,24 +501,23 @@ static int drbd_rs_controller(struct drbd_conf *mdev)
sect_in, mdev->rs_in_flight, want, correction,
steps, cps, mdev->rs_planed, curr_corr, req_sect);
*/
rcu_read_unlock();
spin_unlock(&mdev->peer_seq_lock);

return req_sect;
}

static int drbd_rs_number_requests(struct drbd_conf *mdev)
{
int number;
if (mdev->rs_plan_s->size) { /* rcu_dereference(mdev->ldev->disk_conf)->c_plan_ahead */

rcu_read_lock();
if (rcu_dereference(mdev->rs_plan_s)->size) {
number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
} else {
rcu_read_lock();
mdev->c_sync_rate = rcu_dereference(mdev->ldev->disk_conf)->resync_rate;
rcu_read_unlock();
number = SLEEP_TIME * mdev->c_sync_rate / ((BM_BLOCK_SIZE / 1024) * HZ);
}
rcu_read_unlock();

/* ignore the amount of pending requests, the resync controller should
* throttle down to incoming reply rate soon enough anyways. */
Expand Down Expand Up @@ -1468,13 +1467,21 @@ void drbd_sync_after_changed(struct drbd_conf *mdev)

void drbd_rs_controller_reset(struct drbd_conf *mdev)
{
struct fifo_buffer *plan;

atomic_set(&mdev->rs_sect_in, 0);
atomic_set(&mdev->rs_sect_ev, 0);
mdev->rs_in_flight = 0;
mdev->rs_plan_s->total = 0;
spin_lock(&mdev->peer_seq_lock);
fifo_set(mdev->rs_plan_s, 0);
spin_unlock(&mdev->peer_seq_lock);

/* Updating the RCU protected object in place is necessary since
this function gets called from atomic context.
It is valid since all other updates also lead to an completely
empty fifo */
rcu_read_lock();
plan = rcu_dereference(mdev->rs_plan_s);
plan->total = 0;
fifo_set(plan, 0);
rcu_read_unlock();
}

void start_resync_timer_fn(unsigned long data)
Expand Down

0 comments on commit c8f22ad

Please sign in to comment.