/
bdev.h
2215 lines (2055 loc) · 86.6 KB
/
bdev.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2016 Intel Corporation. All rights reserved.
* Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 2021, 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
/** \file
* Block device abstraction layer
*/
#ifndef SPDK_BDEV_H_
#define SPDK_BDEV_H_
#include "spdk/stdinc.h"
#include "spdk/accel.h"
#include "spdk/scsi_spec.h"
#include "spdk/nvme_spec.h"
#include "spdk/json.h"
#include "spdk/queue.h"
#include "spdk/histogram_data.h"
#include "spdk/dif.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SPDK_BDEV_SMALL_BUF_MAX_SIZE 8192
#define SPDK_BDEV_LARGE_BUF_MAX_SIZE (64 * 1024)
#define SPDK_BDEV_MAX_INTERLEAVED_MD_SIZE (64)
/* Increase the buffer size to store interleaved metadata. Increment is the
* amount necessary to store metadata per data block. SPDK_BDEV_MAX_INTERLEAVED_MD_SIZE
* bytes metadata per 512 byte data block is the current maximum ratio of
* metadata per block.
*/
#define SPDK_BDEV_BUF_SIZE_WITH_MD(x) (((x) / 512) * (512 + SPDK_BDEV_MAX_INTERLEAVED_MD_SIZE))
/** Asynchronous event type */
enum spdk_bdev_event_type {
SPDK_BDEV_EVENT_REMOVE,
SPDK_BDEV_EVENT_RESIZE,
SPDK_BDEV_EVENT_MEDIA_MANAGEMENT,
};
/** Media management event details */
struct spdk_bdev_media_event {
uint64_t offset;
uint64_t num_blocks;
};
/**
* \brief SPDK block device.
*
* This is a virtual representation of a block device that is exported by the backend.
*/
struct spdk_bdev;
/**
* Block device remove callback.
*
* \param remove_ctx Context for the removed block device.
*/
typedef void (*spdk_bdev_remove_cb_t)(void *remove_ctx);
/**
* Block device event callback.
*
* \param type Event type.
* \param bdev Block device that triggered event.
* \param event_ctx Context for the block device event.
*/
typedef void (*spdk_bdev_event_cb_t)(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
void *event_ctx);
/**
* Block device I/O
*
* This is an I/O that is passed to an spdk_bdev.
*/
struct spdk_bdev_io;
struct spdk_bdev_fn_table;
struct spdk_io_channel;
struct spdk_json_write_ctx;
struct spdk_uuid;
/** bdev status */
enum spdk_bdev_status {
SPDK_BDEV_STATUS_INVALID,
SPDK_BDEV_STATUS_READY,
SPDK_BDEV_STATUS_UNREGISTERING,
SPDK_BDEV_STATUS_REMOVING,
};
/**
* \brief Handle to an opened SPDK block device.
*/
struct spdk_bdev_desc;
/** bdev I/O type */
enum spdk_bdev_io_type {
SPDK_BDEV_IO_TYPE_INVALID = 0,
SPDK_BDEV_IO_TYPE_READ,
SPDK_BDEV_IO_TYPE_WRITE,
SPDK_BDEV_IO_TYPE_UNMAP,
SPDK_BDEV_IO_TYPE_FLUSH,
SPDK_BDEV_IO_TYPE_RESET,
SPDK_BDEV_IO_TYPE_NVME_ADMIN,
SPDK_BDEV_IO_TYPE_NVME_IO,
SPDK_BDEV_IO_TYPE_NVME_IO_MD,
SPDK_BDEV_IO_TYPE_WRITE_ZEROES,
SPDK_BDEV_IO_TYPE_ZCOPY,
SPDK_BDEV_IO_TYPE_GET_ZONE_INFO,
SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT,
SPDK_BDEV_IO_TYPE_ZONE_APPEND,
SPDK_BDEV_IO_TYPE_COMPARE,
SPDK_BDEV_IO_TYPE_COMPARE_AND_WRITE,
SPDK_BDEV_IO_TYPE_ABORT,
SPDK_BDEV_IO_TYPE_SEEK_HOLE,
SPDK_BDEV_IO_TYPE_SEEK_DATA,
SPDK_BDEV_IO_TYPE_COPY,
SPDK_BDEV_IO_TYPE_NVME_IOV_MD,
SPDK_BDEV_NUM_IO_TYPES /* Keep last */
};
/** bdev QoS rate limit type */
enum spdk_bdev_qos_rate_limit_type {
/** IOPS rate limit for both read and write */
SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT = 0,
/** Byte per second rate limit for both read and write */
SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT,
/** Byte per second rate limit for read only */
SPDK_BDEV_QOS_R_BPS_RATE_LIMIT,
/** Byte per second rate limit for write only */
SPDK_BDEV_QOS_W_BPS_RATE_LIMIT,
/** Keep last */
SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES
};
/**
* Block device completion callback.
*
* \param bdev_io Block device I/O that has completed.
* \param success True if I/O completed successfully or false if it failed;
* additional error information may be retrieved from bdev_io by calling
* spdk_bdev_io_get_nvme_status() or spdk_bdev_io_get_scsi_status().
* \param cb_arg Callback argument specified when bdev_io was submitted.
*/
typedef void (*spdk_bdev_io_completion_cb)(struct spdk_bdev_io *bdev_io,
bool success,
void *cb_arg);
struct spdk_bdev_io_error_stat;
struct spdk_bdev_io_stat {
uint64_t bytes_read;
uint64_t num_read_ops;
uint64_t bytes_written;
uint64_t num_write_ops;
uint64_t bytes_unmapped;
uint64_t num_unmap_ops;
uint64_t bytes_copied;
uint64_t num_copy_ops;
uint64_t read_latency_ticks;
uint64_t max_read_latency_ticks;
uint64_t min_read_latency_ticks;
uint64_t write_latency_ticks;
uint64_t max_write_latency_ticks;
uint64_t min_write_latency_ticks;
uint64_t unmap_latency_ticks;
uint64_t max_unmap_latency_ticks;
uint64_t min_unmap_latency_ticks;
uint64_t copy_latency_ticks;
uint64_t max_copy_latency_ticks;
uint64_t min_copy_latency_ticks;
uint64_t ticks_rate;
/* This data structure is privately defined in the bdev library.
* This data structure is only used by the bdev_get_iostat RPC now.
*/
struct spdk_bdev_io_error_stat *io_error;
/* For efficient deep copy, no members should be added after io_error. */
};
struct spdk_bdev_opts {
uint32_t bdev_io_pool_size;
uint32_t bdev_io_cache_size;
bool bdev_auto_examine;
/* Hole at bytes 9-15. */
uint8_t reserved9[7];
/**
* The size of spdk_bdev_opts according to the caller of this library is used for ABI
* compatibility. The library uses this field to know how many fields in this
* structure are valid. And the library will populate any remaining fields with default values.
* New added fields should be put at the end of the struct.
*/
size_t opts_size;
/* Size of the per-thread iobuf caches */
uint32_t iobuf_small_cache_size;
uint32_t iobuf_large_cache_size;
} __attribute__((packed));
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_opts) == 32, "Incorrect size");
/**
* Union for controller attributes field, to list whether bdev supports fdp etc.
* By convention we match the NVMe definition, allowing other bdevs to use this feature
*/
union spdk_bdev_nvme_ctratt {
uint32_t raw;
struct {
uint32_t reserved : 19;
/* Supports flexible data placement */
uint32_t fdps : 1;
uint32_t reserved2 : 12;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_bdev_nvme_ctratt) == 4, "Incorrect size");
/**
* Union for command dword 12, which by convention matches the NVMe command dword 12 definition.
* This is used to pass NVMe specific fields to bdevs, that reports support for them as indicated
* by \ref spdk_bdev_get_nvme_ctratt
*/
union spdk_bdev_nvme_cdw12 {
uint32_t raw;
struct {
uint32_t reserved : 20;
/* Directive type */
uint32_t dtype : 4;
uint32_t reserved2 : 8;
} write;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_bdev_nvme_cdw12) == 4, "Incorrect size");
/**
* Union for command dword 13, which by convention matches the NVMe command dword 13 definition.
* This is used to pass NVMe specific fields to bdevs, that reports support for them as indicated
* by \ref spdk_bdev_get_nvme_ctratt
*/
union spdk_bdev_nvme_cdw13 {
uint32_t raw;
struct {
uint32_t reserved : 16;
/* Directive specific */
uint32_t dspec : 16;
} write;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_bdev_nvme_cdw13) == 4, "Incorrect size");
/**
* Structure with optional IO request parameters
*/
struct spdk_bdev_ext_io_opts {
/** Size of this structure in bytes */
size_t size;
/** Memory domain which describes payload in this IO request. bdev must support DMA device type that
* can access this memory domain, refer to \ref spdk_bdev_get_memory_domains and \ref spdk_memory_domain_get_dma_device_type
* If set, that means that data buffers can't be accessed directly and the memory domain must
* be used to fetch data to local buffers or to translate data to another memory domain */
struct spdk_memory_domain *memory_domain;
/** Context to be passed to memory domain operations */
void *memory_domain_ctx;
/** Metadata buffer, optional */
void *metadata;
/**
* Sequence of accel operations to be executed before/after (depending on the IO type) the
* request is submitted.
*/
struct spdk_accel_sequence *accel_sequence;
/**
* Specify which DIF check flags to exclude on a per-IO basis. The default value is
* all zeroes, which includes all of the flags set for this bdev. If any of the flags
* is set, that flag will be excluded from any DIF operations for this IO.
*/
uint32_t dif_check_flags_exclude_mask;
/** defined by \ref spdk_bdev_nvme_cdw12 */
union spdk_bdev_nvme_cdw12 nvme_cdw12;
/** defined by \ref spdk_bdev_nvme_cdw13 */
union spdk_bdev_nvme_cdw13 nvme_cdw13;
} __attribute__((packed));
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_ext_io_opts) == 52, "Incorrect size");
/**
* Get the options for the bdev module.
*
* \param opts Output parameter for options.
* \param opts_size sizeof(*opts)
*/
void spdk_bdev_get_opts(struct spdk_bdev_opts *opts, size_t opts_size);
int spdk_bdev_set_opts(struct spdk_bdev_opts *opts);
typedef void (*spdk_bdev_wait_for_examine_cb)(void *arg);
/**
* Report when all bdevs finished the examine process.
* The registered cb_fn will be called just once.
* This function needs to be called again to receive
* further reports on examine process.
*
* \param cb_fn Callback function.
* \param cb_arg Callback argument.
* \return 0 if function was registered, suitable errno value otherwise
*/
int spdk_bdev_wait_for_examine(spdk_bdev_wait_for_examine_cb cb_fn, void *cb_arg);
/**
* Examine a block device explicitly
*
* This function must be called from the SPDK app thread.
*
* \param name the name or alias of the block device
* \return 0 if block device was examined successfully, suitable errno value otherwise
*/
int spdk_bdev_examine(const char *name);
/**
* Block device initialization callback.
*
* \param cb_arg Callback argument.
* \param rc 0 if block device initialized successfully or negative errno if it failed.
*/
typedef void (*spdk_bdev_init_cb)(void *cb_arg, int rc);
/**
* Block device finish callback.
*
* \param cb_arg Callback argument.
*/
typedef void (*spdk_bdev_fini_cb)(void *cb_arg);
typedef void (*spdk_bdev_get_device_stat_cb)(struct spdk_bdev *bdev,
struct spdk_bdev_io_stat *stat, void *cb_arg, int rc);
/**
* Block device channel IO timeout callback
*
* \param cb_arg Callback argument
* \param bdev_io The IO cause the timeout
*/
typedef void (*spdk_bdev_io_timeout_cb)(void *cb_arg, struct spdk_bdev_io *bdev_io);
/**
* Initialize block device modules.
*
* \param cb_fn Called when the initialization is complete.
* \param cb_arg Argument passed to function cb_fn.
*/
void spdk_bdev_initialize(spdk_bdev_init_cb cb_fn, void *cb_arg);
/**
* Perform cleanup work to remove the registered block device modules.
*
* \param cb_fn Called when the removal is complete.
* \param cb_arg Argument passed to function cb_fn.
*/
void spdk_bdev_finish(spdk_bdev_fini_cb cb_fn, void *cb_arg);
/**
* Get the full configuration options for the registered block device modules and created bdevs.
*
* \param w pointer to a JSON write context where the configuration will be written.
*/
void spdk_bdev_subsystem_config_json(struct spdk_json_write_ctx *w);
/**
* Get block device module name.
*
* \param bdev Block device to query.
* \return Name of bdev module as a null-terminated string.
*/
const char *spdk_bdev_get_module_name(const struct spdk_bdev *bdev);
/**
* Get block device by the block device name.
*
* \param bdev_name The name of the block device.
* \return Block device associated with the name or NULL if no block device with
* bdev_name is currently registered.
*/
struct spdk_bdev *spdk_bdev_get_by_name(const char *bdev_name);
/**
* Get the first registered block device.
*
* \return The first registered block device.
*/
struct spdk_bdev *spdk_bdev_first(void);
/**
* Get the next registered block device.
*
* \param prev The current block device.
* \return The next registered block device.
*/
struct spdk_bdev *spdk_bdev_next(struct spdk_bdev *prev);
/**
* Get the first block device without virtual block devices on top.
*
* This function only traverses over block devices which have no virtual block
* devices on top of them, then get the first one.
*
* \return The first block device without virtual block devices on top.
*/
struct spdk_bdev *spdk_bdev_first_leaf(void);
/**
* Get the next block device without virtual block devices on top.
*
* This function only traverses over block devices which have no virtual block
* devices on top of them, then get the next one.
*
* \param prev The current block device.
* \return The next block device without virtual block devices on top.
*/
struct spdk_bdev *spdk_bdev_next_leaf(struct spdk_bdev *prev);
/**
* Open a block device for I/O operations.
*
* \param bdev_name Block device name to open.
* \param write true is read/write access requested, false if read-only
* \param event_cb notification callback to be called when the bdev triggers
* asynchronous event such as bdev removal. This will always be called on the
* same thread that spdk_bdev_open_ext() was called on. In case of removal event
* the descriptor will have to be manually closed to make the bdev unregister
* proceed.
* \param event_ctx param for event_cb.
* \param desc output parameter for the descriptor when operation is successful
* \return 0 if operation is successful, suitable errno value otherwise
*/
int spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
void *event_ctx, struct spdk_bdev_desc **desc);
/**
* Block device asynchronous open callback.
*
* \param desc Output parameter for the descriptor when operation is successful.
* \param rc 0 if block device is opened successfully or negated errno if failed.
* \param cb_arg Callback argument.
*/
typedef void (*spdk_bdev_open_async_cb_t)(struct spdk_bdev_desc *desc, int rc, void *cb_arg);
/**
* Structure with optional asynchronous bdev open parameters.
*/
struct spdk_bdev_open_async_opts {
/* Size of this structure in bytes. */
size_t size;
/*
* Time in milliseconds to wait for the block device to appear.
*
* When the block device does not exist, wait until the block device appears or the timeout
* is expired if nonzero, or return immediately otherwise.
*
* Default value is zero and is used when options are omitted.
*/
uint64_t timeout_ms;
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_open_async_opts) == 16, "Incorrect size");
/**
* Open a block device for I/O operations asynchronously with options.
*
* \param bdev_name Block device name to open.
* \param write true is read/write access requested, false if read-only
* \param event_cb Notification callback to be called when the bdev triggers
* asynchronous event such as bdev removal. This will always be called on the
* same thread that spdk_bdev_open_async() was called on. In case of removal event
* the descriptor will have to be manually closed to make the bdev unregister
* proceed.
* \param event_ctx param for event_cb.
* \param opts Options for asynchronous block device open. If NULL, default values are used.
* \param open_cb Open callback.
* \param open_cb_arg Parameter for open_cb.
* \return 0 if operation started successfully, suitable errno value otherwise
*/
int spdk_bdev_open_async(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
void *event_ctx, struct spdk_bdev_open_async_opts *opts,
spdk_bdev_open_async_cb_t open_cb, void *open_cb_arg);
/**
* Close a previously opened block device.
*
* Must be called on the same thread that the spdk_bdev_open_ext()
* was performed on.
*
* \param desc Block device descriptor to close.
*/
void spdk_bdev_close(struct spdk_bdev_desc *desc);
/**
* Callback function for spdk_for_each_bdev() and spdk_for_each_bdev_leaf().
*
* \param ctx Context passed to the callback.
* \param bdev Block device the callback handles.
*/
typedef int (*spdk_for_each_bdev_fn)(void *ctx, struct spdk_bdev *bdev);
/**
* Call the provided callback function for every registered block device.
* If fn returns negated errno, spdk_for_each_bdev() terminates iteration.
*
* spdk_for_each_bdev() opens before and closes after executing the provided
* callback function for each bdev internally.
*
* \param ctx Context passed to the callback function.
* \param fn Callback function for each block device.
*
* \return 0 if operation is successful, or suitable errno value one of the
* callback returned otherwise.
*/
int spdk_for_each_bdev(void *ctx, spdk_for_each_bdev_fn fn);
/**
* Call the provided callback function for every block device without virtual
* block devices on top.
*
* spdk_for_each_bdev_leaf() opens before and closes after executing the provided
* callback function for each unclaimed bdev internally.
*
* \param ctx Context passed to the callback function.
* \param fn Callback function for each block device without virtual block devices on top.
*
* \return 0 if operation is successful, or suitable errno value one of the
* callback returned otherwise.
*/
int spdk_for_each_bdev_leaf(void *ctx, spdk_for_each_bdev_fn fn);
/**
* Get the bdev associated with a bdev descriptor.
*
* \param desc Open block device descriptor
* \return bdev associated with the descriptor
*/
struct spdk_bdev *spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc);
/**
* Set a time limit for the timeout IO of the bdev and timeout callback.
* We can use this function to enable/disable the timeout handler. If
* the timeout_in_sec > 0 then it means to enable the timeout IO handling
* or change the time limit. If the timeout_in_sec == 0 it means to
* disable the timeout IO handling. If you want to enable or change the
* timeout IO handle you need to specify the spdk_bdev_io_timeout_cb it
* means the upper user determines what to do if you meet the timeout IO,
* for example, you can reset the device or abort the IO.
* Note: This function must run in the desc's thread.
*
* \param desc Block device descriptor.
* \param timeout_in_sec Timeout value
* \param cb_fn Bdev IO timeout callback
* \param cb_arg Callback argument
*
* \return 0 on success, negated errno on failure.
*/
int spdk_bdev_set_timeout(struct spdk_bdev_desc *desc, uint64_t timeout_in_sec,
spdk_bdev_io_timeout_cb cb_fn, void *cb_arg);
/**
* Check whether the block device supports the I/O type.
*
* \param bdev Block device to check.
* \param io_type The specific I/O type like read, write, flush, unmap.
* \return true if support, false otherwise.
*/
bool spdk_bdev_io_type_supported(struct spdk_bdev *bdev, enum spdk_bdev_io_type io_type);
/**
* Output driver-specific information to a JSON stream.
*
* The JSON write context will be initialized with an open object, so the bdev
* driver should write a name(based on the driver name) followed by a JSON value
* (most likely another nested object).
*
* \param bdev Block device to query.
* \param w JSON write context. It will store the driver-specific configuration context.
* \return 0 on success, negated errno on failure.
*/
int spdk_bdev_dump_info_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w);
/**
* Get block device name.
*
* \param bdev Block device to query.
* \return Name of bdev as a null-terminated string.
*/
const char *spdk_bdev_get_name(const struct spdk_bdev *bdev);
/**
* Get block device product name.
*
* \param bdev Block device to query.
* \return Product name of bdev as a null-terminated string.
*/
const char *spdk_bdev_get_product_name(const struct spdk_bdev *bdev);
/**
* Get block device logical block size.
*
* \param bdev Block device to query.
* \return Size of logical block for this bdev in bytes.
*/
uint32_t spdk_bdev_get_block_size(const struct spdk_bdev *bdev);
/**
* Get the write unit size for this bdev.
*
* Write unit size is required number of logical blocks to perform write
* operation on block device.
*
* Unit of write unit size is logical block and the minimum of write unit
* size is one. Write operations must be multiple of write unit size.
*
* \param bdev Block device to query.
*
* \return The write unit size in logical blocks.
*/
uint32_t spdk_bdev_get_write_unit_size(const struct spdk_bdev *bdev);
/**
* Get size of block device in logical blocks.
*
* \param bdev Block device to query.
* \return Size of bdev in logical blocks.
*
* Logical blocks are numbered from 0 to spdk_bdev_get_num_blocks(bdev) - 1, inclusive.
*/
uint64_t spdk_bdev_get_num_blocks(const struct spdk_bdev *bdev);
/**
* Get the string of quality of service rate limit.
*
* \param type Type of rate limit to query.
* \return String of QoS type.
*/
const char *spdk_bdev_get_qos_rpc_type(enum spdk_bdev_qos_rate_limit_type type);
/**
* Get the quality of service rate limits on a bdev.
*
* \param bdev Block device to query.
* \param limits Pointer to the QoS rate limits array which holding the limits.
*
* The limits are ordered based on the @ref spdk_bdev_qos_rate_limit_type enum.
*/
void spdk_bdev_get_qos_rate_limits(struct spdk_bdev *bdev, uint64_t *limits);
/**
* Set the quality of service rate limits on a bdev.
*
* \param bdev Block device.
* \param limits Pointer to the QoS rate limits array which holding the limits.
* \param cb_fn Callback function to be called when the QoS limit has been updated.
* \param cb_arg Argument to pass to cb_fn.
*
* The limits are ordered based on the @ref spdk_bdev_qos_rate_limit_type enum.
*/
void spdk_bdev_set_qos_rate_limits(struct spdk_bdev *bdev, uint64_t *limits,
void (*cb_fn)(void *cb_arg, int status), void *cb_arg);
/**
* Get minimum I/O buffer address alignment for a bdev.
*
* \param bdev Block device to query.
* \return Required alignment of I/O buffers in bytes.
*/
size_t spdk_bdev_get_buf_align(const struct spdk_bdev *bdev);
/**
* Get optimal I/O boundary for a bdev.
*
* \param bdev Block device to query.
* \return Optimal I/O boundary in blocks that should not be crossed for best performance, or 0 if
* no optimal boundary is reported.
*/
uint32_t spdk_bdev_get_optimal_io_boundary(const struct spdk_bdev *bdev);
/**
* Query whether block device has an enabled write cache.
*
* \param bdev Block device to query.
* \return true if block device has a volatile write cache enabled.
*
* If this function returns true, written data may not be persistent until a flush command
* is issued.
*/
bool spdk_bdev_has_write_cache(const struct spdk_bdev *bdev);
/**
* Get a bdev's UUID.
*
* \param bdev Block device to query.
* \return Pointer to UUID.
*
* All bdevs will have a UUID, but not all UUIDs will be persistent across
* application runs.
*/
const struct spdk_uuid *spdk_bdev_get_uuid(const struct spdk_bdev *bdev);
/**
* Get block device atomic compare and write unit.
*
* \param bdev Block device to query.
* \return Atomic compare and write unit for this bdev in blocks.
*/
uint16_t spdk_bdev_get_acwu(const struct spdk_bdev *bdev);
/**
* Get block device metadata size.
*
* \param bdev Block device to query.
* \return Size of metadata for this bdev in bytes.
*/
uint32_t spdk_bdev_get_md_size(const struct spdk_bdev *bdev);
/**
* Query whether metadata is interleaved with block data or separated
* with block data.
*
* \param bdev Block device to query.
* \return true if metadata is interleaved with block data or false
* if metadata is separated with block data.
*
* Note this function is valid only if there is metadata.
*/
bool spdk_bdev_is_md_interleaved(const struct spdk_bdev *bdev);
/**
* Query whether metadata is interleaved with block data or separated
* from block data.
*
* \param bdev Block device to query.
* \return true if metadata is separated from block data, false
* otherwise.
*
* Note this function is valid only if there is metadata.
*/
bool spdk_bdev_is_md_separate(const struct spdk_bdev *bdev);
/**
* Checks if bdev supports zoned namespace semantics.
*
* \param bdev Block device to query.
* \return true if device supports zoned namespace semantics.
*/
bool spdk_bdev_is_zoned(const struct spdk_bdev *bdev);
/**
* Get block device data block size.
*
* Data block size is equal to block size if there is no metadata or
* metadata is separated with block data, or equal to block size minus
* metadata size if there is metadata and it is interleaved with
* block data.
*
* \param bdev Block device to query.
* \return Size of data block for this bdev in bytes.
*/
uint32_t spdk_bdev_get_data_block_size(const struct spdk_bdev *bdev);
/**
* Get block device physical block size.
*
* \param bdev Block device to query.
* \return Size of physical block size for this bdev in bytes.
*/
uint32_t spdk_bdev_get_physical_block_size(const struct spdk_bdev *bdev);
/**
* Get DIF type of the block device.
*
* \param bdev Block device to query.
* \return DIF type of the block device.
*/
enum spdk_dif_type spdk_bdev_get_dif_type(const struct spdk_bdev *bdev);
/**
* Check whether DIF is set in the first 8/16 bytes or the last 8/16 bytes of metadata.
*
* \param bdev Block device to query.
* \return true if DIF is set in the first 8/16 bytes of metadata, or false
* if DIF is set in the last 8/16 bytes of metadata.
*
* Note that this function is valid only if DIF type is not SPDK_DIF_DISABLE.
*/
bool spdk_bdev_is_dif_head_of_md(const struct spdk_bdev *bdev);
/**
* Check whether the DIF check type is enabled.
*
* \param bdev Block device to query.
* \param check_type The specific DIF check type.
* \return true if enabled, false otherwise.
*/
bool spdk_bdev_is_dif_check_enabled(const struct spdk_bdev *bdev,
enum spdk_dif_check_type check_type);
/**
* Get block device max copy size.
*
* \param bdev Block device to query.
* \return Max copy size for this bdev in blocks. 0 means unlimited.
*/
uint32_t spdk_bdev_get_max_copy(const struct spdk_bdev *bdev);
/**
* Get the most recently measured queue depth from a bdev.
*
* The reported queue depth is the aggregate of outstanding I/O
* across all open channels associated with this bdev.
*
* \param bdev Block device to query.
*
* \return The most recent queue depth measurement for the bdev.
* If tracking is not enabled, the function will return UINT64_MAX
* It is also possible to receive UINT64_MAX after enabling tracking
* but before the first period has expired.
*/
uint64_t
spdk_bdev_get_qd(const struct spdk_bdev *bdev);
/**
* Get the queue depth polling period.
*
* The return value of this function is only valid if the bdev's
* queue depth tracking status is set to true.
*
* \param bdev Block device to query.
*
* \return The period at which this bdev's gueue depth is being refreshed.
*/
uint64_t
spdk_bdev_get_qd_sampling_period(const struct spdk_bdev *bdev);
/**
* Enable or disable queue depth sampling for this bdev.
*
* Enables queue depth sampling when period is greater than 0. Disables it when the period
* is equal to zero. The resulting queue depth is stored in the spdk_bdev object as
* measured_queue_depth.
*
* \param bdev Block device on which to enable queue depth tracking.
* \param period The period at which to poll this bdev's queue depth. If this is set
* to zero, polling will be disabled.
*/
void spdk_bdev_set_qd_sampling_period(struct spdk_bdev *bdev, uint64_t period);
/**
* Get the time spent processing IO for this device.
*
* This value is dependent upon the queue depth sampling period and is
* incremented at sampling time by the sampling period only if the measured
* queue depth is greater than 0.
*
* The disk utilization can be calculated by the following formula:
* disk_util = (io_time_2 - io_time_1) / elapsed_time.
* The user is responsible for tracking the elapsed time between two measurements.
*
* \param bdev Block device to query.
*
* \return The io time for this device in microseconds.
*/
uint64_t spdk_bdev_get_io_time(const struct spdk_bdev *bdev);
/**
* Get the weighted IO processing time for this bdev.
*
* This value is dependent upon the queue depth sampling period and is
* equal to the time spent reading from or writing to a device times
* the measured queue depth during each sampling period.
*
* The average queue depth can be calculated by the following formula:
* queue_depth = (weighted_io_time_2 - weighted_io_time_1) / elapsed_time.
* The user is responsible for tracking the elapsed time between two measurements.
*
* \param bdev Block device to query.
*
* \return The weighted io time for this device in microseconds.
*/
uint64_t spdk_bdev_get_weighted_io_time(const struct spdk_bdev *bdev);
/**
* Obtain an I/O channel for the block device opened by the specified
* descriptor. I/O channels are bound to threads, so the resulting I/O
* channel may only be used from the thread it was originally obtained
* from.
*
* \param desc Block device descriptor.
*
* \return A handle to the I/O channel or NULL on failure.
*/
struct spdk_io_channel *spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc);
/**
* Obtain a bdev module context for the block device opened by the specified
* descriptor.
*
* \param desc Block device descriptor.
*
* \return A bdev module context or NULL on failure.
*/
void *spdk_bdev_get_module_ctx(struct spdk_bdev_desc *desc);
/**
* \defgroup bdev_io_submit_functions bdev I/O Submit Functions
*
* These functions submit a new I/O request to a bdev. The I/O request will
* be represented by an spdk_bdev_io structure allocated from a global pool.
* These functions will return -ENOMEM if the spdk_bdev_io pool is empty.
*/
/**
* Submit a data seek request to the bdev on the given channel.
* Starting from offset_blocks, search for next allocated data:
* seek result can be obtained with spdk_bdev_io_get_seek_offset
*
* \ingroup bdev_io_submit_functions
*
* \param desc Block device descriptor.
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
* \param offset_blocks The offset, in blocks, from the start of the block device.
* \param cb Called when the request is complete.
* \param cb_arg Argument passed to cb.
*
* \return 0 on success. On success, the callback will always
* be called (even if the request ultimately failed). Return
* negated errno on failure, in which case the callback will not be called.
* * -EINVAL - offset_blocks is out of range
* * -ENOMEM - spdk_bdev_io buffer cannot be allocated
*/
int spdk_bdev_seek_data(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
uint64_t offset_blocks,
spdk_bdev_io_completion_cb cb, void *cb_arg);
/**
* Submit a hole seek request to the bdev on the given channel.
* Starting from offset_blocks, search for next unallocated hole:
* seek result can be obtained with spdk_bdev_io_get_seek_offset
*
* \ingroup bdev_io_submit_functions
*
* \param desc Block device descriptor.
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
* \param offset_blocks The offset, in blocks, from the start of the block device.
* \param cb Called when the request is complete.
* \param cb_arg Argument passed to cb.
*
* \return 0 on success. On success, the callback will always
* be called (even if the request ultimately failed). Return
* negated errno on failure, in which case the callback will not be called.
* * -EINVAL - offset_blocks is out of range
* * -ENOMEM - spdk_bdev_io buffer cannot be allocated
*/
int spdk_bdev_seek_hole(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
uint64_t offset_blocks,
spdk_bdev_io_completion_cb cb, void *cb_arg);
/**
* Submit a read request to the bdev on the given channel.
*
* \ingroup bdev_io_submit_functions
*
* \param desc Block device descriptor.
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
* \param buf Data buffer to read into.
* \param offset The offset, in bytes, from the start of the block device.
* \param nbytes The number of bytes to read.
* \param cb Called when the request is complete.
* \param cb_arg Argument passed to cb.
*
* \return 0 on success. On success, the callback will always
* be called (even if the request ultimately failed). Return
* negated errno on failure, in which case the callback will not be called.
* * -EINVAL - offset and/or nbytes are not aligned or out of range
* * -ENOMEM - spdk_bdev_io buffer cannot be allocated
*/
int spdk_bdev_read(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
void *buf, uint64_t offset, uint64_t nbytes,
spdk_bdev_io_completion_cb cb, void *cb_arg);
/**
* Submit a read request to the bdev on the given channel.
*
* \ingroup bdev_io_submit_functions
*
* \param desc Block device descriptor.
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
* \param buf Data buffer to read into.
* \param offset_blocks The offset, in blocks, from the start of the block device.
* \param num_blocks The number of blocks to read.
* \param cb Called when the request is complete.