Commit 73548503 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull block fixes from Jens Axboe:

 - NVMe pull request via Keith:
      - Fix nvme-pci IRQ race and slab-out-of-bounds access
      - Fix recursive workqueue locking for target async events
      - Various cleanups

 - Fix a potential NULL pointer dereference in ublk on size setting

 - ublk automatic partition scanning fix

 - Two s390 dasd fixes

* tag 'block-7.0-20260312' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
  nvme: Annotate struct nvme_dhchap_key with __counted_by
  nvme-core: do not pass empty queue_limits to blk_mq_alloc_queue()
  nvme-pci: Fix race bug in nvme_poll_irqdisable()
  nvmet: move async event work off nvmet-wq
  nvme-pci: Fix slab-out-of-bounds in nvme_dbbuf_set
  s390/dasd: Copy detected format information to secondary device
  s390/dasd: Move quiesce state with pprc swap
  ublk: don't clear GD_SUPPRESS_PART_SCAN for unprivileged daemons
  ublk: fix NULL pointer dereference in ublk_ctrl_set_size()
parents e67bf352 7d0abefe
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -4443,6 +4443,8 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,

	/* Skip partition scan if disabled by user */
	if (ub->dev_info.flags & UBLK_F_NO_AUTO_PART_SCAN) {
		/* Not clear for unprivileged daemons, see comment above */
		if (!ub->unprivileged_daemons)
			clear_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
	} else {
		/* Schedule async partition scan for trusted daemons */
@@ -5006,15 +5008,22 @@ static int ublk_ctrl_get_features(const struct ublksrv_ctrl_cmd *header)
	return 0;
}

static void ublk_ctrl_set_size(struct ublk_device *ub, const struct ublksrv_ctrl_cmd *header)
static int ublk_ctrl_set_size(struct ublk_device *ub, const struct ublksrv_ctrl_cmd *header)
{
	struct ublk_param_basic *p = &ub->params.basic;
	u64 new_size = header->data[0];
	int ret = 0;

	mutex_lock(&ub->mutex);
	if (!ub->ub_disk) {
		ret = -ENODEV;
		goto out;
	}
	p->dev_sectors = new_size;
	set_capacity_and_notify(ub->ub_disk, p->dev_sectors);
out:
	mutex_unlock(&ub->mutex);
	return ret;
}

struct count_busy {
@@ -5335,8 +5344,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
		ret = ublk_ctrl_end_recovery(ub, &header);
		break;
	case UBLK_CMD_UPDATE_SIZE:
		ublk_ctrl_set_size(ub, &header);
		ret = 0;
		ret = ublk_ctrl_set_size(ub, &header);
		break;
	case UBLK_CMD_QUIESCE_DEV:
		ret = ublk_ctrl_quiesce_dev(ub, &header);
+1 −2
Original line number Diff line number Diff line
@@ -4834,7 +4834,6 @@ EXPORT_SYMBOL_GPL(nvme_complete_async_event);
int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set,
		const struct blk_mq_ops *ops, unsigned int cmd_size)
{
	struct queue_limits lim = {};
	int ret;

	memset(set, 0, sizeof(*set));
@@ -4861,7 +4860,7 @@ int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set,
	if (ctrl->admin_q)
		blk_put_queue(ctrl->admin_q);

	ctrl->admin_q = blk_mq_alloc_queue(set, &lim, NULL);
	ctrl->admin_q = blk_mq_alloc_queue(set, NULL, NULL);
	if (IS_ERR(ctrl->admin_q)) {
		ret = PTR_ERR(ctrl->admin_q);
		goto out_free_tagset;
+5 −3
Original line number Diff line number Diff line
@@ -544,7 +544,7 @@ static void nvme_dbbuf_set(struct nvme_dev *dev)
		/* Free memory and continue on */
		nvme_dbbuf_dma_free(dev);

		for (i = 1; i <= dev->online_queues; i++)
		for (i = 1; i < dev->online_queues; i++)
			nvme_dbbuf_free(&dev->queues[i]);
	}
}
@@ -1625,14 +1625,16 @@ static irqreturn_t nvme_irq_check(int irq, void *data)
static void nvme_poll_irqdisable(struct nvme_queue *nvmeq)
{
	struct pci_dev *pdev = to_pci_dev(nvmeq->dev->dev);
	int irq;

	WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags));

	disable_irq(pci_irq_vector(pdev, nvmeq->cq_vector));
	irq = pci_irq_vector(pdev, nvmeq->cq_vector);
	disable_irq(irq);
	spin_lock(&nvmeq->cq_poll_lock);
	nvme_poll_cq(nvmeq, NULL);
	spin_unlock(&nvmeq->cq_poll_lock);
	enable_irq(pci_irq_vector(pdev, nvmeq->cq_vector));
	enable_irq(irq);
}

static int nvme_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
+1 −1
Original line number Diff line number Diff line
@@ -1585,7 +1585,7 @@ void nvmet_execute_async_event(struct nvmet_req *req)
	ctrl->async_event_cmds[ctrl->nr_async_event_cmds++] = req;
	mutex_unlock(&ctrl->lock);

	queue_work(nvmet_wq, &ctrl->async_event_work);
	queue_work(nvmet_aen_wq, &ctrl->async_event_work);
}

void nvmet_execute_keep_alive(struct nvmet_req *req)
+12 −2
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ static DEFINE_IDA(cntlid_ida);

struct workqueue_struct *nvmet_wq;
EXPORT_SYMBOL_GPL(nvmet_wq);
struct workqueue_struct *nvmet_aen_wq;
EXPORT_SYMBOL_GPL(nvmet_aen_wq);

/*
 * This read/write semaphore is used to synchronize access to configuration
@@ -206,7 +208,7 @@ void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
	list_add_tail(&aen->entry, &ctrl->async_events);
	mutex_unlock(&ctrl->lock);

	queue_work(nvmet_wq, &ctrl->async_event_work);
	queue_work(nvmet_aen_wq, &ctrl->async_event_work);
}

static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid)
@@ -1956,9 +1958,14 @@ static int __init nvmet_init(void)
	if (!nvmet_wq)
		goto out_free_buffered_work_queue;

	nvmet_aen_wq = alloc_workqueue("nvmet-aen-wq",
			WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
	if (!nvmet_aen_wq)
		goto out_free_nvmet_work_queue;

	error = nvmet_init_debugfs();
	if (error)
		goto out_free_nvmet_work_queue;
		goto out_free_nvmet_aen_work_queue;

	error = nvmet_init_discovery();
	if (error)
@@ -1974,6 +1981,8 @@ static int __init nvmet_init(void)
	nvmet_exit_discovery();
out_exit_debugfs:
	nvmet_exit_debugfs();
out_free_nvmet_aen_work_queue:
	destroy_workqueue(nvmet_aen_wq);
out_free_nvmet_work_queue:
	destroy_workqueue(nvmet_wq);
out_free_buffered_work_queue:
@@ -1991,6 +2000,7 @@ static void __exit nvmet_exit(void)
	nvmet_exit_discovery();
	nvmet_exit_debugfs();
	ida_destroy(&cntlid_ida);
	destroy_workqueue(nvmet_aen_wq);
	destroy_workqueue(nvmet_wq);
	destroy_workqueue(buffered_io_wq);
	destroy_workqueue(zbd_wq);
Loading