Skip to content

Commit

Permalink
refactor: change split_write fault to torn-op and reorder to torn-seq (
Browse files Browse the repository at this point in the history
…#6)

* refactor: change split_write fault to torn-op and reorder to torn-seq

* readme: minor changes

---------

Co-authored-by: user Grupo de Sistemas Distribuidos <[email protected]>
  • Loading branch information
mj-ramos and user Grupo de Sistemas Distribuidos authored Mar 8, 2024
1 parent 9c5685e commit 229debd
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 40 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

A FUSE file system with an internal dedicated page cache that only flushes data if explicitly requested by the application. This is useful for simulating power failures and losing all unsynced data.

> **Note**: The main branch is probably unstable and with not fully-tested features, so we recommend using one of [existing releases](https://github.com/dsrhaslab/lazyfs/releases) already created.
<!--- > **Note**: The main branch is probably unstable and with not fully-tested features, so we recommend using one of [existing releases](https://github.com/dsrhaslab/lazyfs/releases) already created. -->

## Installation

Expand Down Expand Up @@ -83,14 +83,14 @@ log_all_operations=false
logfile="/tmp/lazyfs.log"

[[injection]]
type="reorder"
type="torn-seq"
op="write"
file="output.txt"
persist=[1,4]
occurrence=2

[[injection]]
type="split_write"
type="torn-op"
file="output1.txt"
occurrence=5
parts=3 #or parts_bytes=[4096,3600,1260]
Expand All @@ -105,8 +105,8 @@ I recommend following the `simple` cache configuration (indicating the cache siz

**Optionally**, users can specify a set of predefined `injection` faults before LazyFS starts running. These faults are introduced as additional features, namely:

- **reorder**: This fault type is used when a sequence of system calls, targeting a single file, is executed consecutively without an intervening `fsync`. *In the example*, during the second group of consecutive writes (the group number is defined by the parameter `occurrence`), to the file "output.txt", the first and fourth writes will be persisted to disk (the writes to be persisted are defined by the parameter `persist`). After the fourth write (the last in the `persist` vector), LazyFS will crash itself.
- **split_write**: This fault type involves dividing a write system call into smaller portions, with some of these portions being persisted while others are not. In the example, the fifth write issued (the number of the write is defined by the parameter `occurrence`) to the file "output1.txt" will be divided into three equal parts if the `parts` parameter is used, or into customizable-sized parts if the `parts_bytes` parameter is defined. In the commented code, there's an example of using `parts_bytes`, where the write will be split into three parts: the first with 4096 bytes, the second with 3600 bytes, and the last with 1200 bytes. The `persist` vector determines which parts will be persisted. After the persistence of these parts, LazyFS will crash.
- **torn-seq**: This fault type is used when a sequence of system calls, targeting a single file, is executed consecutively without an intervening `fsync`. *In the example*, during the second group of consecutive writes (the group number is defined by the parameter `occurrence`), to the file "output.txt", the first and fourth writes will be persisted to disk (the writes to be persisted are defined by the parameter `persist`). After the fourth write (the last in the `persist` vector), LazyFS will crash itself.
- **torn-op**: This fault type involves dividing a write system call into smaller parts, with some of these parts being persisted while others are not. In the example, the fifth write issued (the number of the write is defined by the parameter `occurrence`) to the file "output1.txt" will be divided into three equal parts if the `parts` parameter is used, or into customizable-sized parts if the `parts_bytes` parameter is defined. In the commented code, there's an example of using `parts_bytes`, where the write will be torn into three parts: the first with 4096 bytes, the second with 3600 bytes, and the last with 1200 bytes. The `persist` vector determines which parts will be persisted. After the persistence of these parts, LazyFS will crash.

Other parameters:

Expand Down
8 changes: 4 additions & 4 deletions lazyfs/src/lazyfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ void LazyFS::trigger_crash_fault (string opname,

if (fault_type == CRASH)
this_ ()->command_unsynced_data_report ("none");
else if (fault_type == SPLITWRITE) {
else if (fault_type == TORN_OP) {
this_ ()->command_unsynced_data_report (from_op_path);
} else if (fault_type == REORDER) {
} else if (fault_type == TORN_SEQ) {
this_ ()->command_unsynced_data_report (from_op_path);
}

Expand Down Expand Up @@ -1114,9 +1114,9 @@ int LazyFS::lfs_write (const char* path,
bool crash_added = this_ () -> persist_write(path,buf,size,offset);
if (!crash_added) { //At the moment only one fault type can be injected
crash_added = this_ () -> split_write(path,buf,size,offset);
fault_type = SPLITWRITE;
fault_type = TORN_OP;
} else {
fault_type = REORDER;
fault_type = TORN_SEQ;
}

// res should be = actual bytes written as pwrite could fail...
Expand Down
12 changes: 6 additions & 6 deletions libs/libpcache/include/cache/config/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

#ifndef CACHE_CONFIG_HPP
#define CACHE_CONFIG_HPP
#define SPLITWRITE "split_write"
#define REORDER "reorder"
#define TORN_OP "torn-op"
#define TORN_SEQ "torn-seq"
#define CRASH "crash"

#include <string>
Expand Down Expand Up @@ -53,7 +53,7 @@ class Fault {
};

/**
* @brief Fault for splitting writes in smaller writes.
* @brief Fault for splitting writes in smaller writes and reordering them (torn-op fault).
*/
class SplitWriteF : public Fault {
public:
Expand Down Expand Up @@ -112,7 +112,7 @@ class SplitWriteF : public Fault {
};

/**
* @brief Fault for reordering system calls.
* @brief Fault for reordering system calls (torn-seq fault).
*/
class ReorderF : public Fault {

Expand Down Expand Up @@ -168,7 +168,7 @@ class Config {

private:
/**
* @brief Sets up cache paraments by specifying the total size in bytes and the number
* @brief Sets up cache parameters by specifying the total size in bytes and the number
* of blocks per page. By using this version, a 4k block size is considered.
*
* @param prealloc_bytes The total size in bytes.
Expand All @@ -187,7 +187,7 @@ class Config {

public:
/**
* @brief Wheter to log filesystem operations to stdout
* @brief Whether to log filesystem operations to stdout
*
*/
bool log_all_operations = false;
Expand Down
50 changes: 25 additions & 25 deletions libs/libpcache/src/config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Fault::Fault(string type) {

Fault::~Fault(){}

ReorderF::ReorderF(string op, vector<int> persist, int occurrence) : Fault(REORDER) {
ReorderF::ReorderF(string op, vector<int> persist, int occurrence) : Fault(TORN_SEQ) {
(this->counter).store(0);
this->op = op;
this->persist = persist;
Expand All @@ -39,7 +39,7 @@ ReorderF::ReorderF(string op, vector<int> persist, int occurrence) : Fault(REORD

}

ReorderF::ReorderF() : Fault(REORDER) {
ReorderF::ReorderF() : Fault(TORN_SEQ) {
vector <int> v;
(this->counter).store(0);
(this->group_counter).store(0);
Expand All @@ -50,22 +50,22 @@ ReorderF::ReorderF() : Fault(REORDER) {

ReorderF::~ReorderF(){}

SplitWriteF::SplitWriteF(int occurrence, vector<int> persist, int parts) : Fault(SPLITWRITE) {
SplitWriteF::SplitWriteF(int occurrence, vector<int> persist, int parts) : Fault(TORN_OP) {
(this->counter).store(0);
this->occurrence = occurrence;
this->persist = persist;
this->parts = parts;
}

SplitWriteF::SplitWriteF(int occurrence, vector<int> persist, vector<int> parts_bytes) : Fault(SPLITWRITE) {
SplitWriteF::SplitWriteF(int occurrence, vector<int> persist, vector<int> parts_bytes) : Fault(TORN_OP) {
(this->counter).store(0);
this->occurrence = occurrence;
this->persist = persist;
this->parts = -1;
this->parts_bytes = parts_bytes;
}

SplitWriteF::SplitWriteF() : Fault(SPLITWRITE) {
SplitWriteF::SplitWriteF() : Fault(TORN_OP) {
vector <int> v;
vector<int> p;
(this->counter).store(0);
Expand Down Expand Up @@ -213,26 +213,26 @@ unordered_map<string,vector<Fault*>> Config::load_config (string filename) {
if (!injection.contains("type")) throw std::runtime_error("Key 'type' for some injection of is not defined in the configuration file.");
string type = toml::find<string>(injection,"type");

if (type == REORDER) {
if (type == TORN_SEQ) {
//Checking the values of the parameters of the reordering fault

if (!injection.contains("file")) throw std::runtime_error("Key 'file' for some injection of type \"reorder\" is not defined in the configuration file.");
if (!injection.contains("file")) throw std::runtime_error("Key 'file' for some injection of type \"torn-seq\" is not defined in the configuration file.");
string file = toml::find<string>(injection,"file");

if (!injection.contains("op")) throw std::runtime_error("Key 'op' for some injection of type \"reorder\" is not defined in the configuration file.");
if (!injection.contains("op")) throw std::runtime_error("Key 'op' for some injection of type \"torn-seq\" is not defined in the configuration file.");
string op = toml::find<string>(injection,"op");

if (!injection.contains("occurrence")) throw std::runtime_error("Key 'occurrence' for some injection of type \"reorder\" is not defined in the configuration file.");
if (!injection.contains("occurrence")) throw std::runtime_error("Key 'occurrence' for some injection of type \"torn-seq\" is not defined in the configuration file.");
int occurrence = toml::find<int>(injection,"occurrence");
if (occurrence <= 0) throw std::runtime_error("Key 'occurrence' for some injection of type \"split_write\" has an invalid value in the configuration file. It should be greater than 0.");
if (occurrence <= 0) throw std::runtime_error("Key 'occurrence' for some injection of type \"torn-op\" has an invalid value in the configuration file. It should be greater than 0.");

if (!injection.contains("persist") && op == "write") throw std::runtime_error("Key 'persist' for some injection of type \"reorder\" with \"write\" as op is not defined in the configuration file.");
if (!injection.contains("persist") && op == "write") throw std::runtime_error("Key 'persist' for some injection of type \"torn-seq\" with \"write\" as op is not defined in the configuration file.");

vector<int> persist = toml::find<vector<int>>(injection,"persist");
sort(persist.begin(), persist.end());

for (auto & p : persist) {
if (p <= 0) throw std::runtime_error("Key 'persist' for some injection of type \"reorder\" has an invalid value in the configuration file. The array must contain values greater than 0.");
if (p <= 0) throw std::runtime_error("Key 'persist' for some injection of type \"torn-seq\" has an invalid value in the configuration file. The array must contain values greater than 0.");
}

cache::config::ReorderF * fault = new ReorderF(op,persist,occurrence);
Expand All @@ -243,41 +243,41 @@ unordered_map<string,vector<Fault*>> Config::load_config (string filename) {
v_faults.push_back(fault);
faults[file] = v_faults;
} else {
//At the moment, only one reorder fault per file is acceptable.
//At the moment, only one torn-seq fault per file is acceptable.
for (Fault* fault : it->second) {
ReorderF* reorder_fault = dynamic_cast<ReorderF*>(fault);
if (reorder_fault && reorder_fault->op == op) throw std::runtime_error("It is only acceptable one reorder fault per type of operation for a given file.");
if (reorder_fault && reorder_fault->op == op) throw std::runtime_error("It is only acceptable one torn-seq fault per type of operation for a given file.");
}
(it->second).push_back(fault);
}

} else if (type == SPLITWRITE) {
} else if (type == TORN_OP) {
//Checking the values of the parameters of the split write fault

if (!injection.contains("file")) throw std::runtime_error("Key 'file' for some injection of type \"split_write\" is not defined in the configuration file.");
if (!injection.contains("file")) throw std::runtime_error("Key 'file' for some injection of type \"torn-op\" is not defined in the configuration file.");
string file = toml::find<string>(injection,"file");

if (!injection.contains("occurrence")) throw std::runtime_error("Key 'occurrence' for some injection of type \"split_write\" is not defined in the configuration file.");
if (!injection.contains("occurrence")) throw std::runtime_error("Key 'occurrence' for some injection of type \"torn-op\" is not defined in the configuration file.");
int occurrence = toml::find<int>(injection,"occurrence");
if (occurrence <= 0) throw std::runtime_error("Key 'occurrence' for some injection of type \"split_write\" has an invalid value in the configuration file. It should be greater than 0.");
if (occurrence <= 0) throw std::runtime_error("Key 'occurrence' for some injection of type \"torn-op\" has an invalid value in the configuration file. It should be greater than 0.");

if (!injection.contains("persist")) throw std::runtime_error("Key 'persist' for some injection of type \"split_write\" is not defined in the configuration file.");
if (!injection.contains("persist")) throw std::runtime_error("Key 'persist' for some injection of type \"torn-op\" is not defined in the configuration file.");
vector<int> persist = toml::find<vector<int>>(injection,"persist");

if (!injection.contains("parts") && !injection.contains("parts_bytes")) throw std::runtime_error("None of the keys 'parts' and 'key_parts' for some injection of type \"split_write\" is defined in the configuration file. Please define at most one of them.");
if (!injection.contains("parts") && !injection.contains("parts_bytes")) throw std::runtime_error("None of the keys 'parts' and 'key_parts' for some injection of type \"torn-op\" is defined in the configuration file. Please define at most one of them.");

if (injection.contains("parts") && injection.contains("parts_bytes")) throw std::runtime_error("Keys 'parts' and 'key_parts' for some injection of type \"split_write\" are exclusive in the configuration file. Please define at most one of them.");
if (injection.contains("parts") && injection.contains("parts_bytes")) throw std::runtime_error("Keys 'parts' and 'key_parts' for some injection of type \"torn-op\" are exclusive in the configuration file. Please define at most one of them.");

cache::config::SplitWriteF * fault = NULL;

//A split write fault either contains the parameter "parts" or the "pats_bytes"
if (injection.contains("parts")) {
int parts = toml::find<int>(injection,"parts");

if (parts <= 0) throw std::runtime_error("Key 'parts' for some injection of type \"split_write\" has an invalid value in the configuration file. It should be greater than 0.");
if (parts <= 0) throw std::runtime_error("Key 'parts' for some injection of type \"torn-op\" has an invalid value in the configuration file. It should be greater than 0.");

for (auto & p : persist) {
if (p <= 0 || p>parts) throw std::runtime_error("Key 'persist' for some injection of type \"split_write\" has an invalid value in the configuration file. The array must contain values greater than 0 and lesser than the number of parts.");
if (p <= 0 || p>parts) throw std::runtime_error("Key 'persist' for some injection of type \"torn-op\" has an invalid value in the configuration file. The array must contain values greater than 0 and lesser than the number of parts.");
}
fault = new SplitWriteF(occurrence,persist,parts);
}
Expand All @@ -286,10 +286,10 @@ unordered_map<string,vector<Fault*>> Config::load_config (string filename) {
vector<int> parts_bytes = toml::find<vector<int>>(injection,"parts_bytes");

for (auto & part : parts_bytes) {
if (part <= 0) throw std::runtime_error("Key 'parts_bytes' for some injection of type \"split_write\" has an invalid value in the configuration file. Every part should be greater than 0.");
if (part <= 0) throw std::runtime_error("Key 'parts_bytes' for some injection of type \"torn-op\" has an invalid value in the configuration file. Every part should be greater than 0.");
}
for (auto & p : persist) {
if (p <= 0 || (size_t)p > parts_bytes.size()) throw std::runtime_error("Key 'persist' for some injection of type \"split_write\" has an invalid value in the configuration file. The array must contain values greater than 0 and lesser than the number of parts.");
if (p <= 0 || (size_t)p > parts_bytes.size()) throw std::runtime_error("Key 'persist' for some injection of type \"torn-op\" has an invalid value in the configuration file. The array must contain values greater than 0 and lesser than the number of parts.");
}
fault = new SplitWriteF(occurrence,persist,parts_bytes);
}
Expand Down

0 comments on commit 229debd

Please sign in to comment.