Merge branch 'for-3.19/core' of git://git.kernel.dk/linux-block
Pull block driver core update from Jens Axboe:
"This is the pull request for the core block IO changes for 3.19. Not
a huge round this time, mostly lots of little good fixes:
- Fix a bug in sysfs blktrace interface causing a NULL pointer
dereference, when enabled/disabled through that API. From Arianna
Avanzini.
- Various updates/fixes/improvements for blk-mq:
- A set of updates from Bart, mostly fixing buts in the tag
handling.
- Cleanup/code consolidation from Christoph.
- Extend queue_rq API to be able to handle batching issues of IO
requests. NVMe will utilize this shortly. From me.
- A few tag and request handling updates from me.
- Cleanup of the preempt handling for running queues from Paolo.
- Prevent running of unmapped hardware queues from Ming Lei.
- Move the kdump memory limiting check to be in the correct
location, from Shaohua.
- Initialize all software queues at init time from Takashi. This
prevents a kobject warning when CPUs are brought online that
weren't online when a queue was registered.
- Single writeback fix for I_DIRTY clearing from Tejun. Queued with
the core IO changes, since it's just a single fix.
- Version X of the __bio_add_page() segment addition retry from
Maurizio. Hope the Xth time is the charm.
- Documentation fixup for IO scheduler merging from Jan.
- Introduce (and use) generic IO stat accounting helpers for non-rq
drivers, from Gu Zheng.
- Kill off artificial limiting of max sectors in a request from
Christoph"
* 'for-3.19/core' of git://git.kernel.dk/linux-block: (26 commits)
bio: modify __bio_add_page() to accept pages that don't start a new segment
blk-mq: Fix uninitialized kobject at CPU hotplugging
blktrace: don't let the sysfs interface remove trace from running list
blk-mq: Use all available hardware queues
blk-mq: Micro-optimize bt_get()
blk-mq: Fix a race between bt_clear_tag() and bt_get()
blk-mq: Avoid that __bt_get_word() wraps multiple times
blk-mq: Fix a use-after-free
blk-mq: prevent unmapped hw queue from being scheduled
blk-mq: re-check for available tags after running the hardware queue
blk-mq: fix hang in bt_get()
blk-mq: move the kdump check to blk_mq_alloc_tag_set
blk-mq: cleanup tag free handling
blk-mq: use 'nr_cpu_ids' as highest CPU ID count for hwq <-> cpu map
blk: introduce generic io stat accounting help function
blk-mq: handle the single queue case in blk_mq_hctx_next_cpu
genhd: check for int overflow in disk_expand_part_tbl()
blk-mq: add blk_mq_free_hctx_request()
blk-mq: export blk_mq_free_request()
blk-mq: use get_cpu/put_cpu instead of preempt_disable/preempt_enable
...
This commit is contained in:
+31
-29
@@ -137,6 +137,7 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
|
||||
static int __bt_get_word(struct blk_align_bitmap *bm, unsigned int last_tag)
|
||||
{
|
||||
int tag, org_last_tag, end;
|
||||
bool wrap = last_tag != 0;
|
||||
|
||||
org_last_tag = last_tag;
|
||||
end = bm->depth;
|
||||
@@ -148,15 +149,16 @@ restart:
|
||||
* We started with an offset, start from 0 to
|
||||
* exhaust the map.
|
||||
*/
|
||||
if (org_last_tag && last_tag) {
|
||||
end = last_tag;
|
||||
if (wrap) {
|
||||
wrap = false;
|
||||
end = org_last_tag;
|
||||
last_tag = 0;
|
||||
goto restart;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
last_tag = tag + 1;
|
||||
} while (test_and_set_bit_lock(tag, &bm->word));
|
||||
} while (test_and_set_bit(tag, &bm->word));
|
||||
|
||||
return tag;
|
||||
}
|
||||
@@ -246,14 +248,29 @@ static int bt_get(struct blk_mq_alloc_data *data,
|
||||
if (!(data->gfp & __GFP_WAIT))
|
||||
return -1;
|
||||
|
||||
bs = bt_wait_ptr(bt, hctx);
|
||||
do {
|
||||
bs = bt_wait_ptr(bt, hctx);
|
||||
prepare_to_wait(&bs->wait, &wait, TASK_UNINTERRUPTIBLE);
|
||||
|
||||
tag = __bt_get(hctx, bt, last_tag);
|
||||
if (tag != -1)
|
||||
break;
|
||||
|
||||
/*
|
||||
* We're out of tags on this hardware queue, kick any
|
||||
* pending IO submits before going to sleep waiting for
|
||||
* some to complete.
|
||||
*/
|
||||
blk_mq_run_hw_queue(hctx, false);
|
||||
|
||||
/*
|
||||
* Retry tag allocation after running the hardware queue,
|
||||
* as running the queue may also have found completions.
|
||||
*/
|
||||
tag = __bt_get(hctx, bt, last_tag);
|
||||
if (tag != -1)
|
||||
break;
|
||||
|
||||
blk_mq_put_ctx(data->ctx);
|
||||
|
||||
io_schedule();
|
||||
@@ -268,8 +285,6 @@ static int bt_get(struct blk_mq_alloc_data *data,
|
||||
hctx = data->hctx;
|
||||
bt = &hctx->tags->bitmap_tags;
|
||||
}
|
||||
finish_wait(&bs->wait, &wait);
|
||||
bs = bt_wait_ptr(bt, hctx);
|
||||
} while (1);
|
||||
|
||||
finish_wait(&bs->wait, &wait);
|
||||
@@ -340,11 +355,10 @@ static void bt_clear_tag(struct blk_mq_bitmap_tags *bt, unsigned int tag)
|
||||
struct bt_wait_state *bs;
|
||||
int wait_cnt;
|
||||
|
||||
/*
|
||||
* The unlock memory barrier need to order access to req in free
|
||||
* path and clearing tag bit
|
||||
*/
|
||||
clear_bit_unlock(TAG_TO_BIT(bt, tag), &bt->map[index].word);
|
||||
clear_bit(TAG_TO_BIT(bt, tag), &bt->map[index].word);
|
||||
|
||||
/* Ensure that the wait list checks occur after clear_bit(). */
|
||||
smp_mb();
|
||||
|
||||
bs = bt_wake_ptr(bt);
|
||||
if (!bs)
|
||||
@@ -360,21 +374,6 @@ static void bt_clear_tag(struct blk_mq_bitmap_tags *bt, unsigned int tag)
|
||||
}
|
||||
}
|
||||
|
||||
static void __blk_mq_put_tag(struct blk_mq_tags *tags, unsigned int tag)
|
||||
{
|
||||
BUG_ON(tag >= tags->nr_tags);
|
||||
|
||||
bt_clear_tag(&tags->bitmap_tags, tag);
|
||||
}
|
||||
|
||||
static void __blk_mq_put_reserved_tag(struct blk_mq_tags *tags,
|
||||
unsigned int tag)
|
||||
{
|
||||
BUG_ON(tag >= tags->nr_reserved_tags);
|
||||
|
||||
bt_clear_tag(&tags->breserved_tags, tag);
|
||||
}
|
||||
|
||||
void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, unsigned int tag,
|
||||
unsigned int *last_tag)
|
||||
{
|
||||
@@ -383,10 +382,13 @@ void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, unsigned int tag,
|
||||
if (tag >= tags->nr_reserved_tags) {
|
||||
const int real_tag = tag - tags->nr_reserved_tags;
|
||||
|
||||
__blk_mq_put_tag(tags, real_tag);
|
||||
BUG_ON(real_tag >= tags->nr_tags);
|
||||
bt_clear_tag(&tags->bitmap_tags, real_tag);
|
||||
*last_tag = real_tag;
|
||||
} else
|
||||
__blk_mq_put_reserved_tag(tags, tag);
|
||||
} else {
|
||||
BUG_ON(tag >= tags->nr_reserved_tags);
|
||||
bt_clear_tag(&tags->breserved_tags, tag);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_for_each(struct blk_mq_hw_ctx *hctx,
|
||||
|
||||
Reference in New Issue
Block a user