diff options
Diffstat (limited to 'testing/sg_scat_gath.h')
-rw-r--r-- | testing/sg_scat_gath.h | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/testing/sg_scat_gath.h b/testing/sg_scat_gath.h new file mode 100644 index 00000000..2b17fb3b --- /dev/null +++ b/testing/sg_scat_gath.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2014-2020 Douglas Gilbert. + * All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the BSD_LICENSE file. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +// C headers +#include <stdio.h> +#include <stdint.h> +#define __STDC_FORMAT_MACROS 1 +#include <inttypes.h> + +// C++ headers +#include <vector> + +// This file is a C++ header file + + +#define SG_SGL_MAX_ELEMENTS 16384 + +#define SG_COUNT_INDEFINITE (-1) +#define SG_LBA_INVALID SG_COUNT_INDEFINITE + +/* Sizing matches largest SCSI READ and WRITE commands plus those of Unix + * read(2)s and write(2)s. User can give larger than 31 bit 'num's but they + * are split into several consecutive elements. */ +struct scat_gath_elem { + uint64_t lba; /* of start block */ + uint32_t num; /* number of blocks from and including start block */ + + void make_bad() { lba = UINT64_MAX; num = UINT32_MAX; } + bool is_bad() const { return (lba == UINT64_MAX && num == UINT32_MAX); } +}; + +/* Consider "linearity" as a scatter gather list property. Elements of this + * of from the strongest form to the weakest. */ +enum sgl_linearity_e { + SGL_LINEAR = 0, /* empty list and 0,0 considered linear */ + SGL_MONOTONIC, /* since not linear, implies holes */ + SGL_MONO_OVERLAP, /* monotonic but same LBA in two or more elements */ + SGL_NON_MONOTONIC /* weakest */ +}; + + +/* Holds one scatter gather list and its associated metadata */ +class scat_gath_list { +public: + scat_gath_list() : linearity(SGL_LINEAR), sum_hard(false), m_errno(0), + high_lba_p1(0), lowest_lba(0), sum(0) { } + + scat_gath_list(const scat_gath_list &) = default; + scat_gath_list & operator=(const scat_gath_list &) = default; + ~scat_gath_list() = default; + + bool empty() const; + bool empty_or_00() const; + int num_elems() const; + int64_t get_lowest_lba(bool ignore_degen, bool always_last) const; + int64_t get_low_lba_from_linear() const; + bool is_pipe_suitable() const; + + friend bool sgls_eq_off(const scat_gath_list &left, int l_e_ind, + int l_blk_off, + const scat_gath_list &right, int r_e_ind, + int r_blk_off, bool allow_partial); + + bool load_from_cli(const char * cl_p, bool b_vb); + bool load_from_file(const char * file_name, bool def_hex, bool flexible, + bool b_vb); + int append_1or(int64_t extra_blks, int64_t start_lba); + int append_1or(int64_t extra_blks); + + void dbg_print(bool skip_meta, const char * id_str, bool to_stdout, + bool show_sgl) const; + + /* calculates and sets following bool-s and int64_t-s */ + void sum_scan(const char * id_str, bool show_sgl, bool b_verbose); + + void set_weaker_linearity(enum sgl_linearity_e lin); + enum sgl_linearity_e linearity; + const char * linearity_as_str() const; + + bool sum_hard; /* 'num' in last element of 'sgl' is > 0 */ + int m_errno; /* OS failure errno */ + int64_t high_lba_p1; /* highest LBA plus 1, next write from and above */ + int64_t lowest_lba; /* initialized to 0 */ + int64_t sum; /* of all 'num' elements in 'sgl' */ + + friend int diff_between_iters(const struct scat_gath_iter & left, + const struct scat_gath_iter & right); + +private: + friend class scat_gath_iter; + + bool file2sgl_helper(FILE * fp, const char * fnp, bool def_hex, + bool flexible, bool b_vb); + + std::vector<scat_gath_elem> sgl; /* an array on heap [0..num_elems()) */ +}; + + +class scat_gath_iter { +public: + scat_gath_iter(const scat_gath_list & my_scat_gath_list); + scat_gath_iter(const scat_gath_iter & src) = default; + scat_gath_iter& operator=(const scat_gath_iter&) = delete; + ~scat_gath_iter() = default; + + int64_t current_lba() const; + int64_t current_lba_rem_num(int & rem_num) const; + struct scat_gath_elem current_elem() const; + bool at_end() const; + bool is_sgl_linear() const; /* the whole list */ + int linear_for_n_blks(int max_n) const; + + bool set_by_blk_idx(int64_t _blk_idx); + /* add/sub blocks return true if they reach EOL, else false */ + bool add_blks(uint64_t blk_count); + bool sub_blks(uint64_t blk_count); + + void dbg_print(const char * id_str, bool to_stdout, int verbose) const; + + friend int diff_between_iters(const struct scat_gath_iter & left, + const struct scat_gath_iter & right); + + friend bool sgls_eq_from_iters(const struct scat_gath_iter & left, + const struct scat_gath_iter & right, + bool allow_partial); + +private: + const scat_gath_list &sglist; + + /* dual representation: either it_el_ind,it_blk_off or blk_idx */ + int it_el_ind; /* refers to sge==sglist[it_el_ind] */ + int it_blk_off; /* refers to LBA==(sge.lba + it_blk_off) */ + int64_t blk_idx; /* in range: [0 .. sglist.sum) */ + bool extend_last; +}; |