Skip to content

Commit

Permalink
nvme: use the changed namespaces list log to clear ns data changed AENs
Browse files Browse the repository at this point in the history
Per section 5.2 we need to issue the corresponding log page to clear an
AEN, so for a namespace data changed AEN we need to read the changed
namespace list log.  And once we read that log anyway we might as well
use it to optimize the rescan.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
  • Loading branch information
Christoph Hellwig committed Jun 1, 2018
1 parent 50e8d8e commit 30d9096
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
51 changes: 47 additions & 4 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3194,6 +3194,42 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
nvme_remove_invalid_namespaces(ctrl, nn);
}

static bool nvme_scan_changed_ns_log(struct nvme_ctrl *ctrl)
{
size_t log_size = NVME_MAX_CHANGED_NAMESPACES * sizeof(__le32);
__le32 *log;
int error, i;
bool ret = false;

log = kzalloc(log_size, GFP_KERNEL);
if (!log)
return false;

error = nvme_get_log(ctrl, NVME_LOG_CHANGED_NS, log, log_size);
if (error) {
dev_warn(ctrl->device,
"reading changed ns log failed: %d\n", error);
goto out_free_log;
}

if (log[0] == cpu_to_le32(0xffffffff))
goto out_free_log;

for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) {
u32 nsid = le32_to_cpu(log[i]);

if (nsid == 0)
break;
dev_info(ctrl->device, "rescanning namespace %d.\n", nsid);
nvme_validate_ns(ctrl, nsid);
}
ret = true;

out_free_log:
kfree(log);
return ret;
}

static void nvme_scan_work(struct work_struct *work)
{
struct nvme_ctrl *ctrl =
Expand All @@ -3206,21 +3242,28 @@ static void nvme_scan_work(struct work_struct *work)

WARN_ON_ONCE(!ctrl->tagset);

if (test_and_clear_bit(EVENT_NS_CHANGED, &ctrl->events)) {
if (nvme_scan_changed_ns_log(ctrl))
goto out_sort_namespaces;
dev_info(ctrl->device, "rescanning namespaces.\n");
}

if (nvme_identify_ctrl(ctrl, &id))
return;

nn = le32_to_cpu(id->nn);
if (ctrl->vs >= NVME_VS(1, 1, 0) &&
!(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
if (!nvme_scan_ns_list(ctrl, nn))
goto done;
goto out_free_id;
}
nvme_scan_ns_sequential(ctrl, nn);
done:
out_free_id:
kfree(id);
out_sort_namespaces:
down_write(&ctrl->namespaces_rwsem);
list_sort(NULL, &ctrl->namespaces, ns_cmp);
up_write(&ctrl->namespaces_rwsem);
kfree(id);
}

/*
Expand Down Expand Up @@ -3340,7 +3383,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
{
switch ((result & 0xff00) >> 8) {
case NVME_AER_NOTICE_NS_CHANGED:
dev_info(ctrl->device, "rescanning\n");
set_bit(EVENT_NS_CHANGED, &ctrl->events);
nvme_queue_scan(ctrl);
break;
case NVME_AER_NOTICE_FW_ACT_STARTING:
Expand Down
2 changes: 2 additions & 0 deletions drivers/nvme/host/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ struct nvme_ctrl {
struct delayed_work ka_work;
struct nvme_command ka_cmd;
struct work_struct fw_act_work;
#define EVENT_NS_CHANGED (1 << 0)
unsigned long events;

/* Power saving configuration */
u64 ps_max_latency_us;
Expand Down

0 comments on commit 30d9096

Please sign in to comment.