Commit d9a9755a authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge branch 'nvme-5.7' of git://git.infradead.org/nvme into block-5.7

Pull NVMe fixes from Christoph.

* 'nvme-5.7' of git://git.infradead.org/nvme:
  nvmet-rdma: fix double free of rdma queue
  nvme-fc: Revert "add module to ops template to allow module references"
  nvme: fix deadlock caused by ANA update wrong locking
  nvmet-rdma: fix bonding failover possible NULL deref
  nvmet: fix NULL dereference when removing a referral
  nvme: inherit stable pages constraint in the mpath stack device
  nvme-tcp: fix possible crash in recv error flow
  nvme-tcp: don't poll a non-live queue
  nvme-tcp: fix possible crash in write_zeroes processing
  nvmet-fc: fix typo in comment
  nvme-rdma: Replace comma with a semicolon
  nvme-fcloop: fix deallocation of working context
  nvme: fix compat address handling in several ioctls
parents d3ef5536 21f90243
Loading
Loading
Loading
Loading
+27 −7
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@

#include <linux/blkdev.h>
#include <linux/blk-mq.h>
#include <linux/compat.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/hdreg.h>
@@ -1252,6 +1253,18 @@ static void nvme_enable_aen(struct nvme_ctrl *ctrl)
	queue_work(nvme_wq, &ctrl->async_event_work);
}

/*
 * Convert integer values from ioctl structures to user pointers, silently
 * ignoring the upper bits in the compat case to match behaviour of 32-bit
 * kernels.
 */
static void __user *nvme_to_user_ptr(uintptr_t ptrval)
{
	if (in_compat_syscall())
		ptrval = (compat_uptr_t)ptrval;
	return (void __user *)ptrval;
}

static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
{
	struct nvme_user_io io;
@@ -1275,7 +1288,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)

	length = (io.nblocks + 1) << ns->lba_shift;
	meta_len = (io.nblocks + 1) * ns->ms;
	metadata = (void __user *)(uintptr_t)io.metadata;
	metadata = nvme_to_user_ptr(io.metadata);

	if (ns->ext) {
		length += meta_len;
@@ -1298,7 +1311,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
	c.rw.appmask = cpu_to_le16(io.appmask);

	return nvme_submit_user_cmd(ns->queue, &c,
			(void __user *)(uintptr_t)io.addr, length,
			nvme_to_user_ptr(io.addr), length,
			metadata, meta_len, lower_32_bits(io.slba), NULL, 0);
}

@@ -1418,9 +1431,9 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,

	effects = nvme_passthru_start(ctrl, ns, cmd.opcode);
	status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
			(void __user *)(uintptr_t)cmd.addr, cmd.data_len,
			(void __user *)(uintptr_t)cmd.metadata,
			cmd.metadata_len, 0, &result, timeout);
			nvme_to_user_ptr(cmd.addr), cmd.data_len,
			nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
			0, &result, timeout);
	nvme_passthru_end(ctrl, effects);

	if (status >= 0) {
@@ -1465,8 +1478,8 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,

	effects = nvme_passthru_start(ctrl, ns, cmd.opcode);
	status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
			(void __user *)(uintptr_t)cmd.addr, cmd.data_len,
			(void __user *)(uintptr_t)cmd.metadata, cmd.metadata_len,
			nvme_to_user_ptr(cmd.addr), cmd.data_len,
			nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
			0, &cmd.result, timeout);
	nvme_passthru_end(ctrl, effects);

@@ -1884,6 +1897,13 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
	if (ns->head->disk) {
		nvme_update_disk_info(ns->head->disk, ns, id);
		blk_queue_stack_limits(ns->head->disk->queue, ns->queue);
		if (bdi_cap_stable_pages_required(ns->queue->backing_dev_info)) {
			struct backing_dev_info *info =
				ns->head->disk->queue->backing_dev_info;

                        info->capabilities |= BDI_CAP_STABLE_WRITES;
		}

		revalidate_disk(ns->head->disk);
	}
#endif
+2 −12
Original line number Diff line number Diff line
@@ -342,8 +342,7 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
	    !template->ls_req || !template->fcp_io ||
	    !template->ls_abort || !template->fcp_abort ||
	    !template->max_hw_queues || !template->max_sgl_segments ||
	    !template->max_dif_sgl_segments || !template->dma_boundary ||
	    !template->module) {
	    !template->max_dif_sgl_segments || !template->dma_boundary) {
		ret = -EINVAL;
		goto out_reghost_failed;
	}
@@ -2016,7 +2015,6 @@ nvme_fc_ctrl_free(struct kref *ref)
{
	struct nvme_fc_ctrl *ctrl =
		container_of(ref, struct nvme_fc_ctrl, ref);
	struct nvme_fc_lport *lport = ctrl->lport;
	unsigned long flags;

	if (ctrl->ctrl.tagset) {
@@ -2043,7 +2041,6 @@ nvme_fc_ctrl_free(struct kref *ref)
	if (ctrl->ctrl.opts)
		nvmf_free_options(ctrl->ctrl.opts);
	kfree(ctrl);
	module_put(lport->ops->module);
}

static void
@@ -3074,15 +3071,10 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
		goto out_fail;
	}

	if (!try_module_get(lport->ops->module)) {
		ret = -EUNATCH;
		goto out_free_ctrl;
	}

	idx = ida_simple_get(&nvme_fc_ctrl_cnt, 0, 0, GFP_KERNEL);
	if (idx < 0) {
		ret = -ENOSPC;
		goto out_mod_put;
		goto out_free_ctrl;
	}

	ctrl->ctrl.opts = opts;
@@ -3232,8 +3224,6 @@ out_free_queues:
out_free_ida:
	put_device(ctrl->dev);
	ida_simple_remove(&nvme_fc_ctrl_cnt, ctrl->cnum);
out_mod_put:
	module_put(lport->ops->module);
out_free_ctrl:
	kfree(ctrl);
out_fail:
+2 −2
Original line number Diff line number Diff line
@@ -510,7 +510,7 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
	if (!nr_nsids)
		return 0;

	down_write(&ctrl->namespaces_rwsem);
	down_read(&ctrl->namespaces_rwsem);
	list_for_each_entry(ns, &ctrl->namespaces, list) {
		unsigned nsid = le32_to_cpu(desc->nsids[n]);

@@ -521,7 +521,7 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
		if (++n == nr_nsids)
			break;
	}
	up_write(&ctrl->namespaces_rwsem);
	up_read(&ctrl->namespaces_rwsem);
	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -1350,7 +1350,7 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
	int ret;

	sge->addr   = qe->dma;
	sge->length = sizeof(struct nvme_command),
	sge->length = sizeof(struct nvme_command);
	sge->lkey   = queue->device->pd->local_dma_lkey;

	wr.next       = NULL;
+11 −7
Original line number Diff line number Diff line
@@ -174,16 +174,14 @@ static inline bool nvme_tcp_async_req(struct nvme_tcp_request *req)
static inline bool nvme_tcp_has_inline_data(struct nvme_tcp_request *req)
{
	struct request *rq;
	unsigned int bytes;

	if (unlikely(nvme_tcp_async_req(req)))
		return false; /* async events don't have a request */

	rq = blk_mq_rq_from_pdu(req);
	bytes = blk_rq_payload_bytes(rq);

	return rq_data_dir(rq) == WRITE && bytes &&
		bytes <= nvme_tcp_inline_data_size(req->queue);
	return rq_data_dir(rq) == WRITE && req->data_len &&
		req->data_len <= nvme_tcp_inline_data_size(req->queue);
}

static inline struct page *nvme_tcp_req_cur_page(struct nvme_tcp_request *req)
@@ -1075,7 +1073,7 @@ static void nvme_tcp_io_work(struct work_struct *w)
		if (result > 0)
			pending = true;
		else if (unlikely(result < 0))
			break;
			return;

		if (!pending)
			return;
@@ -2164,7 +2162,9 @@ static blk_status_t nvme_tcp_map_data(struct nvme_tcp_queue *queue,

	c->common.flags |= NVME_CMD_SGL_METABUF;

	if (rq_data_dir(rq) == WRITE && req->data_len &&
	if (!blk_rq_nr_phys_segments(rq))
		nvme_tcp_set_sg_null(c);
	else if (rq_data_dir(rq) == WRITE &&
	    req->data_len <= nvme_tcp_inline_data_size(queue))
		nvme_tcp_set_sg_inline(queue, c, req->data_len);
	else
@@ -2191,7 +2191,8 @@ static blk_status_t nvme_tcp_setup_cmd_pdu(struct nvme_ns *ns,
	req->data_sent = 0;
	req->pdu_len = 0;
	req->pdu_sent = 0;
	req->data_len = blk_rq_payload_bytes(rq);
	req->data_len = blk_rq_nr_phys_segments(rq) ?
				blk_rq_payload_bytes(rq) : 0;
	req->curr_bio = rq->bio;

	if (rq_data_dir(rq) == WRITE &&
@@ -2298,6 +2299,9 @@ static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx)
	struct nvme_tcp_queue *queue = hctx->driver_data;
	struct sock *sk = queue->sock->sk;

	if (!test_bit(NVME_TCP_Q_LIVE, &queue->flags))
		return 0;

	if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue))
		sk_busy_loop(sk, true);
	nvme_tcp_try_recv(queue);
Loading