Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78075631 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.dk/linux-block

Pull block layer fixes from Jens Axboe:
 "A set of fixes for the current series.  This contains:

   - A bunch of fixes for lightnvm, should be the last round for this
     series.  From Matias and Wenwei.

   - A writeback detach inode fix from Ilya, also marked for stable.

   - A block (though it says SCSI) fix for an OOPS in SCSI runtime power
     management.

   - Module init error path fixes for null_blk from Minfei"

* 'for-linus' of git://git.kernel.dk/linux-block:
  null_blk: Fix error path in module initialization
  lightnvm: do not compile in debugging by default
  lightnvm: prevent gennvm module unload on use
  lightnvm: fix media mgr registration
  lightnvm: replace req queue with nvmdev for lld
  lightnvm: comments on constants
  lightnvm: check mm before use
  lightnvm: refactor spin_unlock in gennvm_get_blk
  lightnvm: put blks when luns configure failed
  lightnvm: use flags in rrpc_get_blk
  block: detach bdev inode from its wb in __blkdev_put()
  SCSI: Fix NULL pointer dereference in runtime PM
parents 6539756e af096e22
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3405,6 +3405,9 @@ int blk_pre_runtime_suspend(struct request_queue *q)
{
	int ret = 0;

	if (!q->dev)
		return ret;

	spin_lock_irq(q->queue_lock);
	if (q->nr_pending) {
		ret = -EBUSY;
@@ -3432,6 +3435,9 @@ EXPORT_SYMBOL(blk_pre_runtime_suspend);
 */
void blk_post_runtime_suspend(struct request_queue *q, int err)
{
	if (!q->dev)
		return;

	spin_lock_irq(q->queue_lock);
	if (!err) {
		q->rpm_status = RPM_SUSPENDED;
@@ -3456,6 +3462,9 @@ EXPORT_SYMBOL(blk_post_runtime_suspend);
 */
void blk_pre_runtime_resume(struct request_queue *q)
{
	if (!q->dev)
		return;

	spin_lock_irq(q->queue_lock);
	q->rpm_status = RPM_RESUMING;
	spin_unlock_irq(q->queue_lock);
@@ -3478,6 +3487,9 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
 */
void blk_post_runtime_resume(struct request_queue *q, int err)
{
	if (!q->dev)
		return;

	spin_lock_irq(q->queue_lock);
	if (!err) {
		q->rpm_status = RPM_ACTIVE;
+21 −11
Original line number Diff line number Diff line
@@ -444,8 +444,9 @@ static void null_lnvm_end_io(struct request *rq, int error)
	blk_put_request(rq);
}

static int null_lnvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
static int null_lnvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
{
	struct request_queue *q = dev->q;
	struct request *rq;
	struct bio *bio = rqd->bio;

@@ -470,7 +471,7 @@ static int null_lnvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
	return 0;
}

static int null_lnvm_id(struct request_queue *q, struct nvm_id *id)
static int null_lnvm_id(struct nvm_dev *dev, struct nvm_id *id)
{
	sector_t size = gb * 1024 * 1024 * 1024ULL;
	sector_t blksize;
@@ -523,7 +524,7 @@ static int null_lnvm_id(struct request_queue *q, struct nvm_id *id)
	return 0;
}

static void *null_lnvm_create_dma_pool(struct request_queue *q, char *name)
static void *null_lnvm_create_dma_pool(struct nvm_dev *dev, char *name)
{
	mempool_t *virtmem_pool;

@@ -541,7 +542,7 @@ static void null_lnvm_destroy_dma_pool(void *pool)
	mempool_destroy(pool);
}

static void *null_lnvm_dev_dma_alloc(struct request_queue *q, void *pool,
static void *null_lnvm_dev_dma_alloc(struct nvm_dev *dev, void *pool,
				gfp_t mem_flags, dma_addr_t *dma_handler)
{
	return mempool_alloc(pool, mem_flags);
@@ -765,7 +766,9 @@ static int null_add_dev(void)

static int __init null_init(void)
{
	int ret = 0;
	unsigned int i;
	struct nullb *nullb;

	if (bs > PAGE_SIZE) {
		pr_warn("null_blk: invalid block size\n");
@@ -807,22 +810,29 @@ static int __init null_init(void)
								0, 0, NULL);
		if (!ppa_cache) {
			pr_err("null_blk: unable to create ppa cache\n");
			return -ENOMEM;
			ret = -ENOMEM;
			goto err_ppa;
		}
	}

	for (i = 0; i < nr_devices; i++) {
		if (null_add_dev()) {
			unregister_blkdev(null_major, "nullb");
			goto err_ppa;
		}
		ret = null_add_dev();
		if (ret)
			goto err_dev;
	}

	pr_info("null: module loaded\n");
	return 0;
err_ppa:

err_dev:
	while (!list_empty(&nullb_list)) {
		nullb = list_entry(nullb_list.next, struct nullb, list);
		null_del_dev(nullb);
	}
	kmem_cache_destroy(ppa_cache);
	return -EINVAL;
err_ppa:
	unregister_blkdev(null_major, "nullb");
	return ret;
}

static void __exit null_exit(void)
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ if NVM

config NVM_DEBUG
	bool "Open-Channel SSD debugging support"
	default n
	---help---
	Exposes a debug management interface to create/remove targets at:

+42 −43
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(nvm_unregister_target);
void *nvm_dev_dma_alloc(struct nvm_dev *dev, gfp_t mem_flags,
							dma_addr_t *dma_handler)
{
	return dev->ops->dev_dma_alloc(dev->q, dev->ppalist_pool, mem_flags,
	return dev->ops->dev_dma_alloc(dev, dev->ppalist_pool, mem_flags,
								dma_handler);
}
EXPORT_SYMBOL(nvm_dev_dma_alloc);
@@ -97,15 +97,47 @@ static struct nvmm_type *nvm_find_mgr_type(const char *name)
	return NULL;
}

struct nvmm_type *nvm_init_mgr(struct nvm_dev *dev)
{
	struct nvmm_type *mt;
	int ret;

	lockdep_assert_held(&nvm_lock);

	list_for_each_entry(mt, &nvm_mgrs, list) {
		ret = mt->register_mgr(dev);
		if (ret < 0) {
			pr_err("nvm: media mgr failed to init (%d) on dev %s\n",
								ret, dev->name);
			return NULL; /* initialization failed */
		} else if (ret > 0)
			return mt;
	}

	return NULL;
}

int nvm_register_mgr(struct nvmm_type *mt)
{
	struct nvm_dev *dev;
	int ret = 0;

	down_write(&nvm_lock);
	if (nvm_find_mgr_type(mt->name))
	if (nvm_find_mgr_type(mt->name)) {
		ret = -EEXIST;
	else
		goto finish;
	} else {
		list_add(&mt->list, &nvm_mgrs);
	}

	/* try to register media mgr if any device have none configured */
	list_for_each_entry(dev, &nvm_devices, devices) {
		if (dev->mt)
			continue;

		dev->mt = nvm_init_mgr(dev);
	}
finish:
	up_write(&nvm_lock);

	return ret;
@@ -123,26 +155,6 @@ void nvm_unregister_mgr(struct nvmm_type *mt)
}
EXPORT_SYMBOL(nvm_unregister_mgr);

/* register with device with a supported manager */
static int register_mgr(struct nvm_dev *dev)
{
	struct nvmm_type *mt;
	int ret = 0;

	list_for_each_entry(mt, &nvm_mgrs, list) {
		ret = mt->register_mgr(dev);
		if (ret > 0) {
			dev->mt = mt;
			break; /* successfully initialized */
		}
	}

	if (!ret)
		pr_info("nvm: no compatible nvm manager found.\n");

	return ret;
}

static struct nvm_dev *nvm_find_nvm_dev(const char *name)
{
	struct nvm_dev *dev;
@@ -246,7 +258,7 @@ static int nvm_init(struct nvm_dev *dev)
	if (!dev->q || !dev->ops)
		return ret;

	if (dev->ops->identity(dev->q, &dev->identity)) {
	if (dev->ops->identity(dev, &dev->identity)) {
		pr_err("nvm: device could not be identified\n");
		goto err;
	}
@@ -271,14 +283,6 @@ static int nvm_init(struct nvm_dev *dev)
		goto err;
	}

	down_write(&nvm_lock);
	ret = register_mgr(dev);
	up_write(&nvm_lock);
	if (ret < 0)
		goto err;
	if (!ret)
		return 0;

	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
			dev->name, dev->sec_per_pg, dev->nr_planes,
			dev->pgs_per_blk, dev->blks_per_lun, dev->nr_luns,
@@ -326,8 +330,7 @@ int nvm_register(struct request_queue *q, char *disk_name,
	}

	if (dev->ops->max_phys_sect > 1) {
		dev->ppalist_pool = dev->ops->create_dma_pool(dev->q,
								"ppalist");
		dev->ppalist_pool = dev->ops->create_dma_pool(dev, "ppalist");
		if (!dev->ppalist_pool) {
			pr_err("nvm: could not create ppa pool\n");
			ret = -ENOMEM;
@@ -335,7 +338,9 @@ int nvm_register(struct request_queue *q, char *disk_name,
		}
	}

	/* register device with a supported media manager */
	down_write(&nvm_lock);
	dev->mt = nvm_init_mgr(dev);
	list_add(&dev->devices, &nvm_devices);
	up_write(&nvm_lock);

@@ -380,19 +385,13 @@ static int nvm_create_target(struct nvm_dev *dev,
	struct nvm_tgt_type *tt;
	struct nvm_target *t;
	void *targetdata;
	int ret = 0;

	down_write(&nvm_lock);
	if (!dev->mt) {
		ret = register_mgr(dev);
		if (!ret)
			ret = -ENODEV;
		if (ret < 0) {
			up_write(&nvm_lock);
			return ret;
		}
		pr_info("nvm: device has no media manager registered.\n");
		return -ENODEV;
	}

	down_write(&nvm_lock);
	tt = nvm_find_target_type(create->tgttype);
	if (!tt) {
		pr_err("nvm: target type %s not found\n", create->tgttype);
+11 −9
Original line number Diff line number Diff line
@@ -195,7 +195,7 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn)
	}

	if (dev->ops->get_l2p_tbl) {
		ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages,
		ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_pages,
							gennvm_block_map, dev);
		if (ret) {
			pr_err("gennvm: could not read L2P table.\n");
@@ -219,6 +219,9 @@ static int gennvm_register(struct nvm_dev *dev)
	struct gen_nvm *gn;
	int ret;

	if (!try_module_get(THIS_MODULE))
		return -ENODEV;

	gn = kzalloc(sizeof(struct gen_nvm), GFP_KERNEL);
	if (!gn)
		return -ENOMEM;
@@ -242,12 +245,14 @@ static int gennvm_register(struct nvm_dev *dev)
	return 1;
err:
	gennvm_free(dev);
	module_put(THIS_MODULE);
	return ret;
}

static void gennvm_unregister(struct nvm_dev *dev)
{
	gennvm_free(dev);
	module_put(THIS_MODULE);
}

static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
@@ -262,14 +267,11 @@ static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
	if (list_empty(&lun->free_list)) {
		pr_err_ratelimited("gennvm: lun %u have no free pages available",
								lun->vlun.id);
		spin_unlock(&vlun->lock);
		goto out;
	}

	while (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks) {
		spin_unlock(&vlun->lock);
	if (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks)
		goto out;
	}

	blk = list_first_entry(&lun->free_list, struct nvm_block, list);
	list_move_tail(&blk->list, &lun->used_list);
@@ -278,8 +280,8 @@ static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
	lun->vlun.nr_free_blocks--;
	lun->vlun.nr_inuse_blocks++;

	spin_unlock(&vlun->lock);
out:
	spin_unlock(&vlun->lock);
	return blk;
}

@@ -349,7 +351,7 @@ static int gennvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
	gennvm_generic_to_addr_mode(dev, rqd);

	rqd->dev = dev;
	return dev->ops->submit_io(dev->q, rqd);
	return dev->ops->submit_io(dev, rqd);
}

static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa,
@@ -385,7 +387,7 @@ static void gennvm_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd)
	if (!dev->ops->set_bb_tbl)
		return;

	if (dev->ops->set_bb_tbl(dev->q, rqd, 1))
	if (dev->ops->set_bb_tbl(dev, rqd, 1))
		return;

	gennvm_addr_to_generic_mode(dev, rqd);
@@ -453,7 +455,7 @@ static int gennvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk,

	gennvm_generic_to_addr_mode(dev, &rqd);

	ret = dev->ops->erase_block(dev->q, &rqd);
	ret = dev->ops->erase_block(dev, &rqd);

	if (plane_cnt)
		nvm_dev_dma_free(dev, rqd.ppa_list, rqd.dma_ppa_list);
Loading