Skip to content

Commit

Permalink
Merge branch 'for-3.17/core' of git://git.kernel.dk/linux-block
Browse files Browse the repository at this point in the history
Pull block core bits from Jens Axboe:
 "Small round this time, after the massive blk-mq dump for 3.16.  This
  pull request contains:

   - Fixes for max_sectors overflow in ioctls from Akinoby Mita.

   - Partition off-by-one bug fix in aix partitions from Dan Carpenter.

   - Various small partition cleanups from Fabian Frederick.

   - Fix for the block integrity code sometimes returning the wrong
     vector count from Gu Zheng.

   - Cleanup an re-org of the blk-mq queue enter/exit percpu counters
     from Tejun.  Dependent on the percpu pull for 3.17 (which was in
     the block tree too), that you have already pulled in.

   - A blkcg oops fix, also from Tejun"

* 'for-3.17/core' of git://git.kernel.dk/linux-block:
  partitions: aix.c: off by one bug
  blkcg: don't call into policy draining if root_blkg is already gone
  Revert "bio: modify __bio_add_page() to accept pages that don't start a new segment"
  bio: modify __bio_add_page() to accept pages that don't start a new segment
  block: fix SG_[GS]ET_RESERVED_SIZE ioctl when max_sectors is huge
  block: fix BLKSECTGET ioctl when max_sectors is greater than USHRT_MAX
  block/partitions/efi.c: kerneldoc fixing
  block/partitions/msdos.c: code clean-up
  block/partitions/amiga.c: replace nolevel printk by pr_err
  block/partitions/aix.c: replace count*size kzalloc by kcalloc
  bio-integrity: add "bip_max_vcnt" into struct bio_integrity_payload
  blk-mq: use percpu_ref for mq usage count
  blk-mq: collapse __blk_mq_drain_queue() into blk_mq_freeze_queue()
  blk-mq: decouble blk-mq freezing from generic bypassing
  block, blk-mq: draining can't be skipped even if bypass_depth was non-zero
  blk-mq: fix a memory ordering bug in blk_mq_queue_enter()
  • Loading branch information
torvalds committed Aug 14, 2014
2 parents f0094b2 + d97a86c commit 4a319a4
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 110 deletions.
12 changes: 3 additions & 9 deletions block/bio-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
bs->bvec_integrity_pool);
if (!bip->bip_vec)
goto err;
bip->bip_max_vcnt = bvec_nr_vecs(idx);
} else {
bip->bip_vec = bip->bip_inline_vecs;
bip->bip_max_vcnt = inline_vecs;
}

bip->bip_slab = idx;
Expand Down Expand Up @@ -114,14 +116,6 @@ void bio_integrity_free(struct bio *bio)
}
EXPORT_SYMBOL(bio_integrity_free);

static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip)
{
if (bip->bip_slab == BIO_POOL_NONE)
return BIP_INLINE_VECS;

return bvec_nr_vecs(bip->bip_slab);
}

/**
* bio_integrity_add_page - Attach integrity metadata
* @bio: bio to update
Expand All @@ -137,7 +131,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
struct bio_integrity_payload *bip = bio->bi_integrity;
struct bio_vec *iv;

if (bip->bip_vcnt >= bip_integrity_vecs(bip)) {
if (bip->bip_vcnt >= bip->bip_max_vcnt) {
printk(KERN_ERR "%s: bip_vec full\n", __func__);
return 0;
}
Expand Down
13 changes: 8 additions & 5 deletions block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,17 @@ static void __blk_drain_queue(struct request_queue *q, bool drain_all)
*/
void blk_queue_bypass_start(struct request_queue *q)
{
bool drain;

spin_lock_irq(q->queue_lock);
drain = !q->bypass_depth++;
q->bypass_depth++;
queue_flag_set(QUEUE_FLAG_BYPASS, q);
spin_unlock_irq(q->queue_lock);

if (drain) {
/*
* Queues start drained. Skip actual draining till init is
* complete. This avoids lenghty delays during queue init which
* can happen many times during boot.
*/
if (blk_queue_init_done(q)) {
spin_lock_irq(q->queue_lock);
__blk_drain_queue(q, false);
spin_unlock_irq(q->queue_lock);
Expand Down Expand Up @@ -511,7 +514,7 @@ void blk_cleanup_queue(struct request_queue *q)
* prevent that q->request_fn() gets invoked after draining finished.
*/
if (q->mq_ops) {
blk_mq_drain_queue(q);
blk_mq_freeze_queue(q);
spin_lock_irq(lock);
} else {
spin_lock_irq(lock);
Expand Down
81 changes: 29 additions & 52 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,83 +78,61 @@ static void blk_mq_hctx_clear_pending(struct blk_mq_hw_ctx *hctx,

static int blk_mq_queue_enter(struct request_queue *q)
{
int ret;

__percpu_counter_add(&q->mq_usage_counter, 1, 1000000);
smp_wmb();

/* we have problems freezing the queue if it's initializing */
if (!blk_queue_dying(q) &&
(!blk_queue_bypass(q) || !blk_queue_init_done(q)))
return 0;

__percpu_counter_add(&q->mq_usage_counter, -1, 1000000);
while (true) {
int ret;

spin_lock_irq(q->queue_lock);
ret = wait_event_interruptible_lock_irq(q->mq_freeze_wq,
!blk_queue_bypass(q) || blk_queue_dying(q),
*q->queue_lock);
/* inc usage with lock hold to avoid freeze_queue runs here */
if (!ret && !blk_queue_dying(q))
__percpu_counter_add(&q->mq_usage_counter, 1, 1000000);
else if (blk_queue_dying(q))
ret = -ENODEV;
spin_unlock_irq(q->queue_lock);
if (percpu_ref_tryget_live(&q->mq_usage_counter))
return 0;

return ret;
ret = wait_event_interruptible(q->mq_freeze_wq,
!q->mq_freeze_depth || blk_queue_dying(q));
if (blk_queue_dying(q))
return -ENODEV;
if (ret)
return ret;
}
}

static void blk_mq_queue_exit(struct request_queue *q)
{
__percpu_counter_add(&q->mq_usage_counter, -1, 1000000);
percpu_ref_put(&q->mq_usage_counter);
}

void blk_mq_drain_queue(struct request_queue *q)
static void blk_mq_usage_counter_release(struct percpu_ref *ref)
{
while (true) {
s64 count;

spin_lock_irq(q->queue_lock);
count = percpu_counter_sum(&q->mq_usage_counter);
spin_unlock_irq(q->queue_lock);
struct request_queue *q =
container_of(ref, struct request_queue, mq_usage_counter);

if (count == 0)
break;
blk_mq_start_hw_queues(q);
msleep(10);
}
wake_up_all(&q->mq_freeze_wq);
}

/*
* Guarantee no request is in use, so we can change any data structure of
* the queue afterward.
*/
static void blk_mq_freeze_queue(struct request_queue *q)
void blk_mq_freeze_queue(struct request_queue *q)
{
bool drain;

spin_lock_irq(q->queue_lock);
drain = !q->bypass_depth++;
queue_flag_set(QUEUE_FLAG_BYPASS, q);
q->mq_freeze_depth++;
spin_unlock_irq(q->queue_lock);

if (drain)
blk_mq_drain_queue(q);
percpu_ref_kill(&q->mq_usage_counter);
blk_mq_run_queues(q, false);
wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
}

static void blk_mq_unfreeze_queue(struct request_queue *q)
{
bool wake = false;

spin_lock_irq(q->queue_lock);
if (!--q->bypass_depth) {
queue_flag_clear(QUEUE_FLAG_BYPASS, q);
wake = true;
}
WARN_ON_ONCE(q->bypass_depth < 0);
wake = !--q->mq_freeze_depth;
WARN_ON_ONCE(q->mq_freeze_depth < 0);
spin_unlock_irq(q->queue_lock);
if (wake)
if (wake) {
percpu_ref_reinit(&q->mq_usage_counter);
wake_up_all(&q->mq_freeze_wq);
}
}

bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx)
Expand Down Expand Up @@ -1798,7 +1776,7 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
if (!q)
goto err_hctxs;

if (percpu_counter_init(&q->mq_usage_counter, 0))
if (percpu_ref_init(&q->mq_usage_counter, blk_mq_usage_counter_release))
goto err_map;

setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
Expand Down Expand Up @@ -1891,7 +1869,7 @@ void blk_mq_free_queue(struct request_queue *q)
blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
blk_mq_free_hw_queues(q, set);

percpu_counter_destroy(&q->mq_usage_counter);
percpu_ref_exit(&q->mq_usage_counter);

free_percpu(q->queue_ctx);
kfree(q->queue_hw_ctx);
Expand Down Expand Up @@ -2050,8 +2028,7 @@ static int __init blk_mq_init(void)
{
blk_mq_cpu_init();

/* Must be called after percpu_counter_hotcpu_callback() */
hotcpu_notifier(blk_mq_queue_reinit_notify, -10);
hotcpu_notifier(blk_mq_queue_reinit_notify, 0);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion block/blk-mq.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct blk_mq_ctx {
void __blk_mq_complete_request(struct request *rq);
void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
void blk_mq_init_flush(struct request_queue *q);
void blk_mq_drain_queue(struct request_queue *q);
void blk_mq_freeze_queue(struct request_queue *q);
void blk_mq_free_queue(struct request_queue *q);
void blk_mq_clone_flush_request(struct request *flush_rq,
struct request *orig_rq);
Expand Down
2 changes: 1 addition & 1 deletion block/blk-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,8 @@ int blk_register_queue(struct gendisk *disk)
* Initialization must be complete by now. Finish the initial
* bypass from queue allocation.
*/
blk_queue_bypass_end(q);
queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
blk_queue_bypass_end(q);

ret = blk_trace_init_sysfs(dev);
if (ret)
Expand Down
6 changes: 4 additions & 2 deletions block/compat_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
fmode_t mode = file->f_mode;
struct backing_dev_info *bdi;
loff_t size;
unsigned int max_sectors;

/*
* O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
Expand Down Expand Up @@ -719,8 +720,9 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case BLKSSZGET: /* get block device hardware sector size */
return compat_put_int(arg, bdev_logical_block_size(bdev));
case BLKSECTGET:
return compat_put_ushort(arg,
queue_max_sectors(bdev_get_queue(bdev)));
max_sectors = min_t(unsigned int, USHRT_MAX,
queue_max_sectors(bdev_get_queue(bdev)));
return compat_put_ushort(arg, max_sectors);
case BLKROTATIONAL:
return compat_put_ushort(arg,
!blk_queue_nonrot(bdev_get_queue(bdev)));
Expand Down
5 changes: 4 additions & 1 deletion block/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
struct backing_dev_info *bdi;
loff_t size;
int ret, n;
unsigned int max_sectors;

switch(cmd) {
case BLKFLSBUF:
Expand Down Expand Up @@ -375,7 +376,9 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
case BLKDISCARDZEROES:
return put_uint(arg, bdev_discard_zeroes_data(bdev));
case BLKSECTGET:
return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev)));
max_sectors = min_t(unsigned int, USHRT_MAX,
queue_max_sectors(bdev_get_queue(bdev)));
return put_ushort(arg, max_sectors);
case BLKROTATIONAL:
return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev)));
case BLKRASET:
Expand Down
4 changes: 2 additions & 2 deletions block/partitions/aix.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ int aix_partition(struct parsed_partitions *state)
numlvs = be16_to_cpu(p->numlvs);
put_dev_sector(sect);
}
lvip = kzalloc(sizeof(struct lv_info) * state->limit, GFP_KERNEL);
lvip = kcalloc(state->limit, sizeof(struct lv_info), GFP_KERNEL);
if (!lvip)
return 0;
if (numlvs && (d = read_part_sector(state, vgda_sector + 1, &sect))) {
Expand Down Expand Up @@ -253,7 +253,7 @@ int aix_partition(struct parsed_partitions *state)
continue;
}
lv_ix = be16_to_cpu(p->lv_ix) - 1;
if (lv_ix > state->limit) {
if (lv_ix >= state->limit) {
cur_lv_ix = -1;
continue;
}
Expand Down
12 changes: 7 additions & 5 deletions block/partitions/amiga.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* Re-organised Feb 1998 Russell King
*/

#define pr_fmt(fmt) fmt

#include <linux/types.h>
#include <linux/affs_hardblocks.h>

Expand Down Expand Up @@ -40,7 +42,7 @@ int amiga_partition(struct parsed_partitions *state)
data = read_part_sector(state, blk, &sect);
if (!data) {
if (warn_no_part)
printk("Dev %s: unable to read RDB block %d\n",
pr_err("Dev %s: unable to read RDB block %d\n",
bdevname(state->bdev, b), blk);
res = -1;
goto rdb_done;
Expand All @@ -57,12 +59,12 @@ int amiga_partition(struct parsed_partitions *state)
*(__be32 *)(data+0xdc) = 0;
if (checksum_block((__be32 *)data,
be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
printk("Warning: Trashed word at 0xd0 in block %d "
"ignored in checksum calculation\n",blk);
pr_err("Trashed word at 0xd0 in block %d ignored in checksum calculation\n",
blk);
break;
}

printk("Dev %s: RDB in block %d has bad checksum\n",
pr_err("Dev %s: RDB in block %d has bad checksum\n",
bdevname(state->bdev, b), blk);
}

Expand All @@ -83,7 +85,7 @@ int amiga_partition(struct parsed_partitions *state)
data = read_part_sector(state, blk, &sect);
if (!data) {
if (warn_no_part)
printk("Dev %s: unable to read partition block %d\n",
pr_err("Dev %s: unable to read partition block %d\n",
bdevname(state->bdev, b), blk);
res = -1;
goto rdb_done;
Expand Down
Loading

0 comments on commit 4a319a4

Please sign in to comment.