Skip to content

Commit

Permalink
Merge tag 'nvme-6.13-2024-11-21' of git://git.infradead.org/nvme into…
Browse files Browse the repository at this point in the history
… for-6.13/block

Pull NVMe updates from Keith:

"nvme updates for Linux 6.13

 - Use correct srcu list traversal (Breno)
 - Scatter-gather support for metadata (Keith)
 - Fabrics shutdown race condition fix (Nilay)
 - Persistent reservations updates (Guixin)"

* tag 'nvme-6.13-2024-11-21' of git://git.infradead.org/nvme:
  nvme: tuning pr code by using defined structs and macros
  nvme: introduce change ptpl and iekey definition
  nvme-fabrics: fix kernel crash while shutting down controller
  Revert "nvme: make keep-alive synchronous operation"
  nvme-pci: use sgls for all user requests if possible
  nvme: define the remaining used sgls constants
  nvme-pci: add support for sgl metadata
  nvme/multipath: Fix RCU list traversal to use SRCU primitive
  • Loading branch information
Jens Axboe committed Nov 21, 2024
2 parents 766a71e + 029cc98 commit ec9b3ac
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 85 deletions.
22 changes: 15 additions & 7 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1294,9 +1294,10 @@ static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
}

static void nvme_keep_alive_finish(struct request *rq,
blk_status_t status, struct nvme_ctrl *ctrl)
static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
blk_status_t status)
{
struct nvme_ctrl *ctrl = rq->end_io_data;
unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
unsigned long delay = nvme_keep_alive_work_period(ctrl);
enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);
Expand All @@ -1313,17 +1314,20 @@ static void nvme_keep_alive_finish(struct request *rq,
delay = 0;
}

blk_mq_free_request(rq);

if (status) {
dev_err(ctrl->device,
"failed nvme_keep_alive_end_io error=%d\n",
status);
return;
return RQ_END_IO_NONE;
}

ctrl->ka_last_check_time = jiffies;
ctrl->comp_seen = false;
if (state == NVME_CTRL_LIVE || state == NVME_CTRL_CONNECTING)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
return RQ_END_IO_NONE;
}

static void nvme_keep_alive_work(struct work_struct *work)
Expand All @@ -1332,7 +1336,6 @@ static void nvme_keep_alive_work(struct work_struct *work)
struct nvme_ctrl, ka_work);
bool comp_seen = ctrl->comp_seen;
struct request *rq;
blk_status_t status;

ctrl->ka_last_check_time = jiffies;

Expand All @@ -1355,9 +1358,9 @@ static void nvme_keep_alive_work(struct work_struct *work)
nvme_init_request(rq, &ctrl->ka_cmd);

rq->timeout = ctrl->kato * HZ;
status = blk_execute_rq(rq, false);
nvme_keep_alive_finish(rq, status, ctrl);
blk_mq_free_request(rq);
rq->end_io = nvme_keep_alive_end_io;
rq->end_io_data = ctrl;
blk_execute_rq_nowait(rq, false);
}

static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
Expand Down Expand Up @@ -4571,6 +4574,11 @@ EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set);

void nvme_remove_admin_tag_set(struct nvme_ctrl *ctrl)
{
/*
* As we're about to destroy the queue and free tagset
* we can not have keep-alive work running.
*/
nvme_stop_keep_alive(ctrl);
blk_mq_destroy_queue(ctrl->admin_q);
blk_put_queue(ctrl->admin_q);
if (ctrl->ops->flags & NVME_F_FABRICS) {
Expand Down
12 changes: 10 additions & 2 deletions drivers/nvme/host/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,20 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
struct nvme_ns *ns = q->queuedata;
struct block_device *bdev = ns ? ns->disk->part0 : NULL;
bool supports_metadata = bdev && blk_get_integrity(bdev->bd_disk);
struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
bool has_metadata = meta_buffer && meta_len;
struct bio *bio = NULL;
int ret;

if (has_metadata && !supports_metadata)
return -EINVAL;
if (!nvme_ctrl_sgl_supported(ctrl))
dev_warn_once(ctrl->device, "using unchecked data buffer\n");
if (has_metadata) {
if (!supports_metadata)
return -EINVAL;
if (!nvme_ctrl_meta_sgl_supported(ctrl))
dev_warn_once(ctrl->device,
"using unchecked metadata buffer\n");
}

if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) {
struct iov_iter iter;
Expand Down
21 changes: 14 additions & 7 deletions drivers/nvme/host/multipath.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
int srcu_idx;

srcu_idx = srcu_read_lock(&ctrl->srcu);
list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
srcu_read_lock_held(&ctrl->srcu)) {
if (!ns->head->disk)
continue;
kblockd_schedule_work(&ns->head->requeue_work);
Expand Down Expand Up @@ -209,7 +210,8 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
int srcu_idx;

srcu_idx = srcu_read_lock(&ctrl->srcu);
list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
srcu_read_lock_held(&ctrl->srcu)) {
nvme_mpath_clear_current_path(ns);
kblockd_schedule_work(&ns->head->requeue_work);
}
Expand All @@ -224,7 +226,8 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
int srcu_idx;

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)) {
if (capacity != get_capacity(ns->disk))
clear_bit(NVME_NS_READY, &ns->flags);
}
Expand Down Expand Up @@ -257,7 +260,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
int found_distance = INT_MAX, fallback_distance = INT_MAX, distance;
struct nvme_ns *found = NULL, *fallback = NULL, *ns;

list_for_each_entry_rcu(ns, &head->list, siblings) {
list_for_each_entry_srcu(ns, &head->list, siblings,
srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;

Expand Down Expand Up @@ -356,7 +360,8 @@ static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)
unsigned int min_depth_opt = UINT_MAX, min_depth_nonopt = UINT_MAX;
unsigned int depth;

list_for_each_entry_rcu(ns, &head->list, siblings) {
list_for_each_entry_srcu(ns, &head->list, siblings,
srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;

Expand Down Expand Up @@ -424,7 +429,8 @@ static bool nvme_available_path(struct nvme_ns_head *head)
if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
return NULL;

list_for_each_entry_rcu(ns, &head->list, siblings) {
list_for_each_entry_srcu(ns, &head->list, siblings,
srcu_read_lock_held(&head->srcu)) {
if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags))
continue;
switch (nvme_ctrl_state(ns->ctrl)) {
Expand Down Expand Up @@ -783,7 +789,8 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
return 0;

srcu_idx = srcu_read_lock(&ctrl->srcu);
list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
srcu_read_lock_held(&ctrl->srcu)) {
unsigned nsid;
again:
nsid = le32_to_cpu(desc->nsids[n]);
Expand Down
10 changes: 9 additions & 1 deletion drivers/nvme/host/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,15 @@ static inline void nvme_start_request(struct request *rq)

static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl)
{
return ctrl->sgls & ((1 << 0) | (1 << 1));
return ctrl->sgls & (NVME_CTRL_SGLS_BYTE_ALIGNED |
NVME_CTRL_SGLS_DWORD_ALIGNED);
}

static inline bool nvme_ctrl_meta_sgl_supported(struct nvme_ctrl *ctrl)
{
if (ctrl->ops->flags & NVME_F_FABRICS)
return true;
return ctrl->sgls & NVME_CTRL_SGLS_MSDS;
}

#ifdef CONFIG_NVME_HOST_AUTH
Expand Down
Loading

0 comments on commit ec9b3ac

Please sign in to comment.