diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c index 2e48ac86..8ee92f4a 100644 --- a/src/nvme/fabrics.c +++ b/src/nvme/fabrics.c @@ -1055,45 +1055,55 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h, return NULL; } -static struct nvmf_discovery_log *nvme_discovery_log(nvme_ctrl_t c, - struct nvme_get_log_args *args, - int max_retries) +/* + * Most of nvmf_discovery_log is reserved, so only fetch the initial bytes. + * 8 bytes for GENCTR, 8 for NUMREC, and 2 for RECFMT. + * Since only multiples of 4 bytes are allowed, round 18 up to 20. + */ +#define DISCOVERY_HEADER_LEN 20 + +static struct nvmf_discovery_log *nvme_discovery_log( + const struct nvme_get_discovery_args *args) { - nvme_root_t r = c->s && c->s->h ? c->s->h->r : NULL; - struct nvmf_discovery_log *log = NULL; - int ret, retries = 0; - const char *name = nvme_ctrl_get_name(c); + nvme_root_t r = root_from_ctrl(args->c); + struct nvmf_discovery_log *log; + int retries = 0; + const char *name = nvme_ctrl_get_name(args->c); uint64_t genctr, numrec; - unsigned int size; - int fd = nvme_ctrl_get_fd(c); - - args->fd = fd; + int fd = nvme_ctrl_get_fd(args->c); + struct nvme_get_log_args log_args = { + .result = args->result, + .args_size = sizeof(log_args), + .timeout = args->timeout, + .lid = NVME_LOG_LID_DISCOVER, + .nsid = NVME_NSID_NONE, + .csi = NVME_CSI_NVM, + .lsi = NVME_LOG_LSI_NONE, + .lsp = args->lsp, + .uuidx = NVME_UUID_NONE, + }; - do { - size = sizeof(struct nvmf_discovery_log); + log = __nvme_alloc(sizeof(*log)); + if (!log) { + nvme_msg(r, LOG_ERR, + "could not allocate memory for discovery log header\n"); + errno = ENOMEM; + return NULL; + } - free(log); - log = __nvme_alloc(size); - if (!log) { - nvme_msg(r, LOG_ERR, - "could not allocate memory for discovery log header\n"); - errno = ENOMEM; - return NULL; - } + nvme_msg(r, LOG_DEBUG, "%s: get header (try %d/%d)\n", + name, retries, args->max_retries); + log_args.log = log; + log_args.len = DISCOVERY_HEADER_LEN; + if (nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &log_args)) { + nvme_msg(r, LOG_INFO, + "%s: discover try %d/%d failed, error %d\n", + name, retries, args->max_retries, errno); + goto out_free_log; + } - nvme_msg(r, LOG_DEBUG, "%s: get header (try %d/%d)\n", - name, retries, max_retries); - args->rae = true; - args->lpo = 0; - args->len = size; - args->log = log; - ret = nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, args); - if (ret) { - nvme_msg(r, LOG_INFO, - "%s: discover try %d/%d failed, error %d\n", - name, retries, max_retries, errno); - goto out_free_log; - } + do { + size_t entries_size; numrec = le64_to_cpu(log->numrec); genctr = le64_to_cpu(log->genctr); @@ -1101,11 +1111,9 @@ static struct nvmf_discovery_log *nvme_discovery_log(nvme_ctrl_t c, if (numrec == 0) break; - size = sizeof(struct nvmf_discovery_log) + - sizeof(struct nvmf_disc_log_entry) * numrec; - free(log); - log = __nvme_alloc(size); + entries_size = sizeof(*log->entries) * numrec; + log = __nvme_alloc(sizeof(*log) + entries_size); if (!log) { nvme_msg(r, LOG_ERR, "could not alloc memory for discovery log page\n"); @@ -1114,19 +1122,16 @@ static struct nvmf_discovery_log *nvme_discovery_log(nvme_ctrl_t c, } nvme_msg(r, LOG_DEBUG, - "%s: get %" PRIu64 - " records (length %d genctr %" PRIu64 ")\n", - name, numrec, size, genctr); - - args->rae = true; - args->lpo = sizeof(struct nvmf_discovery_log); - args->len = size - sizeof(struct nvmf_discovery_log); - args->log = log->entries; - ret = nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, args); - if (ret) { + "%s: get %" PRIu64 " records (genctr %" PRIu64 ")\n", + name, numrec, genctr); + + log_args.lpo = sizeof(*log); + log_args.log = log->entries; + log_args.len = entries_size; + if (nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &log_args)) { nvme_msg(r, LOG_INFO, "%s: discover try %d/%d failed, error %d\n", - name, retries, max_retries, errno); + name, retries, args->max_retries, errno); goto out_free_log; } @@ -1136,19 +1141,17 @@ static struct nvmf_discovery_log *nvme_discovery_log(nvme_ctrl_t c, */ nvme_msg(r, LOG_DEBUG, "%s: get header again\n", name); - args->rae = false; - args->lpo = 0; - args->len = sizeof(struct nvmf_discovery_log); - args->log = log; - ret = nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, args); - if (ret) { + log_args.lpo = 0; + log_args.log = log; + log_args.len = DISCOVERY_HEADER_LEN; + if (nvme_get_log_page(fd, NVME_LOG_PAGE_PDU_SIZE, &log_args)) { nvme_msg(r, LOG_INFO, "%s: discover try %d/%d failed, error %d\n", - name, retries, max_retries, errno); + name, retries, args->max_retries, errno); goto out_free_log; } } while (genctr != le64_to_cpu(log->genctr) && - ++retries < max_retries); + ++retries < args->max_retries); if (genctr != le64_to_cpu(log->genctr)) { nvme_msg(r, LOG_INFO, "%s: discover genctr mismatch\n", name); @@ -1177,58 +1180,22 @@ static void sanitize_discovery_log_entry(struct nvmf_disc_log_entry *e) int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp, int max_retries) { - struct nvmf_discovery_log *log; - - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = nvme_ctrl_get_fd(c), - .nsid = NVME_NSID_NONE, - .lsp = NVMF_LOG_DISC_LSP_NONE, - .lsi = NVME_LOG_LSI_NONE, - .uuidx = NVME_UUID_NONE, + struct nvme_get_discovery_args args = { + .c = c, + .max_retries = max_retries, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - .lid = NVME_LOG_LID_DISCOVER, - .log = NULL, - .len = 0, - .csi = NVME_CSI_NVM, - .rae = false, - .ot = false, + .lsp = NVMF_LOG_DISC_LSP_NONE, }; - log = nvme_discovery_log(c, &args, max_retries); - if (!log) - return -1; - - for (int i = 0; i < le64_to_cpu(log->numrec); i++) - sanitize_discovery_log_entry(&log->entries[i]); - - *logp = log; - return 0; + *logp = nvmf_get_discovery_wargs(&args); + return *logp ? 0 : -1; } struct nvmf_discovery_log *nvmf_get_discovery_wargs(struct nvme_get_discovery_args *args) { struct nvmf_discovery_log *log; - struct nvme_get_log_args _args = { - .args_size = sizeof(_args), - .fd = nvme_ctrl_get_fd(args->c), - .nsid = NVME_NSID_NONE, - .lsp = args->lsp, - .lsi = NVME_LOG_LSI_NONE, - .uuidx = NVME_UUID_NONE, - .timeout = args->timeout, - .result = args->result, - .lid = NVME_LOG_LID_DISCOVER, - .log = NULL, - .len = 0, - .csi = NVME_CSI_NVM, - .rae = false, - .ot = false, - }; - - log = nvme_discovery_log(args->c, &_args, args->max_retries); + log = nvme_discovery_log(args); if (!log) return NULL; diff --git a/test/ioctl/discovery.c b/test/ioctl/discovery.c index 7e075b8c..f5f6f516 100644 --- a/test/ioctl/discovery.c +++ b/test/ioctl/discovery.c @@ -13,6 +13,7 @@ #include "util.h" #define TEST_FD 0xFD +#define HEADER_LEN 20 static void arbitrary_ascii_string(size_t max_len, char *str, char *log_str) { @@ -61,9 +62,8 @@ static void test_no_entries(nvme_ctrl_t c) struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header, }, @@ -90,9 +90,8 @@ static void test_four_entries(nvme_ctrl_t c) struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header, }, @@ -100,15 +99,14 @@ static void test_four_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = sizeof(entries), .cdw10 = (sizeof(entries) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* LID */ .cdw12 = sizeof(header), /* LPOL */ .out_data = log_entries, }, { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header, }, @@ -142,9 +140,8 @@ static void test_five_entries(nvme_ctrl_t c) struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header, }, @@ -161,15 +158,14 @@ static void test_five_entries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = second_data_len, .cdw10 = (second_data_len / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* LID */ .cdw12 = sizeof(header) + first_data_len, /* LPOL */ .out_data = log_entries + first_entries, }, { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header, }, @@ -200,14 +196,13 @@ static void test_genctr_change(nvme_ctrl_t c) }; /* * genctr changes after the entries are fetched the first time, - * so the log page fetch is retried + * so the log page entries are refetched */ struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header1), - .cdw10 = (sizeof(header1) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header1, }, @@ -215,23 +210,14 @@ static void test_genctr_change(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = sizeof(entries1), .cdw10 = (sizeof(entries1) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* NUMDL */ .cdw12 = sizeof(header1), /* LPOL */ .out_data = entries1, }, { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header2), - .cdw10 = (sizeof(header2) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ - .out_data = &header2, - }, - { - .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header2), - .cdw10 = (sizeof(header2) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header2, }, @@ -239,15 +225,14 @@ static void test_genctr_change(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = sizeof(entries2), .cdw10 = (sizeof(entries2) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* LID */ .cdw12 = sizeof(header2), /* LPOL */ .out_data = log_entries2, }, { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header2), - .cdw10 = (sizeof(header2) / 4 - 1) << 16 /* NUMDL */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header2, }, @@ -280,9 +265,8 @@ static void test_max_retries(nvme_ctrl_t c) struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header1), - .cdw10 = (sizeof(header1) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header1, }, @@ -290,23 +274,14 @@ static void test_max_retries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = sizeof(entry), .cdw10 = (sizeof(entry) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* LID */ .cdw12 = sizeof(header1), /* LPOL */ .out_data = &entry, }, { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header2), - .cdw10 = (sizeof(header2) / 4 - 1) << 16 /* NUMDL */ - | NVME_LOG_LID_DISCOVER, /* LID */ - .out_data = &header2, - }, - { - .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header2), - .cdw10 = (sizeof(header2) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header2, }, @@ -314,15 +289,14 @@ static void test_max_retries(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = sizeof(entry), .cdw10 = (sizeof(entry) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* LID */ .cdw12 = sizeof(header2), /* LPOL */ .out_data = &entry, }, { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header3), - .cdw10 = (sizeof(header3) / 4 - 1) << 16 /* NUMDL */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header3, }, @@ -339,14 +313,12 @@ static void test_max_retries(nvme_ctrl_t c) static void test_header_error(nvme_ctrl_t c) { - size_t header_size = sizeof(struct nvmf_discovery_log); /* Stop after an error in fetching the header the first time */ struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = header_size, - .cdw10 = (header_size / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .err = NVME_SC_INVALID_OPCODE, }, @@ -367,9 +339,8 @@ static void test_entries_error(nvme_ctrl_t c) struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header, }, @@ -377,7 +348,6 @@ static void test_entries_error(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = entry_size, .cdw10 = (entry_size / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* LID */ .cdw12 = sizeof(header), /* LPOL */ .err = -EIO, @@ -400,9 +370,8 @@ static void test_genctr_error(nvme_ctrl_t c) struct mock_cmd mock_admin_cmds[] = { { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .out_data = &header, }, @@ -410,15 +379,14 @@ static void test_genctr_error(nvme_ctrl_t c) .opcode = nvme_admin_get_log_page, .data_len = sizeof(entry), .cdw10 = (sizeof(entry) / 4 - 1) << 16 /* NUMDL */ - | 1 << 15 /* RAE */ | NVME_LOG_LID_DISCOVER, /* LID */ .cdw12 = sizeof(header), /* LPOL */ .out_data = &entry, }, { .opcode = nvme_admin_get_log_page, - .data_len = sizeof(header), - .cdw10 = (sizeof(header) / 4 - 1) << 16 /* NUMDL */ + .data_len = HEADER_LEN, + .cdw10 = (HEADER_LEN / 4 - 1) << 16 /* NUMDL */ | NVME_LOG_LID_DISCOVER, /* LID */ .err = NVME_SC_INTERNAL, },