diff options
author | Chaitanya Kulkarni <ckulkarnilinux@gmail.com> | 2016-09-01 15:45:03 -0400 |
---|---|---|
committer | Sagi Grimberg <sagi@grimberg.me> | 2016-09-23 18:37:37 -0400 |
commit | 2d79c7dc8fe5cf1158250a5fd25c02d781324cd3 (patch) | |
tree | 7ebc782814221d1da76dcf2a780d3464968528c5 | |
parent | 478bcb9388f2c3eedba34ed5811793400047f95d (diff) |
admin-cmd: Added smart-log command support.
This patch implements the support for smart-log command
(NVM Express 1.2.1-section 5.10.1.2 SMART / Health Information
(Log Identifier 02h)) on the target for NVMe over Fabric.
In current implementation host can retrieve following statistics:-
1. Data Units Read.
2. Data Units Written.
3. Host Read Commands.
4. Host Write Commands.
Signed-off-by: Chaitanya Kulkarni <ckulkarnilinux@gmail.com>
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
-rw-r--r-- | drivers/nvme/target/admin-cmd.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c index 47c564b5a289..7ab9c9381b98 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <generated/utsrelease.h> | 16 | #include <generated/utsrelease.h> |
17 | #include <asm/unaligned.h> | ||
17 | #include "nvmet.h" | 18 | #include "nvmet.h" |
18 | 19 | ||
19 | u32 nvmet_get_log_page_len(struct nvme_command *cmd) | 20 | u32 nvmet_get_log_page_len(struct nvme_command *cmd) |
@@ -29,8 +30,84 @@ u32 nvmet_get_log_page_len(struct nvme_command *cmd) | |||
29 | return len; | 30 | return len; |
30 | } | 31 | } |
31 | 32 | ||
33 | static u16 nvmet_get_smart_log_nsid(struct nvmet_req *req, | ||
34 | struct nvme_smart_log *slog) | ||
35 | { | ||
36 | u16 status; | ||
37 | struct nvmet_ns *ns; | ||
38 | u64 host_reads, host_writes, data_units_read, data_units_written; | ||
39 | |||
40 | status = NVME_SC_SUCCESS; | ||
41 | ns = nvmet_find_namespace(req->sq->ctrl, req->cmd->get_log_page.nsid); | ||
42 | if (!ns) { | ||
43 | status = NVME_SC_INVALID_NS; | ||
44 | pr_err("nvmet : Counld not find namespace id : %d\n", | ||
45 | le32_to_cpu(req->cmd->get_log_page.nsid)); | ||
46 | goto out; | ||
47 | } | ||
48 | |||
49 | host_reads = part_stat_read(ns->bdev->bd_part, ios[READ]); | ||
50 | data_units_read = part_stat_read(ns->bdev->bd_part, sectors[READ]); | ||
51 | host_writes = part_stat_read(ns->bdev->bd_part, ios[WRITE]); | ||
52 | data_units_written = part_stat_read(ns->bdev->bd_part, sectors[WRITE]); | ||
53 | |||
54 | put_unaligned_le64(host_reads, &slog->host_reads[0]); | ||
55 | put_unaligned_le64(data_units_read, &slog->data_units_read[0]); | ||
56 | put_unaligned_le64(host_writes, &slog->host_writes[0]); | ||
57 | put_unaligned_le64(data_units_written, &slog->data_units_written[0]); | ||
58 | nvmet_put_namespace(ns); | ||
59 | out: | ||
60 | return status; | ||
61 | } | ||
62 | |||
63 | static u16 nvmet_get_smart_log_all(struct nvmet_req *req, | ||
64 | struct nvme_smart_log *slog) | ||
65 | { | ||
66 | u16 status; | ||
67 | u64 host_reads = 0, host_writes = 0; | ||
68 | u64 data_units_read = 0, data_units_written = 0; | ||
69 | struct nvmet_ns *ns; | ||
70 | struct nvmet_ctrl *ctrl; | ||
71 | |||
72 | status = NVME_SC_SUCCESS; | ||
73 | ctrl = req->sq->ctrl; | ||
74 | |||
75 | rcu_read_lock(); | ||
76 | list_for_each_entry_rcu(ns, &ctrl->subsys->namespaces, dev_link) { | ||
77 | host_reads += part_stat_read(ns->bdev->bd_part, ios[READ]); | ||
78 | data_units_read += | ||
79 | part_stat_read(ns->bdev->bd_part, sectors[READ]); | ||
80 | host_writes += part_stat_read(ns->bdev->bd_part, ios[WRITE]); | ||
81 | data_units_written += | ||
82 | part_stat_read(ns->bdev->bd_part, sectors[WRITE]); | ||
83 | |||
84 | } | ||
85 | rcu_read_unlock(); | ||
86 | |||
87 | put_unaligned_le64(host_reads, &slog->host_reads[0]); | ||
88 | put_unaligned_le64(data_units_read, &slog->data_units_read[0]); | ||
89 | put_unaligned_le64(host_writes, &slog->host_writes[0]); | ||
90 | put_unaligned_le64(data_units_written, &slog->data_units_written[0]); | ||
91 | |||
92 | return status; | ||
93 | } | ||
94 | |||
95 | static u16 nvmet_get_smart_log(struct nvmet_req *req, | ||
96 | struct nvme_smart_log *slog) | ||
97 | { | ||
98 | u16 status; | ||
99 | |||
100 | WARN_ON(req == NULL || slog == NULL); | ||
101 | if (req->cmd->get_log_page.nsid == 0xFFFFFFFF) | ||
102 | status = nvmet_get_smart_log_all(req, slog); | ||
103 | else | ||
104 | status = nvmet_get_smart_log_nsid(req, slog); | ||
105 | return status; | ||
106 | } | ||
107 | |||
32 | static void nvmet_execute_get_log_page(struct nvmet_req *req) | 108 | static void nvmet_execute_get_log_page(struct nvmet_req *req) |
33 | { | 109 | { |
110 | struct nvme_smart_log *smart_log; | ||
34 | size_t data_len = nvmet_get_log_page_len(req->cmd); | 111 | size_t data_len = nvmet_get_log_page_len(req->cmd); |
35 | void *buf; | 112 | void *buf; |
36 | u16 status = 0; | 113 | u16 status = 0; |
@@ -59,6 +136,16 @@ static void nvmet_execute_get_log_page(struct nvmet_req *req) | |||
59 | * available (e.g. units or commands read/written) those aren't | 136 | * available (e.g. units or commands read/written) those aren't |
60 | * persistent over power loss. | 137 | * persistent over power loss. |
61 | */ | 138 | */ |
139 | if (data_len != sizeof(*smart_log)) { | ||
140 | status = NVME_SC_INTERNAL; | ||
141 | goto err; | ||
142 | } | ||
143 | smart_log = buf; | ||
144 | status = nvmet_get_smart_log(req, smart_log); | ||
145 | if (status) { | ||
146 | memset(buf, '\0', data_len); | ||
147 | goto err; | ||
148 | } | ||
62 | break; | 149 | break; |
63 | case 0x03: | 150 | case 0x03: |
64 | /* | 151 | /* |
@@ -73,6 +160,7 @@ static void nvmet_execute_get_log_page(struct nvmet_req *req) | |||
73 | 160 | ||
74 | status = nvmet_copy_to_sgl(req, 0, buf, data_len); | 161 | status = nvmet_copy_to_sgl(req, 0, buf, data_len); |
75 | 162 | ||
163 | err: | ||
76 | kfree(buf); | 164 | kfree(buf); |
77 | out: | 165 | out: |
78 | nvmet_req_complete(req, status); | 166 | nvmet_req_complete(req, status); |