Commit e205ff48 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'block-6.15-20250502' of git://git.kernel.dk/linux

Pull block fixes from Jens Axboe:

 - NVMe pull request via Christoph:
     - fix queue unquiesce check on PCI slot_reset (Keith Busch)
     - fix premature queue removal and I/O failover in nvme-tcp (Michael
       Liang)
     - don't restore null sk_state_change (Alistair Francis)
     - select CONFIG_TLS where needed (Alistair Francis)
     - always free derived key data (Hannes Reinecke)
     - more quirks (Wentao Guan)

 - ublk zero copy fix

 - ublk selftest fix for UBLK_F_NEED_GET_DATA

* tag 'block-6.15-20250502' of git://git.kernel.dk/linux:
  nvmet-auth: always free derived key data
  nvmet-tcp: don't restore null sk_state_change
  nvmet-tcp: select CONFIG_TLS from CONFIG_NVME_TARGET_TCP_TLS
  nvme-tcp: select CONFIG_TLS from CONFIG_NVME_TCP_TLS
  nvme-tcp: fix premature queue removal and I/O failover
  nvme-pci: add quirks for WDC Blue SN550 15b7:5009
  nvme-pci: add quirks for device 126f:1001
  nvme-pci: fix queue unquiesce check on slot_reset
  ublk: remove the check of ublk_need_req_ref() from __ublk_check_and_get_req
  ublk: enhance check for register/unregister io buffer command
  ublk: decouple zero copy from user copy
  selftests: ublk: fix UBLK_F_NEED_GET_DATA
parents 731e5e1a 6d732e8d
Loading
Loading
Loading
Loading
+43 −19
Original line number Diff line number Diff line
@@ -201,15 +201,10 @@ struct ublk_params_header {
static void ublk_stop_dev_unlocked(struct ublk_device *ub);
static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq);
static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
		struct ublk_queue *ubq, int tag, size_t offset);
		const struct ublk_queue *ubq, int tag, size_t offset);
static inline unsigned int ublk_req_build_flags(struct request *req);
static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
						   int tag);
static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
{
	return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
}

static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
{
	return ub->dev_info.flags & UBLK_F_ZONED;
@@ -609,14 +604,19 @@ static void ublk_apply_params(struct ublk_device *ub)
		ublk_dev_param_zoned_apply(ub);
}

static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
{
	return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
}

static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
{
	return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
	return ubq->flags & UBLK_F_USER_COPY;
}

static inline bool ublk_need_map_io(const struct ublk_queue *ubq)
{
	return !ublk_support_user_copy(ubq);
	return !ublk_support_user_copy(ubq) && !ublk_support_zero_copy(ubq);
}

static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
@@ -624,8 +624,11 @@ static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
	/*
	 * read()/write() is involved in user copy, so request reference
	 * has to be grabbed
	 *
	 * for zero copy, request buffer need to be registered to io_uring
	 * buffer table, so reference is needed
	 */
	return ublk_support_user_copy(ubq);
	return ublk_support_user_copy(ubq) || ublk_support_zero_copy(ubq);
}

static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
@@ -1946,13 +1949,20 @@ static void ublk_io_release(void *priv)
}

static int ublk_register_io_buf(struct io_uring_cmd *cmd,
				struct ublk_queue *ubq, unsigned int tag,
				const struct ublk_queue *ubq, unsigned int tag,
				unsigned int index, unsigned int issue_flags)
{
	struct ublk_device *ub = cmd->file->private_data;
	const struct ublk_io *io = &ubq->ios[tag];
	struct request *req;
	int ret;

	if (!ublk_support_zero_copy(ubq))
		return -EINVAL;

	if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
		return -EINVAL;

	req = __ublk_check_and_get_req(ub, ubq, tag, 0);
	if (!req)
		return -EINVAL;
@@ -1968,8 +1978,17 @@ static int ublk_register_io_buf(struct io_uring_cmd *cmd,
}

static int ublk_unregister_io_buf(struct io_uring_cmd *cmd,
				  const struct ublk_queue *ubq, unsigned int tag,
				  unsigned int index, unsigned int issue_flags)
{
	const struct ublk_io *io = &ubq->ios[tag];

	if (!ublk_support_zero_copy(ubq))
		return -EINVAL;

	if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
		return -EINVAL;

	return io_buffer_unregister_bvec(cmd, index, issue_flags);
}

@@ -2073,7 +2092,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
	case UBLK_IO_REGISTER_IO_BUF:
		return ublk_register_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
	case UBLK_IO_UNREGISTER_IO_BUF:
		return ublk_unregister_io_buf(cmd, ub_cmd->addr, issue_flags);
		return ublk_unregister_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
	case UBLK_IO_FETCH_REQ:
		ret = ublk_fetch(cmd, ubq, io, ub_cmd->addr);
		if (ret)
@@ -2125,13 +2144,10 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
}

static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
		struct ublk_queue *ubq, int tag, size_t offset)
		const struct ublk_queue *ubq, int tag, size_t offset)
{
	struct request *req;

	if (!ublk_need_req_ref(ubq))
		return NULL;

	req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag);
	if (!req)
		return NULL;
@@ -2245,6 +2261,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
	if (!ubq)
		return ERR_PTR(-EINVAL);

	if (!ublk_support_user_copy(ubq))
		return ERR_PTR(-EACCES);

	if (tag >= ubq->q_depth)
		return ERR_PTR(-EINVAL);

@@ -2783,13 +2802,18 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
	ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
		UBLK_F_URING_CMD_COMP_IN_TASK;

	/* GET_DATA isn't needed any more with USER_COPY */
	if (ublk_dev_is_user_copy(ub))
	/* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
	if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY))
		ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;

	/* Zoned storage support requires user copy feature */
	/*
	 * Zoned storage support requires reuse `ublksrv_io_cmd->addr` for
	 * returning write_append_lba, which is only allowed in case of
	 * user copy or zero copy
	 */
	if (ublk_dev_is_zoned(ub) &&
	    (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !ublk_dev_is_user_copy(ub))) {
	    (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !(ub->dev_info.flags &
	     (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY)))) {
		ret = -EINVAL;
		goto out_free_dev_number;
	}
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ config NVME_TCP_TLS
	depends on NVME_TCP
	select NET_HANDSHAKE
	select KEYS
	select TLS
	help
	  Enables TLS encryption for NVMe TCP using the netlink handshake API.

+7 −1
Original line number Diff line number Diff line
@@ -3575,7 +3575,7 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)

	dev_info(dev->ctrl.device, "restart after slot reset\n");
	pci_restore_state(pdev);
	if (!nvme_try_sched_reset(&dev->ctrl))
	if (nvme_try_sched_reset(&dev->ctrl))
		nvme_unquiesce_io_queues(&dev->ctrl);
	return PCI_ERS_RESULT_RECOVERED;
}
@@ -3623,6 +3623,9 @@ static const struct pci_device_id nvme_id_table[] = {
		.driver_data = NVME_QUIRK_BOGUS_NID, },
	{ PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */
		.driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, },
	{ PCI_DEVICE(0x126f, 0x1001),	/* Silicon Motion generic */
		.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
				NVME_QUIRK_IGNORE_DEV_SUBNQN, },
	{ PCI_DEVICE(0x126f, 0x2262),	/* Silicon Motion generic */
		.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
				NVME_QUIRK_BOGUS_NID, },
@@ -3646,6 +3649,9 @@ static const struct pci_device_id nvme_id_table[] = {
				NVME_QUIRK_IGNORE_DEV_SUBNQN, },
	{ PCI_DEVICE(0x15b7, 0x5008),   /* Sandisk SN530 */
		.driver_data = NVME_QUIRK_BROKEN_MSI },
	{ PCI_DEVICE(0x15b7, 0x5009),   /* Sandisk SN550 */
		.driver_data = NVME_QUIRK_BROKEN_MSI |
				NVME_QUIRK_NO_DEEPEST_PS },
	{ PCI_DEVICE(0x1987, 0x5012),	/* Phison E12 */
		.driver_data = NVME_QUIRK_BOGUS_NID, },
	{ PCI_DEVICE(0x1987, 0x5016),	/* Phison E16 */
+29 −2
Original line number Diff line number Diff line
@@ -1946,7 +1946,7 @@ static void __nvme_tcp_stop_queue(struct nvme_tcp_queue *queue)
	cancel_work_sync(&queue->io_work);
}

static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
static void nvme_tcp_stop_queue_nowait(struct nvme_ctrl *nctrl, int qid)
{
	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
	struct nvme_tcp_queue *queue = &ctrl->queues[qid];
@@ -1965,6 +1965,31 @@ static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
	mutex_unlock(&queue->queue_lock);
}

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

	while (timeout > 0) {
		if (!test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags) ||
		    !sk_wmem_alloc_get(queue->sock->sk))
			return;
		msleep(2);
		timeout -= 2;
	}
	dev_warn(nctrl->device,
		 "qid %d: timeout draining sock wmem allocation expired\n",
		 qid);
}

static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
{
	nvme_tcp_stop_queue_nowait(nctrl, qid);
	nvme_tcp_wait_queue(nctrl, qid);
}


static void nvme_tcp_setup_sock_ops(struct nvme_tcp_queue *queue)
{
	write_lock_bh(&queue->sock->sk->sk_callback_lock);
@@ -2032,7 +2057,9 @@ static void nvme_tcp_stop_io_queues(struct nvme_ctrl *ctrl)
	int i;

	for (i = 1; i < ctrl->queue_count; i++)
		nvme_tcp_stop_queue(ctrl, i);
		nvme_tcp_stop_queue_nowait(ctrl, i);
	for (i = 1; i < ctrl->queue_count; i++)
		nvme_tcp_wait_queue(ctrl, i);
}

static int nvme_tcp_start_io_queues(struct nvme_ctrl *ctrl,
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ config NVME_TARGET_TCP_TLS
	bool "NVMe over Fabrics TCP target TLS encryption support"
	depends on NVME_TARGET_TCP
	select NET_HANDSHAKE
	select TLS
	help
	  Enables TLS encryption for the NVMe TCP target using the netlink handshake API.

Loading