aboutsummaryrefslogtreecommitdiff
path: root/testing/sg_scat_gath.h
diff options
context:
space:
mode:
Diffstat (limited to 'testing/sg_scat_gath.h')
-rw-r--r--testing/sg_scat_gath.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/testing/sg_scat_gath.h b/testing/sg_scat_gath.h
new file mode 100644
index 00000000..d316a7b1
--- /dev/null
+++ b/testing/sg_scat_gath.h
@@ -0,0 +1,143 @@
+/*
+ * 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 standard headers
+#include <stdio.h>
+#include <stdint.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+// C++ standard 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.
+class scat_gath_elem {
+public:
+ 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 class scat_gath_iter & left,
+ const class 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:
+ explicit 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;
+ class scat_gath_elem current_elem() const;
+ bool at_end() const;
+ bool is_sgl_linear() const; // the whole list
+ // Should return 1 or more unless max_n<=0 or at_end()
+ 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/start, 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 class scat_gath_iter & left,
+ const class scat_gath_iter & right);
+
+ friend bool sgls_eq_from_iters(const class scat_gath_iter & left,
+ const class 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;
+};