Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1802979a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull block updates and fixes from Jens Axboe:

 - NVMe updates and fixes that missed the first pull request. This
   includes bug fixes, and support for autonomous power management.

 - Fix from Christoph for missing clear of the request payload, causing
   a problem with (at least) the storvsc driver.

 - Further fixes for the queue/bdi life time issues from Jan.

 - The Kconfig mq scheduler update from me.

 - Fixing a use-after-free in dm-rq, spotted by Bart, introduced in this
   merge window.

 - Three fixes for nbd from Josef.

 - Bug fix from Omar, fixing a bug in sas transport code that oopses
   when bsg ioctls were used. From Omar.

 - Improvements to the queue restart and tag wait from from Omar.

 - Set of fixes for the sed/opal code from Scott.

 - Three trivial patches to cciss from Tobin

* 'for-linus' of git://git.kernel.dk/linux-block: (41 commits)
  dm-rq: don't dereference request payload after ending request
  blk-mq-sched: separate mark hctx and queue restart operations
  blk-mq: use sbq wait queues instead of restart for driver tags
  block/sed-opal: Propagate original error message to userland.
  nvme/pci: re-check security protocol support after reset
  block/sed-opal: Introduce free_opal_dev to free the structure and clean up state
  nvme: detect NVMe controller in recent MacBooks
  nvme-rdma: add support for host_traddr
  nvmet-rdma: Fix error handling
  nvmet-rdma: use nvme cm status helper
  nvme-rdma: move nvme cm status helper to .h file
  nvme-fc: don't bother to validate ioccsz and iorcsz
  nvme/pci: No special case for queue busy on IO
  nvme/core: Fix race kicking freed request_queue
  nvme/pci: Disable on removal when disconnected
  nvme: Enable autonomous power state transitions
  nvme: Add a quirk mechanism that uses identify_ctrl
  nvme: make nvmf_register_transport require a create_ctrl callback
  nvme: Use CNS as 8-bit field and avoid endianness conversion
  nvme: add semicolon in nvme_command setting
  ...
parents f1ef09fd 61febef4
Loading
Loading
Loading
Loading
+0 −44
Original line number Diff line number Diff line
@@ -69,50 +69,6 @@ config MQ_IOSCHED_DEADLINE
	---help---
	  MQ version of the deadline IO scheduler.

config MQ_IOSCHED_NONE
	bool
	default y

choice
	prompt "Default single-queue blk-mq I/O scheduler"
	default DEFAULT_SQ_NONE
	help
	  Select the I/O scheduler which will be used by default for blk-mq
	  managed block devices with a single queue.

	config DEFAULT_SQ_DEADLINE
		bool "MQ Deadline" if MQ_IOSCHED_DEADLINE=y

	config DEFAULT_SQ_NONE
		bool "None"

endchoice

config DEFAULT_SQ_IOSCHED
	string
	default "mq-deadline" if DEFAULT_SQ_DEADLINE
	default "none" if DEFAULT_SQ_NONE

choice
	prompt "Default multi-queue blk-mq I/O scheduler"
	default DEFAULT_MQ_NONE
	help
	  Select the I/O scheduler which will be used by default for blk-mq
	  managed block devices with multiple queues.

	config DEFAULT_MQ_DEADLINE
		bool "MQ Deadline" if MQ_IOSCHED_DEADLINE=y

	config DEFAULT_MQ_NONE
		bool "None"

endchoice

config DEFAULT_MQ_IOSCHED
	string
	default "mq-deadline" if DEFAULT_MQ_DEADLINE
	default "none" if DEFAULT_MQ_NONE

endmenu

endif
+8 −21
Original line number Diff line number Diff line
@@ -205,7 +205,7 @@ void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
	 * needing a restart in that case.
	 */
	if (!list_empty(&rq_list)) {
		blk_mq_sched_mark_restart(hctx);
		blk_mq_sched_mark_restart_hctx(hctx);
		did_work = blk_mq_dispatch_rq_list(hctx, &rq_list);
	} else if (!has_sched_dispatch) {
		blk_mq_flush_busy_ctxs(hctx, &rq_list);
@@ -331,21 +331,17 @@ static void blk_mq_sched_restart_hctx(struct blk_mq_hw_ctx *hctx)

void blk_mq_sched_restart_queues(struct blk_mq_hw_ctx *hctx)
{
	unsigned int i;

	if (!(hctx->flags & BLK_MQ_F_TAG_SHARED))
		blk_mq_sched_restart_hctx(hctx);
	else {
	struct request_queue *q = hctx->queue;
	unsigned int i;

		if (!test_bit(QUEUE_FLAG_RESTART, &q->queue_flags))
			return;

		clear_bit(QUEUE_FLAG_RESTART, &q->queue_flags);

	if (test_bit(QUEUE_FLAG_RESTART, &q->queue_flags)) {
		if (test_and_clear_bit(QUEUE_FLAG_RESTART, &q->queue_flags)) {
			queue_for_each_hw_ctx(q, hctx, i)
				blk_mq_sched_restart_hctx(hctx);
		}
	} else {
		blk_mq_sched_restart_hctx(hctx);
	}
}

/*
@@ -498,15 +494,6 @@ int blk_mq_sched_init(struct request_queue *q)
{
	int ret;

#if defined(CONFIG_DEFAULT_SQ_NONE)
	if (q->nr_hw_queues == 1)
		return 0;
#endif
#if defined(CONFIG_DEFAULT_MQ_NONE)
	if (q->nr_hw_queues > 1)
		return 0;
#endif

	mutex_lock(&q->sysfs_lock);
	ret = elevator_init(q, NULL);
	mutex_unlock(&q->sysfs_lock);
+18 −8
Original line number Diff line number Diff line
@@ -122,18 +122,28 @@ static inline bool blk_mq_sched_has_work(struct blk_mq_hw_ctx *hctx)
	return false;
}

static inline void blk_mq_sched_mark_restart(struct blk_mq_hw_ctx *hctx)
/*
 * Mark a hardware queue as needing a restart.
 */
static inline void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
{
	if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state)) {
	if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
		set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
		if (hctx->flags & BLK_MQ_F_TAG_SHARED) {
}

/*
 * Mark a hardware queue and the request queue it belongs to as needing a
 * restart.
 */
static inline void blk_mq_sched_mark_restart_queue(struct blk_mq_hw_ctx *hctx)
{
	struct request_queue *q = hctx->queue;

	if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
		set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
	if (!test_bit(QUEUE_FLAG_RESTART, &q->queue_flags))
		set_bit(QUEUE_FLAG_RESTART, &q->queue_flags);
}
	}
}

static inline bool blk_mq_sched_needs_restart(struct blk_mq_hw_ctx *hctx)
{
+55 −9
Original line number Diff line number Diff line
@@ -904,6 +904,44 @@ static bool reorder_tags_to_front(struct list_head *list)
	return first != NULL;
}

static int blk_mq_dispatch_wake(wait_queue_t *wait, unsigned mode, int flags,
				void *key)
{
	struct blk_mq_hw_ctx *hctx;

	hctx = container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);

	list_del(&wait->task_list);
	clear_bit_unlock(BLK_MQ_S_TAG_WAITING, &hctx->state);
	blk_mq_run_hw_queue(hctx, true);
	return 1;
}

static bool blk_mq_dispatch_wait_add(struct blk_mq_hw_ctx *hctx)
{
	struct sbq_wait_state *ws;

	/*
	 * The TAG_WAITING bit serves as a lock protecting hctx->dispatch_wait.
	 * The thread which wins the race to grab this bit adds the hardware
	 * queue to the wait queue.
	 */
	if (test_bit(BLK_MQ_S_TAG_WAITING, &hctx->state) ||
	    test_and_set_bit_lock(BLK_MQ_S_TAG_WAITING, &hctx->state))
		return false;

	init_waitqueue_func_entry(&hctx->dispatch_wait, blk_mq_dispatch_wake);
	ws = bt_wait_ptr(&hctx->tags->bitmap_tags, hctx);

	/*
	 * As soon as this returns, it's no longer safe to fiddle with
	 * hctx->dispatch_wait, since a completion can wake up the wait queue
	 * and unlock the bit.
	 */
	add_wait_queue(&ws->wait, &hctx->dispatch_wait);
	return true;
}

bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
{
	struct request_queue *q = hctx->queue;
@@ -931,15 +969,22 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
				continue;

			/*
			 * We failed getting a driver tag. Mark the queue(s)
			 * as needing a restart. Retry getting a tag again,
			 * in case the needed IO completed right before we
			 * marked the queue as needing a restart.
			 * The initial allocation attempt failed, so we need to
			 * rerun the hardware queue when a tag is freed.
			 */
			if (blk_mq_dispatch_wait_add(hctx)) {
				/*
				 * It's possible that a tag was freed in the
				 * window between the allocation failure and
				 * adding the hardware queue to the wait queue.
				 */
			blk_mq_sched_mark_restart(hctx);
				if (!blk_mq_get_driver_tag(rq, &hctx, false))
					break;
			} else {
				break;
			}
		}

		list_del_init(&rq->queuelist);

		bd.rq = rq;
@@ -995,10 +1040,11 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
		 *
		 * blk_mq_run_hw_queue() already checks the STOPPED bit
		 *
		 * If RESTART is set, then let completion restart the queue
		 * instead of potentially looping here.
		 * If RESTART or TAG_WAITING is set, then let completion restart
		 * the queue instead of potentially looping here.
		 */
		if (!blk_mq_sched_needs_restart(hctx))
		if (!blk_mq_sched_needs_restart(hctx) &&
		    !test_bit(BLK_MQ_S_TAG_WAITING, &hctx->state))
			blk_mq_run_hw_queue(hctx, true);
	}

+13 −6
Original line number Diff line number Diff line
@@ -220,17 +220,24 @@ int elevator_init(struct request_queue *q, char *name)
	}

	if (!e) {
		if (q->mq_ops && q->nr_hw_queues == 1)
			e = elevator_get(CONFIG_DEFAULT_SQ_IOSCHED, false);
		else if (q->mq_ops)
			e = elevator_get(CONFIG_DEFAULT_MQ_IOSCHED, false);
		else
		/*
		 * For blk-mq devices, we default to using mq-deadline,
		 * if available, for single queue devices. If deadline
		 * isn't available OR we have multiple queues, default
		 * to "none".
		 */
		if (q->mq_ops) {
			if (q->nr_hw_queues == 1)
				e = elevator_get("mq-deadline", false);
			if (!e)
				return 0;
		} else
			e = elevator_get(CONFIG_DEFAULT_IOSCHED, false);

		if (!e) {
			printk(KERN_ERR
				"Default I/O scheduler not found. " \
				"Using noop/none.\n");
				"Using noop.\n");
			e = elevator_get("noop", false);
		}
	}
Loading