xref: /aosp_15_r20/external/sg3_utils/testing/sg_scat_gath.h (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche  * Copyright (c) 2014-2020 Douglas Gilbert.
3*44704f69SBart Van Assche  * All rights reserved.
4*44704f69SBart Van Assche  * Use of this source code is governed by a BSD-style
5*44704f69SBart Van Assche  * license that can be found in the BSD_LICENSE file.
6*44704f69SBart Van Assche  *
7*44704f69SBart Van Assche  * SPDX-License-Identifier: BSD-2-Clause
8*44704f69SBart Van Assche  */
9*44704f69SBart Van Assche 
10*44704f69SBart Van Assche // C standard headers
11*44704f69SBart Van Assche #include <stdio.h>
12*44704f69SBart Van Assche #include <stdint.h>
13*44704f69SBart Van Assche #define __STDC_FORMAT_MACROS 1
14*44704f69SBart Van Assche #include <inttypes.h>
15*44704f69SBart Van Assche 
16*44704f69SBart Van Assche // C++ standard headers
17*44704f69SBart Van Assche #include <vector>
18*44704f69SBart Van Assche 
19*44704f69SBart Van Assche // This file is a C++ header file
20*44704f69SBart Van Assche 
21*44704f69SBart Van Assche 
22*44704f69SBart Van Assche #define SG_SGL_MAX_ELEMENTS 16384
23*44704f69SBart Van Assche 
24*44704f69SBart Van Assche #define SG_COUNT_INDEFINITE (-1)
25*44704f69SBart Van Assche #define SG_LBA_INVALID SG_COUNT_INDEFINITE
26*44704f69SBart Van Assche 
27*44704f69SBart Van Assche // Sizing matches largest SCSI READ and WRITE commands plus those of Unix
28*44704f69SBart Van Assche // read(2)s and write(2)s. User can give larger than 31 bit 'num's but they
29*44704f69SBart Van Assche // are split into several consecutive elements.
30*44704f69SBart Van Assche class scat_gath_elem {
31*44704f69SBart Van Assche public:
32*44704f69SBart Van Assche     uint64_t lba;       // of start block
33*44704f69SBart Van Assche     uint32_t num;       // number of blocks from and including start block
34*44704f69SBart Van Assche 
make_bad()35*44704f69SBart Van Assche     void make_bad() { lba = UINT64_MAX; num = UINT32_MAX; }
is_bad()36*44704f69SBart Van Assche     bool is_bad() const { return (lba == UINT64_MAX && num == UINT32_MAX); }
37*44704f69SBart Van Assche };
38*44704f69SBart Van Assche 
39*44704f69SBart Van Assche // Consider "linearity" as a scatter gather list property. Elements of this
40*44704f69SBart Van Assche // of from the strongest form to the weakest.
41*44704f69SBart Van Assche enum sgl_linearity_e {
42*44704f69SBart Van Assche     SGL_LINEAR = 0,     // empty list and 0,0 considered linear
43*44704f69SBart Van Assche     SGL_MONOTONIC,      // since not linear, implies holes
44*44704f69SBart Van Assche     SGL_MONO_OVERLAP,   // monotonic but same LBA in two or more elements
45*44704f69SBart Van Assche     SGL_NON_MONOTONIC   // weakest
46*44704f69SBart Van Assche };
47*44704f69SBart Van Assche 
48*44704f69SBart Van Assche 
49*44704f69SBart Van Assche // Holds one scatter gather list and its associated metadata
50*44704f69SBart Van Assche class scat_gath_list {
51*44704f69SBart Van Assche public:
scat_gath_list()52*44704f69SBart Van Assche     scat_gath_list() : linearity(SGL_LINEAR), sum_hard(false), m_errno(0),
53*44704f69SBart Van Assche         high_lba_p1(0), lowest_lba(0), sum(0) { }
54*44704f69SBart Van Assche 
55*44704f69SBart Van Assche     scat_gath_list(const scat_gath_list &) = default;
56*44704f69SBart Van Assche     scat_gath_list & operator=(const scat_gath_list &) = default;
57*44704f69SBart Van Assche     ~scat_gath_list() = default;
58*44704f69SBart Van Assche 
59*44704f69SBart Van Assche     bool empty() const;
60*44704f69SBart Van Assche     bool empty_or_00() const;
61*44704f69SBart Van Assche     int num_elems() const;
62*44704f69SBart Van Assche     int64_t get_lowest_lba(bool ignore_degen, bool always_last) const;
63*44704f69SBart Van Assche     int64_t get_low_lba_from_linear() const;
64*44704f69SBart Van Assche     bool is_pipe_suitable() const;
65*44704f69SBart Van Assche 
66*44704f69SBart Van Assche     friend bool sgls_eq_off(const scat_gath_list &left, int l_e_ind,
67*44704f69SBart Van Assche                             int l_blk_off,
68*44704f69SBart Van Assche                             const scat_gath_list &right, int r_e_ind,
69*44704f69SBart Van Assche                             int r_blk_off, bool allow_partial);
70*44704f69SBart Van Assche 
71*44704f69SBart Van Assche     bool load_from_cli(const char * cl_p, bool b_vb);
72*44704f69SBart Van Assche     bool load_from_file(const char * file_name, bool def_hex, bool flexible,
73*44704f69SBart Van Assche                         bool b_vb);
74*44704f69SBart Van Assche     int append_1or(int64_t extra_blks, int64_t start_lba);
75*44704f69SBart Van Assche     int append_1or(int64_t extra_blks);
76*44704f69SBart Van Assche 
77*44704f69SBart Van Assche     void dbg_print(bool skip_meta, const char * id_str, bool to_stdout,
78*44704f69SBart Van Assche                    bool show_sgl) const;
79*44704f69SBart Van Assche 
80*44704f69SBart Van Assche     // calculates and sets following bool-s and int64_t-s
81*44704f69SBart Van Assche     void sum_scan(const char * id_str, bool show_sgl, bool b_verbose);
82*44704f69SBart Van Assche 
83*44704f69SBart Van Assche     void set_weaker_linearity(enum sgl_linearity_e lin);
84*44704f69SBart Van Assche     enum sgl_linearity_e linearity;
85*44704f69SBart Van Assche     const char * linearity_as_str() const;
86*44704f69SBart Van Assche 
87*44704f69SBart Van Assche     bool sum_hard;      // 'num' in last element of 'sgl' is > 0
88*44704f69SBart Van Assche     int m_errno;        // OS failure errno
89*44704f69SBart Van Assche     int64_t high_lba_p1;  // highest LBA plus 1, next write from and above
90*44704f69SBart Van Assche     int64_t lowest_lba; // initialized to 0
91*44704f69SBart Van Assche     int64_t sum;        // of all 'num' elements in 'sgl'
92*44704f69SBart Van Assche 
93*44704f69SBart Van Assche     friend int diff_between_iters(const class scat_gath_iter & left,
94*44704f69SBart Van Assche                                   const class scat_gath_iter & right);
95*44704f69SBart Van Assche 
96*44704f69SBart Van Assche private:
97*44704f69SBart Van Assche     friend class scat_gath_iter;
98*44704f69SBart Van Assche 
99*44704f69SBart Van Assche     bool file2sgl_helper(FILE * fp, const char * fnp, bool def_hex,
100*44704f69SBart Van Assche                          bool flexible, bool b_vb);
101*44704f69SBart Van Assche 
102*44704f69SBart Van Assche     std::vector<scat_gath_elem> sgl;  // an array on heap [0..num_elems())
103*44704f69SBart Van Assche };
104*44704f69SBart Van Assche 
105*44704f69SBart Van Assche 
106*44704f69SBart Van Assche class scat_gath_iter {
107*44704f69SBart Van Assche public:
108*44704f69SBart Van Assche     explicit scat_gath_iter(const scat_gath_list & my_scat_gath_list);
109*44704f69SBart Van Assche     scat_gath_iter(const scat_gath_iter & src) = default;
110*44704f69SBart Van Assche     scat_gath_iter&  operator=(const scat_gath_iter&) = delete;
111*44704f69SBart Van Assche     ~scat_gath_iter() = default;
112*44704f69SBart Van Assche 
113*44704f69SBart Van Assche     int64_t current_lba() const;
114*44704f69SBart Van Assche     int64_t current_lba_rem_num(int & rem_num) const;
115*44704f69SBart Van Assche     class scat_gath_elem current_elem() const;
116*44704f69SBart Van Assche     bool at_end() const;
117*44704f69SBart Van Assche     bool is_sgl_linear() const; // the whole list
118*44704f69SBart Van Assche     // Should return 1 or more unless max_n<=0 or at_end()
119*44704f69SBart Van Assche     int linear_for_n_blks(int max_n) const;
120*44704f69SBart Van Assche 
121*44704f69SBart Van Assche     bool set_by_blk_idx(int64_t _blk_idx);
122*44704f69SBart Van Assche     // add/sub blocks return true if they reach EOL/start, else false
123*44704f69SBart Van Assche     bool add_blks(uint64_t blk_count);
124*44704f69SBart Van Assche     bool sub_blks(uint64_t blk_count);
125*44704f69SBart Van Assche 
126*44704f69SBart Van Assche     void dbg_print(const char * id_str, bool to_stdout, int verbose) const;
127*44704f69SBart Van Assche 
128*44704f69SBart Van Assche     friend int diff_between_iters(const class scat_gath_iter & left,
129*44704f69SBart Van Assche                                   const class scat_gath_iter & right);
130*44704f69SBart Van Assche 
131*44704f69SBart Van Assche     friend bool sgls_eq_from_iters(const class scat_gath_iter & left,
132*44704f69SBart Van Assche                                    const class scat_gath_iter & right,
133*44704f69SBart Van Assche                                    bool allow_partial);
134*44704f69SBart Van Assche 
135*44704f69SBart Van Assche private:
136*44704f69SBart Van Assche     const scat_gath_list &sglist;
137*44704f69SBart Van Assche 
138*44704f69SBart Van Assche     // dual representation: either it_el_ind,it_blk_off or blk_idx
139*44704f69SBart Van Assche     int it_el_ind;      // refers to sge==sglist[it_el_ind]
140*44704f69SBart Van Assche     int it_blk_off;     // refers to LBA==(sge.lba + it_blk_off)
141*44704f69SBart Van Assche     int64_t blk_idx;    // in range: [0 .. sglist.sum)
142*44704f69SBart Van Assche     bool extend_last;
143*44704f69SBart Van Assche };
144