aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChaitanya Kulkarni <ckulkarnilinux@gmail.com>2016-09-01 15:45:03 -0400
committerSagi Grimberg <sagi@grimberg.me>2016-09-23 18:37:37 -0400
commit2d79c7dc8fe5cf1158250a5fd25c02d781324cd3 (patch)
tree7ebc782814221d1da76dcf2a780d3464968528c5
parent478bcb9388f2c3eedba34ed5811793400047f95d (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.c88
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
19u32 nvmet_get_log_page_len(struct nvme_command *cmd) 20u32 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
33static 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);
59out:
60 return status;
61}
62
63static 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
95static 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
32static void nvmet_execute_get_log_page(struct nvmet_req *req) 108static 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
163err:
76 kfree(buf); 164 kfree(buf);
77out: 165out:
78 nvmet_req_complete(req, status); 166 nvmet_req_complete(req, status);