* [PATCH] Various block throttling fixes
@ 2010-09-28 17:10 Vivek Goyal
2010-09-28 17:10 ` [PATCH 1/4] blkio: Do not export throttle files if CONFIG_BLK_DEV_THROTTLING=n Vivek Goyal
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Vivek Goyal @ 2010-09-28 17:10 UTC (permalink / raw)
To: linux-kernel, axboe; +Cc: vgoyal
Hi Jens,
During testing of block device throttling, I found few issues. Here are
the fixes for those issues.
[PATCH 1/4] blkio: Do not export throttle files if CONFIG_BLK_DEV_THROTTLING=n
[PATCH 2/4] blkio: deletion of a cgroup was causes oops
[PATCH 3/4] blkio: Add root group to td->tg_list
[PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change
Overall diff
block/blk-cgroup.c | 121 +++++++++++++++++++++------------------
block/blk-cgroup.h | 21 ++++---
block/blk-throttle.c | 151 ++++++++++++++++++++++++++++++++++++++++++-------
block/cfq-iosched.c | 4 +-
4 files changed, 207 insertions(+), 90 deletions(-)
Thanks
Vivek
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] blkio: Do not export throttle files if CONFIG_BLK_DEV_THROTTLING=n
2010-09-28 17:10 [PATCH] Various block throttling fixes Vivek Goyal
@ 2010-09-28 17:10 ` Vivek Goyal
2010-09-28 17:10 ` [PATCH 2/4] blkio: deletion of a cgroup was causes oops Vivek Goyal
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Vivek Goyal @ 2010-09-28 17:10 UTC (permalink / raw)
To: linux-kernel, axboe; +Cc: vgoyal
Currently throttling related files were visible even if user had disabled
throttling using config options. It was switching off background throttling
of bio but not the cgroup files. This patch fixes it.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
block/blk-cgroup.c | 97 +++++++++++++++++++++++++++-------------------------
1 files changed, 50 insertions(+), 47 deletions(-)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 31a0d4d..1916bc0 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1242,41 +1242,6 @@ struct cftype blkio_files[] = {
.write_u64 = blkiocg_file_write_u64,
},
{
- .name = "throttle.read_bps_device",
- .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
- BLKIO_THROTL_read_bps_device),
- .read_seq_string = blkiocg_file_read,
- .write_string = blkiocg_file_write,
- .max_write_len = 256,
- },
-
- {
- .name = "throttle.write_bps_device",
- .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
- BLKIO_THROTL_write_bps_device),
- .read_seq_string = blkiocg_file_read,
- .write_string = blkiocg_file_write,
- .max_write_len = 256,
- },
-
- {
- .name = "throttle.read_iops_device",
- .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
- BLKIO_THROTL_read_iops_device),
- .read_seq_string = blkiocg_file_read,
- .write_string = blkiocg_file_write,
- .max_write_len = 256,
- },
-
- {
- .name = "throttle.write_iops_device",
- .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
- BLKIO_THROTL_write_iops_device),
- .read_seq_string = blkiocg_file_read,
- .write_string = blkiocg_file_write,
- .max_write_len = 256,
- },
- {
.name = "time",
.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
BLKIO_PROP_time),
@@ -1295,24 +1260,12 @@ struct cftype blkio_files[] = {
.read_map = blkiocg_file_read_map,
},
{
- .name = "throttle.io_service_bytes",
- .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
- BLKIO_THROTL_io_service_bytes),
- .read_map = blkiocg_file_read_map,
- },
- {
.name = "io_serviced",
.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
BLKIO_PROP_io_serviced),
.read_map = blkiocg_file_read_map,
},
{
- .name = "throttle.io_serviced",
- .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
- BLKIO_THROTL_io_serviced),
- .read_map = blkiocg_file_read_map,
- },
- {
.name = "io_service_time",
.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
BLKIO_PROP_io_service_time),
@@ -1340,6 +1293,56 @@ struct cftype blkio_files[] = {
.name = "reset_stats",
.write_u64 = blkiocg_reset_stats,
},
+#ifdef CONFIG_BLK_DEV_THROTTLING
+ {
+ .name = "throttle.read_bps_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_read_bps_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+
+ {
+ .name = "throttle.write_bps_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_write_bps_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+
+ {
+ .name = "throttle.read_iops_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_read_iops_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+
+ {
+ .name = "throttle.write_iops_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_write_iops_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+ {
+ .name = "throttle.io_service_bytes",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_io_service_bytes),
+ .read_map = blkiocg_file_read_map,
+ },
+ {
+ .name = "throttle.io_serviced",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_io_serviced),
+ .read_map = blkiocg_file_read_map,
+ },
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
#ifdef CONFIG_DEBUG_BLK_CGROUP
{
.name = "avg_queue_size",
--
1.7.2.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] blkio: deletion of a cgroup was causes oops
2010-09-28 17:10 [PATCH] Various block throttling fixes Vivek Goyal
2010-09-28 17:10 ` [PATCH 1/4] blkio: Do not export throttle files if CONFIG_BLK_DEV_THROTTLING=n Vivek Goyal
@ 2010-09-28 17:10 ` Vivek Goyal
2010-09-28 17:10 ` [PATCH 3/4] blkio: Add root group to td->tg_list Vivek Goyal
2010-09-28 17:10 ` [PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change Vivek Goyal
3 siblings, 0 replies; 7+ messages in thread
From: Vivek Goyal @ 2010-09-28 17:10 UTC (permalink / raw)
To: linux-kernel, axboe; +Cc: vgoyal
o Now a cgroup list of blkg elements can contain blkg from multiple policies.
Before sending an unlink event, make sure blkg belongs to they policy. If
policy does not own the blkg, do not send update for this blkg.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
block/blk-cgroup.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 1916bc0..357f472 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1411,13 +1411,14 @@ static void blkiocg_destroy(struct cgroup_subsys *subsys, struct cgroup *cgroup)
/*
* This blkio_group is being unlinked as associated cgroup is
* going away. Let all the IO controlling policies know about
- * this event. Currently this is static call to one io
- * controlling policy. Once we have more policies in place, we
- * need some dynamic registration of callback function.
+ * this event.
*/
spin_lock(&blkio_list_lock);
- list_for_each_entry(blkiop, &blkio_list, list)
+ list_for_each_entry(blkiop, &blkio_list, list) {
+ if (blkiop->plid != blkg->plid)
+ continue;
blkiop->ops.blkio_unlink_group_fn(key, blkg);
+ }
spin_unlock(&blkio_list_lock);
} while (1);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] blkio: Add root group to td->tg_list
2010-09-28 17:10 [PATCH] Various block throttling fixes Vivek Goyal
2010-09-28 17:10 ` [PATCH 1/4] blkio: Do not export throttle files if CONFIG_BLK_DEV_THROTTLING=n Vivek Goyal
2010-09-28 17:10 ` [PATCH 2/4] blkio: deletion of a cgroup was causes oops Vivek Goyal
@ 2010-09-28 17:10 ` Vivek Goyal
2010-09-28 17:10 ` [PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change Vivek Goyal
3 siblings, 0 replies; 7+ messages in thread
From: Vivek Goyal @ 2010-09-28 17:10 UTC (permalink / raw)
To: linux-kernel, axboe; +Cc: vgoyal
o Currently all the dynamically allocated groups, except root grp is added
to td->tg_list. This was not a problem so far but in next patch I will
travel through td->tg_list to process any updates of limits on the group.
If root group is not in tg_list, then root group's updates are not
processed.
o It is better to root group also to tg_list instead of doing special
processing for it during limit updates.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
block/blk-throttle.c | 17 +++++++++++++----
1 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index af53f37..bc2936b 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -87,7 +87,7 @@ struct throtl_data
unsigned int nr_queued[2];
/*
- * number of total undestroyed groups (excluding root group)
+ * number of total undestroyed groups
*/
unsigned int nr_undestroyed_grps;
@@ -940,7 +940,17 @@ int blk_throtl_init(struct request_queue *q)
/* Practically unlimited BW */
tg->bps[0] = tg->bps[1] = -1;
tg->iops[0] = tg->iops[1] = -1;
- atomic_set(&tg->ref, 1);
+
+ /*
+ * Set root group reference to 2. One reference will be dropped when
+ * all groups on tg_list are being deleted during queue exit. Other
+ * reference will remain there as we don't want to delete this group
+ * as it is statically allocated and gets destroyed when throtl_data
+ * goes away.
+ */
+ atomic_set(&tg->ref, 2);
+ hlist_add_head(&tg->tg_node, &td->tg_list);
+ td->nr_undestroyed_grps++;
INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work);
@@ -966,10 +976,9 @@ void blk_throtl_exit(struct request_queue *q)
spin_lock_irq(q->queue_lock);
throtl_release_tgs(td);
- blkiocg_del_blkio_group(&td->root_tg.blkg);
/* If there are other groups */
- if (td->nr_undestroyed_grps >= 1)
+ if (td->nr_undestroyed_grps > 0)
wait = true;
spin_unlock_irq(q->queue_lock);
--
1.7.2.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change
2010-09-28 17:10 [PATCH] Various block throttling fixes Vivek Goyal
` (2 preceding siblings ...)
2010-09-28 17:10 ` [PATCH 3/4] blkio: Add root group to td->tg_list Vivek Goyal
@ 2010-09-28 17:10 ` Vivek Goyal
2010-09-28 17:16 ` Randy Dunlap
3 siblings, 1 reply; 7+ messages in thread
From: Vivek Goyal @ 2010-09-28 17:10 UTC (permalink / raw)
To: linux-kernel, axboe; +Cc: vgoyal
o Currently any cgroup throttle limit changes are processed asynchronousy and
the change does not take affect till a new bio is dispatched from same group.
o It might happen that a user sets a redicuously low limit on throttling.
Say 1 bytes per second on reads. In such cases simple operations like mount
a disk can wait for a very long time.
o Once bio is throttled, there is no easy way to come out of that wait even if
user increases the read limit later.
o This patch fixes it. Now if a user changes the cgroup limits, we recalculate
the bio dispatch time according to new limits.
o Can't take queueu lock under blkcg_lock, hence after the change I wake
up the dispatch thread again which recalculates the time. So there are some
variables being synchronized across two threads without lock and I had to
make use of barriers. Hoping I have used barriers correctly. Any review of
memory barrier code especially will help.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
block/blk-cgroup.c | 15 ++++--
block/blk-cgroup.h | 21 ++++----
block/blk-throttle.c | 134 +++++++++++++++++++++++++++++++++++++++++++-------
block/cfq-iosched.c | 4 +-
4 files changed, 139 insertions(+), 35 deletions(-)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 357f472..e863418 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -124,7 +124,8 @@ blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
if (blkiop->plid != blkg->plid)
continue;
if (blkiop->ops.blkio_update_group_weight_fn)
- blkiop->ops.blkio_update_group_weight_fn(blkg, weight);
+ blkiop->ops.blkio_update_group_weight_fn(blkg->key,
+ blkg, weight);
}
}
@@ -141,11 +142,13 @@ static inline void blkio_update_group_bps(struct blkio_group *blkg, u64 bps,
if (fileid == BLKIO_THROTL_read_bps_device
&& blkiop->ops.blkio_update_group_read_bps_fn)
- blkiop->ops.blkio_update_group_read_bps_fn(blkg, bps);
+ blkiop->ops.blkio_update_group_read_bps_fn(blkg->key,
+ blkg, bps);
if (fileid == BLKIO_THROTL_write_bps_device
&& blkiop->ops.blkio_update_group_write_bps_fn)
- blkiop->ops.blkio_update_group_write_bps_fn(blkg, bps);
+ blkiop->ops.blkio_update_group_write_bps_fn(blkg->key,
+ blkg, bps);
}
}
@@ -162,11 +165,13 @@ static inline void blkio_update_group_iops(struct blkio_group *blkg,
if (fileid == BLKIO_THROTL_read_iops_device
&& blkiop->ops.blkio_update_group_read_iops_fn)
- blkiop->ops.blkio_update_group_read_iops_fn(blkg, iops);
+ blkiop->ops.blkio_update_group_read_iops_fn(blkg->key,
+ blkg, iops);
if (fileid == BLKIO_THROTL_write_iops_device
&& blkiop->ops.blkio_update_group_write_iops_fn)
- blkiop->ops.blkio_update_group_write_iops_fn(blkg,iops);
+ blkiop->ops.blkio_update_group_write_iops_fn(blkg->key,
+ blkg,iops);
}
}
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 2070053..034c355 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -186,16 +186,17 @@ extern unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg,
dev_t dev);
typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg);
-typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg,
- unsigned int weight);
-typedef void (blkio_update_group_read_bps_fn) (struct blkio_group *blkg,
- u64 read_bps);
-typedef void (blkio_update_group_write_bps_fn) (struct blkio_group *blkg,
- u64 write_bps);
-typedef void (blkio_update_group_read_iops_fn) (struct blkio_group *blkg,
- unsigned int read_iops);
-typedef void (blkio_update_group_write_iops_fn) (struct blkio_group *blkg,
- unsigned int write_iops);
+
+typedef void (blkio_update_group_weight_fn) (void *key,
+ struct blkio_group *blkg, unsigned int weight);
+typedef void (blkio_update_group_read_bps_fn) (void * key,
+ struct blkio_group *blkg, u64 read_bps);
+typedef void (blkio_update_group_write_bps_fn) (void *key,
+ struct blkio_group *blkg, u64 write_bps);
+typedef void (blkio_update_group_read_iops_fn) (void *key,
+ struct blkio_group *blkg, unsigned int read_iops);
+typedef void (blkio_update_group_write_iops_fn) (void *key,
+ struct blkio_group *blkg, unsigned int write_iops);
struct blkio_policy_ops {
blkio_unlink_group_fn *blkio_unlink_group_fn;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index bc2936b..11713ed 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -70,6 +70,9 @@ struct throtl_grp {
/* When did we start a new slice */
unsigned long slice_start[2];
unsigned long slice_end[2];
+
+ /* Some throttle limits got updated for the group */
+ bool limits_changed;
};
struct throtl_data
@@ -93,6 +96,8 @@ struct throtl_data
/* Work for dispatching throttled bios */
struct delayed_work throtl_work;
+
+ atomic_t limits_changed;
};
enum tg_state_flags {
@@ -592,15 +597,6 @@ static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg)
min_wait = min(read_wait, write_wait);
disptime = jiffies + min_wait;
- /*
- * If group is already on active tree, then update dispatch time
- * only if it is lesser than existing dispatch time. Otherwise
- * always update the dispatch time
- */
-
- if (throtl_tg_on_rr(tg) && time_before(disptime, tg->disptime))
- return;
-
/* Update dispatch time */
throtl_dequeue_tg(td, tg);
tg->disptime = disptime;
@@ -691,6 +687,46 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl)
return nr_disp;
}
+static void throtl_process_limit_change(struct throtl_data *td)
+{
+ struct throtl_grp *tg;
+ struct hlist_node *pos, *n;
+
+ /*
+ * Make sure atomic_inc() effects from
+ * throtl_update_blkio_group_read_bps(), group of functions are
+ * visible.
+ * Is this required or smp_mb__after_atomic_inc() was suffcient
+ * after the atomic_inc().
+ */
+ smp_rmb();
+ if (!atomic_read(&td->limits_changed))
+ return;
+
+ throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
+
+ hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
+ /*
+ * Do I need an smp_rmb() here to make sure tg->limits_changed
+ * update is visible. I am relying on smp_rmb() at the
+ * beginning of function and not putting a new one here.
+ */
+
+ if (throtl_tg_on_rr(tg) && tg->limits_changed) {
+ throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
+ " riops=%u wiops=%u", tg->bps[READ],
+ tg->bps[WRITE], tg->iops[READ],
+ tg->iops[WRITE]);
+ tg_update_disptime(td, tg);
+ tg->limits_changed = false;
+ }
+ }
+
+ smp_mb__before_atomic_dec();
+ atomic_dec(&td->limits_changed);
+ smp_mb__after_atomic_dec();
+}
+
/* Dispatch throttled bios. Should be called without queue lock held. */
static int throtl_dispatch(struct request_queue *q)
{
@@ -701,6 +737,8 @@ static int throtl_dispatch(struct request_queue *q)
spin_lock_irq(q->queue_lock);
+ throtl_process_limit_change(td);
+
if (!total_nr_queued(td))
goto out;
@@ -821,28 +859,74 @@ void throtl_unlink_blkio_group(void *key, struct blkio_group *blkg)
spin_unlock_irqrestore(td->queue->queue_lock, flags);
}
-static void throtl_update_blkio_group_read_bps (struct blkio_group *blkg,
- u64 read_bps)
+/*
+ * For all update functions, key should be a valid pointer because these
+ * update functions are called under blkcg_lock, that means, blkg is
+ * valid and in turn key is valid. queue exit path can not race becuase
+ * of blkcg_lock
+ *
+ * Can not take queue lock in update functions as queue lock under blkcg_lock
+ * is not allowed. Under other paths we take blkcg_lock under queue_lock.
+ */
+static void throtl_update_blkio_group_read_bps(void *key,
+ struct blkio_group *blkg, u64 read_bps)
{
+ struct throtl_data *td = key;
+
tg_of_blkg(blkg)->bps[READ] = read_bps;
+ /* Make sure read_bps is updated before setting limits_changed */
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+
+ /* Make sure tg->limits_changed is updated before td->limits_changed */
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+
+ /* Schedule a work now to process the limit change */
+ throtl_schedule_delayed_work(td->queue, 0);
}
-static void throtl_update_blkio_group_write_bps (struct blkio_group *blkg,
- u64 write_bps)
+static void throtl_update_blkio_group_write_bps(void *key,
+ struct blkio_group *blkg, u64 write_bps)
{
+ struct throtl_data *td = key;
+
tg_of_blkg(blkg)->bps[WRITE] = write_bps;
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+ throtl_schedule_delayed_work(td->queue, 0);
}
-static void throtl_update_blkio_group_read_iops (struct blkio_group *blkg,
- unsigned int read_iops)
+static void throtl_update_blkio_group_read_iops(void *key,
+ struct blkio_group *blkg, unsigned int read_iops)
{
+ struct throtl_data *td = key;
+
tg_of_blkg(blkg)->iops[READ] = read_iops;
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+ throtl_schedule_delayed_work(td->queue, 0);
}
-static void throtl_update_blkio_group_write_iops (struct blkio_group *blkg,
- unsigned int write_iops)
+static void throtl_update_blkio_group_write_iops(void *key,
+ struct blkio_group *blkg, unsigned int write_iops)
{
+ struct throtl_data *td = key;
+
tg_of_blkg(blkg)->iops[WRITE] = write_iops;
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+ throtl_schedule_delayed_work(td->queue, 0);
}
void throtl_shutdown_timer_wq(struct request_queue *q)
@@ -886,8 +970,14 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop)
/*
* There is already another bio queued in same dir. No
* need to update dispatch time.
+ * Still update the disptime if rate limits on this group
+ * were changed.
*/
- update_disptime = false;
+ if (!tg->limits_changed)
+ update_disptime = false;
+ else
+ tg->limits_changed = false;
+
goto queue_bio;
}
@@ -929,6 +1019,7 @@ int blk_throtl_init(struct request_queue *q)
INIT_HLIST_HEAD(&td->tg_list);
td->tg_service_tree = THROTL_RB_ROOT;
+ atomic_set(&td->limits_changed, 0);
/* Init root group */
tg = &td->root_tg;
@@ -996,6 +1087,13 @@ void blk_throtl_exit(struct request_queue *q)
*/
if (wait)
synchronize_rcu();
+
+ /*
+ * Just being safe to make sure after previous flush if some body did
+ * update limits through cgroup and another work got queued, cancel
+ * it.
+ */
+ throtl_shutdown_timer_wq(q);
throtl_td_free(td);
}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 6db8884..ee9cd3a 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -976,8 +976,8 @@ static inline struct cfq_group *cfqg_of_blkg(struct blkio_group *blkg)
return NULL;
}
-void
-cfq_update_blkio_group_weight(struct blkio_group *blkg, unsigned int weight)
+void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
+ unsigned int weight)
{
cfqg_of_blkg(blkg)->weight = weight;
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change
2010-09-28 17:10 ` [PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change Vivek Goyal
@ 2010-09-28 17:16 ` Randy Dunlap
2010-09-28 17:36 ` Vivek Goyal
0 siblings, 1 reply; 7+ messages in thread
From: Randy Dunlap @ 2010-09-28 17:16 UTC (permalink / raw)
To: Vivek Goyal; +Cc: linux-kernel, axboe
On Tue, 28 Sep 2010 13:10:59 -0400 Vivek Goyal wrote:
> o Currently any cgroup throttle limit changes are processed asynchronousy and
> the change does not take affect till a new bio is dispatched from same group.
>
> o It might happen that a user sets a redicuously low limit on throttling.
> Say 1 bytes per second on reads. In such cases simple operations like mount
> a disk can wait for a very long time.
>
> o Once bio is throttled, there is no easy way to come out of that wait even if
> user increases the read limit later.
>
> o This patch fixes it. Now if a user changes the cgroup limits, we recalculate
> the bio dispatch time according to new limits.
>
> o Can't take queueu lock under blkcg_lock, hence after the change I wake
> up the dispatch thread again which recalculates the time. So there are some
> variables being synchronized across two threads without lock and I had to
> make use of barriers. Hoping I have used barriers correctly. Any review of
> memory barrier code especially will help.
Hi,
Has this report been addressed/fixed?
on i386:
blk-throttle.c:(.text+0x1abb8): undefined reference to `__udivdi3'
blk-throttle.c:(.text+0x1b1dc): undefined reference to `__udivdi3'
on linux-next 2010-0924 and 2010-0927.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change
2010-09-28 17:16 ` Randy Dunlap
@ 2010-09-28 17:36 ` Vivek Goyal
0 siblings, 0 replies; 7+ messages in thread
From: Vivek Goyal @ 2010-09-28 17:36 UTC (permalink / raw)
To: Randy Dunlap; +Cc: linux-kernel, axboe
On Tue, Sep 28, 2010 at 10:16:41AM -0700, Randy Dunlap wrote:
> On Tue, 28 Sep 2010 13:10:59 -0400 Vivek Goyal wrote:
>
> > o Currently any cgroup throttle limit changes are processed asynchronousy and
> > the change does not take affect till a new bio is dispatched from same group.
> >
> > o It might happen that a user sets a redicuously low limit on throttling.
> > Say 1 bytes per second on reads. In such cases simple operations like mount
> > a disk can wait for a very long time.
> >
> > o Once bio is throttled, there is no easy way to come out of that wait even if
> > user increases the read limit later.
> >
> > o This patch fixes it. Now if a user changes the cgroup limits, we recalculate
> > the bio dispatch time according to new limits.
> >
> > o Can't take queueu lock under blkcg_lock, hence after the change I wake
> > up the dispatch thread again which recalculates the time. So there are some
> > variables being synchronized across two threads without lock and I had to
> > make use of barriers. Hoping I have used barriers correctly. Any review of
> > memory barrier code especially will help.
>
>
> Hi,
> Has this report been addressed/fixed?
>
Hi Randy,
No. I was not aware of it. Thanks for bringing it to my notice. I will look
into it.
Vivek
>
> on i386:
>
> blk-throttle.c:(.text+0x1abb8): undefined reference to `__udivdi3'
> blk-throttle.c:(.text+0x1b1dc): undefined reference to `__udivdi3'
>
>
> on linux-next 2010-0924 and 2010-0927.
>
> ---
> ~Randy
> *** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2010-09-28 17:36 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-28 17:10 [PATCH] Various block throttling fixes Vivek Goyal
2010-09-28 17:10 ` [PATCH 1/4] blkio: Do not export throttle files if CONFIG_BLK_DEV_THROTTLING=n Vivek Goyal
2010-09-28 17:10 ` [PATCH 2/4] blkio: deletion of a cgroup was causes oops Vivek Goyal
2010-09-28 17:10 ` [PATCH 3/4] blkio: Add root group to td->tg_list Vivek Goyal
2010-09-28 17:10 ` [PATCH 4/4] blkio: Recalculate the throttled bio dispatch time upon throttle limit change Vivek Goyal
2010-09-28 17:16 ` Randy Dunlap
2010-09-28 17:36 ` Vivek Goyal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox