From 9958c857c760eec76f4fdf288b6f33a1c3b41833 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 3 May 2011 16:19:31 +0200 Subject: [PATCH] drbd: Made the fifo object a self contained object (preparing for RCU) * Moved rs_planed into it, named total * When having a pointer to the object the values can be embedded into the fifo object. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 7 +++--- drivers/block/drbd/drbd_main.c | 1 + drivers/block/drbd/drbd_nl.c | 34 +++++++++++++++++++----------- drivers/block/drbd/drbd_receiver.c | 13 ++++++------ drivers/block/drbd/drbd_worker.c | 33 +++++++++++++++++++++-------- 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index cd77dd497b94..2ecee6cd2bdb 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -802,10 +802,12 @@ enum write_ordering_e { }; struct fifo_buffer { - int *values; unsigned int head_index; unsigned int size; + int total; /* sum of all values */ + int values[0]; }; +extern struct fifo_buffer *fifo_alloc(int fifo_size); /* flag bits per tconn */ enum { @@ -996,9 +998,8 @@ 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 */ int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */ - int rs_planed; /* resync sectors already planned */ atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */ int peer_max_bio_size; int local_max_bio_size; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index de6afa75dec6..240319ce8650 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2310,6 +2310,7 @@ void drbd_delete_device(struct drbd_conf *mdev) __free_page(mdev->md_io_page); put_disk(mdev->vdisk); blk_cleanup_queue(mdev->rq_queue); + kfree(mdev->rs_plan_s); kfree(mdev); kref_put(&tconn->kref, &conn_destroy); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index ea62838e0794..7fda3d9445ca 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1107,8 +1107,8 @@ 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; int err, fifo_size; - int *rs_plan_s = NULL; retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR); if (!adm_ctx.reply_skb) @@ -1153,8 +1153,8 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) new_disk_conf->al_extents = DRBD_AL_EXTENTS_MAX; fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ; - if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) { - rs_plan_s = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL); + if (fifo_size != mdev->rs_plan_s->size) { + rs_plan_s = fifo_alloc(fifo_size); if (!rs_plan_s) { dev_err(DEV, "kmalloc of fifo_buffer failed"); retcode = ERR_NOMEM; @@ -1162,14 +1162,6 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) } } - if (fifo_size != mdev->rs_plan_s.size) { - kfree(mdev->rs_plan_s.values); - mdev->rs_plan_s.values = rs_plan_s; - mdev->rs_plan_s.size = fifo_size; - mdev->rs_planed = 0; - rs_plan_s = NULL; - } - wait_event(mdev->al_wait, lc_try_lock(mdev->act_log)); drbd_al_shrink(mdev); err = drbd_check_al_size(mdev, new_disk_conf); @@ -1192,6 +1184,14 @@ 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; + } + spin_unlock(&mdev->peer_seq_lock); + drbd_md_sync(mdev); if (mdev->state.conn >= C_CONNECTED) @@ -1226,6 +1226,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) struct disk_conf *new_disk_conf = NULL; struct block_device *bdev; struct lru_cache *resync_lru = NULL; + struct fifo_buffer *new_plan = NULL; union drbd_state ns, os; enum drbd_state_rv rv; struct net_conf *nc; @@ -1272,6 +1273,12 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) goto fail; } + new_plan = fifo_alloc((new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ); + if (!new_plan) { + retcode = ERR_NOMEM; + goto fail; + } + if (new_disk_conf->meta_dev_idx < DRBD_MD_INDEX_FLEX_INT) { retcode = ERR_MD_IDX_INVALID; goto fail; @@ -1443,7 +1450,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) else clear_bit(MD_NO_FUA, &mdev->flags); - /* FIXME Missing stuff: rs_plan_s, clip al range */ + /* FIXME Missing stuff: clip al range */ /* Point of no return reached. * Devices and memory are no longer released by error cleanup below. @@ -1452,9 +1459,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) D_ASSERT(mdev->ldev == NULL); mdev->ldev = nbc; mdev->resync = resync_lru; + mdev->rs_plan_s = new_plan; nbc = NULL; resync_lru = NULL; new_disk_conf = NULL; + new_plan = NULL; mdev->write_ordering = WO_bdev_flush; drbd_bump_write_ordering(mdev, WO_bdev_flush); @@ -1615,6 +1624,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) } kfree(new_disk_conf); lc_destroy(resync_lru); + kfree(new_plan); finish: drbd_adm_finish(info, retcode); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index add41764ec54..19b421f44ff7 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3159,7 +3159,7 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi) struct net_conf *old_net_conf, *new_net_conf = NULL; struct disk_conf *old_disk_conf, *new_disk_conf = NULL; const int apv = tconn->agreed_pro_version; - int *rs_plan_s = NULL; + struct fifo_buffer *rs_plan_s = NULL; int fifo_size = 0; int err; @@ -3277,8 +3277,8 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi) 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 && fifo_size > 0) { - rs_plan_s = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL); + if (fifo_size != mdev->rs_plan_s->size) { + rs_plan_s = fifo_alloc(fifo_size); if (!rs_plan_s) { dev_err(DEV, "kmalloc of fifo_buffer failed"); put_ldev(mdev); @@ -3317,10 +3317,8 @@ 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.values); - mdev->rs_plan_s.values = rs_plan_s; - mdev->rs_plan_s.size = fifo_size; - mdev->rs_planed = 0; + kfree(mdev->rs_plan_s); + mdev->rs_plan_s = rs_plan_s; } spin_unlock(&mdev->peer_seq_lock); @@ -3333,6 +3331,7 @@ static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi) return 0; disconnect: + kfree(rs_plan_s); mutex_unlock(&mdev->tconn->conf_update); /* just for completeness: actually not needed, * as this is not reached if csums_tfm was ok. */ diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 4f45f75173ac..131887b7855f 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -434,6 +434,21 @@ static void fifo_add_val(struct fifo_buffer *fb, int value) fb->values[i] += value; } +struct fifo_buffer *fifo_alloc(int fifo_size) +{ + struct fifo_buffer *fb; + + fb = kzalloc(sizeof(struct fifo_buffer) + sizeof(int) * fifo_size, GFP_KERNEL); + if (!fb) + return NULL; + + fb->head_index = 0; + fb->size = fifo_size; + fb->total = 0; + + return fb; +} + static int drbd_rs_controller(struct drbd_conf *mdev) { struct disk_conf *dc; @@ -453,7 +468,7 @@ static int drbd_rs_controller(struct drbd_conf *mdev) rcu_read_lock(); dc = rcu_dereference(mdev->ldev->disk_conf); - steps = mdev->rs_plan_s.size; /* (dc->c_plan_ahead * 10 * SLEEP_TIME) / HZ; */ + steps = mdev->rs_plan_s->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; @@ -462,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_planed; + correction = want - mdev->rs_in_flight - mdev->rs_plan_s->total; /* Plan ahead */ cps = correction / steps; - fifo_add_val(&mdev->rs_plan_s, cps); - mdev->rs_planed += cps * steps; + fifo_add_val(mdev->rs_plan_s, cps); + mdev->rs_plan_s->total += cps * steps; /* What we do in this step */ - curr_corr = fifo_push(&mdev->rs_plan_s, 0); - mdev->rs_planed -= curr_corr; + curr_corr = fifo_push(mdev->rs_plan_s, 0); + mdev->rs_plan_s->total -= curr_corr; req_sect = sect_in + curr_corr; if (req_sect < 0) @@ -495,7 +510,7 @@ static int drbd_rs_controller(struct drbd_conf *mdev) 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 */ + if (mdev->rs_plan_s->size) { /* rcu_dereference(mdev->ldev->disk_conf)->c_plan_ahead */ number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9); mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME; } else { @@ -1456,9 +1471,9 @@ void drbd_rs_controller_reset(struct drbd_conf *mdev) atomic_set(&mdev->rs_sect_in, 0); atomic_set(&mdev->rs_sect_ev, 0); mdev->rs_in_flight = 0; - mdev->rs_planed = 0; + mdev->rs_plan_s->total = 0; spin_lock(&mdev->peer_seq_lock); - fifo_set(&mdev->rs_plan_s, 0); + fifo_set(mdev->rs_plan_s, 0); spin_unlock(&mdev->peer_seq_lock); }