Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "thread/thread_internal.h"
8 : : #include "bs_scheduler.c"
9 : :
10 : :
11 : : #define DEV_BUFFER_SIZE (64 * 1024 * 1024)
12 : : #define DEV_BUFFER_BLOCKLEN (4096)
13 : : #define DEV_BUFFER_BLOCKCNT (DEV_BUFFER_SIZE / DEV_BUFFER_BLOCKLEN)
14 : : uint8_t *g_dev_buffer;
15 : : uint64_t g_dev_write_bytes;
16 : : uint64_t g_dev_read_bytes;
17 : : uint64_t g_dev_copy_bytes;
18 : : bool g_dev_writev_ext_called;
19 : : bool g_dev_readv_ext_called;
20 : : bool g_dev_copy_enabled;
21 : : struct spdk_blob_ext_io_opts g_blob_ext_io_opts;
22 : :
23 : : struct spdk_power_failure_counters {
24 : : uint64_t general_counter;
25 : : uint64_t read_counter;
26 : : uint64_t write_counter;
27 : : uint64_t unmap_counter;
28 : : uint64_t write_zero_counter;
29 : : uint64_t flush_counter;
30 : : };
31 : :
32 : : static struct spdk_power_failure_counters g_power_failure_counters = {};
33 : :
34 : : struct spdk_power_failure_thresholds {
35 : : uint64_t general_threshold;
36 : : uint64_t read_threshold;
37 : : uint64_t write_threshold;
38 : : uint64_t unmap_threshold;
39 : : uint64_t write_zero_threshold;
40 : : uint64_t flush_threshold;
41 : : };
42 : :
43 : : static struct spdk_power_failure_thresholds g_power_failure_thresholds = {};
44 : :
45 : : static uint64_t g_power_failure_rc;
46 : :
47 : : void dev_reset_power_failure_event(void);
48 : : void dev_reset_power_failure_counters(void);
49 : : void dev_set_power_failure_thresholds(struct spdk_power_failure_thresholds thresholds);
50 : :
51 : : void
52 : 246 : dev_reset_power_failure_event(void)
53 : : {
54 [ - + ]: 246 : memset(&g_power_failure_counters, 0, sizeof(g_power_failure_counters));
55 [ - + ]: 246 : memset(&g_power_failure_thresholds, 0, sizeof(g_power_failure_thresholds));
56 : 246 : g_power_failure_rc = 0;
57 : 246 : }
58 : :
59 : : void
60 : 0 : dev_reset_power_failure_counters(void)
61 : : {
62 [ # # ]: 0 : memset(&g_power_failure_counters, 0, sizeof(g_power_failure_counters));
63 : 0 : g_power_failure_rc = 0;
64 : 0 : }
65 : :
66 : : /**
67 : : * Set power failure event. Power failure will occur after given number
68 : : * of IO operations. It may occur after number of particular operations
69 : : * (read, write, unmap, write zero or flush) or after given number of
70 : : * any IO operations (general_threshold). Value 0 means that the threshold
71 : : * is disabled. Any other value is the number of operation starting from
72 : : * which power failure event will happen.
73 : : */
74 : : void
75 : 246 : dev_set_power_failure_thresholds(struct spdk_power_failure_thresholds thresholds)
76 : : {
77 : 246 : g_power_failure_thresholds = thresholds;
78 : 246 : }
79 : :
80 : : /* Define here for UT only. */
81 : : struct spdk_io_channel g_io_channel;
82 : :
83 : : static struct spdk_io_channel *
84 : 2388 : dev_create_channel(struct spdk_bs_dev *dev)
85 : : {
86 : 2388 : return &g_io_channel;
87 : : }
88 : :
89 : : static void
90 : 2388 : dev_destroy_channel(struct spdk_bs_dev *dev, struct spdk_io_channel *channel)
91 : : {
92 : 2388 : }
93 : :
94 : : static void
95 : 2448 : dev_destroy(struct spdk_bs_dev *dev)
96 : : {
97 : 2448 : free(dev);
98 : 2448 : }
99 : :
100 : :
101 : : static void
102 : 190056 : dev_complete_cb(void *arg)
103 : : {
104 : 190056 : struct spdk_bs_dev_cb_args *cb_args = arg;
105 : :
106 : 190056 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, g_power_failure_rc);
107 : 190056 : }
108 : :
109 : : static void
110 : 190056 : dev_complete(void *arg)
111 : : {
112 : 190056 : _bs_send_msg(dev_complete_cb, arg, NULL);
113 : 190056 : }
114 : :
115 : : static void
116 : 86739 : dev_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
117 : : uint64_t lba, uint32_t lba_count,
118 : : struct spdk_bs_dev_cb_args *cb_args)
119 : : {
120 : : uint64_t offset, length;
121 : :
122 [ - + ]: 86739 : if (g_power_failure_thresholds.read_threshold != 0) {
123 : 0 : g_power_failure_counters.read_counter++;
124 : : }
125 : :
126 [ + + ]: 86739 : if (g_power_failure_thresholds.general_threshold != 0) {
127 : 606 : g_power_failure_counters.general_counter++;
128 : : }
129 : :
130 [ - + ]: 86739 : if ((g_power_failure_thresholds.read_threshold == 0 ||
131 [ # # ]: 0 : g_power_failure_counters.read_counter < g_power_failure_thresholds.read_threshold) &&
132 [ + + ]: 86739 : (g_power_failure_thresholds.general_threshold == 0 ||
133 [ + + ]: 606 : g_power_failure_counters.general_counter < g_power_failure_thresholds.general_threshold)) {
134 : 86649 : offset = lba * dev->blocklen;
135 : 86649 : length = lba_count * dev->blocklen;
136 [ - + ]: 86649 : SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
137 : :
138 [ + - ]: 86649 : if (length > 0) {
139 [ - + - + ]: 86649 : memcpy(payload, &g_dev_buffer[offset], length);
140 : 86649 : g_dev_read_bytes += length;
141 : : }
142 : : } else {
143 : 90 : g_power_failure_rc = -EIO;
144 : : }
145 : :
146 : 86739 : spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
147 : 86739 : }
148 : :
149 : : static void
150 : 87357 : dev_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
151 : : uint64_t lba, uint32_t lba_count,
152 : : struct spdk_bs_dev_cb_args *cb_args)
153 : : {
154 : : uint64_t offset, length;
155 : :
156 [ - + ]: 87357 : if (g_power_failure_thresholds.write_threshold != 0) {
157 : 0 : g_power_failure_counters.write_counter++;
158 : : }
159 : :
160 [ + + ]: 87357 : if (g_power_failure_thresholds.general_threshold != 0) {
161 : 408 : g_power_failure_counters.general_counter++;
162 : : }
163 : :
164 [ - + ]: 87357 : if ((g_power_failure_thresholds.write_threshold == 0 ||
165 [ # # ]: 0 : g_power_failure_counters.write_counter < g_power_failure_thresholds.write_threshold) &&
166 [ + + ]: 87357 : (g_power_failure_thresholds.general_threshold == 0 ||
167 [ + + ]: 408 : g_power_failure_counters.general_counter < g_power_failure_thresholds.general_threshold)) {
168 : 87225 : offset = lba * dev->blocklen;
169 : 87225 : length = lba_count * dev->blocklen;
170 [ - + ]: 87225 : SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
171 : :
172 [ - + - + ]: 87225 : memcpy(&g_dev_buffer[offset], payload, length);
173 : 87225 : g_dev_write_bytes += length;
174 : : } else {
175 : 132 : g_power_failure_rc = -EIO;
176 : : }
177 : :
178 : 87357 : spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
179 : 87357 : }
180 : :
181 : : static void
182 : 2448 : __check_iov(struct iovec *iov, int iovcnt, uint64_t length)
183 : : {
184 : : int i;
185 : :
186 [ + + ]: 6468 : for (i = 0; i < iovcnt; i++) {
187 : 4020 : length -= iov[i].iov_len;
188 : : }
189 : :
190 : 2448 : CU_ASSERT(length == 0);
191 : 2448 : }
192 : :
193 : : static void
194 : 1620 : dev_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
195 : : struct iovec *iov, int iovcnt,
196 : : uint64_t lba, uint32_t lba_count,
197 : : struct spdk_bs_dev_cb_args *cb_args)
198 : : {
199 : : uint64_t offset, length;
200 : : int i;
201 : :
202 [ - + ]: 1620 : if (g_power_failure_thresholds.read_threshold != 0) {
203 : 0 : g_power_failure_counters.read_counter++;
204 : : }
205 : :
206 [ - + ]: 1620 : if (g_power_failure_thresholds.general_threshold != 0) {
207 : 0 : g_power_failure_counters.general_counter++;
208 : : }
209 : :
210 [ - + ]: 1620 : if ((g_power_failure_thresholds.read_threshold == 0 ||
211 [ # # ]: 0 : g_power_failure_counters.read_counter < g_power_failure_thresholds.read_threshold) &&
212 [ - + ]: 1620 : (g_power_failure_thresholds.general_threshold == 0 ||
213 [ # # ]: 0 : g_power_failure_counters.general_counter < g_power_failure_thresholds.general_threshold)) {
214 : 1620 : offset = lba * dev->blocklen;
215 : 1620 : length = lba_count * dev->blocklen;
216 [ - + ]: 1620 : SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
217 : 1620 : __check_iov(iov, iovcnt, length);
218 : :
219 [ + + ]: 4752 : for (i = 0; i < iovcnt; i++) {
220 [ - + - + ]: 3132 : memcpy(iov[i].iov_base, &g_dev_buffer[offset], iov[i].iov_len);
221 : 3132 : offset += iov[i].iov_len;
222 : : }
223 : :
224 : 1620 : g_dev_read_bytes += length;
225 : : } else {
226 : 0 : g_power_failure_rc = -EIO;
227 : : }
228 : :
229 : 1620 : spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
230 : 1620 : }
231 : :
232 : : static void
233 : 648 : dev_readv_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
234 : : struct iovec *iov, int iovcnt,
235 : : uint64_t lba, uint32_t lba_count,
236 : : struct spdk_bs_dev_cb_args *cb_args,
237 : : struct spdk_blob_ext_io_opts *io_opts)
238 : : {
239 : 648 : g_dev_readv_ext_called = true;
240 : 648 : g_blob_ext_io_opts = *io_opts;
241 : 648 : dev_readv(dev, channel, iov, iovcnt, lba, lba_count, cb_args);
242 : 648 : }
243 : :
244 : : static void
245 : 828 : dev_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
246 : : struct iovec *iov, int iovcnt,
247 : : uint64_t lba, uint32_t lba_count,
248 : : struct spdk_bs_dev_cb_args *cb_args)
249 : : {
250 : : uint64_t offset, length;
251 : : int i;
252 : :
253 [ - + ]: 828 : if (g_power_failure_thresholds.write_threshold != 0) {
254 : 0 : g_power_failure_counters.write_counter++;
255 : : }
256 : :
257 [ - + ]: 828 : if (g_power_failure_thresholds.general_threshold != 0) {
258 : 0 : g_power_failure_counters.general_counter++;
259 : : }
260 : :
261 [ - + ]: 828 : if ((g_power_failure_thresholds.write_threshold == 0 ||
262 [ # # ]: 0 : g_power_failure_counters.write_counter < g_power_failure_thresholds.write_threshold) &&
263 [ - + ]: 828 : (g_power_failure_thresholds.general_threshold == 0 ||
264 [ # # ]: 0 : g_power_failure_counters.general_counter < g_power_failure_thresholds.general_threshold)) {
265 : 828 : offset = lba * dev->blocklen;
266 : 828 : length = lba_count * dev->blocklen;
267 [ - + ]: 828 : SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
268 : 828 : __check_iov(iov, iovcnt, length);
269 : :
270 [ + + ]: 1716 : for (i = 0; i < iovcnt; i++) {
271 [ - + - + ]: 888 : memcpy(&g_dev_buffer[offset], iov[i].iov_base, iov[i].iov_len);
272 : 888 : offset += iov[i].iov_len;
273 : : }
274 : :
275 : 828 : g_dev_write_bytes += length;
276 : : } else {
277 : 0 : g_power_failure_rc = -EIO;
278 : : }
279 : :
280 : 828 : spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
281 : 828 : }
282 : :
283 : : static void
284 : 216 : dev_writev_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
285 : : struct iovec *iov, int iovcnt,
286 : : uint64_t lba, uint32_t lba_count,
287 : : struct spdk_bs_dev_cb_args *cb_args,
288 : : struct spdk_blob_ext_io_opts *io_opts)
289 : : {
290 : 216 : g_dev_writev_ext_called = true;
291 : 216 : g_blob_ext_io_opts = *io_opts;
292 : 216 : dev_writev(dev, channel, iov, iovcnt, lba, lba_count, cb_args);
293 : 216 : }
294 : :
295 : : static void
296 : 0 : dev_flush(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
297 : : struct spdk_bs_dev_cb_args *cb_args)
298 : : {
299 [ # # ]: 0 : if (g_power_failure_thresholds.flush_threshold != 0) {
300 : 0 : g_power_failure_counters.flush_counter++;
301 : : }
302 : :
303 [ # # ]: 0 : if (g_power_failure_thresholds.general_threshold != 0) {
304 : 0 : g_power_failure_counters.general_counter++;
305 : : }
306 : :
307 [ # # ]: 0 : if ((g_power_failure_thresholds.flush_threshold != 0 &&
308 [ # # ]: 0 : g_power_failure_counters.flush_counter >= g_power_failure_thresholds.flush_threshold) ||
309 [ # # ]: 0 : (g_power_failure_thresholds.general_threshold != 0 &&
310 [ # # ]: 0 : g_power_failure_counters.general_counter >= g_power_failure_thresholds.general_threshold)) {
311 : 0 : g_power_failure_rc = -EIO;
312 : : }
313 : :
314 : 0 : spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
315 : 0 : }
316 : :
317 : : static void
318 : 5430 : dev_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
319 : : uint64_t lba, uint64_t lba_count,
320 : : struct spdk_bs_dev_cb_args *cb_args)
321 : : {
322 : : uint64_t offset, length;
323 : :
324 [ - + ]: 5430 : if (g_power_failure_thresholds.unmap_threshold != 0) {
325 : 0 : g_power_failure_counters.unmap_counter++;
326 : : }
327 : :
328 [ - + ]: 5430 : if (g_power_failure_thresholds.general_threshold != 0) {
329 : 0 : g_power_failure_counters.general_counter++;
330 : : }
331 : :
332 [ - + ]: 5430 : if ((g_power_failure_thresholds.unmap_threshold == 0 ||
333 [ # # ]: 0 : g_power_failure_counters.unmap_counter < g_power_failure_thresholds.unmap_threshold) &&
334 [ - + ]: 5430 : (g_power_failure_thresholds.general_threshold == 0 ||
335 [ # # ]: 0 : g_power_failure_counters.general_counter < g_power_failure_thresholds.general_threshold)) {
336 : 5430 : offset = lba * dev->blocklen;
337 : 5430 : length = lba_count * dev->blocklen;
338 [ - + ]: 5430 : SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
339 [ - + ]: 5430 : memset(&g_dev_buffer[offset], 0, length);
340 : : } else {
341 : 0 : g_power_failure_rc = -EIO;
342 : : }
343 : :
344 : 5430 : spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
345 : 5430 : }
346 : :
347 : : static void
348 : 8082 : dev_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
349 : : uint64_t lba, uint64_t lba_count,
350 : : struct spdk_bs_dev_cb_args *cb_args)
351 : : {
352 : : uint64_t offset, length;
353 : :
354 [ - + ]: 8082 : if (g_power_failure_thresholds.write_zero_threshold != 0) {
355 : 0 : g_power_failure_counters.write_zero_counter++;
356 : : }
357 : :
358 [ + + ]: 8082 : if (g_power_failure_thresholds.general_threshold != 0) {
359 : 24 : g_power_failure_counters.general_counter++;
360 : : }
361 : :
362 [ - + ]: 8082 : if ((g_power_failure_thresholds.write_zero_threshold == 0 ||
363 [ # # ]: 0 : g_power_failure_counters.write_zero_counter < g_power_failure_thresholds.write_zero_threshold) &&
364 [ + + ]: 8082 : (g_power_failure_thresholds.general_threshold == 0 ||
365 [ + + ]: 24 : g_power_failure_counters.general_counter < g_power_failure_thresholds.general_threshold)) {
366 : 8070 : offset = lba * dev->blocklen;
367 : 8070 : length = lba_count * dev->blocklen;
368 [ - + ]: 8070 : SPDK_CU_ASSERT_FATAL(offset + length <= DEV_BUFFER_SIZE);
369 [ - + ]: 8070 : memset(&g_dev_buffer[offset], 0, length);
370 : 8070 : g_dev_write_bytes += length;
371 : : } else {
372 : 12 : g_power_failure_rc = -EIO;
373 : : }
374 : :
375 : 8082 : spdk_thread_send_msg(spdk_get_thread(), dev_complete, cb_args);
376 : 8082 : }
377 : :
378 : : static bool
379 : 0 : dev_translate_lba(struct spdk_bs_dev *dev, uint64_t lba, uint64_t *base_lba)
380 : : {
381 : 0 : *base_lba = lba;
382 : 0 : return true;
383 : : }
384 : :
385 : : static void
386 : 384 : dev_copy(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t dst_lba,
387 : : uint64_t src_lba, uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
388 : : {
389 : 384 : void *dst = &g_dev_buffer[dst_lba * dev->blocklen];
390 : 384 : const void *src = &g_dev_buffer[src_lba * dev->blocklen];
391 : 384 : uint64_t size = lba_count * dev->blocklen;
392 : :
393 [ - + - + ]: 384 : memcpy(dst, src, size);
394 : 384 : g_dev_copy_bytes += size;
395 : :
396 : 384 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0);
397 : 384 : }
398 : :
399 : : static struct spdk_bs_dev *
400 : 2448 : init_dev(void)
401 : : {
402 : 2448 : struct spdk_bs_dev *dev = calloc(1, sizeof(*dev));
403 : :
404 [ - + ]: 2448 : SPDK_CU_ASSERT_FATAL(dev != NULL);
405 : :
406 : 2448 : dev->create_channel = dev_create_channel;
407 : 2448 : dev->destroy_channel = dev_destroy_channel;
408 : 2448 : dev->destroy = dev_destroy;
409 : 2448 : dev->read = dev_read;
410 : 2448 : dev->write = dev_write;
411 : 2448 : dev->readv = dev_readv;
412 : 2448 : dev->writev = dev_writev;
413 : 2448 : dev->readv_ext = dev_readv_ext;
414 : 2448 : dev->writev_ext = dev_writev_ext;
415 : 2448 : dev->flush = dev_flush;
416 : 2448 : dev->unmap = dev_unmap;
417 : 2448 : dev->write_zeroes = dev_write_zeroes;
418 : 2448 : dev->translate_lba = dev_translate_lba;
419 [ + + + + ]: 2448 : dev->copy = g_dev_copy_enabled ? dev_copy : NULL;
420 : 2448 : dev->blockcnt = DEV_BUFFER_BLOCKCNT;
421 : 2448 : dev->blocklen = DEV_BUFFER_BLOCKLEN;
422 : :
423 : 2448 : return dev;
424 : : }
|