Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: mtd_blkdevs: Replace request handler kthread with a workqueue

By replacing a kthread with a workqueue, the code is now a bit clearer.
There's also a slight reduction of code size (numbers apply for x86):
Before:
text data bss dec hex filename
3248 36 0 3284 cd4 drivers/mtd/mtd_blkdevs.o

After:
text data bss dec hex filename
3150 36 0 3186 c72 drivers/mtd/mtd_blkdevs.o

Due to lack of real hardware, tests have been performed on an emulated
environment with mtdswap and mtdblock over nandsim devices.
Some real testing should be done, before merging this patch.

Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

authored by

Ezequiel Garcia and committed by
Artem Bityutskiy
22a8578f 9329c5eb

+18 -33
+15 -32
drivers/mtd/mtd_blkdevs.c
··· 32 32 #include <linux/hdreg.h> 33 33 #include <linux/init.h> 34 34 #include <linux/mutex.h> 35 - #include <linux/kthread.h> 36 35 #include <asm/uaccess.h> 37 36 38 37 #include "mtdcore.h" ··· 120 121 121 122 int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev) 122 123 { 123 - if (kthread_should_stop()) 124 - return 1; 125 - 126 124 return dev->bg_stop; 127 125 } 128 126 EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background); 129 127 130 - static int mtd_blktrans_thread(void *arg) 128 + static void mtd_blktrans_work(struct work_struct *work) 131 129 { 132 - struct mtd_blktrans_dev *dev = arg; 130 + struct mtd_blktrans_dev *dev = 131 + container_of(work, struct mtd_blktrans_dev, work); 133 132 struct mtd_blktrans_ops *tr = dev->tr; 134 133 struct request_queue *rq = dev->rq; 135 134 struct request *req = NULL; ··· 135 138 136 139 spin_lock_irq(rq->queue_lock); 137 140 138 - while (!kthread_should_stop()) { 141 + while (1) { 139 142 int res; 140 143 141 144 dev->bg_stop = false; ··· 153 156 background_done = !dev->bg_stop; 154 157 continue; 155 158 } 156 - set_current_state(TASK_INTERRUPTIBLE); 157 - 158 - if (kthread_should_stop()) 159 - set_current_state(TASK_RUNNING); 160 - 161 - spin_unlock_irq(rq->queue_lock); 162 - schedule(); 163 - spin_lock_irq(rq->queue_lock); 164 - continue; 159 + break; 165 160 } 166 161 167 162 spin_unlock_irq(rq->queue_lock); ··· 174 185 __blk_end_request_all(req, -EIO); 175 186 176 187 spin_unlock_irq(rq->queue_lock); 177 - 178 - return 0; 179 188 } 180 189 181 190 static void mtd_blktrans_request(struct request_queue *rq) ··· 186 199 if (!dev) 187 200 while ((req = blk_fetch_request(rq)) != NULL) 188 201 __blk_end_request_all(req, -ENODEV); 189 - else { 190 - dev->bg_stop = true; 191 - wake_up_process(dev->thread); 192 - } 202 + else 203 + queue_work(dev->wq, &dev->work); 193 204 } 194 205 195 206 static int blktrans_open(struct block_device *bdev, fmode_t mode) ··· 422 437 423 438 gd->queue = new->rq; 424 439 425 - /* Create processing thread */ 426 - /* TODO: workqueue ? */ 427 - new->thread = kthread_run(mtd_blktrans_thread, new, 428 - "%s%d", tr->name, new->mtd->index); 429 - if (IS_ERR(new->thread)) { 430 - ret = PTR_ERR(new->thread); 440 + /* Create processing workqueue */ 441 + new->wq = alloc_workqueue("%s%d", 0, 0, 442 + tr->name, new->mtd->index); 443 + if (!new->wq) 431 444 goto error4; 432 - } 445 + INIT_WORK(&new->work, mtd_blktrans_work); 446 + 433 447 gd->driverfs_dev = &new->mtd->dev; 434 448 435 449 if (new->readonly) ··· 468 484 /* Stop new requests to arrive */ 469 485 del_gendisk(old->disk); 470 486 471 - 472 - /* Stop the thread */ 473 - kthread_stop(old->thread); 487 + /* Stop workqueue. This will perform any pending request. */ 488 + destroy_workqueue(old->wq); 474 489 475 490 /* Kill current requests */ 476 491 spin_lock_irqsave(&old->queue_lock, flags);
+3 -1
include/linux/mtd/blktrans.h
··· 23 23 #include <linux/mutex.h> 24 24 #include <linux/kref.h> 25 25 #include <linux/sysfs.h> 26 + #include <linux/workqueue.h> 26 27 27 28 struct hd_geometry; 28 29 struct mtd_info; ··· 44 43 struct kref ref; 45 44 struct gendisk *disk; 46 45 struct attribute_group *disk_attributes; 47 - struct task_struct *thread; 46 + struct workqueue_struct *wq; 47 + struct work_struct work; 48 48 struct request_queue *rq; 49 49 spinlock_t queue_lock; 50 50 void *priv;