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 layer fixes from Jens Axboe:
 "A small collection of fixes for the current series. It contains:

   - A fix for a use-after-free of a request in blk-mq.  From Ming Lei

   - A fix for a blk-mq bug that could attempt to dereference a NULL rq
     if allocation failed

   - Two xen-blkfront small fixes

   - Cleanup of submit_bio_wait() type uses in the kernel, unifying
     that.  From Kent

   - A fix for 32-bit blkg_rwstat reading.  I apologize for this one
     looking mangled in the shortlog, it's entirely my fault for missing
     an empty line between the description and body of the text"

* 'for-linus' of git://git.kernel.dk/linux-block:
  blk-mq: fix use-after-free of request
  blk-mq: fix dereference of rq->mq_ctx if allocation fails
  block: xen-blkfront: Fix possible NULL ptr dereference
  xen-blkfront: Silence pfn maybe-uninitialized warning
  block: submit_bio_wait() conversions
  Update of blkg_stat and blkg_rwstat may happen in bh context
  • Loading branch information
torvalds committed Dec 5, 2013
2 parents 29be634 + 0d11e6a commit 5ee5406
Show file tree
Hide file tree
Showing 11 changed files with 44 additions and 127 deletions.
8 changes: 4 additions & 4 deletions block/blk-cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,9 @@ static inline uint64_t blkg_stat_read(struct blkg_stat *stat)
uint64_t v;

do {
start = u64_stats_fetch_begin(&stat->syncp);
start = u64_stats_fetch_begin_bh(&stat->syncp);
v = stat->cnt;
} while (u64_stats_fetch_retry(&stat->syncp, start));
} while (u64_stats_fetch_retry_bh(&stat->syncp, start));

return v;
}
Expand Down Expand Up @@ -508,9 +508,9 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat)
struct blkg_rwstat tmp;

do {
start = u64_stats_fetch_begin(&rwstat->syncp);
start = u64_stats_fetch_begin_bh(&rwstat->syncp);
tmp = *rwstat;
} while (u64_stats_fetch_retry(&rwstat->syncp, start));
} while (u64_stats_fetch_retry_bh(&rwstat->syncp, start));

return tmp;
}
Expand Down
19 changes: 1 addition & 18 deletions block/blk-flush.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,15 +502,6 @@ void blk_abort_flushes(struct request_queue *q)
}
}

static void bio_end_flush(struct bio *bio, int err)
{
if (err)
clear_bit(BIO_UPTODATE, &bio->bi_flags);
if (bio->bi_private)
complete(bio->bi_private);
bio_put(bio);
}

/**
* blkdev_issue_flush - queue a flush
* @bdev: blockdev to issue flush for
Expand All @@ -526,7 +517,6 @@ static void bio_end_flush(struct bio *bio, int err)
int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
sector_t *error_sector)
{
DECLARE_COMPLETION_ONSTACK(wait);
struct request_queue *q;
struct bio *bio;
int ret = 0;
Expand All @@ -548,13 +538,9 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
return -ENXIO;

bio = bio_alloc(gfp_mask, 0);
bio->bi_end_io = bio_end_flush;
bio->bi_bdev = bdev;
bio->bi_private = &wait;

bio_get(bio);
submit_bio(WRITE_FLUSH, bio);
wait_for_completion_io(&wait);
ret = submit_bio_wait(WRITE_FLUSH, bio);

/*
* The driver must store the error location in ->bi_sector, if
Expand All @@ -564,9 +550,6 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
if (error_sector)
*error_sector = bio->bi_sector;

if (!bio_flagged(bio, BIO_UPTODATE))
ret = -EIO;

bio_put(bio);
return ret;
}
Expand Down
16 changes: 10 additions & 6 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,12 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q,
if (rq) {
blk_mq_rq_ctx_init(q, ctx, rq, rw);
break;
} else if (!(gfp & __GFP_WAIT))
break;
}

blk_mq_put_ctx(ctx);
if (!(gfp & __GFP_WAIT))
break;

__blk_mq_run_hw_queue(hctx);
blk_mq_wait_for_tags(hctx->tags);
} while (1);
Expand All @@ -222,7 +224,8 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
return NULL;

rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved);
blk_mq_put_ctx(rq->mq_ctx);
if (rq)
blk_mq_put_ctx(rq->mq_ctx);
return rq;
}

Expand All @@ -235,7 +238,8 @@ struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw,
return NULL;

rq = blk_mq_alloc_request_pinned(q, rw, gfp, true);
blk_mq_put_ctx(rq->mq_ctx);
if (rq)
blk_mq_put_ctx(rq->mq_ctx);
return rq;
}
EXPORT_SYMBOL(blk_mq_alloc_reserved_request);
Expand Down Expand Up @@ -308,12 +312,12 @@ void blk_mq_complete_request(struct request *rq, int error)

blk_account_io_completion(rq, bytes);

blk_account_io_done(rq);

if (rq->end_io)
rq->end_io(rq, error);
else
blk_mq_free_request(rq);

blk_account_io_done(rq);
}

void __blk_mq_end_io(struct request *rq, int error)
Expand Down
7 changes: 6 additions & 1 deletion drivers/block/xen-blkfront.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ static int blkif_queue_request(struct request *req)

if ((ring_req->operation == BLKIF_OP_INDIRECT) &&
(i % SEGS_PER_INDIRECT_FRAME == 0)) {
unsigned long pfn;
unsigned long uninitialized_var(pfn);

if (segments)
kunmap_atomic(segments);
Expand Down Expand Up @@ -2011,6 +2011,10 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)

bdev = bdget_disk(disk, 0);

if (!bdev) {
WARN(1, "Block device %s yanked out from us!\n", disk->disk_name);
goto out_mutex;
}
if (bdev->bd_openers)
goto out;

Expand Down Expand Up @@ -2041,6 +2045,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)

out:
bdput(bdev);
out_mutex:
mutex_unlock(&blkfront_mutex);
}

Expand Down
12 changes: 1 addition & 11 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,16 +776,10 @@ void md_super_wait(struct mddev *mddev)
finish_wait(&mddev->sb_wait, &wq);
}

static void bi_complete(struct bio *bio, int error)
{
complete((struct completion*)bio->bi_private);
}

int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
struct page *page, int rw, bool metadata_op)
{
struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
struct completion event;
int ret;

rw |= REQ_SYNC;
Expand All @@ -801,11 +795,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
else
bio->bi_sector = sector + rdev->data_offset;
bio_add_page(bio, page, size, 0);
init_completion(&event);
bio->bi_private = &event;
bio->bi_end_io = bi_complete;
submit_bio(rw, bio);
wait_for_completion(&event);
submit_bio_wait(rw, bio);

ret = test_bit(BIO_UPTODATE, &bio->bi_flags);
bio_put(bio);
Expand Down
32 changes: 13 additions & 19 deletions fs/btrfs/check-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
static int btrfsic_read_block(struct btrfsic_state *state,
struct btrfsic_block_data_ctx *block_ctx);
static void btrfsic_dump_database(struct btrfsic_state *state);
static void btrfsic_complete_bio_end_io(struct bio *bio, int err);
static int btrfsic_test_for_metadata(struct btrfsic_state *state,
char **datav, unsigned int num_pages);
static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
Expand Down Expand Up @@ -1687,7 +1686,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
for (i = 0; i < num_pages;) {
struct bio *bio;
unsigned int j;
DECLARE_COMPLETION_ONSTACK(complete);

bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
if (!bio) {
Expand All @@ -1698,8 +1696,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
}
bio->bi_bdev = block_ctx->dev->bdev;
bio->bi_sector = dev_bytenr >> 9;
bio->bi_end_io = btrfsic_complete_bio_end_io;
bio->bi_private = &complete;

for (j = i; j < num_pages; j++) {
ret = bio_add_page(bio, block_ctx->pagev[j],
Expand All @@ -1712,12 +1708,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
"btrfsic: error, failed to add a single page!\n");
return -1;
}
submit_bio(READ, bio);

/* this will also unplug the queue */
wait_for_completion(&complete);

if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
if (submit_bio_wait(READ, bio)) {
printk(KERN_INFO
"btrfsic: read error at logical %llu dev %s!\n",
block_ctx->start, block_ctx->dev->name);
Expand All @@ -1740,11 +1731,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
return block_ctx->len;
}

static void btrfsic_complete_bio_end_io(struct bio *bio, int err)
{
complete((struct completion *)bio->bi_private);
}

static void btrfsic_dump_database(struct btrfsic_state *state)
{
struct list_head *elem_all;
Expand Down Expand Up @@ -3008,14 +2994,12 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh)
return submit_bh(rw, bh);
}

void btrfsic_submit_bio(int rw, struct bio *bio)
static void __btrfsic_submit_bio(int rw, struct bio *bio)
{
struct btrfsic_dev_state *dev_state;

if (!btrfsic_is_initialized) {
submit_bio(rw, bio);
if (!btrfsic_is_initialized)
return;
}

mutex_lock(&btrfsic_mutex);
/* since btrfsic_submit_bio() is also called before
Expand Down Expand Up @@ -3106,10 +3090,20 @@ void btrfsic_submit_bio(int rw, struct bio *bio)
}
leave:
mutex_unlock(&btrfsic_mutex);
}

void btrfsic_submit_bio(int rw, struct bio *bio)
{
__btrfsic_submit_bio(rw, bio);
submit_bio(rw, bio);
}

int btrfsic_submit_bio_wait(int rw, struct bio *bio)
{
__btrfsic_submit_bio(rw, bio);
return submit_bio_wait(rw, bio);
}

int btrfsic_mount(struct btrfs_root *root,
struct btrfs_fs_devices *fs_devices,
int including_extent_data, u32 print_mask)
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/check-integrity.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
int btrfsic_submit_bh(int rw, struct buffer_head *bh);
void btrfsic_submit_bio(int rw, struct bio *bio);
int btrfsic_submit_bio_wait(int rw, struct bio *bio);
#else
#define btrfsic_submit_bh submit_bh
#define btrfsic_submit_bio submit_bio
#define btrfsic_submit_bio_wait submit_bio_wait
#endif

int btrfsic_mount(struct btrfs_root *root,
Expand Down
12 changes: 1 addition & 11 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1952,11 +1952,6 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec,
return err;
}

static void repair_io_failure_callback(struct bio *bio, int err)
{
complete(bio->bi_private);
}

/*
* this bypasses the standard btrfs submit functions deliberately, as
* the standard behavior is to write all copies in a raid setup. here we only
Expand All @@ -1973,7 +1968,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
{
struct bio *bio;
struct btrfs_device *dev;
DECLARE_COMPLETION_ONSTACK(compl);
u64 map_length = 0;
u64 sector;
struct btrfs_bio *bbio = NULL;
Expand All @@ -1990,8 +1984,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
if (!bio)
return -EIO;
bio->bi_private = &compl;
bio->bi_end_io = repair_io_failure_callback;
bio->bi_size = 0;
map_length = length;

Expand All @@ -2012,10 +2004,8 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
}
bio->bi_bdev = dev->bdev;
bio_add_page(bio, page, length, start - page_offset(page));
btrfsic_submit_bio(WRITE_SYNC, bio);
wait_for_completion(&compl);

if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
/* try to remap that extent elsewhere? */
bio_put(bio);
btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
Expand Down
Loading

0 comments on commit 5ee5406

Please sign in to comment.