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 fixes from Jens Axboe:
 "Final round of fixes for this merge window - some of this has come up
  after the initial pull request, and some of it was put in a post-merge
  branch before the merge window.

  This contains:

   - Fix for a bad check for an error on dma mapping in the mtip32xx
     driver, from Alexey Khoroshilov.

   - A set of fixes for lightnvm, from Javier, Matias, and Wenwei.

   - An NVMe completion record corruption fix from Marta, ensuring that
     we read things in the right order.

   - Two writeback fixes from Tejun, marked for stable@ as well.

   - A blk-mq sw queue iterator fix from Thomas, fixing an oops for
     sparse CPU maps.  They hit this in the hot plug/unplug rework"

* 'for-linus' of git://git.kernel.dk/linux-block:
  nvme: avoid cqe corruption when update at the same time as read
  writeback, cgroup: fix use of the wrong bdi_writeback which mismatches the inode
  writeback, cgroup: fix premature wb_put() in locked_inode_to_wb_and_lock_list()
  blk-mq: Use proper cpumask iterator
  mtip32xx: fix checks for dma mapping errors
  lightnvm: do not load L2P table if not supported
  lightnvm: do not reserve lun on l2p loading
  nvme: lightnvm: return ppa completion status
  lightnvm: add a bitmap of luns
  lightnvm: specify target's logical address area
  null_blk: add lightnvm null_blk device to the nullb_list
  • Loading branch information
torvalds committed Mar 25, 2016
2 parents 8f40842 + d783e0b commit 1d02369
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 78 deletions.
6 changes: 4 additions & 2 deletions block/blk-mq-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,12 +416,14 @@ void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx)
static void blk_mq_sysfs_init(struct request_queue *q)
{
struct blk_mq_ctx *ctx;
int i;
int cpu;

kobject_init(&q->mq_kobj, &blk_mq_ktype);

queue_for_each_ctx(q, ctx, i)
for_each_possible_cpu(cpu) {
ctx = per_cpu_ptr(q->queue_ctx, cpu);
kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
}
}

int blk_mq_register_disk(struct gendisk *disk)
Expand Down
3 changes: 2 additions & 1 deletion block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1798,11 +1798,12 @@ static void blk_mq_map_swqueue(struct request_queue *q,
/*
* Map software to hardware queues
*/
queue_for_each_ctx(q, ctx, i) {
for_each_possible_cpu(i) {
/* If the cpu isn't online, the cpu is mapped to first hctx */
if (!cpumask_test_cpu(i, online_mask))
continue;

ctx = per_cpu_ptr(q->queue_ctx, i);
hctx = q->mq_ops->map_queue(q, i);

cpumask_set_cpu(i, hctx->cpumask);
Expand Down
4 changes: 2 additions & 2 deletions drivers/block/mtip32xx/mtip32xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2051,7 +2051,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
outbuf,
taskout,
DMA_TO_DEVICE);
if (outbuf_dma == 0) {
if (pci_dma_mapping_error(dd->pdev, outbuf_dma)) {
err = -ENOMEM;
goto abort;
}
Expand All @@ -2068,7 +2068,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
inbuf_dma = pci_map_single(dd->pdev,
inbuf,
taskin, DMA_FROM_DEVICE);
if (inbuf_dma == 0) {
if (pci_dma_mapping_error(dd->pdev, inbuf_dma)) {
err = -ENOMEM;
goto abort;
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/block/null_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,10 +742,11 @@ static int null_add_dev(void)

add_disk(disk);

done:
mutex_lock(&lock);
list_add_tail(&nullb->list, &nullb_list);
mutex_unlock(&lock);
done:

return 0;

out_cleanup_lightnvm:
Expand Down
7 changes: 7 additions & 0 deletions drivers/lightnvm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,13 @@ static int nvm_core_init(struct nvm_dev *dev)
dev->nr_luns = dev->luns_per_chnl * dev->nr_chnls;

dev->total_secs = dev->nr_luns * dev->sec_per_lun;
dev->lun_map = kcalloc(BITS_TO_LONGS(dev->nr_luns),
sizeof(unsigned long), GFP_KERNEL);
if (!dev->lun_map)
return -ENOMEM;
INIT_LIST_HEAD(&dev->online_targets);
mutex_init(&dev->mlock);
spin_lock_init(&dev->lock);

return 0;
}
Expand Down Expand Up @@ -585,6 +590,7 @@ int nvm_register(struct request_queue *q, char *disk_name,

return 0;
err_init:
kfree(dev->lun_map);
kfree(dev);
return ret;
}
Expand All @@ -607,6 +613,7 @@ void nvm_unregister(char *disk_name)
up_write(&nvm_lock);

nvm_exit(dev);
kfree(dev->lun_map);
kfree(dev);
}
EXPORT_SYMBOL(nvm_unregister);
Expand Down
84 changes: 83 additions & 1 deletion drivers/lightnvm/gennvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,68 @@

#include "gennvm.h"

static int gennvm_get_area(struct nvm_dev *dev, sector_t *lba, sector_t len)
{
struct gen_nvm *gn = dev->mp;
struct gennvm_area *area, *prev, *next;
sector_t begin = 0;
sector_t max_sectors = (dev->sec_size * dev->total_secs) >> 9;

if (len > max_sectors)
return -EINVAL;

area = kmalloc(sizeof(struct gennvm_area), GFP_KERNEL);
if (!area)
return -ENOMEM;

prev = NULL;

spin_lock(&dev->lock);
list_for_each_entry(next, &gn->area_list, list) {
if (begin + len > next->begin) {
begin = next->end;
prev = next;
continue;
}
break;
}

if ((begin + len) > max_sectors) {
spin_unlock(&dev->lock);
kfree(area);
return -EINVAL;
}

area->begin = *lba = begin;
area->end = begin + len;

if (prev) /* insert into sorted order */
list_add(&area->list, &prev->list);
else
list_add(&area->list, &gn->area_list);
spin_unlock(&dev->lock);

return 0;
}

static void gennvm_put_area(struct nvm_dev *dev, sector_t begin)
{
struct gen_nvm *gn = dev->mp;
struct gennvm_area *area;

spin_lock(&dev->lock);
list_for_each_entry(area, &gn->area_list, list) {
if (area->begin != begin)
continue;

list_del(&area->list);
spin_unlock(&dev->lock);
kfree(area);
return;
}
spin_unlock(&dev->lock);
}

static void gennvm_blocks_free(struct nvm_dev *dev)
{
struct gen_nvm *gn = dev->mp;
Expand Down Expand Up @@ -195,7 +257,7 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn)
}
}

if (dev->ops->get_l2p_tbl) {
if ((dev->identity.dom & NVM_RSP_L2P) && dev->ops->get_l2p_tbl) {
ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_secs,
gennvm_block_map, dev);
if (ret) {
Expand Down Expand Up @@ -229,6 +291,7 @@ static int gennvm_register(struct nvm_dev *dev)

gn->dev = dev;
gn->nr_luns = dev->nr_luns;
INIT_LIST_HEAD(&gn->area_list);
dev->mp = gn;

ret = gennvm_luns_init(dev, gn);
Expand Down Expand Up @@ -419,10 +482,23 @@ static int gennvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk,
return nvm_erase_ppa(dev, &addr, 1);
}

static int gennvm_reserve_lun(struct nvm_dev *dev, int lunid)
{
return test_and_set_bit(lunid, dev->lun_map);
}

static void gennvm_release_lun(struct nvm_dev *dev, int lunid)
{
WARN_ON(!test_and_clear_bit(lunid, dev->lun_map));
}

static struct nvm_lun *gennvm_get_lun(struct nvm_dev *dev, int lunid)
{
struct gen_nvm *gn = dev->mp;

if (unlikely(lunid >= dev->nr_luns))
return NULL;

return &gn->luns[lunid].vlun;
}

Expand Down Expand Up @@ -464,7 +540,13 @@ static struct nvmm_type gennvm = {
.erase_blk = gennvm_erase_blk,

.get_lun = gennvm_get_lun,
.reserve_lun = gennvm_reserve_lun,
.release_lun = gennvm_release_lun,
.lun_info_print = gennvm_lun_info_print,

.get_area = gennvm_get_area,
.put_area = gennvm_put_area,

};

static int __init gennvm_module_init(void)
Expand Down
6 changes: 6 additions & 0 deletions drivers/lightnvm/gennvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,14 @@ struct gen_nvm {

int nr_luns;
struct gen_lun *luns;
struct list_head area_list;
};

struct gennvm_area {
struct list_head list;
sector_t begin;
sector_t end; /* end is excluded */
};
#define gennvm_for_each_lun(bm, lun, i) \
for ((i) = 0, lun = &(bm)->luns[0]; \
(i) < (bm)->nr_luns; (i)++, lun = &(bm)->luns[(i)])
Expand Down
Loading

0 comments on commit 1d02369

Please sign in to comment.