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:
 "Another week, another round of fixes.

  These have been brewing for a bit and in various iterations, but I
  feel pretty comfortable about the quality of them.  They fix real
  issues.  The pull request is mostly blk-mq related, and the only one
  not fixing a real bug, is the tag iterator abstraction from Christoph.
  But it's pretty trivial, and we'll need it for another fix soon.

  Apart from the blk-mq fixes, there's an NVMe affinity fix from Keith,
  and a single fix for xen-blkback from Roger fixing failure to free
  requests on disconnect"

* 'for-linus' of git://git.kernel.dk/linux-block:
  blk-mq: factor out a helper to iterate all tags for a request_queue
  blk-mq: fix racy updates of rq->errors
  blk-mq: fix deadlock when reading cpu_list
  blk-mq: avoid inserting requests before establishing new mapping
  blk-mq: fix q->mq_usage_counter access race
  blk-mq: Fix use after of free q->mq_map
  blk-mq: fix sysfs registration/unregistration race
  blk-mq: avoid setting hctx->tags->cpumask before allocation
  NVMe: Set affinity after allocating request queues
  xen/blkback: free requests on disconnection
  • Loading branch information
Linus Torvalds committed Oct 2, 2015
2 parents 36f8daf + 0bf6cd5 commit 27728bf
Show file tree
Hide file tree
Showing 15 changed files with 193 additions and 133 deletions.
9 changes: 5 additions & 4 deletions block/blk-mq-cpumap.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ static int get_first_sibling(unsigned int cpu)
return cpu;
}

int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)
int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
const struct cpumask *online_mask)
{
unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling;
cpumask_var_t cpus;
Expand All @@ -41,7 +42,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)

cpumask_clear(cpus);
nr_cpus = nr_uniq_cpus = 0;
for_each_online_cpu(i) {
for_each_cpu(i, online_mask) {
nr_cpus++;
first_sibling = get_first_sibling(i);
if (!cpumask_test_cpu(first_sibling, cpus))
Expand All @@ -51,7 +52,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)

queue = 0;
for_each_possible_cpu(i) {
if (!cpu_online(i)) {
if (!cpumask_test_cpu(i, online_mask)) {
map[i] = 0;
continue;
}
Expand Down Expand Up @@ -95,7 +96,7 @@ unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set)
if (!map)
return NULL;

if (!blk_mq_update_queue_map(map, set->nr_hw_queues))
if (!blk_mq_update_queue_map(map, set->nr_hw_queues, cpu_online_mask))
return map;

kfree(map);
Expand Down
34 changes: 22 additions & 12 deletions block/blk-mq-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,6 @@ static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
unsigned int i, first = 1;
ssize_t ret = 0;

blk_mq_disable_hotplug();

for_each_cpu(i, hctx->cpumask) {
if (first)
ret += sprintf(ret + page, "%u", i);
Expand All @@ -240,8 +238,6 @@ static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
first = 0;
}

blk_mq_enable_hotplug();

ret += sprintf(ret + page, "\n");
return ret;
}
Expand Down Expand Up @@ -343,7 +339,7 @@ static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
struct blk_mq_ctx *ctx;
int i;

if (!hctx->nr_ctx || !(hctx->flags & BLK_MQ_F_SYSFS_UP))
if (!hctx->nr_ctx)
return;

hctx_for_each_ctx(hctx, ctx, i)
Expand All @@ -358,7 +354,7 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
struct blk_mq_ctx *ctx;
int i, ret;

if (!hctx->nr_ctx || !(hctx->flags & BLK_MQ_F_SYSFS_UP))
if (!hctx->nr_ctx)
return 0;

ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", hctx->queue_num);
Expand All @@ -381,6 +377,8 @@ void blk_mq_unregister_disk(struct gendisk *disk)
struct blk_mq_ctx *ctx;
int i, j;

blk_mq_disable_hotplug();

queue_for_each_hw_ctx(q, hctx, i) {
blk_mq_unregister_hctx(hctx);

Expand All @@ -395,6 +393,9 @@ void blk_mq_unregister_disk(struct gendisk *disk)
kobject_put(&q->mq_kobj);

kobject_put(&disk_to_dev(disk)->kobj);

q->mq_sysfs_init_done = false;
blk_mq_enable_hotplug();
}

static void blk_mq_sysfs_init(struct request_queue *q)
Expand Down Expand Up @@ -425,27 +426,30 @@ int blk_mq_register_disk(struct gendisk *disk)
struct blk_mq_hw_ctx *hctx;
int ret, i;

blk_mq_disable_hotplug();

blk_mq_sysfs_init(q);

ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
if (ret < 0)
return ret;
goto out;

kobject_uevent(&q->mq_kobj, KOBJ_ADD);

queue_for_each_hw_ctx(q, hctx, i) {
hctx->flags |= BLK_MQ_F_SYSFS_UP;
ret = blk_mq_register_hctx(hctx);
if (ret)
break;
}

if (ret) {
if (ret)
blk_mq_unregister_disk(disk);
return ret;
}
else
q->mq_sysfs_init_done = true;
out:
blk_mq_enable_hotplug();

return 0;
return ret;
}
EXPORT_SYMBOL_GPL(blk_mq_register_disk);

Expand All @@ -454,6 +458,9 @@ void blk_mq_sysfs_unregister(struct request_queue *q)
struct blk_mq_hw_ctx *hctx;
int i;

if (!q->mq_sysfs_init_done)
return;

queue_for_each_hw_ctx(q, hctx, i)
blk_mq_unregister_hctx(hctx);
}
Expand All @@ -463,6 +470,9 @@ int blk_mq_sysfs_register(struct request_queue *q)
struct blk_mq_hw_ctx *hctx;
int i, ret = 0;

if (!q->mq_sysfs_init_done)
return ret;

queue_for_each_hw_ctx(q, hctx, i) {
ret = blk_mq_register_hctx(hctx);
if (ret)
Expand Down
27 changes: 20 additions & 7 deletions block/blk-mq-tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,17 +471,30 @@ void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
}
EXPORT_SYMBOL(blk_mq_all_tag_busy_iter);

void blk_mq_tag_busy_iter(struct blk_mq_hw_ctx *hctx, busy_iter_fn *fn,
void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
void *priv)
{
struct blk_mq_tags *tags = hctx->tags;
struct blk_mq_hw_ctx *hctx;
int i;


queue_for_each_hw_ctx(q, hctx, i) {
struct blk_mq_tags *tags = hctx->tags;

/*
* If not software queues are currently mapped to this
* hardware queue, there's nothing to check
*/
if (!blk_mq_hw_queue_mapped(hctx))
continue;

if (tags->nr_reserved_tags)
bt_for_each(hctx, &tags->breserved_tags, 0, fn, priv, true);
bt_for_each(hctx, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
false);
}

if (tags->nr_reserved_tags)
bt_for_each(hctx, &tags->breserved_tags, 0, fn, priv, true);
bt_for_each(hctx, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
false);
}
EXPORT_SYMBOL(blk_mq_tag_busy_iter);

static unsigned int bt_unused_tags(struct blk_mq_bitmap_tags *bt)
{
Expand Down
2 changes: 2 additions & 0 deletions block/blk-mq-tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ extern ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page);
extern void blk_mq_tag_init_last_tag(struct blk_mq_tags *tags, unsigned int *last_tag);
extern int blk_mq_tag_update_depth(struct blk_mq_tags *tags, unsigned int depth);
extern void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags, bool);
void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
void *priv);

enum {
BLK_MQ_TAG_CACHE_MIN = 1,
Expand Down
Loading

0 comments on commit 27728bf

Please sign in to comment.