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