nvme: Notify namespace changes better
When we get a namespace notification, we have to reconstrut the namespace to get the new identification data from the namespace. For each namespace in the AEN, we will reconstrict it before we call the notification. We also flag it as changed for the duration of the change callback (prior versions of the patch needed to keep track, but we no longer do, so this bit may be removed). Note when we've seen the namespace so we can notify when it goes away. Co-authored-by: imp Differential Revision: https://reviews.freebsd.org/D33032
This commit is contained in:
committed by
Warner Losh
parent
27481c2689
commit
20e94950c5
+5
-2
@@ -1929,8 +1929,11 @@ typedef void (*nvme_cons_async_fn_t)(void *, const struct nvme_completion *,
|
||||
typedef void (*nvme_cons_fail_fn_t)(void *);
|
||||
|
||||
enum nvme_namespace_flags {
|
||||
NVME_NS_DEALLOCATE_SUPPORTED = 0x1,
|
||||
NVME_NS_FLUSH_SUPPORTED = 0x2,
|
||||
NVME_NS_DEALLOCATE_SUPPORTED = 0x01,
|
||||
NVME_NS_FLUSH_SUPPORTED = 0x02,
|
||||
NVME_NS_ADDED = 0x04,
|
||||
NVME_NS_CHANGED = 0x08,
|
||||
NVME_NS_GONE = 0x10,
|
||||
};
|
||||
|
||||
int nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr,
|
||||
|
||||
@@ -1216,10 +1216,20 @@ nvme_ctrlr_aer_task(void *arg, int pending)
|
||||
} else if (aer->log_page_id == NVME_LOG_CHANGED_NAMESPACE) {
|
||||
struct nvme_ns_list *nsl =
|
||||
(struct nvme_ns_list *)aer->log_page_buffer;
|
||||
struct nvme_controller *ctrlr = aer->ctrlr;
|
||||
|
||||
for (int i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) {
|
||||
struct nvme_namespace *ns;
|
||||
uint32_t id = nsl->ns[i];
|
||||
|
||||
if (nsl->ns[i] > NVME_MAX_NAMESPACES)
|
||||
break;
|
||||
nvme_notify_ns(aer->ctrlr, nsl->ns[i]);
|
||||
|
||||
ns = &ctrlr->ns[id - 1];
|
||||
ns->flags |= NVME_NS_CHANGED;
|
||||
nvme_ns_construct(ns, id, ctrlr);
|
||||
nvme_notify_ns(ctrlr, id);
|
||||
ns->flags &= ~NVME_NS_CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ nvme_ns_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
|
||||
break;
|
||||
case NVME_PASSTHROUGH_CMD:
|
||||
pt = (struct nvme_pt_command *)arg;
|
||||
return (nvme_ctrlr_passthrough_cmd(ctrlr, pt, ns->id,
|
||||
return (nvme_ctrlr_passthrough_cmd(ctrlr, pt, ns->id,
|
||||
1 /* is_user_buffer */, 0 /* is_admin_cmd */));
|
||||
case NVME_GET_NSID:
|
||||
{
|
||||
@@ -558,8 +558,10 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id,
|
||||
* standard says the entire id will be zeros, so this is a
|
||||
* cheap way to test for that.
|
||||
*/
|
||||
if (ns->data.nsze == 0)
|
||||
return (ENXIO);
|
||||
if (ns->data.nsze == 0) {
|
||||
ns->flags |= NVME_NS_GONE;
|
||||
return ((ns->flags & NVME_NS_ADDED) ? 0 : ENXIO);
|
||||
}
|
||||
|
||||
flbas_fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, ns->data.flbas);
|
||||
|
||||
@@ -623,6 +625,7 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id,
|
||||
ns->cdev->si_drv2 = make_dev_alias(ns->cdev, "%sns%d",
|
||||
device_get_nameunit(ctrlr->dev), ns->id);
|
||||
ns->cdev->si_flags |= SI_UNMAPPED;
|
||||
ns->flags |= NVME_NS_ADDED;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user