aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/nvme/host/core.c36
1 files changed, 11 insertions, 25 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index d6ca4598c027..dee8e71baf62 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3197,40 +3197,28 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
3197 nvme_remove_invalid_namespaces(ctrl, nn); 3197 nvme_remove_invalid_namespaces(ctrl, nn);
3198} 3198}
3199 3199
3200static bool nvme_scan_changed_ns_log(struct nvme_ctrl *ctrl) 3200static void nvme_clear_changed_ns_log(struct nvme_ctrl *ctrl)
3201{ 3201{
3202 size_t log_size = NVME_MAX_CHANGED_NAMESPACES * sizeof(__le32); 3202 size_t log_size = NVME_MAX_CHANGED_NAMESPACES * sizeof(__le32);
3203 __le32 *log; 3203 __le32 *log;
3204 int error, i; 3204 int error;
3205 bool ret = false;
3206 3205
3207 log = kzalloc(log_size, GFP_KERNEL); 3206 log = kzalloc(log_size, GFP_KERNEL);
3208 if (!log) 3207 if (!log)
3209 return false; 3208 return;
3210 3209
3210 /*
3211 * We need to read the log to clear the AEN, but we don't want to rely
3212 * on it for the changed namespace information as userspace could have
3213 * raced with us in reading the log page, which could cause us to miss
3214 * updates.
3215 */
3211 error = nvme_get_log(ctrl, NVME_LOG_CHANGED_NS, log, log_size); 3216 error = nvme_get_log(ctrl, NVME_LOG_CHANGED_NS, log, log_size);
3212 if (error) { 3217 if (error)
3213 dev_warn(ctrl->device, 3218 dev_warn(ctrl->device,
3214 "reading changed ns log failed: %d\n", error); 3219 "reading changed ns log failed: %d\n", error);
3215 goto out_free_log;
3216 }
3217
3218 if (log[0] == cpu_to_le32(0xffffffff))
3219 goto out_free_log;
3220 3220
3221 for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) {
3222 u32 nsid = le32_to_cpu(log[i]);
3223
3224 if (nsid == 0)
3225 break;
3226 dev_info(ctrl->device, "rescanning namespace %d.\n", nsid);
3227 nvme_validate_ns(ctrl, nsid);
3228 }
3229 ret = true;
3230
3231out_free_log:
3232 kfree(log); 3221 kfree(log);
3233 return ret;
3234} 3222}
3235 3223
3236static void nvme_scan_work(struct work_struct *work) 3224static void nvme_scan_work(struct work_struct *work)
@@ -3246,9 +3234,8 @@ static void nvme_scan_work(struct work_struct *work)
3246 WARN_ON_ONCE(!ctrl->tagset); 3234 WARN_ON_ONCE(!ctrl->tagset);
3247 3235
3248 if (test_and_clear_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) { 3236 if (test_and_clear_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) {
3249 if (nvme_scan_changed_ns_log(ctrl))
3250 goto out_sort_namespaces;
3251 dev_info(ctrl->device, "rescanning namespaces.\n"); 3237 dev_info(ctrl->device, "rescanning namespaces.\n");
3238 nvme_clear_changed_ns_log(ctrl);
3252 } 3239 }
3253 3240
3254 if (nvme_identify_ctrl(ctrl, &id)) 3241 if (nvme_identify_ctrl(ctrl, &id))
@@ -3263,7 +3250,6 @@ static void nvme_scan_work(struct work_struct *work)
3263 nvme_scan_ns_sequential(ctrl, nn); 3250 nvme_scan_ns_sequential(ctrl, nn);
3264out_free_id: 3251out_free_id:
3265 kfree(id); 3252 kfree(id);
3266out_sort_namespaces:
3267 down_write(&ctrl->namespaces_rwsem); 3253 down_write(&ctrl->namespaces_rwsem);
3268 list_sort(NULL, &ctrl->namespaces, ns_cmp); 3254 list_sort(NULL, &ctrl->namespaces, ns_cmp);
3269 up_write(&ctrl->namespaces_rwsem); 3255 up_write(&ctrl->namespaces_rwsem);