Commit 8ced7ca3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'block-5.16-2021-11-25' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:

 - NVMe pull request via Christoph:
      - Add a NO APST quirk for a Kioxia device (Enzo Matsumiya)
      - Fix write zeroes pi (Klaus Jensen)
      - Various TCP transport fixes (Maurizio Lombardi and Varun
        Prakash)
      - Ignore invalid fast_io_fail_tmo values (Maurizio Lombardi)
      - Use IOCB_NOWAIT only if the filesystem supports it (Maurizio
        Lombardi)

 - Module loading fix (Ming)

 - Kerneldoc warning fix (Yang)

* tag 'block-5.16-2021-11-25' of git://git.kernel.dk/linux-block:
  block: fix parameter not described warning
  nvmet: use IOCB_NOWAIT only if the filesystem supports it
  nvme: fix write zeroes pi
  nvme-fabrics: ignore invalid fast_io_fail_tmo values
  nvme-pci: add NO APST quirk for Kioxia device
  nvme-tcp: fix memory leak when freeing a queue
  nvme-tcp: validate R2T PDU in nvme_tcp_handle_r2t()
  nvmet-tcp: fix incomplete data digest send
  nvmet-tcp: fix memory leak when performing a controller reset
  nvmet-tcp: add an helper to free the cmd buffers
  nvmet-tcp: fix a race condition between release_queue and io_work
  block: avoid to touch unloaded module instance when opening bdev
parents de4444f5 e30028ac
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -753,8 +753,7 @@ struct block_device *blkdev_get_no_open(dev_t dev)

	if (!bdev)
		return NULL;
	if ((bdev->bd_disk->flags & GENHD_FL_HIDDEN) ||
	    !try_module_get(bdev->bd_disk->fops->owner)) {
	if ((bdev->bd_disk->flags & GENHD_FL_HIDDEN)) {
		put_device(&bdev->bd_device);
		return NULL;
	}
@@ -764,7 +763,6 @@ struct block_device *blkdev_get_no_open(dev_t dev)

void blkdev_put_no_open(struct block_device *bdev)
{
	module_put(bdev->bd_disk->fops->owner);
	put_device(&bdev->bd_device);
}

@@ -820,12 +818,14 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
	ret = -ENXIO;
	if (!disk_live(disk))
		goto abort_claiming;
	if (!try_module_get(disk->fops->owner))
		goto abort_claiming;
	if (bdev_is_partition(bdev))
		ret = blkdev_get_part(bdev, mode);
	else
		ret = blkdev_get_whole(bdev, mode);
	if (ret)
		goto abort_claiming;
		goto put_module;
	if (mode & FMODE_EXCL) {
		bd_finish_claiming(bdev, holder);

@@ -847,7 +847,8 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
	if (unblock_events)
		disk_unblock_events(disk);
	return bdev;

put_module:
	module_put(disk->fops->owner);
abort_claiming:
	if (mode & FMODE_EXCL)
		bd_abort_claiming(bdev, holder);
@@ -956,6 +957,7 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
		blkdev_put_whole(bdev, mode);
	mutex_unlock(&disk->open_mutex);

	module_put(disk->fops->owner);
	blkdev_put_no_open(bdev);
}
EXPORT_SYMBOL(blkdev_put);
+1 −0
Original line number Diff line number Diff line
@@ -1017,6 +1017,7 @@ EXPORT_SYMBOL(submit_bio);
/**
 * bio_poll - poll for BIO completions
 * @bio: bio to poll for
 * @iob: batches of IO
 * @flags: BLK_POLL_* flags that control the behavior
 *
 * Poll for completions on queue associated with the bio. Returns number of
+26 −3
Original line number Diff line number Diff line
@@ -895,10 +895,19 @@ static inline blk_status_t nvme_setup_write_zeroes(struct nvme_ns *ns,
		cpu_to_le64(nvme_sect_to_lba(ns, blk_rq_pos(req)));
	cmnd->write_zeroes.length =
		cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
	if (nvme_ns_has_pi(ns))

	if (nvme_ns_has_pi(ns)) {
		cmnd->write_zeroes.control = cpu_to_le16(NVME_RW_PRINFO_PRACT);
	else
		cmnd->write_zeroes.control = 0;

		switch (ns->pi_type) {
		case NVME_NS_DPS_PI_TYPE1:
		case NVME_NS_DPS_PI_TYPE2:
			cmnd->write_zeroes.reftag =
				cpu_to_le32(t10_pi_ref_tag(req));
			break;
		}
	}

	return BLK_STS_OK;
}

@@ -2469,6 +2478,20 @@ static const struct nvme_core_quirk_entry core_quirks[] = {
		.vid = 0x14a4,
		.fr = "22301111",
		.quirks = NVME_QUIRK_SIMPLE_SUSPEND,
	},
	{
		/*
		 * This Kioxia CD6-V Series / HPE PE8030 device times out and
		 * aborts I/O during any load, but more easily reproducible
		 * with discards (fstrim).
		 *
		 * The device is left in a state where it is also not possible
		 * to use "nvme set-feature" to disable APST, but booting with
		 * nvme_core.default_ps_max_latency=0 works.
		 */
		.vid = 0x1e0f,
		.mn = "KCD6XVUL6T40",
		.quirks = NVME_QUIRK_NO_APST,
	}
};

+3 −0
Original line number Diff line number Diff line
@@ -698,6 +698,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
			if (token >= 0)
				pr_warn("I/O fail on reconnect controller after %d sec\n",
					token);
			else
				token = -1;

			opts->fast_io_fail_tmo = token;
			break;
		case NVMF_OPT_HOSTNQN:
+30 −31
Original line number Diff line number Diff line
@@ -572,7 +572,7 @@ static int nvme_tcp_handle_comp(struct nvme_tcp_queue *queue,
	return ret;
}

static int nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
static void nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
		struct nvme_tcp_r2t_pdu *pdu)
{
	struct nvme_tcp_data_pdu *data = req->pdu;
@@ -581,32 +581,11 @@ static int nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
	u8 hdgst = nvme_tcp_hdgst_len(queue);
	u8 ddgst = nvme_tcp_ddgst_len(queue);

	req->state = NVME_TCP_SEND_H2C_PDU;
	req->offset = 0;
	req->pdu_len = le32_to_cpu(pdu->r2t_length);
	req->pdu_sent = 0;

	if (unlikely(!req->pdu_len)) {
		dev_err(queue->ctrl->ctrl.device,
			"req %d r2t len is %u, probably a bug...\n",
			rq->tag, req->pdu_len);
		return -EPROTO;
	}

	if (unlikely(req->data_sent + req->pdu_len > req->data_len)) {
		dev_err(queue->ctrl->ctrl.device,
			"req %d r2t len %u exceeded data len %u (%zu sent)\n",
			rq->tag, req->pdu_len, req->data_len,
			req->data_sent);
		return -EPROTO;
	}

	if (unlikely(le32_to_cpu(pdu->r2t_offset) < req->data_sent)) {
		dev_err(queue->ctrl->ctrl.device,
			"req %d unexpected r2t offset %u (expected %zu)\n",
			rq->tag, le32_to_cpu(pdu->r2t_offset),
			req->data_sent);
		return -EPROTO;
	}

	memset(data, 0, sizeof(*data));
	data->hdr.type = nvme_tcp_h2c_data;
	data->hdr.flags = NVME_TCP_F_DATA_LAST;
@@ -622,7 +601,6 @@ static int nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
	data->command_id = nvme_cid(rq);
	data->data_offset = pdu->r2t_offset;
	data->data_length = cpu_to_le32(req->pdu_len);
	return 0;
}

static int nvme_tcp_handle_r2t(struct nvme_tcp_queue *queue,
@@ -630,7 +608,7 @@ static int nvme_tcp_handle_r2t(struct nvme_tcp_queue *queue,
{
	struct nvme_tcp_request *req;
	struct request *rq;
	int ret;
	u32 r2t_length = le32_to_cpu(pdu->r2t_length);

	rq = nvme_find_rq(nvme_tcp_tagset(queue), pdu->command_id);
	if (!rq) {
@@ -641,13 +619,28 @@ static int nvme_tcp_handle_r2t(struct nvme_tcp_queue *queue,
	}
	req = blk_mq_rq_to_pdu(rq);

	ret = nvme_tcp_setup_h2c_data_pdu(req, pdu);
	if (unlikely(ret))
		return ret;
	if (unlikely(!r2t_length)) {
		dev_err(queue->ctrl->ctrl.device,
			"req %d r2t len is %u, probably a bug...\n",
			rq->tag, r2t_length);
		return -EPROTO;
	}

	req->state = NVME_TCP_SEND_H2C_PDU;
	req->offset = 0;
	if (unlikely(req->data_sent + r2t_length > req->data_len)) {
		dev_err(queue->ctrl->ctrl.device,
			"req %d r2t len %u exceeded data len %u (%zu sent)\n",
			rq->tag, r2t_length, req->data_len, req->data_sent);
		return -EPROTO;
	}

	if (unlikely(le32_to_cpu(pdu->r2t_offset) < req->data_sent)) {
		dev_err(queue->ctrl->ctrl.device,
			"req %d unexpected r2t offset %u (expected %zu)\n",
			rq->tag, le32_to_cpu(pdu->r2t_offset), req->data_sent);
		return -EPROTO;
	}

	nvme_tcp_setup_h2c_data_pdu(req, pdu);
	nvme_tcp_queue_request(req, false, true);

	return 0;
@@ -1232,6 +1225,7 @@ static int nvme_tcp_alloc_async_req(struct nvme_tcp_ctrl *ctrl)

static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
{
	struct page *page;
	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
	struct nvme_tcp_queue *queue = &ctrl->queues[qid];

@@ -1241,6 +1235,11 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
	if (queue->hdr_digest || queue->data_digest)
		nvme_tcp_free_crypto(queue);

	if (queue->pf_cache.va) {
		page = virt_to_head_page(queue->pf_cache.va);
		__page_frag_cache_drain(page, queue->pf_cache.pagecnt_bias);
		queue->pf_cache.va = NULL;
	}
	sock_release(queue->sock);
	kfree(queue->pdu);
	mutex_destroy(&queue->send_mutex);
Loading