aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-05-25 12:17:41 -0400
committerChristoph Hellwig <hch@lst.de>2018-06-01 08:37:35 -0400
commit30d90964e7b80a0723921e8b464c5ceda7297a7b (patch)
treec418113e30345fb7ccc120a7babbb28c1ef7d296
parent50e8d8eeede8d1ef48699a82acfb7d4be07a05d9 (diff)
nvme: use the changed namespaces list log to clear ns data changed AENs
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>
-rw-r--r--drivers/nvme/host/core.c51
-rw-r--r--drivers/nvme/host/nvme.h2
2 files changed, 49 insertions, 4 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 06cd04dcffbc..1ae77428a1a5 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3194,6 +3194,42 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
3194 nvme_remove_invalid_namespaces(ctrl, nn); 3194 nvme_remove_invalid_namespaces(ctrl, nn);
3195} 3195}
3196 3196
3197static bool nvme_scan_changed_ns_log(struct nvme_ctrl *ctrl)
3198{
3199 size_t log_size = NVME_MAX_CHANGED_NAMESPACES * sizeof(__le32);
3200 __le32 *log;
3201 int error, i;
3202 bool ret = false;
3203
3204 log = kzalloc(log_size, GFP_KERNEL);
3205 if (!log)
3206 return false;
3207
3208 error = nvme_get_log(ctrl, NVME_LOG_CHANGED_NS, log, log_size);
3209 if (error) {
3210 dev_warn(ctrl->device,
3211 "reading changed ns log failed: %d\n", error);
3212 goto out_free_log;
3213 }
3214
3215 if (log[0] == cpu_to_le32(0xffffffff))
3216 goto out_free_log;
3217
3218 for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) {
3219 u32 nsid = le32_to_cpu(log[i]);
3220
3221 if (nsid == 0)
3222 break;
3223 dev_info(ctrl->device, "rescanning namespace %d.\n", nsid);
3224 nvme_validate_ns(ctrl, nsid);
3225 }
3226 ret = true;
3227
3228out_free_log:
3229 kfree(log);
3230 return ret;
3231}
3232
3197static void nvme_scan_work(struct work_struct *work) 3233static void nvme_scan_work(struct work_struct *work)
3198{ 3234{
3199 struct nvme_ctrl *ctrl = 3235 struct nvme_ctrl *ctrl =
@@ -3206,6 +3242,12 @@ static void nvme_scan_work(struct work_struct *work)
3206 3242
3207 WARN_ON_ONCE(!ctrl->tagset); 3243 WARN_ON_ONCE(!ctrl->tagset);
3208 3244
3245 if (test_and_clear_bit(EVENT_NS_CHANGED, &ctrl->events)) {
3246 if (nvme_scan_changed_ns_log(ctrl))
3247 goto out_sort_namespaces;
3248 dev_info(ctrl->device, "rescanning namespaces.\n");
3249 }
3250
3209 if (nvme_identify_ctrl(ctrl, &id)) 3251 if (nvme_identify_ctrl(ctrl, &id))
3210 return; 3252 return;
3211 3253
@@ -3213,14 +3255,15 @@ static void nvme_scan_work(struct work_struct *work)
3213 if (ctrl->vs >= NVME_VS(1, 1, 0) && 3255 if (ctrl->vs >= NVME_VS(1, 1, 0) &&
3214 !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) { 3256 !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
3215 if (!nvme_scan_ns_list(ctrl, nn)) 3257 if (!nvme_scan_ns_list(ctrl, nn))
3216 goto done; 3258 goto out_free_id;
3217 } 3259 }
3218 nvme_scan_ns_sequential(ctrl, nn); 3260 nvme_scan_ns_sequential(ctrl, nn);
3219 done: 3261out_free_id:
3262 kfree(id);
3263out_sort_namespaces:
3220 down_write(&ctrl->namespaces_rwsem); 3264 down_write(&ctrl->namespaces_rwsem);
3221 list_sort(NULL, &ctrl->namespaces, ns_cmp); 3265 list_sort(NULL, &ctrl->namespaces, ns_cmp);
3222 up_write(&ctrl->namespaces_rwsem); 3266 up_write(&ctrl->namespaces_rwsem);
3223 kfree(id);
3224} 3267}
3225 3268
3226/* 3269/*
@@ -3340,7 +3383,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
3340{ 3383{
3341 switch ((result & 0xff00) >> 8) { 3384 switch ((result & 0xff00) >> 8) {
3342 case NVME_AER_NOTICE_NS_CHANGED: 3385 case NVME_AER_NOTICE_NS_CHANGED:
3343 dev_info(ctrl->device, "rescanning\n"); 3386 set_bit(EVENT_NS_CHANGED, &ctrl->events);
3344 nvme_queue_scan(ctrl); 3387 nvme_queue_scan(ctrl);
3345 break; 3388 break;
3346 case NVME_AER_NOTICE_FW_ACT_STARTING: 3389 case NVME_AER_NOTICE_FW_ACT_STARTING:
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 11681278fdf6..07e8bfe705c6 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -189,6 +189,8 @@ struct nvme_ctrl {
189 struct delayed_work ka_work; 189 struct delayed_work ka_work;
190 struct nvme_command ka_cmd; 190 struct nvme_command ka_cmd;
191 struct work_struct fw_act_work; 191 struct work_struct fw_act_work;
192#define EVENT_NS_CHANGED (1 << 0)
193 unsigned long events;
192 194
193 /* Power saving configuration */ 195 /* Power saving configuration */
194 u64 ps_max_latency_us; 196 u64 ps_max_latency_us;