Skip to content

Commit

Permalink
Thin provisioning : Enable zero detecting for requests (#349)
Browse files Browse the repository at this point in the history
* Enable zero detecting for requests
Added a manual io job test
  • Loading branch information
shosseinimotlagh authored Mar 13, 2024
1 parent b3d7e28 commit ed3ffae
Show file tree
Hide file tree
Showing 9 changed files with 406 additions and 20 deletions.
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class HomestoreConan(ConanFile):
name = "homestore"
version = "3.7.1"
version = "3.7.2"

homepage = "https://github.corp.ebay.com/SDS/homestore"
description = "HomeStore"
Expand Down
1 change: 0 additions & 1 deletion src/.clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ AlignOperands: false
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
# AllowShortFunctionsOnASingleLine: InlineOnly
# AllowShortLoopsOnASingleLine: false
Expand Down
18 changes: 17 additions & 1 deletion src/api/vol_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,22 @@ struct vol_interface_req : public sisl::ObjLifeCounter< vol_interface_req > {
bool is_write() const { return op_type == Op_type::WRITE; }
bool is_unmap() const { return op_type == Op_type::UNMAP; }

bool is_zero_request(const uint64_t page_size) {
if (iovecs.empty()) {
return !buffer || hs_utils::is_buf_zero(static_cast< uint8_t* >(buffer), nlbas * page_size);
}
return is_iovec_zero();
}

bool is_iovec_zero() {
for (const auto& iovec : iovecs) {
auto data = static_cast< uint8_t* >(iovec.iov_base);
const size_t size = iovec.iov_len;
if (!hs_utils::is_buf_zero(data, size)) { return false; }
}
return true;
}

friend void intrusive_ptr_add_ref(vol_interface_req* req) { req->refcount.increment(1); }

friend void intrusive_ptr_release(vol_interface_req* req) {
Expand Down Expand Up @@ -316,7 +332,7 @@ class VolInterface {

virtual const char* get_name(const VolumePtr& vol) = 0;
virtual uint64_t get_size(const VolumePtr& vol) = 0;
virtual std::map<boost::uuids::uuid, uint64_t> get_used_size(const VolumePtr& vol) = 0;
virtual std::map< boost::uuids::uuid, uint64_t > get_used_size(const VolumePtr& vol) = 0;
virtual uint64_t get_page_size(const VolumePtr& vol) = 0;
virtual boost::uuids::uuid get_uuid(std::shared_ptr< Volume > vol) = 0;
virtual sisl::blob at_offset(const boost::intrusive_ptr< BlkBuffer >& buf, uint32_t offset) = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/engine/common/homestore_config.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ table Generic {
// percentage of cache used to create indx mempool. It should be more than 100 to
// take into account some floating buffers in writeback cache.
indx_mempool_percent : uint32 = 110;

boot_thin_provisioning: bool = false;
}

table ResourceLimits {
Expand Down
53 changes: 43 additions & 10 deletions src/engine/common/homestore_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <isa-l/crc.h>

namespace homestore {
uint8_t* hs_utils::iobuf_alloc(const size_t size, const sisl::buftag tag, const size_t alignment) {
Expand Down Expand Up @@ -76,6 +77,42 @@ sisl::byte_array hs_utils::extract_byte_array(const sisl::byte_view& b, const bo
return (is_aligned_needed) ? b.extract(alignment) : b.extract(0);
};

constexpr unsigned long long operator"" _KB(unsigned long long x) { return x * 1024; }

constexpr std::array< size_t, 7 > predefined_sizes = {4_KB, 8_KB, 16_KB, 32_KB, 64_KB, 128_KB, 256_KB};

// Function to initialize the CRC map with predefined sizes
void initialize_crc_map(std::map< size_t, uint16_t >& crc_map) {
std::vector< uint8_t > zero_buf;
for (auto s : predefined_sizes) {
zero_buf.resize(s, 0); // Resize buffer to the required size, filling with zeros
crc_map[s] = crc16_t10dif(init_crc_16, zero_buf.data(), s);
}
}

uint16_t hs_utils::crc_zero(const size_t size) {
static std::map< size_t, uint16_t > crc_map;
static std::once_flag init_flag;

// Thread-safe initialization of the CRC map
std::call_once(init_flag, initialize_crc_map, std::ref(crc_map));

// Check if the size is already in the map
if (auto it = crc_map.find(size); it != crc_map.end()) { return it->second; }

std::vector< uint8_t > zero_buf(size, 0);
return crc16_t10dif(init_crc_16, zero_buf.data(), size);
}

bool hs_utils::is_buf_zero(const uint8_t* buf, size_t size) {
// TODO: subsample the buffer to detect zero request instead of working on the whole buffer to achieve constant
// processing time for large buffer size requests. Needs to investigate the performance impact of this change
// in end2end testing.
auto zero_crc = crc_zero(size);
const auto crc = crc16_t10dif(init_crc_16, buf, size);
return (crc == zero_crc) ? (buf[0] == 0 && !std::memcmp(buf, buf + 1, size - 1)) : false;
}

std::string hs_utils::encodeBase64(const uint8_t* first, std::size_t size) {
using Base64FromBinary = boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width< const char*, // sequence of chars
Expand All @@ -90,15 +127,12 @@ std::string hs_utils::encodeBase64(const uint8_t* first, std::size_t size) {
return encoded.append(bytes_to_pad, '=');
}

std::string hs_utils::encodeBase64(const sisl::byte_view& b){
return encodeBase64(b.bytes(), b.size());
}
std::string hs_utils::encodeBase64(const sisl::byte_view& b) { return encodeBase64(b.bytes(), b.size()); }

template <typename T>
void hs_utils::decodeBase64(const std::string &encoded_data, T out)
{
template < typename T >
void hs_utils::decodeBase64(const std::string& encoded_data, T out) {
using BinaryFromBase64 = boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
boost::archive::iterators::binary_from_base64< std::string::const_iterator >,
8, // get a view of 8 bit
6 // from a sequence of 6 bit
>;
Expand All @@ -107,14 +141,13 @@ void hs_utils::decodeBase64(const std::string &encoded_data, T out)
std::replace(begin(unpadded_data), end(unpadded_data), '=', 'A'); // A_64 == \0

std::string decoded_data{BinaryFromBase64{begin(unpadded_data)},
BinaryFromBase64{begin(unpadded_data) + unpadded_data.length()}};
BinaryFromBase64{begin(unpadded_data) + unpadded_data.length()}};

decoded_data.erase(end(decoded_data) - bytes_to_pad, end(decoded_data));
std::copy(begin(decoded_data), end(decoded_data), out);
}

std::string hs_utils::decodeBase64(const std::string &encoded_data)
{
std::string hs_utils::decodeBase64(const std::string& encoded_data) {
std::string rv;
decodeBase64(encoded_data, std::back_inserter(rv));
return rv;
Expand Down
2 changes: 2 additions & 0 deletions src/engine/common/homestore_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class hs_utils {
static sisl::byte_array make_byte_array(const uint64_t size, const bool is_aligned_needed, const sisl::buftag tag,
const size_t alignment);
static hs_uuid_t gen_system_uuid();
static uint16_t crc_zero(const size_t size);
static bool is_buf_zero(const uint8_t* buf, size_t size);
static std::string encodeBase64(const uint8_t* first, std::size_t size);
static std::string encodeBase64(const sisl::byte_view& b);
template <typename T> static void decodeBase64(const std::string &encoded_data, T out);
Expand Down
Loading

0 comments on commit ed3ffae

Please sign in to comment.