aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/loop.c79
-rw-r--r--drivers/block/loop.h10
2 files changed, 28 insertions, 61 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index eee751032cad..1875aadb31b0 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -688,6 +688,23 @@ static void loop_config_discard(struct loop_device *lo)
688 queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); 688 queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
689} 689}
690 690
691static void loop_unprepare_queue(struct loop_device *lo)
692{
693 flush_kthread_worker(&lo->worker);
694 kthread_stop(lo->worker_task);
695}
696
697static 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
691static int loop_set_fd(struct loop_device *lo, fmode_t mode, 708static int loop_set_fd(struct loop_device *lo, fmode_t mode,
692 struct block_device *bdev, unsigned int arg) 709 struct block_device *bdev, unsigned int arg)
693{ 710{
@@ -745,11 +762,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
745 size = get_loop_size(lo, file); 762 size = get_loop_size(lo, file);
746 if ((loff_t)(sector_t)size != size) 763 if ((loff_t)(sector_t)size != size)
747 goto out_putf; 764 goto out_putf;
748 error = -ENOMEM; 765 error = loop_prepare_queue(lo);
749 lo->wq = alloc_workqueue("kloopd%d", 766 if (error)
750 WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 16,
751 lo->lo_number);
752 if (!lo->wq)
753 goto out_putf; 767 goto out_putf;
754 768
755 error = 0; 769 error = 0;
@@ -903,8 +917,7 @@ static int loop_clr_fd(struct loop_device *lo)
903 lo->lo_flags = 0; 917 lo->lo_flags = 0;
904 if (!part_shift) 918 if (!part_shift)
905 lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN; 919 lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
906 destroy_workqueue(lo->wq); 920 loop_unprepare_queue(lo);
907 lo->wq = NULL;
908 mutex_unlock(&lo->lo_ctl_mutex); 921 mutex_unlock(&lo->lo_ctl_mutex);
909 /* 922 /*
910 * Need not hold lo_ctl_mutex to fput backing file. 923 * 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,
1461 if (lo->lo_state != Lo_bound) 1474 if (lo->lo_state != Lo_bound)
1462 return -EIO; 1475 return -EIO;
1463 1476
1464 if (cmd->rq->cmd_flags & REQ_WRITE) { 1477 queue_kthread_work(&lo->worker, &cmd->work);
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 }
1481 1478
1482 return BLK_MQ_RQ_QUEUE_OK; 1479 return BLK_MQ_RQ_QUEUE_OK;
1483} 1480}
@@ -1499,35 +1496,10 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
1499 blk_mq_complete_request(cmd->rq); 1496 blk_mq_complete_request(cmd->rq);
1500} 1497}
1501 1498
1502static void loop_queue_write_work(struct work_struct *work) 1499static void loop_queue_work(struct kthread_work *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
1527static void loop_queue_read_work(struct work_struct *work)
1528{ 1500{
1529 struct loop_cmd *cmd = 1501 struct loop_cmd *cmd =
1530 container_of(work, struct loop_cmd, read_work); 1502 container_of(work, struct loop_cmd, work);
1531 1503
1532 loop_handle_cmd(cmd); 1504 loop_handle_cmd(cmd);
1533} 1505}
@@ -1539,7 +1511,7 @@ static int loop_init_request(void *data, struct request *rq,
1539 struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq); 1511 struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);
1540 1512
1541 cmd->rq = rq; 1513 cmd->rq = rq;
1542 INIT_WORK(&cmd->read_work, loop_queue_read_work); 1514 init_kthread_work(&cmd->work, loop_queue_work);
1543 1515
1544 return 0; 1516 return 0;
1545} 1517}
@@ -1601,9 +1573,6 @@ static int loop_add(struct loop_device **l, int i)
1601 */ 1573 */
1602 queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, lo->lo_queue); 1574 queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, lo->lo_queue);
1603 1575
1604 INIT_LIST_HEAD(&lo->write_cmd_head);
1605 INIT_WORK(&lo->write_work, loop_queue_write_work);
1606
1607 disk = lo->lo_disk = alloc_disk(1 << part_shift); 1576 disk = lo->lo_disk = alloc_disk(1 << part_shift);
1608 if (!disk) 1577 if (!disk)
1609 goto out_free_queue; 1578 goto out_free_queue;
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index 25e8997ed246..b6c7d21a453a 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -14,7 +14,7 @@
14#include <linux/blk-mq.h> 14#include <linux/blk-mq.h>
15#include <linux/spinlock.h> 15#include <linux/spinlock.h>
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/workqueue.h> 17#include <linux/kthread.h>
18#include <uapi/linux/loop.h> 18#include <uapi/linux/loop.h>
19 19
20/* Possible states of device */ 20/* Possible states of device */
@@ -54,12 +54,10 @@ struct loop_device {
54 gfp_t old_gfp_mask; 54 gfp_t old_gfp_mask;
55 55
56 spinlock_t lo_lock; 56 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;
61 int lo_state; 57 int lo_state;
62 struct mutex lo_ctl_mutex; 58 struct mutex lo_ctl_mutex;
59 struct kthread_worker worker;
60 struct task_struct *worker_task;
63 61
64 struct request_queue *lo_queue; 62 struct request_queue *lo_queue;
65 struct blk_mq_tag_set tag_set; 63 struct blk_mq_tag_set tag_set;
@@ -67,7 +65,7 @@ struct loop_device {
67}; 65};
68 66
69struct loop_cmd { 67struct loop_cmd {
70 struct work_struct read_work; 68 struct kthread_work work;
71 struct request *rq; 69 struct request *rq;
72 struct list_head list; 70 struct list_head list;
73}; 71};