Skip to content

Commit e03a3d7

Browse files
Ming Leiaxboe
authored andcommitted
block: loop: use kthread_work
The following patch will use dio/aio to submit IO to backing file, then it needn't to schedule IO concurrently from work, so use kthread_work for decreasing context switch cost a lot. For non-AIO case, single thread has been used for long long time, and it was just converted to work in v4.0, which has caused performance regression for fedora live booting already. In discussion[1], even though submitting I/O via work concurrently can improve random read IO throughput, meantime it might hurt sequential read IO performance, so better to restore to single thread behaviour. For the following AIO support, it is better to use multi hw-queue with per-hwq kthread than current work approach suppose there is so high performance requirement for loop. [1] http://marc.info/?t=143082678400002&r=1&w=2 Signed-off-by: Ming Lei <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 5b5e20f commit e03a3d7

File tree

2 files changed

+28
-61
lines changed

2 files changed

+28
-61
lines changed

drivers/block/loop.c

Lines changed: 24 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,23 @@ static void loop_config_discard(struct loop_device *lo)
688688
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
689689
}
690690

691+
static void loop_unprepare_queue(struct loop_device *lo)
692+
{
693+
flush_kthread_worker(&lo->worker);
694+
kthread_stop(lo->worker_task);
695+
}
696+
697+
static int loop_prepare_queue(struct loop_device *lo)
698+
{
699+
init_kthread_worker(&lo->worker);
700+
lo->worker_task = kthread_run(kthread_worker_fn,
701+
&lo->worker, "loop%d", lo->lo_number);
702+
if (IS_ERR(lo->worker_task))
703+
return -ENOMEM;
704+
set_user_nice(lo->worker_task, MIN_NICE);
705+
return 0;
706+
}
707+
691708
static int loop_set_fd(struct loop_device *lo, fmode_t mode,
692709
struct block_device *bdev, unsigned int arg)
693710
{
@@ -745,11 +762,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
745762
size = get_loop_size(lo, file);
746763
if ((loff_t)(sector_t)size != size)
747764
goto out_putf;
748-
error = -ENOMEM;
749-
lo->wq = alloc_workqueue("kloopd%d",
750-
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 16,
751-
lo->lo_number);
752-
if (!lo->wq)
765+
error = loop_prepare_queue(lo);
766+
if (error)
753767
goto out_putf;
754768

755769
error = 0;
@@ -903,8 +917,7 @@ static int loop_clr_fd(struct loop_device *lo)
903917
lo->lo_flags = 0;
904918
if (!part_shift)
905919
lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
906-
destroy_workqueue(lo->wq);
907-
lo->wq = NULL;
920+
loop_unprepare_queue(lo);
908921
mutex_unlock(&lo->lo_ctl_mutex);
909922
/*
910923
* Need not hold lo_ctl_mutex to fput backing file.
@@ -1461,23 +1474,7 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
14611474
if (lo->lo_state != Lo_bound)
14621475
return -EIO;
14631476

1464-
if (cmd->rq->cmd_flags & REQ_WRITE) {
1465-
struct loop_device *lo = cmd->rq->q->queuedata;
1466-
bool need_sched = true;
1467-
1468-
spin_lock_irq(&lo->lo_lock);
1469-
if (lo->write_started)
1470-
need_sched = false;
1471-
else
1472-
lo->write_started = true;
1473-
list_add_tail(&cmd->list, &lo->write_cmd_head);
1474-
spin_unlock_irq(&lo->lo_lock);
1475-
1476-
if (need_sched)
1477-
queue_work(lo->wq, &lo->write_work);
1478-
} else {
1479-
queue_work(lo->wq, &cmd->read_work);
1480-
}
1477+
queue_kthread_work(&lo->worker, &cmd->work);
14811478

14821479
return BLK_MQ_RQ_QUEUE_OK;
14831480
}
@@ -1499,35 +1496,10 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
14991496
blk_mq_complete_request(cmd->rq);
15001497
}
15011498

1502-
static void loop_queue_write_work(struct work_struct *work)
1503-
{
1504-
struct loop_device *lo =
1505-
container_of(work, struct loop_device, write_work);
1506-
LIST_HEAD(cmd_list);
1507-
1508-
spin_lock_irq(&lo->lo_lock);
1509-
repeat:
1510-
list_splice_init(&lo->write_cmd_head, &cmd_list);
1511-
spin_unlock_irq(&lo->lo_lock);
1512-
1513-
while (!list_empty(&cmd_list)) {
1514-
struct loop_cmd *cmd = list_first_entry(&cmd_list,
1515-
struct loop_cmd, list);
1516-
list_del_init(&cmd->list);
1517-
loop_handle_cmd(cmd);
1518-
}
1519-
1520-
spin_lock_irq(&lo->lo_lock);
1521-
if (!list_empty(&lo->write_cmd_head))
1522-
goto repeat;
1523-
lo->write_started = false;
1524-
spin_unlock_irq(&lo->lo_lock);
1525-
}
1526-
1527-
static void loop_queue_read_work(struct work_struct *work)
1499+
static void loop_queue_work(struct kthread_work *work)
15281500
{
15291501
struct loop_cmd *cmd =
1530-
container_of(work, struct loop_cmd, read_work);
1502+
container_of(work, struct loop_cmd, work);
15311503

15321504
loop_handle_cmd(cmd);
15331505
}
@@ -1539,7 +1511,7 @@ static int loop_init_request(void *data, struct request *rq,
15391511
struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);
15401512

15411513
cmd->rq = rq;
1542-
INIT_WORK(&cmd->read_work, loop_queue_read_work);
1514+
init_kthread_work(&cmd->work, loop_queue_work);
15431515

15441516
return 0;
15451517
}
@@ -1601,9 +1573,6 @@ static int loop_add(struct loop_device **l, int i)
16011573
*/
16021574
queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, lo->lo_queue);
16031575

1604-
INIT_LIST_HEAD(&lo->write_cmd_head);
1605-
INIT_WORK(&lo->write_work, loop_queue_write_work);
1606-
16071576
disk = lo->lo_disk = alloc_disk(1 << part_shift);
16081577
if (!disk)
16091578
goto out_free_queue;

drivers/block/loop.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <linux/blk-mq.h>
1515
#include <linux/spinlock.h>
1616
#include <linux/mutex.h>
17-
#include <linux/workqueue.h>
17+
#include <linux/kthread.h>
1818
#include <uapi/linux/loop.h>
1919

2020
/* Possible states of device */
@@ -54,20 +54,18 @@ struct loop_device {
5454
gfp_t old_gfp_mask;
5555

5656
spinlock_t lo_lock;
57-
struct workqueue_struct *wq;
58-
struct list_head write_cmd_head;
59-
struct work_struct write_work;
60-
bool write_started;
6157
int lo_state;
6258
struct mutex lo_ctl_mutex;
59+
struct kthread_worker worker;
60+
struct task_struct *worker_task;
6361

6462
struct request_queue *lo_queue;
6563
struct blk_mq_tag_set tag_set;
6664
struct gendisk *lo_disk;
6765
};
6866

6967
struct loop_cmd {
70-
struct work_struct read_work;
68+
struct kthread_work work;
7169
struct request *rq;
7270
struct list_head list;
7371
};

0 commit comments

Comments
 (0)