Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Dec 12, 2015
2 parents 6539756 + af096e2 commit 7807563
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 89 deletions.
12 changes: 12 additions & 0 deletions block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down
32 changes: 21 additions & 11 deletions drivers/block/null_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions drivers/lightnvm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
85 changes: 42 additions & 43 deletions drivers/lightnvm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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,
Expand Down Expand Up @@ -326,16 +330,17 @@ 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;
goto err_init;
}
}

/* 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);

Expand Down Expand Up @@ -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);
Expand Down
20 changes: 11 additions & 9 deletions drivers/lightnvm/gennvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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;
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 7807563

Please sign in to comment.