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:
 "Here's the second round of block updates for this merge window.

  It's a mix of fixes for changes that went in previously in this round,
  and fixes in general.  This pull request contains:

   - Fixes for loop from Christoph

   - A bdi vs gendisk lifetime fix from Dan, worth two cookies.

   - A blk-mq timeout fix, when on frozen queues.  From Gabriel.

   - Writeback fix from Jan, ensuring that __writeback_single_inode()
     does the right thing.

   - Fix for bio->bi_rw usage in f2fs from me.

   - Error path deadlock fix in blk-mq sysfs registration from me.

   - Floppy O_ACCMODE fix from Jiri.

   - Fix to the new bio op methods from Mike.

     One more followup will be coming here, ensuring that we don't
     propagate the block types outside of block.  That, and a rename of
     bio->bi_rw is coming right after -rc1 is cut.

   - Various little fixes"

* 'for-linus' of git://git.kernel.dk/linux-block:
  mm/block: convert rw_page users to bio op use
  loop: make do_req_filebacked more robust
  loop: don't try to use AIO for discards
  blk-mq: fix deadlock in blk_mq_register_disk() error path
  Include: blkdev: Removed duplicate 'struct request;' declaration.
  Fixup direct bi_rw modifiers
  block: fix bdi vs gendisk lifetime mismatch
  blk-mq: Allow timeouts to run while queue is freezing
  nbd: fix race in ioctl
  block: fix use-after-free in seq file
  f2fs: drop bio->bi_rw manual assignment
  block: add missing group association in bio-cloning functions
  blkcg: kill unused field nr_undestroyed_grps
  writeback: Write dirty times for WB_SYNC_ALL writeback
  floppy: fix open(O_ACCMODE) for ioctl-only open
  • Loading branch information
torvalds committed Aug 6, 2016
2 parents 62e6e9b + abf5454 commit fff648d
Show file tree
Hide file tree
Showing 26 changed files with 168 additions and 136 deletions.
15 changes: 15 additions & 0 deletions block/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src)
bio->bi_rw = bio_src->bi_rw;
bio->bi_iter = bio_src->bi_iter;
bio->bi_io_vec = bio_src->bi_io_vec;

bio_clone_blkcg_association(bio, bio_src);
}
EXPORT_SYMBOL(__bio_clone_fast);

Expand Down Expand Up @@ -687,6 +689,8 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
}
}

bio_clone_blkcg_association(bio, bio_src);

return bio;
}
EXPORT_SYMBOL(bio_clone_bioset);
Expand Down Expand Up @@ -2004,6 +2008,17 @@ void bio_disassociate_task(struct bio *bio)
}
}

/**
* bio_clone_blkcg_association - clone blkcg association from src to dst bio
* @dst: destination bio
* @src: source bio
*/
void bio_clone_blkcg_association(struct bio *dst, struct bio *src)
{
if (src->bi_css)
WARN_ON(bio_associate_blkcg(dst, src->bi_css));
}

#endif /* CONFIG_BLK_CGROUP */

static void __init biovec_init_slabs(void)
Expand Down
12 changes: 8 additions & 4 deletions block/blk-mq-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,15 +380,13 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
return ret;
}

void blk_mq_unregister_disk(struct gendisk *disk)
static void __blk_mq_unregister_disk(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
struct blk_mq_hw_ctx *hctx;
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 @@ -405,6 +403,12 @@ void blk_mq_unregister_disk(struct gendisk *disk)
kobject_put(&disk_to_dev(disk)->kobj);

q->mq_sysfs_init_done = false;
}

void blk_mq_unregister_disk(struct gendisk *disk)
{
blk_mq_disable_hotplug();
__blk_mq_unregister_disk(disk);
blk_mq_enable_hotplug();
}

Expand Down Expand Up @@ -450,7 +454,7 @@ int blk_mq_register_disk(struct gendisk *disk)
}

if (ret)
blk_mq_unregister_disk(disk);
__blk_mq_unregister_disk(disk);
else
q->mq_sysfs_init_done = true;
out:
Expand Down
15 changes: 14 additions & 1 deletion block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,20 @@ static void blk_mq_timeout_work(struct work_struct *work)
};
int i;

if (blk_queue_enter(q, true))
/* A deadlock might occur if a request is stuck requiring a
* timeout at the same time a queue freeze is waiting
* completion, since the timeout code would not be able to
* acquire the queue reference here.
*
* That's why we don't use blk_queue_enter here; instead, we use
* percpu_ref_tryget directly, because we need to be able to
* obtain a reference even in the short window between the queue
* starting to freeze, by dropping the first reference in
* blk_mq_freeze_queue_start, and the moment the last request is
* consumed, marked by the instant q_usage_counter reaches
* zero.
*/
if (!percpu_ref_tryget(&q->q_usage_counter))
return;

blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &data);
Expand Down
5 changes: 0 additions & 5 deletions block/blk-throttle.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,6 @@ struct throtl_data
/* Total Number of queued bios on READ and WRITE lists */
unsigned int nr_queued[2];

/*
* number of total undestroyed groups
*/
unsigned int nr_undestroyed_grps;

/* Work for dispatching throttled bios */
struct work_struct dispatch_work;
};
Expand Down
3 changes: 2 additions & 1 deletion block/genhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ void device_add_disk(struct device *parent, struct gendisk *disk)

/* Register BDI before referencing it from bdev */
bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, disk_devt(disk));
bdi_register_owner(bdi, disk_to_dev(disk));

blk_register_region(disk_devt(disk), disk->minors, NULL,
exact_match, exact_lock, disk);
Expand Down Expand Up @@ -856,6 +856,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v)
if (iter) {
class_dev_iter_exit(iter);
kfree(iter);
seqf->private = NULL;
}
}

Expand Down
17 changes: 7 additions & 10 deletions drivers/block/brd.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,20 +300,20 @@ static void copy_from_brd(void *dst, struct brd_device *brd,
* Process a single bvec of a bio.
*/
static int brd_do_bvec(struct brd_device *brd, struct page *page,
unsigned int len, unsigned int off, int rw,
unsigned int len, unsigned int off, int op,
sector_t sector)
{
void *mem;
int err = 0;

if (rw != READ) {
if (op_is_write(op)) {
err = copy_to_brd_setup(brd, sector, len);
if (err)
goto out;
}

mem = kmap_atomic(page);
if (rw == READ) {
if (!op_is_write(op)) {
copy_from_brd(mem + off, brd, sector, len);
flush_dcache_page(page);
} else {
Expand All @@ -330,7 +330,6 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
struct brd_device *brd = bdev->bd_disk->private_data;
int rw;
struct bio_vec bvec;
sector_t sector;
struct bvec_iter iter;
Expand All @@ -347,14 +346,12 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
goto out;
}

rw = bio_data_dir(bio);

bio_for_each_segment(bvec, bio, iter) {
unsigned int len = bvec.bv_len;
int err;

err = brd_do_bvec(brd, bvec.bv_page, len,
bvec.bv_offset, rw, sector);
bvec.bv_offset, bio_op(bio), sector);
if (err)
goto io_error;
sector += len >> SECTOR_SHIFT;
Expand All @@ -369,11 +366,11 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
}

static int brd_rw_page(struct block_device *bdev, sector_t sector,
struct page *page, int rw)
struct page *page, int op)
{
struct brd_device *brd = bdev->bd_disk->private_data;
int err = brd_do_bvec(brd, page, PAGE_SIZE, 0, rw, sector);
page_endio(page, rw & WRITE, err);
int err = brd_do_bvec(brd, page, PAGE_SIZE, 0, op, sector);
page_endio(page, op, err);
return err;
}

Expand Down
21 changes: 9 additions & 12 deletions drivers/block/floppy.c
Original file line number Diff line number Diff line change
Expand Up @@ -3663,11 +3663,6 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)

opened_bdev[drive] = bdev;

if (!(mode & (FMODE_READ|FMODE_WRITE))) {
res = -EINVAL;
goto out;
}

res = -ENXIO;

if (!floppy_track_buffer) {
Expand Down Expand Up @@ -3711,13 +3706,15 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
if (UFDCS->rawcmd == 1)
UFDCS->rawcmd = 2;

UDRS->last_checked = 0;
clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
check_disk_change(bdev);
if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
goto out;
if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
goto out;
if (mode & (FMODE_READ|FMODE_WRITE)) {
UDRS->last_checked = 0;
clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
check_disk_change(bdev);
if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
goto out;
if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
goto out;
}

res = -EROFS;

Expand Down
67 changes: 30 additions & 37 deletions drivers/block/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,14 +510,10 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
return 0;
}


static inline int lo_rw_simple(struct loop_device *lo,
struct request *rq, loff_t pos, bool rw)
static int do_req_filebacked(struct loop_device *lo, struct request *rq)
{
struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);

if (cmd->use_aio)
return lo_rw_aio(lo, cmd, pos, rw);
loff_t pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset;

/*
* lo_write_simple and lo_read_simple should have been covered
Expand All @@ -528,37 +524,30 @@ static inline int lo_rw_simple(struct loop_device *lo,
* of the req at one time. And direct read IO doesn't need to
* run flush_dcache_page().
*/
if (rw == WRITE)
return lo_write_simple(lo, rq, pos);
else
return lo_read_simple(lo, rq, pos);
}

static int do_req_filebacked(struct loop_device *lo, struct request *rq)
{
loff_t pos;
int ret;

pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset;

if (op_is_write(req_op(rq))) {
if (req_op(rq) == REQ_OP_FLUSH)
ret = lo_req_flush(lo, rq);
else if (req_op(rq) == REQ_OP_DISCARD)
ret = lo_discard(lo, rq, pos);
else if (lo->transfer)
ret = lo_write_transfer(lo, rq, pos);
switch (req_op(rq)) {
case REQ_OP_FLUSH:
return lo_req_flush(lo, rq);
case REQ_OP_DISCARD:
return lo_discard(lo, rq, pos);
case REQ_OP_WRITE:
if (lo->transfer)
return lo_write_transfer(lo, rq, pos);
else if (cmd->use_aio)
return lo_rw_aio(lo, cmd, pos, WRITE);
else
ret = lo_rw_simple(lo, rq, pos, WRITE);

} else {
return lo_write_simple(lo, rq, pos);
case REQ_OP_READ:
if (lo->transfer)
ret = lo_read_transfer(lo, rq, pos);
return lo_read_transfer(lo, rq, pos);
else if (cmd->use_aio)
return lo_rw_aio(lo, cmd, pos, READ);
else
ret = lo_rw_simple(lo, rq, pos, READ);
return lo_read_simple(lo, rq, pos);
default:
WARN_ON_ONCE(1);
return -EIO;
break;
}

return ret;
}

struct switch_request {
Expand Down Expand Up @@ -1659,11 +1648,15 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
if (lo->lo_state != Lo_bound)
return -EIO;

if (lo->use_dio && (req_op(cmd->rq) != REQ_OP_FLUSH ||
req_op(cmd->rq) == REQ_OP_DISCARD))
cmd->use_aio = true;
else
switch (req_op(cmd->rq)) {
case REQ_OP_FLUSH:
case REQ_OP_DISCARD:
cmd->use_aio = false;
break;
default:
cmd->use_aio = lo->use_dio;
break;
}

queue_kthread_work(&lo->worker, &cmd->work);

Expand Down
12 changes: 4 additions & 8 deletions drivers/block/nbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,14 +451,9 @@ static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)

sk_set_memalloc(nbd->sock->sk);

nbd->task_recv = current;

ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
if (ret) {
dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");

nbd->task_recv = NULL;

return ret;
}

Expand All @@ -477,9 +472,6 @@ static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
nbd_size_clear(nbd, bdev);

device_remove_file(disk_to_dev(nbd->disk), &pid_attr);

nbd->task_recv = NULL;

return ret;
}

Expand Down Expand Up @@ -788,6 +780,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
if (!nbd->sock)
return -EINVAL;

/* We have to claim the device under the lock */
nbd->task_recv = current;
mutex_unlock(&nbd->tx_lock);

nbd_parse_flags(nbd, bdev);
Expand All @@ -796,6 +790,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
nbd_name(nbd));
if (IS_ERR(thread)) {
mutex_lock(&nbd->tx_lock);
nbd->task_recv = NULL;
return PTR_ERR(thread);
}

Expand All @@ -805,6 +800,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
kthread_stop(thread);

mutex_lock(&nbd->tx_lock);
nbd->task_recv = NULL;

sock_shutdown(nbd);
nbd_clear_que(nbd);
Expand Down
Loading

0 comments on commit fff648d

Please sign in to comment.