Commit 1880df2c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'block-6.16-20250704' of git://git.kernel.dk/linux

Pull block fixes from Jens Axboe:

 - NVMe fixes via Christoph:
     - fix incorrect cdw15 value in passthru error logging (Alok Tiwari)
     - fix memory leak of bio integrity in nvmet (Dmitry Bogdanov)
     - refresh visible attrs after being checked (Eugen Hristev)
     - fix suspicious RCU usage warning in the multipath code (Geliang Tang)
     - correctly account for namespace head reference counter (Nilay Shroff)

 - Fix for a regression introduced in ublk in this cycle, where it would
   attempt to queue a canceled request.

 - brd RCU sleeping fix, also introduced in this cycle. Bare bones fix,
   should be improved upon for the next release.

* tag 'block-6.16-20250704' of git://git.kernel.dk/linux:
  brd: fix sleeping function called from invalid context in brd_insert_page()
  ublk: don't queue request if the associated uring_cmd is canceled
  nvme-multipath: fix suspicious RCU usage warning
  nvme-pci: refresh visible attrs after being checked
  nvmet: fix memory leak of bio integrity
  nvme: correctly account for namespace head reference counter
  nvme: Fix incorrect cdw15 value in passthru error logging
parents 482deed9 75ef7b8d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -64,13 +64,15 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector,

	rcu_read_unlock();
	page = alloc_page(gfp | __GFP_ZERO | __GFP_HIGHMEM);
	if (!page) {
		rcu_read_lock();
	if (!page)
		return ERR_PTR(-ENOMEM);
	}

	xa_lock(&brd->brd_pages);
	ret = __xa_cmpxchg(&brd->brd_pages, sector >> PAGE_SECTORS_SHIFT, NULL,
			page, gfp);
	rcu_read_lock();
	if (ret) {
		xa_unlock(&brd->brd_pages);
		__free_page(page);
+6 −5
Original line number Diff line number Diff line
@@ -1442,15 +1442,16 @@ static void ublk_queue_rqs(struct rq_list *rqlist)
		struct ublk_queue *this_q = req->mq_hctx->driver_data;
		struct ublk_io *this_io = &this_q->ios[req->tag];

		if (ublk_prep_req(this_q, req, true) != BLK_STS_OK) {
			rq_list_add_tail(&requeue_list, req);
			continue;
		}

		if (io && !ublk_belong_to_same_batch(io, this_io) &&
				!rq_list_empty(&submit_list))
			ublk_queue_cmd_list(io, &submit_list);
		io = this_io;

		if (ublk_prep_req(this_q, req, true) == BLK_STS_OK)
		rq_list_add_tail(&submit_list, req);
		else
			rq_list_add_tail(&requeue_list, req);
	}

	if (!rq_list_empty(&submit_list))
+16 −2
Original line number Diff line number Diff line
@@ -386,7 +386,7 @@ static void nvme_log_err_passthru(struct request *req)
		nr->cmd->common.cdw12,
		nr->cmd->common.cdw13,
		nr->cmd->common.cdw14,
		nr->cmd->common.cdw14);
		nr->cmd->common.cdw15);
}

enum nvme_disposition {
@@ -4086,6 +4086,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
	struct nvme_ns *ns;
	struct gendisk *disk;
	int node = ctrl->numa_node;
	bool last_path = false;

	ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node);
	if (!ns)
@@ -4178,9 +4179,22 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
 out_unlink_ns:
	mutex_lock(&ctrl->subsys->lock);
	list_del_rcu(&ns->siblings);
	if (list_empty(&ns->head->list))
	if (list_empty(&ns->head->list)) {
		list_del_init(&ns->head->entry);
		/*
		 * If multipath is not configured, we still create a namespace
		 * head (nshead), but head->disk is not initialized in that
		 * case.  As a result, only a single reference to nshead is held
		 * (via kref_init()) when it is created. Therefore, ensure that
		 * we do not release the reference to nshead twice if head->disk
		 * is not present.
		 */
		if (ns->head->disk)
			last_path = true;
	}
	mutex_unlock(&ctrl->subsys->lock);
	if (last_path)
		nvme_put_ns_head(ns->head);
	nvme_put_ns_head(ns->head);
 out_cleanup_disk:
	put_disk(disk);
+6 −2
Original line number Diff line number Diff line
@@ -690,8 +690,8 @@ static void nvme_remove_head(struct nvme_ns_head *head)
		nvme_cdev_del(&head->cdev, &head->cdev_device);
		synchronize_srcu(&head->srcu);
		del_gendisk(head->disk);
		nvme_put_ns_head(head);
	}
	nvme_put_ns_head(head);
}

static void nvme_remove_head_work(struct work_struct *work)
@@ -1200,7 +1200,8 @@ void nvme_mpath_add_sysfs_link(struct nvme_ns_head *head)
	 */
	srcu_idx = srcu_read_lock(&head->srcu);

	list_for_each_entry_rcu(ns, &head->list, siblings) {
	list_for_each_entry_srcu(ns, &head->list, siblings,
				 srcu_read_lock_held(&head->srcu)) {
		/*
		 * Ensure that ns path disk node is already added otherwise we
		 * may get invalid kobj name for target
@@ -1291,6 +1292,9 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
{
	bool remove = false;

	if (!head->disk)
		return;

	mutex_lock(&head->subsys->lock);
	/*
	 * We are called when all paths have been removed, and at that point
+4 −2
Original line number Diff line number Diff line
@@ -2101,8 +2101,6 @@ static void nvme_map_cmb(struct nvme_dev *dev)
	if ((dev->cmbsz & (NVME_CMBSZ_WDS | NVME_CMBSZ_RDS)) ==
			(NVME_CMBSZ_WDS | NVME_CMBSZ_RDS))
		pci_p2pmem_publish(pdev, true);

	nvme_update_attrs(dev);
}

static int nvme_set_host_mem(struct nvme_dev *dev, u32 bits)
@@ -3010,6 +3008,8 @@ static void nvme_reset_work(struct work_struct *work)
	if (result < 0)
		goto out;

	nvme_update_attrs(dev);

	result = nvme_setup_io_queues(dev);
	if (result)
		goto out;
@@ -3343,6 +3343,8 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	if (result < 0)
		goto out_disable;

	nvme_update_attrs(dev);

	result = nvme_setup_io_queues(dev);
	if (result)
		goto out_disable;
Loading