Merge branch 'for-linus' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:
 "Here's a set of block fixes for the current 4.8-rc release.  This
  contains:

   - a fix for a secure erase regression, from Adrian.

   - a fix for an mmc use-after-free bug regression, also from Adrian.

   - potential zero pointer deference in bdev freezing, from Andrey.

   - a race fix for blk_set_queue_dying() from Bart.

   - a set of xen blkfront fixes from Bob Liu.

   - three small fixes for bcache, from Eric and Kent.

   - a fix for a potential invalid NVMe state transition, from Gabriel.

   - blk-mq CPU offline fix, preventing us from issuing and completing a
     request on the wrong queue.  From me.

   - revert two previous floppy changes, since they caused a user
     visibile regression.  A better fix is in the works.

   - ensure that we don't send down bios that have more than 256
     elements in them.  Fixes a crash with bcache, for example.  From
     Ming.

   - a fix for deferencing an error pointer with cgroup writeback.
     Fixes a regression.  From Vegard"

* 'for-linus' of git://git.kernel.dk/linux-block:
  mmc: fix use-after-free of struct request
  Revert "floppy: refactor open() flags handling"
  Revert "floppy: fix open(O_ACCMODE) for ioctl-only open"
  fs/block_dev: fix potential NULL ptr deref in freeze_bdev()
  blk-mq: improve warning for running a queue on the wrong CPU
  blk-mq: don't overwrite rq->mq_ctx
  block: make sure a big bio is split into at most 256 bvecs
  nvme: Fix nvme_get/set_features() with a NULL result pointer
  bdev: fix NULL pointer dereference
  xen-blkfront: free resources if xlvbd_alloc_gendisk fails
  xen-blkfront: introduce blkif_set_queue_limits()
  xen-blkfront: fix places not updated after introducing 64KB page granularity
  bcache: pr_err: more meaningful error message when nr_stripes is invalid
  bcache: RESERVE_PRIO is too small by one when prio_buckets() is a power of two.
  bcache: register_bcache(): call blkdev_put() when cache_alloc() fails
  block: Fix race triggered by blk_set_queue_dying()
  block: Fix secure erase
  nvme: Prevent controller state invalid transition
This commit is contained in:
Linus Torvalds 2016-08-26 18:50:07 -07:00
commit fd1ae51452
16 changed files with 188 additions and 142 deletions

View File

@ -667,18 +667,19 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector;
bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; bio->bi_iter.bi_size = bio_src->bi_iter.bi_size;
if (bio_op(bio) == REQ_OP_DISCARD) switch (bio_op(bio)) {
goto integrity_clone; case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE:
if (bio_op(bio) == REQ_OP_WRITE_SAME) { break;
case REQ_OP_WRITE_SAME:
bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0];
goto integrity_clone; break;
default:
bio_for_each_segment(bv, bio_src, iter)
bio->bi_io_vec[bio->bi_vcnt++] = bv;
break;
} }
bio_for_each_segment(bv, bio_src, iter)
bio->bi_io_vec[bio->bi_vcnt++] = bv;
integrity_clone:
if (bio_integrity(bio_src)) { if (bio_integrity(bio_src)) {
int ret; int ret;
@ -1788,7 +1789,7 @@ struct bio *bio_split(struct bio *bio, int sectors,
* Discards need a mutable bio_vec to accommodate the payload * Discards need a mutable bio_vec to accommodate the payload
* required by the DSM TRIM and UNMAP commands. * required by the DSM TRIM and UNMAP commands.
*/ */
if (bio_op(bio) == REQ_OP_DISCARD) if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE)
split = bio_clone_bioset(bio, gfp, bs); split = bio_clone_bioset(bio, gfp, bs);
else else
split = bio_clone_fast(bio, gfp, bs); split = bio_clone_fast(bio, gfp, bs);

View File

@ -515,7 +515,9 @@ EXPORT_SYMBOL_GPL(blk_queue_bypass_end);
void blk_set_queue_dying(struct request_queue *q) void blk_set_queue_dying(struct request_queue *q)
{ {
queue_flag_set_unlocked(QUEUE_FLAG_DYING, q); spin_lock_irq(q->queue_lock);
queue_flag_set(QUEUE_FLAG_DYING, q);
spin_unlock_irq(q->queue_lock);
if (q->mq_ops) if (q->mq_ops)
blk_mq_wake_waiters(q); blk_mq_wake_waiters(q);

View File

@ -94,8 +94,30 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
bool do_split = true; bool do_split = true;
struct bio *new = NULL; struct bio *new = NULL;
const unsigned max_sectors = get_max_io_size(q, bio); const unsigned max_sectors = get_max_io_size(q, bio);
unsigned bvecs = 0;
bio_for_each_segment(bv, bio, iter) { bio_for_each_segment(bv, bio, iter) {
/*
* With arbitrary bio size, the incoming bio may be very
* big. We have to split the bio into small bios so that
* each holds at most BIO_MAX_PAGES bvecs because
* bio_clone() can fail to allocate big bvecs.
*
* It should have been better to apply the limit per
* request queue in which bio_clone() is involved,
* instead of globally. The biggest blocker is the
* bio_clone() in bio bounce.
*
* If bio is splitted by this reason, we should have
* allowed to continue bios merging, but don't do
* that now for making the change simple.
*
* TODO: deal with bio bounce's bio_clone() gracefully
* and convert the global limit into per-queue limit.
*/
if (bvecs++ >= BIO_MAX_PAGES)
goto split;
/* /*
* If the queue doesn't support SG gaps and adding this * If the queue doesn't support SG gaps and adding this
* offset would create a gap, disallow it. * offset would create a gap, disallow it.
@ -172,12 +194,18 @@ void blk_queue_split(struct request_queue *q, struct bio **bio,
struct bio *split, *res; struct bio *split, *res;
unsigned nsegs; unsigned nsegs;
if (bio_op(*bio) == REQ_OP_DISCARD) switch (bio_op(*bio)) {
case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE:
split = blk_bio_discard_split(q, *bio, bs, &nsegs); split = blk_bio_discard_split(q, *bio, bs, &nsegs);
else if (bio_op(*bio) == REQ_OP_WRITE_SAME) break;
case REQ_OP_WRITE_SAME:
split = blk_bio_write_same_split(q, *bio, bs, &nsegs); split = blk_bio_write_same_split(q, *bio, bs, &nsegs);
else break;
default:
split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs); split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs);
break;
}
/* physical segments can be figured out during splitting */ /* physical segments can be figured out during splitting */
res = split ? split : *bio; res = split ? split : *bio;
@ -213,7 +241,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
* This should probably be returning 0, but blk_add_request_payload() * This should probably be returning 0, but blk_add_request_payload()
* (Christoph!!!!) * (Christoph!!!!)
*/ */
if (bio_op(bio) == REQ_OP_DISCARD) if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE)
return 1; return 1;
if (bio_op(bio) == REQ_OP_WRITE_SAME) if (bio_op(bio) == REQ_OP_WRITE_SAME)
@ -385,7 +413,9 @@ static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio,
nsegs = 0; nsegs = 0;
cluster = blk_queue_cluster(q); cluster = blk_queue_cluster(q);
if (bio_op(bio) == REQ_OP_DISCARD) { switch (bio_op(bio)) {
case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE:
/* /*
* This is a hack - drivers should be neither modifying the * This is a hack - drivers should be neither modifying the
* biovec, nor relying on bi_vcnt - but because of * biovec, nor relying on bi_vcnt - but because of
@ -393,19 +423,16 @@ static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio,
* a payload we need to set up here (thank you Christoph) and * a payload we need to set up here (thank you Christoph) and
* bi_vcnt is really the only way of telling if we need to. * bi_vcnt is really the only way of telling if we need to.
*/ */
if (!bio->bi_vcnt)
if (bio->bi_vcnt) return 0;
goto single_segment; /* Fall through */
case REQ_OP_WRITE_SAME:
return 0;
}
if (bio_op(bio) == REQ_OP_WRITE_SAME) {
single_segment:
*sg = sglist; *sg = sglist;
bvec = bio_iovec(bio); bvec = bio_iovec(bio);
sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
return 1; return 1;
default:
break;
} }
for_each_bio(bio) for_each_bio(bio)

View File

@ -793,11 +793,12 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
struct list_head *dptr; struct list_head *dptr;
int queued; int queued;
WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask));
if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state))) if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
return; return;
WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) &&
cpu_online(hctx->next_cpu));
hctx->run++; hctx->run++;
/* /*
@ -1036,10 +1037,11 @@ void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
EXPORT_SYMBOL(blk_mq_delay_queue); EXPORT_SYMBOL(blk_mq_delay_queue);
static inline void __blk_mq_insert_req_list(struct blk_mq_hw_ctx *hctx, static inline void __blk_mq_insert_req_list(struct blk_mq_hw_ctx *hctx,
struct blk_mq_ctx *ctx,
struct request *rq, struct request *rq,
bool at_head) bool at_head)
{ {
struct blk_mq_ctx *ctx = rq->mq_ctx;
trace_block_rq_insert(hctx->queue, rq); trace_block_rq_insert(hctx->queue, rq);
if (at_head) if (at_head)
@ -1053,20 +1055,16 @@ static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx,
{ {
struct blk_mq_ctx *ctx = rq->mq_ctx; struct blk_mq_ctx *ctx = rq->mq_ctx;
__blk_mq_insert_req_list(hctx, ctx, rq, at_head); __blk_mq_insert_req_list(hctx, rq, at_head);
blk_mq_hctx_mark_pending(hctx, ctx); blk_mq_hctx_mark_pending(hctx, ctx);
} }
void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue, void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
bool async) bool async)
{ {
struct blk_mq_ctx *ctx = rq->mq_ctx;
struct request_queue *q = rq->q; struct request_queue *q = rq->q;
struct blk_mq_hw_ctx *hctx; struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *ctx = rq->mq_ctx, *current_ctx;
current_ctx = blk_mq_get_ctx(q);
if (!cpu_online(ctx->cpu))
rq->mq_ctx = ctx = current_ctx;
hctx = q->mq_ops->map_queue(q, ctx->cpu); hctx = q->mq_ops->map_queue(q, ctx->cpu);
@ -1076,8 +1074,6 @@ void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
if (run_queue) if (run_queue)
blk_mq_run_hw_queue(hctx, async); blk_mq_run_hw_queue(hctx, async);
blk_mq_put_ctx(current_ctx);
} }
static void blk_mq_insert_requests(struct request_queue *q, static void blk_mq_insert_requests(struct request_queue *q,
@ -1088,14 +1084,9 @@ static void blk_mq_insert_requests(struct request_queue *q,
{ {
struct blk_mq_hw_ctx *hctx; struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *current_ctx;
trace_block_unplug(q, depth, !from_schedule); trace_block_unplug(q, depth, !from_schedule);
current_ctx = blk_mq_get_ctx(q);
if (!cpu_online(ctx->cpu))
ctx = current_ctx;
hctx = q->mq_ops->map_queue(q, ctx->cpu); hctx = q->mq_ops->map_queue(q, ctx->cpu);
/* /*
@ -1107,15 +1098,14 @@ static void blk_mq_insert_requests(struct request_queue *q,
struct request *rq; struct request *rq;
rq = list_first_entry(list, struct request, queuelist); rq = list_first_entry(list, struct request, queuelist);
BUG_ON(rq->mq_ctx != ctx);
list_del_init(&rq->queuelist); list_del_init(&rq->queuelist);
rq->mq_ctx = ctx; __blk_mq_insert_req_list(hctx, rq, false);
__blk_mq_insert_req_list(hctx, ctx, rq, false);
} }
blk_mq_hctx_mark_pending(hctx, ctx); blk_mq_hctx_mark_pending(hctx, ctx);
spin_unlock(&ctx->lock); spin_unlock(&ctx->lock);
blk_mq_run_hw_queue(hctx, from_schedule); blk_mq_run_hw_queue(hctx, from_schedule);
blk_mq_put_ctx(current_ctx);
} }
static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b) static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b)
@ -1630,16 +1620,17 @@ static int blk_mq_alloc_bitmap(struct blk_mq_ctxmap *bitmap, int node)
return 0; return 0;
} }
/*
* 'cpu' is going away. splice any existing rq_list entries from this
* software queue to the hw queue dispatch list, and ensure that it
* gets run.
*/
static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu) static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu)
{ {
struct request_queue *q = hctx->queue;
struct blk_mq_ctx *ctx; struct blk_mq_ctx *ctx;
LIST_HEAD(tmp); LIST_HEAD(tmp);
/* ctx = __blk_mq_get_ctx(hctx->queue, cpu);
* Move ctx entries to new CPU, if this one is going away.
*/
ctx = __blk_mq_get_ctx(q, cpu);
spin_lock(&ctx->lock); spin_lock(&ctx->lock);
if (!list_empty(&ctx->rq_list)) { if (!list_empty(&ctx->rq_list)) {
@ -1651,24 +1642,11 @@ static int blk_mq_hctx_cpu_offline(struct blk_mq_hw_ctx *hctx, int cpu)
if (list_empty(&tmp)) if (list_empty(&tmp))
return NOTIFY_OK; return NOTIFY_OK;
ctx = blk_mq_get_ctx(q); spin_lock(&hctx->lock);
spin_lock(&ctx->lock); list_splice_tail_init(&tmp, &hctx->dispatch);
spin_unlock(&hctx->lock);
while (!list_empty(&tmp)) {
struct request *rq;
rq = list_first_entry(&tmp, struct request, queuelist);
rq->mq_ctx = ctx;
list_move_tail(&rq->queuelist, &ctx->rq_list);
}
hctx = q->mq_ops->map_queue(q, ctx->cpu);
blk_mq_hctx_mark_pending(hctx, ctx);
spin_unlock(&ctx->lock);
blk_mq_run_hw_queue(hctx, true); blk_mq_run_hw_queue(hctx, true);
blk_mq_put_ctx(ctx);
return NOTIFY_OK; return NOTIFY_OK;
} }

View File

@ -366,7 +366,7 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq)
list_for_each_prev(entry, &q->queue_head) { list_for_each_prev(entry, &q->queue_head) {
struct request *pos = list_entry_rq(entry); struct request *pos = list_entry_rq(entry);
if ((req_op(rq) == REQ_OP_DISCARD) != (req_op(pos) == REQ_OP_DISCARD)) if (req_op(rq) != req_op(pos))
break; break;
if (rq_data_dir(rq) != rq_data_dir(pos)) if (rq_data_dir(rq) != rq_data_dir(pos))
break; break;

View File

@ -3706,22 +3706,21 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
if (UFDCS->rawcmd == 1) if (UFDCS->rawcmd == 1)
UFDCS->rawcmd = 2; UFDCS->rawcmd = 2;
if (mode & (FMODE_READ|FMODE_WRITE)) { if (!(mode & FMODE_NDELAY)) {
UDRS->last_checked = 0; if (mode & (FMODE_READ|FMODE_WRITE)) {
clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); UDRS->last_checked = 0;
check_disk_change(bdev); clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) check_disk_change(bdev);
goto out; if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) goto out;
if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
goto out;
}
res = -EROFS;
if ((mode & FMODE_WRITE) &&
!test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
goto out; goto out;
} }
res = -EROFS;
if ((mode & FMODE_WRITE) &&
!test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
goto out;
mutex_unlock(&open_lock); mutex_unlock(&open_lock);
mutex_unlock(&floppy_mutex); mutex_unlock(&floppy_mutex);
return 0; return 0;

View File

@ -189,6 +189,8 @@ struct blkfront_info
struct mutex mutex; struct mutex mutex;
struct xenbus_device *xbdev; struct xenbus_device *xbdev;
struct gendisk *gd; struct gendisk *gd;
u16 sector_size;
unsigned int physical_sector_size;
int vdevice; int vdevice;
blkif_vdev_t handle; blkif_vdev_t handle;
enum blkif_state connected; enum blkif_state connected;
@ -910,9 +912,45 @@ static struct blk_mq_ops blkfront_mq_ops = {
.map_queue = blk_mq_map_queue, .map_queue = blk_mq_map_queue,
}; };
static void blkif_set_queue_limits(struct blkfront_info *info)
{
struct request_queue *rq = info->rq;
struct gendisk *gd = info->gd;
unsigned int segments = info->max_indirect_segments ? :
BLKIF_MAX_SEGMENTS_PER_REQUEST;
queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
if (info->feature_discard) {
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, rq);
blk_queue_max_discard_sectors(rq, get_capacity(gd));
rq->limits.discard_granularity = info->discard_granularity;
rq->limits.discard_alignment = info->discard_alignment;
if (info->feature_secdiscard)
queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, rq);
}
/* Hard sector size and max sectors impersonate the equiv. hardware. */
blk_queue_logical_block_size(rq, info->sector_size);
blk_queue_physical_block_size(rq, info->physical_sector_size);
blk_queue_max_hw_sectors(rq, (segments * XEN_PAGE_SIZE) / 512);
/* Each segment in a request is up to an aligned page in size. */
blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
blk_queue_max_segment_size(rq, PAGE_SIZE);
/* Ensure a merged request will fit in a single I/O ring slot. */
blk_queue_max_segments(rq, segments / GRANTS_PER_PSEG);
/* Make sure buffer addresses are sector-aligned. */
blk_queue_dma_alignment(rq, 511);
/* Make sure we don't use bounce buffers. */
blk_queue_bounce_limit(rq, BLK_BOUNCE_ANY);
}
static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size, static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
unsigned int physical_sector_size, unsigned int physical_sector_size)
unsigned int segments)
{ {
struct request_queue *rq; struct request_queue *rq;
struct blkfront_info *info = gd->private_data; struct blkfront_info *info = gd->private_data;
@ -944,36 +982,11 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
} }
rq->queuedata = info; rq->queuedata = info;
queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq); info->rq = gd->queue = rq;
info->gd = gd;
if (info->feature_discard) { info->sector_size = sector_size;
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, rq); info->physical_sector_size = physical_sector_size;
blk_queue_max_discard_sectors(rq, get_capacity(gd)); blkif_set_queue_limits(info);
rq->limits.discard_granularity = info->discard_granularity;
rq->limits.discard_alignment = info->discard_alignment;
if (info->feature_secdiscard)
queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, rq);
}
/* Hard sector size and max sectors impersonate the equiv. hardware. */
blk_queue_logical_block_size(rq, sector_size);
blk_queue_physical_block_size(rq, physical_sector_size);
blk_queue_max_hw_sectors(rq, (segments * XEN_PAGE_SIZE) / 512);
/* Each segment in a request is up to an aligned page in size. */
blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
blk_queue_max_segment_size(rq, PAGE_SIZE);
/* Ensure a merged request will fit in a single I/O ring slot. */
blk_queue_max_segments(rq, segments / GRANTS_PER_PSEG);
/* Make sure buffer addresses are sector-aligned. */
blk_queue_dma_alignment(rq, 511);
/* Make sure we don't use bounce buffers. */
blk_queue_bounce_limit(rq, BLK_BOUNCE_ANY);
gd->queue = rq;
return 0; return 0;
} }
@ -1136,16 +1149,11 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
gd->private_data = info; gd->private_data = info;
set_capacity(gd, capacity); set_capacity(gd, capacity);
if (xlvbd_init_blk_queue(gd, sector_size, physical_sector_size, if (xlvbd_init_blk_queue(gd, sector_size, physical_sector_size)) {
info->max_indirect_segments ? :
BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
del_gendisk(gd); del_gendisk(gd);
goto release; goto release;
} }
info->rq = gd->queue;
info->gd = gd;
xlvbd_flush(info); xlvbd_flush(info);
if (vdisk_info & VDISK_READONLY) if (vdisk_info & VDISK_READONLY)
@ -1315,7 +1323,7 @@ free_shadow:
rinfo->ring_ref[i] = GRANT_INVALID_REF; rinfo->ring_ref[i] = GRANT_INVALID_REF;
} }
} }
free_pages((unsigned long)rinfo->ring.sring, get_order(info->nr_ring_pages * PAGE_SIZE)); free_pages((unsigned long)rinfo->ring.sring, get_order(info->nr_ring_pages * XEN_PAGE_SIZE));
rinfo->ring.sring = NULL; rinfo->ring.sring = NULL;
if (rinfo->irq) if (rinfo->irq)
@ -2007,8 +2015,10 @@ static int blkif_recover(struct blkfront_info *info)
struct split_bio *split_bio; struct split_bio *split_bio;
blkfront_gather_backend_features(info); blkfront_gather_backend_features(info);
/* Reset limits changed by blk_mq_update_nr_hw_queues(). */
blkif_set_queue_limits(info);
segs = info->max_indirect_segments ? : BLKIF_MAX_SEGMENTS_PER_REQUEST; segs = info->max_indirect_segments ? : BLKIF_MAX_SEGMENTS_PER_REQUEST;
blk_queue_max_segments(info->rq, segs); blk_queue_max_segments(info->rq, segs / GRANTS_PER_PSEG);
for (r_index = 0; r_index < info->nr_rings; r_index++) { for (r_index = 0; r_index < info->nr_rings; r_index++) {
struct blkfront_ring_info *rinfo = &info->rinfo[r_index]; struct blkfront_ring_info *rinfo = &info->rinfo[r_index];
@ -2432,7 +2442,7 @@ static void blkfront_connect(struct blkfront_info *info)
if (err) { if (err) {
xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
info->xbdev->otherend); info->xbdev->otherend);
return; goto fail;
} }
xenbus_switch_state(info->xbdev, XenbusStateConnected); xenbus_switch_state(info->xbdev, XenbusStateConnected);
@ -2445,6 +2455,11 @@ static void blkfront_connect(struct blkfront_info *info)
device_add_disk(&info->xbdev->dev, info->gd); device_add_disk(&info->xbdev->dev, info->gd);
info->is_ready = 1; info->is_ready = 1;
return;
fail:
blkif_free(info, 0);
return;
} }
/** /**

View File

@ -760,7 +760,8 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
if (!d->nr_stripes || if (!d->nr_stripes ||
d->nr_stripes > INT_MAX || d->nr_stripes > INT_MAX ||
d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) { d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) {
pr_err("nr_stripes too large"); pr_err("nr_stripes too large or invalid: %u (start sector beyond end of disk?)",
(unsigned)d->nr_stripes);
return -ENOMEM; return -ENOMEM;
} }
@ -1820,7 +1821,7 @@ static int cache_alloc(struct cache *ca)
free = roundup_pow_of_two(ca->sb.nbuckets) >> 10; free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
if (!init_fifo(&ca->free[RESERVE_BTREE], 8, GFP_KERNEL) || if (!init_fifo(&ca->free[RESERVE_BTREE], 8, GFP_KERNEL) ||
!init_fifo(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) || !init_fifo_exact(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) ||
!init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) || !init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) ||
!init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) || !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) ||
!init_fifo(&ca->free_inc, free << 2, GFP_KERNEL) || !init_fifo(&ca->free_inc, free << 2, GFP_KERNEL) ||
@ -1844,7 +1845,7 @@ static int register_cache(struct cache_sb *sb, struct page *sb_page,
struct block_device *bdev, struct cache *ca) struct block_device *bdev, struct cache *ca)
{ {
char name[BDEVNAME_SIZE]; char name[BDEVNAME_SIZE];
const char *err = NULL; const char *err = NULL; /* must be set for any error case */
int ret = 0; int ret = 0;
memcpy(&ca->sb, sb, sizeof(struct cache_sb)); memcpy(&ca->sb, sb, sizeof(struct cache_sb));
@ -1861,8 +1862,13 @@ static int register_cache(struct cache_sb *sb, struct page *sb_page,
ca->discard = CACHE_DISCARD(&ca->sb); ca->discard = CACHE_DISCARD(&ca->sb);
ret = cache_alloc(ca); ret = cache_alloc(ca);
if (ret != 0) if (ret != 0) {
if (ret == -ENOMEM)
err = "cache_alloc(): -ENOMEM";
else
err = "cache_alloc(): unknown error";
goto err; goto err;
}
if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) { if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) {
err = "error calling kobject_add"; err = "error calling kobject_add";

View File

@ -1726,6 +1726,7 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
break; break;
if (req_op(next) == REQ_OP_DISCARD || if (req_op(next) == REQ_OP_DISCARD ||
req_op(next) == REQ_OP_SECURE_ERASE ||
req_op(next) == REQ_OP_FLUSH) req_op(next) == REQ_OP_FLUSH)
break; break;
@ -2150,6 +2151,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
struct mmc_card *card = md->queue.card; struct mmc_card *card = md->queue.card;
struct mmc_host *host = card->host; struct mmc_host *host = card->host;
unsigned long flags; unsigned long flags;
bool req_is_special = mmc_req_is_special(req);
if (req && !mq->mqrq_prev->req) if (req && !mq->mqrq_prev->req)
/* claim host only for the first request */ /* claim host only for the first request */
@ -2190,8 +2192,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
} }
out: out:
if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || req_is_special)
mmc_req_is_special(req))
/* /*
* Release host when there are no more requests * Release host when there are no more requests
* and after special request(discard, flush) is done. * and after special request(discard, flush) is done.

View File

@ -33,7 +33,8 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
/* /*
* We only like normal block requests and discards. * We only like normal block requests and discards.
*/ */
if (req->cmd_type != REQ_TYPE_FS && req_op(req) != REQ_OP_DISCARD) { if (req->cmd_type != REQ_TYPE_FS && req_op(req) != REQ_OP_DISCARD &&
req_op(req) != REQ_OP_SECURE_ERASE) {
blk_dump_rq_flags(req, "MMC bad request"); blk_dump_rq_flags(req, "MMC bad request");
return BLKPREP_KILL; return BLKPREP_KILL;
} }
@ -64,6 +65,8 @@ static int mmc_queue_thread(void *d)
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
if (req || mq->mqrq_prev->req) { if (req || mq->mqrq_prev->req) {
bool req_is_special = mmc_req_is_special(req);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
mq->issue_fn(mq, req); mq->issue_fn(mq, req);
cond_resched(); cond_resched();
@ -79,7 +82,7 @@ static int mmc_queue_thread(void *d)
* has been finished. Do not assign it to previous * has been finished. Do not assign it to previous
* request. * request.
*/ */
if (mmc_req_is_special(req)) if (req_is_special)
mq->mqrq_cur->req = NULL; mq->mqrq_cur->req = NULL;
mq->mqrq_prev->brq.mrq.data = NULL; mq->mqrq_prev->brq.mrq.data = NULL;

View File

@ -4,7 +4,9 @@
static inline bool mmc_req_is_special(struct request *req) static inline bool mmc_req_is_special(struct request *req)
{ {
return req && return req &&
(req_op(req) == REQ_OP_FLUSH || req_op(req) == REQ_OP_DISCARD); (req_op(req) == REQ_OP_FLUSH ||
req_op(req) == REQ_OP_DISCARD ||
req_op(req) == REQ_OP_SECURE_ERASE);
} }
struct request; struct request;

View File

@ -81,10 +81,12 @@ EXPORT_SYMBOL_GPL(nvme_cancel_request);
bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
enum nvme_ctrl_state new_state) enum nvme_ctrl_state new_state)
{ {
enum nvme_ctrl_state old_state = ctrl->state; enum nvme_ctrl_state old_state;
bool changed = false; bool changed = false;
spin_lock_irq(&ctrl->lock); spin_lock_irq(&ctrl->lock);
old_state = ctrl->state;
switch (new_state) { switch (new_state) {
case NVME_CTRL_LIVE: case NVME_CTRL_LIVE:
switch (old_state) { switch (old_state) {
@ -140,11 +142,12 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
default: default:
break; break;
} }
spin_unlock_irq(&ctrl->lock);
if (changed) if (changed)
ctrl->state = new_state; ctrl->state = new_state;
spin_unlock_irq(&ctrl->lock);
return changed; return changed;
} }
EXPORT_SYMBOL_GPL(nvme_change_ctrl_state); EXPORT_SYMBOL_GPL(nvme_change_ctrl_state);
@ -608,7 +611,7 @@ int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, NULL, 0, 0, ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, NULL, 0, 0,
NVME_QID_ANY, 0, 0); NVME_QID_ANY, 0, 0);
if (ret >= 0) if (ret >= 0 && result)
*result = le32_to_cpu(cqe.result); *result = le32_to_cpu(cqe.result);
return ret; return ret;
} }
@ -628,7 +631,7 @@ int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, NULL, 0, 0, ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, NULL, 0, 0,
NVME_QID_ANY, 0, 0); NVME_QID_ANY, 0, 0);
if (ret >= 0) if (ret >= 0 && result)
*result = le32_to_cpu(cqe.result); *result = le32_to_cpu(cqe.result);
return ret; return ret;
} }

View File

@ -249,7 +249,8 @@ struct super_block *freeze_bdev(struct block_device *bdev)
* thaw_bdev drops it. * thaw_bdev drops it.
*/ */
sb = get_super(bdev); sb = get_super(bdev);
drop_super(sb); if (sb)
drop_super(sb);
mutex_unlock(&bdev->bd_fsfreeze_mutex); mutex_unlock(&bdev->bd_fsfreeze_mutex);
return sb; return sb;
} }
@ -646,7 +647,7 @@ static struct dentry *bd_mount(struct file_system_type *fs_type,
{ {
struct dentry *dent; struct dentry *dent;
dent = mount_pseudo(fs_type, "bdev:", &bdev_sops, NULL, BDEVFS_MAGIC); dent = mount_pseudo(fs_type, "bdev:", &bdev_sops, NULL, BDEVFS_MAGIC);
if (dent) if (!IS_ERR(dent))
dent->d_sb->s_iflags |= SB_I_CGROUPWB; dent->d_sb->s_iflags |= SB_I_CGROUPWB;
return dent; return dent;
} }

View File

@ -71,7 +71,8 @@ static inline bool bio_has_data(struct bio *bio)
{ {
if (bio && if (bio &&
bio->bi_iter.bi_size && bio->bi_iter.bi_size &&
bio_op(bio) != REQ_OP_DISCARD) bio_op(bio) != REQ_OP_DISCARD &&
bio_op(bio) != REQ_OP_SECURE_ERASE)
return true; return true;
return false; return false;
@ -79,7 +80,9 @@ static inline bool bio_has_data(struct bio *bio)
static inline bool bio_no_advance_iter(struct bio *bio) static inline bool bio_no_advance_iter(struct bio *bio)
{ {
return bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_WRITE_SAME; return bio_op(bio) == REQ_OP_DISCARD ||
bio_op(bio) == REQ_OP_SECURE_ERASE ||
bio_op(bio) == REQ_OP_WRITE_SAME;
} }
static inline bool bio_is_rw(struct bio *bio) static inline bool bio_is_rw(struct bio *bio)
@ -199,6 +202,9 @@ static inline unsigned bio_segments(struct bio *bio)
if (bio_op(bio) == REQ_OP_DISCARD) if (bio_op(bio) == REQ_OP_DISCARD)
return 1; return 1;
if (bio_op(bio) == REQ_OP_SECURE_ERASE)
return 1;
if (bio_op(bio) == REQ_OP_WRITE_SAME) if (bio_op(bio) == REQ_OP_WRITE_SAME)
return 1; return 1;

View File

@ -882,7 +882,7 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq)
static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q, static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
int op) int op)
{ {
if (unlikely(op == REQ_OP_DISCARD)) if (unlikely(op == REQ_OP_DISCARD || op == REQ_OP_SECURE_ERASE))
return min(q->limits.max_discard_sectors, UINT_MAX >> 9); return min(q->limits.max_discard_sectors, UINT_MAX >> 9);
if (unlikely(op == REQ_OP_WRITE_SAME)) if (unlikely(op == REQ_OP_WRITE_SAME))
@ -913,7 +913,9 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq,
if (unlikely(rq->cmd_type != REQ_TYPE_FS)) if (unlikely(rq->cmd_type != REQ_TYPE_FS))
return q->limits.max_hw_sectors; return q->limits.max_hw_sectors;
if (!q->limits.chunk_sectors || (req_op(rq) == REQ_OP_DISCARD)) if (!q->limits.chunk_sectors ||
req_op(rq) == REQ_OP_DISCARD ||
req_op(rq) == REQ_OP_SECURE_ERASE)
return blk_queue_get_max_sectors(q, req_op(rq)); return blk_queue_get_max_sectors(q, req_op(rq));
return min(blk_max_size_offset(q, offset), return min(blk_max_size_offset(q, offset),

View File

@ -223,7 +223,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
what |= MASK_TC_BIT(op_flags, META); what |= MASK_TC_BIT(op_flags, META);
what |= MASK_TC_BIT(op_flags, PREFLUSH); what |= MASK_TC_BIT(op_flags, PREFLUSH);
what |= MASK_TC_BIT(op_flags, FUA); what |= MASK_TC_BIT(op_flags, FUA);
if (op == REQ_OP_DISCARD) if (op == REQ_OP_DISCARD || op == REQ_OP_SECURE_ERASE)
what |= BLK_TC_ACT(BLK_TC_DISCARD); what |= BLK_TC_ACT(BLK_TC_DISCARD);
if (op == REQ_OP_FLUSH) if (op == REQ_OP_FLUSH)
what |= BLK_TC_ACT(BLK_TC_FLUSH); what |= BLK_TC_ACT(BLK_TC_FLUSH);