Commit 50e73a4a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull block fixes from Jens Axboe:

 - Revert of a bcache patch that caused an oops for some (Coly)

 - ata rb532 unused warning fix (Gustavo)

 - AoE kernel crash fix (He)

 - Error handling fixup for blkdev_get() (Jan)

 - libata read/write translation and SFF PIO fix (me)

 - Use after free and error handling fix for O_DIRECT fragments. There's
   still a nowait + sync oddity in there, we'll nail that start next
   week. If all else fails, I'll queue a revert of the NOWAIT change.
   (me)

 - Loop GFP_KERNEL -> GFP_NOIO deadlock fix (Mikulas)

 - Two BFQ regression fixes that caused crashes (Paolo)

* tag 'for-linus-20190809' of git://git.kernel.dk/linux-block:
  bcache: Revert "bcache: use sysfs_match_string() instead of __sysfs_match_string()"
  loop: set PF_MEMALLOC_NOIO for the worker thread
  bdev: Fixup error handling in blkdev_get()
  block, bfq: handle NULL return value by bfq_init_rq()
  block, bfq: move update of waker and woken list to queue freeing
  block, bfq: reset last_completed_rq_bfqq if the pointed queue is freed
  block: aoe: Fix kernel crash due to atomic sleep when exiting
  libata: add SG safety checks in SFF pio transfers
  libata: have ata_scsi_rw_xlat() fail invalid passthrough requests
  block: fix O_DIRECT error handling for bio fragments
  ata: rb532_cf: Fix unused variable warning in rb532_pata_driver_probe
parents 461d2815 20621fed
Loading
Loading
Loading
Loading
+47 −21
Original line number Diff line number Diff line
@@ -1924,7 +1924,8 @@ static void bfq_add_request(struct request *rq)
		 * confirmed no later than during the next
		 * I/O-plugging interval for bfqq.
		 */
		if (!bfq_bfqq_has_short_ttime(bfqq) &&
		if (bfqd->last_completed_rq_bfqq &&
		    !bfq_bfqq_has_short_ttime(bfqq) &&
		    ktime_get_ns() - bfqd->last_completion <
		    200 * NSEC_PER_USEC) {
			if (bfqd->last_completed_rq_bfqq != bfqq &&
@@ -2250,9 +2251,14 @@ static void bfq_request_merged(struct request_queue *q, struct request *req,
	    blk_rq_pos(container_of(rb_prev(&req->rb_node),
				    struct request, rb_node))) {
		struct bfq_queue *bfqq = bfq_init_rq(req);
		struct bfq_data *bfqd = bfqq->bfqd;
		struct bfq_data *bfqd;
		struct request *prev, *next_rq;

		if (!bfqq)
			return;

		bfqd = bfqq->bfqd;

		/* Reposition request in its sort_list */
		elv_rb_del(&bfqq->sort_list, req);
		elv_rb_add(&bfqq->sort_list, req);
@@ -2299,6 +2305,9 @@ static void bfq_requests_merged(struct request_queue *q, struct request *rq,
	struct bfq_queue *bfqq = bfq_init_rq(rq),
		*next_bfqq = bfq_init_rq(next);

	if (!bfqq)
		return;

	/*
	 * If next and rq belong to the same bfq_queue and next is older
	 * than rq, then reposition rq in the fifo (by substituting next
@@ -4764,6 +4773,8 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
 */
void bfq_put_queue(struct bfq_queue *bfqq)
{
	struct bfq_queue *item;
	struct hlist_node *n;
#ifdef CONFIG_BFQ_GROUP_IOSCHED
	struct bfq_group *bfqg = bfqq_group(bfqq);
#endif
@@ -4808,6 +4819,36 @@ void bfq_put_queue(struct bfq_queue *bfqq)
			bfqq->bfqd->burst_size--;
	}

	/*
	 * bfqq does not exist any longer, so it cannot be woken by
	 * any other queue, and cannot wake any other queue. Then bfqq
	 * must be removed from the woken list of its possible waker
	 * queue, and all queues in the woken list of bfqq must stop
	 * having a waker queue. Strictly speaking, these updates
	 * should be performed when bfqq remains with no I/O source
	 * attached to it, which happens before bfqq gets freed. In
	 * particular, this happens when the last process associated
	 * with bfqq exits or gets associated with a different
	 * queue. However, both events lead to bfqq being freed soon,
	 * and dangling references would come out only after bfqq gets
	 * freed. So these updates are done here, as a simple and safe
	 * way to handle all cases.
	 */
	/* remove bfqq from woken list */
	if (!hlist_unhashed(&bfqq->woken_list_node))
		hlist_del_init(&bfqq->woken_list_node);

	/* reset waker for all queues in woken list */
	hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
				  woken_list_node) {
		item->waker_bfqq = NULL;
		bfq_clear_bfqq_has_waker(item);
		hlist_del_init(&item->woken_list_node);
	}

	if (bfqq->bfqd && bfqq->bfqd->last_completed_rq_bfqq == bfqq)
		bfqq->bfqd->last_completed_rq_bfqq = NULL;

	kmem_cache_free(bfq_pool, bfqq);
#ifdef CONFIG_BFQ_GROUP_IOSCHED
	bfqg_and_blkg_put(bfqg);
@@ -4835,9 +4876,6 @@ static void bfq_put_cooperator(struct bfq_queue *bfqq)

static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
{
	struct bfq_queue *item;
	struct hlist_node *n;

	if (bfqq == bfqd->in_service_queue) {
		__bfq_bfqq_expire(bfqd, bfqq, BFQQE_BUDGET_TIMEOUT);
		bfq_schedule_dispatch(bfqd);
@@ -4847,18 +4885,6 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)

	bfq_put_cooperator(bfqq);

	/* remove bfqq from woken list */
	if (!hlist_unhashed(&bfqq->woken_list_node))
		hlist_del_init(&bfqq->woken_list_node);

	/* reset waker for all queues in woken list */
	hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
				  woken_list_node) {
		item->waker_bfqq = NULL;
		bfq_clear_bfqq_has_waker(item);
		hlist_del_init(&item->woken_list_node);
	}

	bfq_put_queue(bfqq); /* release process reference */
}

@@ -5436,12 +5462,12 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,

	spin_lock_irq(&bfqd->lock);
	bfqq = bfq_init_rq(rq);
	if (at_head || blk_rq_is_passthrough(rq)) {
	if (!bfqq || at_head || blk_rq_is_passthrough(rq)) {
		if (at_head)
			list_add(&rq->queuelist, &bfqd->dispatch);
		else
			list_add_tail(&rq->queuelist, &bfqd->dispatch);
	} else { /* bfqq is assumed to be non null here */
	} else {
		idle_timer_disabled = __bfq_insert_request(bfqd, rq);
		/*
		 * Update bfqq, because, if a queue merge has occurred
+21 −0
Original line number Diff line number Diff line
@@ -1786,6 +1786,21 @@ nothing_to_do:
	return 1;
}

static bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks)
{
	struct request *rq = scmd->request;
	u32 req_blocks;

	if (!blk_rq_is_passthrough(rq))
		return true;

	req_blocks = blk_rq_bytes(rq) / scmd->device->sector_size;
	if (n_blocks > req_blocks)
		return false;

	return true;
}

/**
 *	ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
 *	@qc: Storage for translated ATA taskfile
@@ -1830,6 +1845,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
		scsi_10_lba_len(cdb, &block, &n_block);
		if (cdb[1] & (1 << 3))
			tf_flags |= ATA_TFLAG_FUA;
		if (!ata_check_nblocks(scmd, n_block))
			goto invalid_fld;
		break;
	case READ_6:
	case WRITE_6:
@@ -1844,6 +1861,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
		 */
		if (!n_block)
			n_block = 256;
		if (!ata_check_nblocks(scmd, n_block))
			goto invalid_fld;
		break;
	case READ_16:
	case WRITE_16:
@@ -1854,6 +1873,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
		scsi_16_lba_len(cdb, &block, &n_block);
		if (cdb[1] & (1 << 3))
			tf_flags |= ATA_TFLAG_FUA;
		if (!ata_check_nblocks(scmd, n_block))
			goto invalid_fld;
		break;
	default:
		DPRINTK("no-byte command\n");
+6 −0
Original line number Diff line number Diff line
@@ -658,6 +658,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
	unsigned int offset;
	unsigned char *buf;

	if (!qc->cursg) {
		qc->curbytes = qc->nbytes;
		return;
	}
	if (qc->curbytes == qc->nbytes - qc->sect_size)
		ap->hsm_task_state = HSM_ST_LAST;

@@ -683,6 +687,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)

	if (qc->cursg_ofs == qc->cursg->length) {
		qc->cursg = sg_next(qc->cursg);
		if (!qc->cursg)
			ap->hsm_task_state = HSM_ST_LAST;
		qc->cursg_ofs = 0;
	}
}
+0 −1
Original line number Diff line number Diff line
@@ -158,7 +158,6 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
static int rb532_pata_driver_remove(struct platform_device *pdev)
{
	struct ata_host *ah = platform_get_drvdata(pdev);
	struct rb532_cf_info *info = ah->private_data;

	ata_host_detach(ah);

+10 −3
Original line number Diff line number Diff line
@@ -323,10 +323,14 @@ flush(const char __user *str, size_t cnt, int exiting)
	}

	flush_scheduled_work();
	/* pass one: without sleeping, do aoedev_downdev */
	/* pass one: do aoedev_downdev, which might sleep */
restart1:
	spin_lock_irqsave(&devlist_lock, flags);
	for (d = devlist; d; d = d->next) {
		spin_lock(&d->lock);
		if (d->flags & DEVFL_TKILL)
			goto cont;

		if (exiting) {
			/* unconditionally take each device down */
		} else if (specified) {
@@ -338,8 +342,11 @@ flush(const char __user *str, size_t cnt, int exiting)
		|| d->ref)
			goto cont;

		spin_unlock(&d->lock);
		spin_unlock_irqrestore(&devlist_lock, flags);
		aoedev_downdev(d);
		d->flags |= DEVFL_TKILL;
		goto restart1;
cont:
		spin_unlock(&d->lock);
	}
@@ -348,7 +355,7 @@ cont:
	/* pass two: call freedev, which might sleep,
	 * for aoedevs marked with DEVFL_TKILL
	 */
restart:
restart2:
	spin_lock_irqsave(&devlist_lock, flags);
	for (d = devlist; d; d = d->next) {
		spin_lock(&d->lock);
@@ -357,7 +364,7 @@ restart:
			spin_unlock(&d->lock);
			spin_unlock_irqrestore(&devlist_lock, flags);
			freedev(d);
			goto restart;
			goto restart2;
		}
		spin_unlock(&d->lock);
	}
Loading