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