]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: PEL need to check gen number for verification of collected log
authorSteven Seungcheol Lee <sc108.lee@samsung.com>
Thu, 26 Aug 2021 03:06:11 +0000 (12:06 +0900)
committerDaniel Wagner <dwagner@suse.de>
Mon, 15 Nov 2021 11:06:29 +0000 (12:06 +0100)
If the Persistent Event Log is not read with a single Get Log Page
command, then host software should read the Generation Number field in
the Persistent Event Log header after establishing a reporting context
but before reading the remainder of the log and then re-read the
Generation Number field after it has read the entire log.

If the generation numbers do not match, then:
    - the reporting context may have been lost while reading the log;
    - the Persistent Event Log contents read may be invalid; and
    - host software should re-read the log.

While at it, fix bug (unallocated pointer free)

Signed-off-by: Steven Seungcheol Lee <sc108.lee@samsung.com>
[dwagner: ported from monolitic branch and updated context]
Signed-off-by: Daniel Wagner <dwagner@suse.de>
nvme.c

diff --git a/nvme.c b/nvme.c
index 6691e478190c234f8f1bf1a4b67f7287edd9ad1b..ccd6af8e376ee1abeb3aab1e259f40d276c33d76 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -963,7 +963,7 @@ static int get_persistent_event_log(int argc, char **argv,
                        " processing this persistent log page command.";
        const char *log_len = "number of bytes to retrieve";
        const char *raw = "use binary output";
-       struct nvme_persistent_event_log *pevent;
+       struct nvme_persistent_event_log *pevent, *pevent_collected;
        enum nvme_print_flags flags;
        void *pevent_log_info;
        int err, fd;
@@ -1012,22 +1012,22 @@ static int get_persistent_event_log(int argc, char **argv,
                        sizeof(*pevent), pevent);
        if (err < 0) {
                perror("persistent event log");
-               goto close_fd;
+               goto free_pevent;
        } else if (err) {
                nvme_show_status(err);
-               goto close_fd;
+               goto free_pevent;
        }
 
        if (cfg.action == NVME_PEVENT_LOG_RELEASE_CTX) {
                printf("Releasing Persistent Event Log Context\n");
-               goto close_fd;
+               goto free_pevent;
        }
 
        if (!cfg.log_len && cfg.action != NVME_PEVENT_LOG_EST_CTX_AND_READ) {
                cfg.log_len = le64_to_cpu(pevent->tll);
        } else if (!cfg.log_len && cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ) {
                printf("Establishing Persistent Event Log Context\n");
-               goto close_fd;
+               goto free_pevent;
        }
 
        /*
@@ -1044,22 +1044,39 @@ static int get_persistent_event_log(int argc, char **argv,
        if (!pevent_log_info) {
                perror("could not alloc buffer for persistent event log page\n");
                err = -ENOMEM;
-               goto close_fd;
+               goto free_pevent;
        }
        err = nvme_get_log_persistent_event(fd, cfg.action,
                cfg.log_len, pevent_log_info);
-       if (!err)
+       if (!err) {
+               err = nvme_get_log_persistent_event(fd, cfg.action,
+                               sizeof(*pevent), pevent);
+               if (err < 0) {
+                       perror("persistent event log");
+                       goto free;
+               } else if (err) {
+                       nvme_show_status(err);
+                       goto free;
+               }
+               pevent_collected = pevent_log_info;
+               if (pevent_collected->gen_number != pevent->gen_number) {
+                       printf("Collected Persistent Event Log may be invalid, "\
+                               "Re-read the log is reiquired\n");
+                       goto free;
+               }
+
                nvme_show_persistent_event_log(pevent_log_info, cfg.action,
                        cfg.log_len, devicename, flags);
-       else if (err > 0)
+       else if (err > 0)
                nvme_show_status(err);
        else
                perror("persistent event log");
 
+free:
        nvme_free(pevent_log_info, huge);
-
-close_fd:
+free_pevent:
        free(pevent);
+close_fd:
        close(fd);
 ret:
        return nvme_status_to_errno(err, false);