Skip to content

Commit 7fae4e1

Browse files
committed
modify readme to use a greater value of period-us
Signed-off-by: YangKeao <[email protected]>
1 parent be3c233 commit 7fae4e1

File tree

2 files changed

+21
-54
lines changed

2 files changed

+21
-54
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ If your system don't support multiqueue IO (which is the default for linux < 4.1
2727
Then, you can use the client to send commands to the kernel module:
2828

2929
```bash
30-
sudo ./bin/kchaos inject ioem limit --period-us 1000 --quota 15
30+
sudo ./bin/kchaos inject ioem limit --period-us 100000 --quota 1500
3131
```
3232

33-
Then the IOPS of `sda` will be limited to `1000 * 1000 / 1000 * 15 = 15k`, which can be verified by a raw scan through `fio`:
33+
Then the IOPS of `sda` will be limited to `1000 * 1000 / 100000 * 1500 = 15k`, which can be verified by a raw scan through `fio`:
3434

3535
```bash
3636
sudo fio --filename=/dev/sda --direct=1 --rw=randread --bs=4k --ioengine=libaio --iodepth=256 --runtime=120 --numjobs=16 --time_based --group_reporting --name=iops-test-job --eta-newline=1 --readonly
@@ -54,7 +54,8 @@ Jobs: 16 (f=16): [r(16)][10.8%][r=55.5MiB/s,w=0KiB/s][r=14.2k,w=0 IOPS][eta 01m:
5454

5555
#### Warning
5656

57-
Injecting too much delay on the root device could make your system blocked. Please make sure you have some emergency methods to make the system come back.
57+
1. Injecting too much delay on the root device could make your system blocked. Please make sure you have some emergency methods to make the system come back.
58+
2. Small `period-us` in limit injection will cost a lot of cpu time, and may block the io request of other processes (not selected by the filter) on the same block device. It's always suggested to be set greater than `5000`.
5859

5960
### Syscall Injection
6061

driver/ioem.c

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "comp.h"
1717

1818
#define rb_to_rq(rb) rb_entry_safe(rb, struct request, rb_node)
19-
#define rq_rb_first(root) rb_to_rq(rb_first(root))
19+
#define rq_rb_first_cached(root) rb_to_rq(rb_first_cached(root))
2020

2121
static void ioem_error_injection(struct request* rq);
2222

@@ -46,7 +46,7 @@ static void ioem_error_injection(struct request* rq);
4646
* this struct is only allocated per `request_queue`.
4747
*/
4848
struct ioem_data {
49-
struct rb_root root;
49+
struct rb_root_cached root;
5050
spinlock_t lock;
5151

5252
struct hrtimer timer;
@@ -112,8 +112,6 @@ struct irl {
112112
atomic64_t io_counter;
113113
atomic64_t last_expire_time;
114114
struct hrtimer timer;
115-
116-
atomic64_t affected_request_counter;
117115
};
118116

119117
/**
@@ -193,7 +191,7 @@ static struct irl_dispatch_return irl_dispatch(struct ioem_data* data, struct re
193191
read_lock(&irl->lock);
194192

195193
period = atomic64_read(&irl->io_period_us);
196-
if (period == 0 || !ioem_priv(rq)->ioem_limit_should_affect) {
194+
if (period == 0) {
197195
// the irl is not enabled
198196
ret.dispatch = 1;
199197
ret.time_to_send = 0;
@@ -208,9 +206,9 @@ static struct irl_dispatch_return irl_dispatch(struct ioem_data* data, struct re
208206
counter = atomic64_read(&irl->io_counter);
209207
}
210208
if (counter < quota) {
209+
//
211210
ret.dispatch = 1;
212211
ret.time_to_send = 0;
213-
atomic64_dec(&irl->affected_request_counter);
214212
} else {
215213
ret.dispatch = 0;
216214
ret.time_to_send = last_expire_time + period * NSEC_PER_USEC;
@@ -222,36 +220,6 @@ static struct irl_dispatch_return irl_dispatch(struct ioem_data* data, struct re
222220
return ret;
223221
}
224222

225-
/**
226-
* irl_enqueue() - optimize the time_to_send of a request which will enqueue
227-
* @data: The corresponding ioem_data struct
228-
* @rq: The request to be dispatch
229-
*
230-
* This function will read the counter inside irl. If the counter is already
231-
* greater than the quota and the `time_to_send` is earlier than the next
232-
* period, it will set the `time_to_send` of the request to the next period.
233-
*/
234-
static void irl_enqueue(struct ioem_data* data, struct request* rq)
235-
{
236-
u64 next_period, period, counter;
237-
struct irl* irl = data->irl;
238-
239-
period = atomic64_read(&irl->io_period_us);
240-
if (period == 0 || !ioem_priv(rq)->ioem_limit_should_affect) {
241-
return;
242-
}
243-
244-
counter = atomic64_fetch_add(1, &irl->affected_request_counter);
245-
read_lock(&irl->lock);
246-
if (atomic64_read(&irl->io_counter) > irl->io_quota) {
247-
next_period = atomic64_read(&irl->last_expire_time) + atomic64_read(&irl->io_period_us) * NSEC_PER_USEC * (counter / irl->io_quota);
248-
if (ioem_priv(rq)->time_to_send < next_period) {
249-
ioem_priv(rq)->time_to_send = next_period;
250-
};
251-
}
252-
read_unlock(&irl->lock);
253-
}
254-
255223
static void ioem_data_sync_with_injections(struct ioem_data* data);
256224

257225
/**
@@ -264,7 +232,7 @@ static void ioem_data_sync_with_injections(struct ioem_data* data);
264232
*/
265233
static void ioem_erase_head(struct ioem_data *data, struct request *rq)
266234
{
267-
rb_erase(&rq->rb_node, &data->root);
235+
rb_erase_cached(&rq->rb_node, &data->root);
268236
RB_CLEAR_NODE(&rq->rb_node);
269237
INIT_LIST_HEAD(&rq->queuelist);
270238
}
@@ -275,7 +243,7 @@ static void ioem_erase_head(struct ioem_data *data, struct request *rq)
275243
*/
276244
static struct request* ioem_peek_request(struct ioem_data *data)
277245
{
278-
struct request* ioem_rq = rq_rb_first(&data->root);
246+
struct request* ioem_rq = rq_rb_first_cached(&data->root);
279247

280248
return ioem_rq;
281249
}
@@ -299,7 +267,7 @@ static void ioem_data_init(struct ioem_data* data, enum hrtimer_restart (*functi
299267
hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
300268

301269
spin_lock_init(&data->lock);
302-
data->root = RB_ROOT;
270+
data->root = RB_ROOT_CACHED;
303271
data->timer.function = function;
304272
data->next_expires = 0;
305273

@@ -311,30 +279,29 @@ static void ioem_data_init(struct ioem_data* data, enum hrtimer_restart (*functi
311279
* @data: The `ioem_data` strucutre
312280
* @rq: The request
313281
*
314-
* The request will be inserted into the rb tree. Before inserting the request,
315-
* it will also check whether this request will be affected by the irl and
316-
* whether the irl has
282+
* The request will be inserted into the rb tree
317283
*/
318284
static void ioem_enqueue(struct ioem_data *data, struct request *rq)
319285
{
320-
struct rb_node **p = &data->root.rb_node, *parent = NULL;
286+
struct rb_node **p = &data->root.rb_root.rb_node, *parent = NULL;
287+
bool leftmost = true;
321288

322-
irl_enqueue(data, rq);
323-
324289
while (*p) {
325290
struct request* parent_rq;
326291

327292
parent = *p;
328293
parent_rq = rb_entry_safe(parent, struct request, rb_node);
329294

330-
if (ioem_priv(rq)->time_to_send > ioem_priv(parent_rq)->time_to_send)
295+
if (ioem_priv(rq)->time_to_send > ioem_priv(parent_rq)->time_to_send) {
331296
p = &parent->rb_right;
297+
leftmost = false;
298+
}
332299
else
333300
p = &parent->rb_left;
334301
}
335302

336303
rb_link_node(&rq->rb_node, parent, p);
337-
rb_insert_color(&rq->rb_node, &data->root);
304+
rb_insert_color_cached(&rq->rb_node, &data->root, leftmost);
338305
}
339306

340307
/**
@@ -354,7 +321,7 @@ static struct request* ioem_dequeue(struct ioem_data *data)
354321
u64 now, time_to_send;
355322
struct request* rq = NULL;
356323

357-
if (RB_EMPTY_ROOT(&data->root)) {
324+
if (RB_EMPTY_ROOT(&data->root.rb_root)) {
358325
return NULL;
359326
}
360327

@@ -531,8 +498,6 @@ static void ioem_mq_insert_requests(struct blk_mq_hw_ctx * hctx, struct list_hea
531498
ioem_data_sync_with_injections(id);
532499

533500
list_for_each_entry_safe(rq, next, list, queuelist) {
534-
rq = list_first_entry(list, struct request, queuelist);
535-
536501
list_del(&rq->queuelist);
537502

538503
if (at_head) {
@@ -558,7 +523,7 @@ static bool ioem_mq_has_work(struct blk_mq_hw_ctx * hctx)
558523
struct ioem_data *id = hctx->sched_data;
559524
bool has_work = 0;
560525

561-
has_work = !RB_EMPTY_ROOT(&id->root);
526+
has_work = !RB_EMPTY_ROOT(&id->root.rb_root);
562527

563528
return has_work;
564529
}
@@ -988,6 +953,7 @@ int ioem_del(unsigned long id) {
988953
{
989954
list_del(&e->list);
990955
kref_put(&e->refcount, ioem_injection_release);
956+
break;
991957
}
992958
}
993959

0 commit comments

Comments
 (0)