• Home
  • Raw
  • Download

Lines Matching +full:background +full:- +full:layer

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Interface to Linux block layer for MTD 'translation layers'.
5 * Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org>
16 #include <linux/blk-mq.h>
33 dev->disk->private_data = NULL; in blktrans_dev_release()
34 blk_cleanup_queue(dev->rq); in blktrans_dev_release()
35 blk_mq_free_tag_set(dev->tag_set); in blktrans_dev_release()
36 kfree(dev->tag_set); in blktrans_dev_release()
37 put_disk(dev->disk); in blktrans_dev_release()
38 list_del(&dev->list); in blktrans_dev_release()
47 dev = disk->private_data; in blktrans_dev_get()
51 kref_get(&dev->ref); in blktrans_dev_get()
60 kref_put(&dev->ref, blktrans_dev_release); in blktrans_dev_put()
72 block = blk_rq_pos(req) << 9 >> tr->blkshift; in do_blktrans_request()
73 nsect = blk_rq_cur_bytes(req) >> tr->blkshift; in do_blktrans_request()
76 if (tr->flush(dev)) in do_blktrans_request()
82 get_capacity(req->rq_disk)) in do_blktrans_request()
87 if (tr->discard(dev, block, nsect)) in do_blktrans_request()
91 buf = kmap(bio_page(req->bio)) + bio_offset(req->bio); in do_blktrans_request()
92 for (; nsect > 0; nsect--, block++, buf += tr->blksize) { in do_blktrans_request()
93 if (tr->readsect(dev, block, buf)) { in do_blktrans_request()
94 kunmap(bio_page(req->bio)); in do_blktrans_request()
98 kunmap(bio_page(req->bio)); in do_blktrans_request()
102 if (!tr->writesect) in do_blktrans_request()
106 buf = kmap(bio_page(req->bio)) + bio_offset(req->bio); in do_blktrans_request()
107 for (; nsect > 0; nsect--, block++, buf += tr->blksize) { in do_blktrans_request()
108 if (tr->writesect(dev, block, buf)) { in do_blktrans_request()
109 kunmap(bio_page(req->bio)); in do_blktrans_request()
113 kunmap(bio_page(req->bio)); in do_blktrans_request()
122 return dev->bg_stop; in mtd_blktrans_cease_background()
130 rq = list_first_entry_or_null(&dev->rq_list, struct request, queuelist); in mtd_next_request()
132 list_del_init(&rq->queuelist); in mtd_next_request()
141 __releases(&dev->queue_lock) in mtd_blktrans_work()
142 __acquires(&dev->queue_lock) in mtd_blktrans_work()
144 struct mtd_blktrans_ops *tr = dev->tr; in mtd_blktrans_work()
151 dev->bg_stop = false; in mtd_blktrans_work()
153 if (tr->background && !background_done) { in mtd_blktrans_work()
154 spin_unlock_irq(&dev->queue_lock); in mtd_blktrans_work()
155 mutex_lock(&dev->lock); in mtd_blktrans_work()
156 tr->background(dev); in mtd_blktrans_work()
157 mutex_unlock(&dev->lock); in mtd_blktrans_work()
158 spin_lock_irq(&dev->queue_lock); in mtd_blktrans_work()
160 * Do background processing just once per idle in mtd_blktrans_work()
163 background_done = !dev->bg_stop; in mtd_blktrans_work()
169 spin_unlock_irq(&dev->queue_lock); in mtd_blktrans_work()
171 mutex_lock(&dev->lock); in mtd_blktrans_work()
172 res = do_blktrans_request(dev->tr, dev, req); in mtd_blktrans_work()
173 mutex_unlock(&dev->lock); in mtd_blktrans_work()
181 spin_lock_irq(&dev->queue_lock); in mtd_blktrans_work()
190 dev = hctx->queue->queuedata; in mtd_queue_rq()
192 blk_mq_start_request(bd->rq); in mtd_queue_rq()
196 spin_lock_irq(&dev->queue_lock); in mtd_queue_rq()
197 list_add_tail(&bd->rq->queuelist, &dev->rq_list); in mtd_queue_rq()
199 spin_unlock_irq(&dev->queue_lock); in mtd_queue_rq()
206 struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); in blktrans_open()
210 return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ in blktrans_open()
213 mutex_lock(&dev->lock); in blktrans_open()
215 if (dev->open) in blktrans_open()
218 kref_get(&dev->ref); in blktrans_open()
219 __module_get(dev->tr->owner); in blktrans_open()
221 if (!dev->mtd) in blktrans_open()
224 if (dev->tr->open) { in blktrans_open()
225 ret = dev->tr->open(dev); in blktrans_open()
230 ret = __get_mtd_device(dev->mtd); in blktrans_open()
233 dev->file_mode = mode; in blktrans_open()
236 dev->open++; in blktrans_open()
237 mutex_unlock(&dev->lock); in blktrans_open()
243 if (dev->tr->release) in blktrans_open()
244 dev->tr->release(dev); in blktrans_open()
246 module_put(dev->tr->owner); in blktrans_open()
247 kref_put(&dev->ref, blktrans_dev_release); in blktrans_open()
248 mutex_unlock(&dev->lock); in blktrans_open()
262 mutex_lock(&dev->lock); in blktrans_release()
264 if (--dev->open) in blktrans_release()
267 kref_put(&dev->ref, blktrans_dev_release); in blktrans_release()
268 module_put(dev->tr->owner); in blktrans_release()
270 if (dev->mtd) { in blktrans_release()
271 if (dev->tr->release) in blktrans_release()
272 dev->tr->release(dev); in blktrans_release()
273 __put_mtd_device(dev->mtd); in blktrans_release()
276 mutex_unlock(&dev->lock); in blktrans_release()
283 struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); in blktrans_getgeo()
284 int ret = -ENXIO; in blktrans_getgeo()
289 mutex_lock(&dev->lock); in blktrans_getgeo()
291 if (!dev->mtd) in blktrans_getgeo()
294 ret = dev->tr->getgeo ? dev->tr->getgeo(dev, geo) : -ENOTTY; in blktrans_getgeo()
296 mutex_unlock(&dev->lock); in blktrans_getgeo()
304 struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); in blktrans_ioctl()
305 int ret = -ENXIO; in blktrans_ioctl()
310 mutex_lock(&dev->lock); in blktrans_ioctl()
312 if (!dev->mtd) in blktrans_ioctl()
317 ret = dev->tr->flush ? dev->tr->flush(dev) : 0; in blktrans_ioctl()
320 ret = -ENOTTY; in blktrans_ioctl()
323 mutex_unlock(&dev->lock); in blktrans_ioctl()
342 struct mtd_blktrans_ops *tr = new->tr; in add_mtd_blktrans_dev()
344 int last_devnum = -1; in add_mtd_blktrans_dev()
351 list_for_each_entry(d, &tr->devs, list) { in add_mtd_blktrans_dev()
352 if (new->devnum == -1) { in add_mtd_blktrans_dev()
354 if (d->devnum != last_devnum+1) { in add_mtd_blktrans_dev()
356 new->devnum = last_devnum+1; in add_mtd_blktrans_dev()
357 list_add_tail(&new->list, &d->list); in add_mtd_blktrans_dev()
360 } else if (d->devnum == new->devnum) { in add_mtd_blktrans_dev()
363 return -EBUSY; in add_mtd_blktrans_dev()
364 } else if (d->devnum > new->devnum) { in add_mtd_blktrans_dev()
366 list_add_tail(&new->list, &d->list); in add_mtd_blktrans_dev()
369 last_devnum = d->devnum; in add_mtd_blktrans_dev()
372 ret = -EBUSY; in add_mtd_blktrans_dev()
373 if (new->devnum == -1) in add_mtd_blktrans_dev()
374 new->devnum = last_devnum+1; in add_mtd_blktrans_dev()
379 if (new->devnum > (MINORMASK >> tr->part_bits) || in add_mtd_blktrans_dev()
380 (tr->part_bits && new->devnum >= 27 * 26)) { in add_mtd_blktrans_dev()
385 list_add_tail(&new->list, &tr->devs); in add_mtd_blktrans_dev()
389 mutex_init(&new->lock); in add_mtd_blktrans_dev()
390 kref_init(&new->ref); in add_mtd_blktrans_dev()
391 if (!tr->writesect) in add_mtd_blktrans_dev()
392 new->readonly = 1; in add_mtd_blktrans_dev()
395 ret = -ENOMEM; in add_mtd_blktrans_dev()
396 gd = alloc_disk(1 << tr->part_bits); in add_mtd_blktrans_dev()
401 new->disk = gd; in add_mtd_blktrans_dev()
402 gd->private_data = new; in add_mtd_blktrans_dev()
403 gd->major = tr->major; in add_mtd_blktrans_dev()
404 gd->first_minor = (new->devnum) << tr->part_bits; in add_mtd_blktrans_dev()
405 gd->fops = &mtd_block_ops; in add_mtd_blktrans_dev()
407 if (tr->part_bits) in add_mtd_blktrans_dev()
408 if (new->devnum < 26) in add_mtd_blktrans_dev()
409 snprintf(gd->disk_name, sizeof(gd->disk_name), in add_mtd_blktrans_dev()
410 "%s%c", tr->name, 'a' + new->devnum); in add_mtd_blktrans_dev()
412 snprintf(gd->disk_name, sizeof(gd->disk_name), in add_mtd_blktrans_dev()
413 "%s%c%c", tr->name, in add_mtd_blktrans_dev()
414 'a' - 1 + new->devnum / 26, in add_mtd_blktrans_dev()
415 'a' + new->devnum % 26); in add_mtd_blktrans_dev()
417 snprintf(gd->disk_name, sizeof(gd->disk_name), in add_mtd_blktrans_dev()
418 "%s%d", tr->name, new->devnum); in add_mtd_blktrans_dev()
420 set_capacity(gd, ((u64)new->size * tr->blksize) >> 9); in add_mtd_blktrans_dev()
423 spin_lock_init(&new->queue_lock); in add_mtd_blktrans_dev()
424 INIT_LIST_HEAD(&new->rq_list); in add_mtd_blktrans_dev()
426 new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL); in add_mtd_blktrans_dev()
427 if (!new->tag_set) in add_mtd_blktrans_dev()
430 new->rq = blk_mq_init_sq_queue(new->tag_set, &mtd_mq_ops, 2, in add_mtd_blktrans_dev()
432 if (IS_ERR(new->rq)) { in add_mtd_blktrans_dev()
433 ret = PTR_ERR(new->rq); in add_mtd_blktrans_dev()
434 new->rq = NULL; in add_mtd_blktrans_dev()
438 if (tr->flush) in add_mtd_blktrans_dev()
439 blk_queue_write_cache(new->rq, true, false); in add_mtd_blktrans_dev()
441 new->rq->queuedata = new; in add_mtd_blktrans_dev()
442 blk_queue_logical_block_size(new->rq, tr->blksize); in add_mtd_blktrans_dev()
444 blk_queue_flag_set(QUEUE_FLAG_NONROT, new->rq); in add_mtd_blktrans_dev()
445 blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, new->rq); in add_mtd_blktrans_dev()
447 if (tr->discard) { in add_mtd_blktrans_dev()
448 blk_queue_flag_set(QUEUE_FLAG_DISCARD, new->rq); in add_mtd_blktrans_dev()
449 blk_queue_max_discard_sectors(new->rq, UINT_MAX); in add_mtd_blktrans_dev()
450 new->rq->limits.discard_granularity = tr->blksize; in add_mtd_blktrans_dev()
453 gd->queue = new->rq; in add_mtd_blktrans_dev()
455 if (new->readonly) in add_mtd_blktrans_dev()
458 device_add_disk(&new->mtd->dev, gd, NULL); in add_mtd_blktrans_dev()
460 if (new->disk_attributes) { in add_mtd_blktrans_dev()
461 ret = sysfs_create_group(&disk_to_dev(gd)->kobj, in add_mtd_blktrans_dev()
462 new->disk_attributes); in add_mtd_blktrans_dev()
467 kfree(new->tag_set); in add_mtd_blktrans_dev()
469 put_disk(new->disk); in add_mtd_blktrans_dev()
471 list_del(&new->list); in add_mtd_blktrans_dev()
481 if (old->disk_attributes) in del_mtd_blktrans_dev()
482 sysfs_remove_group(&disk_to_dev(old->disk)->kobj, in del_mtd_blktrans_dev()
483 old->disk_attributes); in del_mtd_blktrans_dev()
486 del_gendisk(old->disk); in del_mtd_blktrans_dev()
489 spin_lock_irqsave(&old->queue_lock, flags); in del_mtd_blktrans_dev()
490 old->rq->queuedata = NULL; in del_mtd_blktrans_dev()
491 spin_unlock_irqrestore(&old->queue_lock, flags); in del_mtd_blktrans_dev()
494 blk_mq_freeze_queue(old->rq); in del_mtd_blktrans_dev()
495 blk_mq_quiesce_queue(old->rq); in del_mtd_blktrans_dev()
496 blk_mq_unquiesce_queue(old->rq); in del_mtd_blktrans_dev()
497 blk_mq_unfreeze_queue(old->rq); in del_mtd_blktrans_dev()
501 mutex_lock(&old->lock); in del_mtd_blktrans_dev()
502 if (old->open) { in del_mtd_blktrans_dev()
503 if (old->tr->release) in del_mtd_blktrans_dev()
504 old->tr->release(old); in del_mtd_blktrans_dev()
505 __put_mtd_device(old->mtd); in del_mtd_blktrans_dev()
508 old->mtd = NULL; in del_mtd_blktrans_dev()
510 mutex_unlock(&old->lock); in del_mtd_blktrans_dev()
521 list_for_each_entry_safe(dev, next, &tr->devs, list) in blktrans_notify_remove()
522 if (dev->mtd == mtd) in blktrans_notify_remove()
523 tr->remove_dev(dev); in blktrans_notify_remove()
530 if (mtd->type == MTD_ABSENT || mtd->type == MTD_UBIVOLUME) in blktrans_notify_add()
534 tr->add_mtd(tr, mtd); in blktrans_notify_add()
556 ret = register_blkdev(tr->major, tr->name); in register_mtd_blktrans()
559 tr->name, tr->major, ret); in register_mtd_blktrans()
565 tr->major = ret; in register_mtd_blktrans()
567 tr->blkshift = ffs(tr->blksize) - 1; in register_mtd_blktrans()
569 INIT_LIST_HEAD(&tr->devs); in register_mtd_blktrans()
570 list_add(&tr->list, &blktrans_majors); in register_mtd_blktrans()
573 if (mtd->type != MTD_ABSENT && mtd->type != MTD_UBIVOLUME) in register_mtd_blktrans()
574 tr->add_mtd(tr, mtd); in register_mtd_blktrans()
587 list_del(&tr->list); in deregister_mtd_blktrans()
589 list_for_each_entry_safe(dev, next, &tr->devs, list) in deregister_mtd_blktrans()
590 tr->remove_dev(dev); in deregister_mtd_blktrans()
592 unregister_blkdev(tr->major, tr->name); in deregister_mtd_blktrans()
595 BUG_ON(!list_empty(&tr->devs)); in deregister_mtd_blktrans()
601 /* No race here -- if someone's currently in register_mtd_blktrans in mtd_blktrans_exit()
616 MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'");