Changeset View
Standalone View
sys/dev/nvd/nvd.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
static disk_getattr_t nvd_getattr; | static disk_getattr_t nvd_getattr; | ||||
static void nvd_done(void *arg, const struct nvme_completion *cpl); | static void nvd_done(void *arg, const struct nvme_completion *cpl); | ||||
static void nvd_gone(struct nvd_disk *ndisk); | static void nvd_gone(struct nvd_disk *ndisk); | ||||
static void *nvd_new_disk(struct nvme_namespace *ns, void *ctrlr); | static void *nvd_new_disk(struct nvme_namespace *ns, void *ctrlr); | ||||
static void *nvd_new_controller(struct nvme_controller *ctrlr); | static void *nvd_new_controller(struct nvme_controller *ctrlr); | ||||
static void nvd_controller_async(void *ctrlr_arg, | |||||
const struct nvme_completion *async_cpl, | |||||
uint32_t log_page_id, void *log_page_buffer, uint32_t log_page_size); | |||||
static void nvd_controller_fail(void *ctrlr); | static void nvd_controller_fail(void *ctrlr); | ||||
static int nvd_load(void); | static int nvd_load(void); | ||||
static void nvd_unload(void); | static void nvd_unload(void); | ||||
MALLOC_DEFINE(M_NVD, "nvd", "nvd(4) allocations"); | MALLOC_DEFINE(M_NVD, "nvd", "nvd(4) allocations"); | ||||
struct nvme_consumer *consumer_handle; | struct nvme_consumer *consumer_handle; | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | nvd_load() | ||||
if (!nvme_use_nvd) | if (!nvme_use_nvd) | ||||
return 0; | return 0; | ||||
mtx_init(&nvd_lock, "nvd_lock", NULL, MTX_DEF); | mtx_init(&nvd_lock, "nvd_lock", NULL, MTX_DEF); | ||||
TAILQ_INIT(&ctrlr_head); | TAILQ_INIT(&ctrlr_head); | ||||
TAILQ_INIT(&disk_head); | TAILQ_INIT(&disk_head); | ||||
consumer_handle = nvme_register_consumer(nvd_new_disk, | consumer_handle = nvme_register_consumer(nvd_new_disk, | ||||
nvd_new_controller, NULL, nvd_controller_fail); | nvd_new_controller, nvd_controller_async, nvd_controller_fail); | ||||
imp: But we do the following:
} else if (aer->log_page_id ==… | |||||
Done Inline ActionsYou are right. when I test this, I remove the !nvme_use_nvd make sure async event will let nvd knows. nvme_ctrlr_cmd_identify_namespace(ctrlr, id, &ns->data, nvme_completion_poll_cb, &status); nvme_completion_poll(&status); if (nvme_completion_is_error(&status.cpl)) { nvme_printf(ctrlr, "nvme_identify_namespace failed\n"); return (ENXIO); } I am not idea why it happens. wanpengqian_gmail.com: You are right. when I test this, I remove the `!nvme_use_nvd` make sure async event will let… | |||||
Done Inline Actionsif nvd & nda implement nvme_constroller_async() callback, do we need this here? it will call nvd_new_disk() for nvd, nvme_sim_ns_change() for nda. } else if (aer->log_page_id == NVME_LOG_CHANGED_NAMESPACE && !nvme_use_nvd) { nsl = (struct nvme_ns_list *)aer->log_page_buffer; for (i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) { if (nsl->ns[i] > NVME_MAX_NAMESPACES) break; nvme_notify_ns(aer->ctrlr, nsl->ns[i]); } } wanpengqian_gmail.com: if nvd & nda implement nvme_constroller_async() callback, do we need this here? it will call… | |||||
return (consumer_handle != NULL ? 0 : -1); | return (consumer_handle != NULL ? 0 : -1); | ||||
} | } | ||||
static void | static void | ||||
nvd_unload() | nvd_unload() | ||||
{ | { | ||||
struct nvd_controller *ctrlr; | struct nvd_controller *ctrlr; | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | while ((bp = bioq_takefirst(&ndisk->bioq)) != NULL) { | ||||
bp->bio_flags |= BIO_ERROR; | bp->bio_flags |= BIO_ERROR; | ||||
bp->bio_resid = bp->bio_bcount; | bp->bio_resid = bp->bio_bcount; | ||||
biodone(bp); | biodone(bp); | ||||
} | } | ||||
mtx_unlock(&ndisk->bioqlock); | mtx_unlock(&ndisk->bioqlock); | ||||
} | } | ||||
static void | static void | ||||
nvd_resize(struct nvd_disk *ndisk) | |||||
{ | |||||
struct disk *disk = ndisk->disk; | |||||
struct nvme_namespace *ns = ndisk->ns; | |||||
disk->d_sectorsize = nvme_ns_get_sector_size(ns); | |||||
disk->d_mediasize = (off_t)nvme_ns_get_size(ns); | |||||
disk->d_maxsize = nvme_ns_get_max_io_xfer_size(ns); | |||||
disk->d_delmaxsize = (off_t)nvme_ns_get_size(ns); | |||||
if (disk->d_delmaxsize > nvd_delete_max) | |||||
disk->d_delmaxsize = nvd_delete_max; | |||||
disk_resize(disk, M_NOWAIT); | |||||
printf(NVD_STR"%u: NVMe namespace resized\n", ndisk->unit); | |||||
printf(NVD_STR"%u: %juMB (%ju %u byte sectors)\n", disk->d_unit, | |||||
(uintmax_t)disk->d_mediasize / (1024*1024), | |||||
(uintmax_t)disk->d_mediasize / disk->d_sectorsize, | |||||
disk->d_sectorsize); | |||||
} | |||||
static void | |||||
nvd_gonecb(struct disk *dp) | nvd_gonecb(struct disk *dp) | ||||
{ | { | ||||
struct nvd_disk *ndisk = (struct nvd_disk *)dp->d_drv1; | struct nvd_disk *ndisk = (struct nvd_disk *)dp->d_drv1; | ||||
disk_destroy(ndisk->disk); | disk_destroy(ndisk->disk); | ||||
mtx_lock(&nvd_lock); | mtx_lock(&nvd_lock); | ||||
TAILQ_REMOVE(&disk_head, ndisk, global_tailq); | TAILQ_REMOVE(&disk_head, ndisk, global_tailq); | ||||
TAILQ_REMOVE(&ndisk->ctrlr->disk_head, ndisk, ctrlr_tailq); | TAILQ_REMOVE(&ndisk->ctrlr->disk_head, ndisk, ctrlr_tailq); | ||||
▲ Show 20 Lines • Show All 220 Lines • ▼ Show 20 Lines | nvd_new_disk(struct nvme_namespace *ns, void *ctrlr_arg) | ||||
printf(NVD_STR"%u: <%s> NVMe namespace\n", disk->d_unit, descr); | printf(NVD_STR"%u: <%s> NVMe namespace\n", disk->d_unit, descr); | ||||
printf(NVD_STR"%u: %juMB (%ju %u byte sectors)\n", disk->d_unit, | printf(NVD_STR"%u: %juMB (%ju %u byte sectors)\n", disk->d_unit, | ||||
(uintmax_t)disk->d_mediasize / (1024*1024), | (uintmax_t)disk->d_mediasize / (1024*1024), | ||||
(uintmax_t)disk->d_mediasize / disk->d_sectorsize, | (uintmax_t)disk->d_mediasize / disk->d_sectorsize, | ||||
disk->d_sectorsize); | disk->d_sectorsize); | ||||
return (ndisk); | return (ndisk); | ||||
} | |||||
static void | |||||
nvd_controller_async(void *ctrlr_arg, const struct nvme_completion *async_cpl, | |||||
uint32_t log_page_id, void *log_page_buffer, uint32_t log_page_size) | |||||
{ | |||||
struct nvd_controller *ctrlr = ctrlr_arg; | |||||
struct nvd_disk *ndisk; | |||||
switch (log_page_id) { | |||||
case NVME_LOG_CHANGED_NAMESPACE: | |||||
Not Done Inline ActionsAt the very least, we need to filter out all the non NMVE_LOG_CHANGED_NAMESPACE page notifications, but maybe it would be better to adapt the nvd_new_disk cope better, mostly because I want to remove the nvd hack that's in the nvme driver right now. imp: At the very least, we need to filter out all the non NMVE_LOG_CHANGED_NAMESPACE page… | |||||
Done Inline ActionsYes, we should have a switch here. wanpengqian_gmail.com: Yes, we should have a switch here. | |||||
mtx_lock(&nvd_lock); | |||||
TAILQ_FOREACH(ndisk, &ctrlr->disk_head, ctrlr_tailq) | |||||
nvd_resize(ndisk); | |||||
mtx_unlock(&nvd_lock); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | } | ||||
static void | static void | ||||
nvd_controller_fail(void *ctrlr_arg) | nvd_controller_fail(void *ctrlr_arg) | ||||
{ | { | ||||
struct nvd_controller *ctrlr = ctrlr_arg; | struct nvd_controller *ctrlr = ctrlr_arg; | ||||
struct nvd_disk *ndisk; | struct nvd_disk *ndisk; | ||||
Show All 9 Lines |
But we do the following:
so nvd should use this and we should remove the !nvme_use_nvd which is there because we know that nvd doesn't do things right in new_disk. nvd needs some additional work to support name space arrival, though.
Plus the async call is for much much more than just namespace as well...