Skip to content

Commit 50f2aaa

Browse files
authored
feat: allow configuring clear-cache statically and injecting torn writes at runtime (#7)
1 parent 74db98e commit 50f2aaa

File tree

10 files changed

+1164
-381
lines changed

10 files changed

+1164
-381
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ file="output1.txt"
9393
occurrence=5
9494
parts=3 #or parts_bytes=[4096,3600,1260]
9595
persist=[1,3]
96+
97+
[[injection]]
98+
type="clear"
99+
from="f1.txt"
100+
timing="before"
101+
op="fsync"
102+
occurrence=6
103+
crash=true
96104
```
97105

98106
I recommend following the `simple` cache configuration (indicating the cache size and using a similar configuration file as `default.toml`), since it's currently the most tested schema in our experiments. Additionally, for the section **[cache]**, you can specify the following:
@@ -105,6 +113,7 @@ I recommend following the `simple` cache configuration (indicating the cache siz
105113

106114
- **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.
107115
- **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.
116+
- **clear-cache**: Clears unsynced data in a certain point of the execution. In the example above, this fault will be injected after (`timing`) the sixth (`occurrence`) `fsync` (`op`) to the file "f1.txt" (`from`). The `op` parameter must be a system call, and if it involves two paths (such as `rename`), the `to` parameter should also be specified. The `crash` parameter determines whether LazyFS should crash after the fault injection.
108117

109118
Other parameters:
110119

@@ -209,6 +218,19 @@ Finally, one can control LazyFS by echoing the following commands to the configu
209218

210219
> Kills LazyFS before executing a link operation to the file pattern 'fileabd'.
211220

221+
- **Kill the filesystem** after injecting `torn-op` or `torn-seq`faults:
222+
223+
The parameters are the same as the ones presented in the above configuration file. Parameters that have multiple values, must be specified without the parenthesis (e.g., `persist=1,2` ).
224+
225+
- ```bash
226+
echo "lazyfs::torn-op::file=...::persist=...::parts=...::occurrence=..." > /my/path/faults.fifo
227+
```
228+
229+
- ```bash
230+
echo "lazyfs::torn-seq::op=...::file=...::persist=...::occurrence=..." > /my/path/faults.fifo
231+
```
232+
233+
212234
LazyFS expects that every buffer written to the FIFO file terminates with a new line character (**echo** does this by default). Thus, if using `pwrite`, for example, make sure you end the buffer with `\n`.
213235

214236
## Contact

lazyfs/config/default.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ blocks_per_page=1
1212
# no_pages=10
1313
[filesystem]
1414
log_all_operations=false
15-
logfile=""
15+
logfile=""

lazyfs/include/lazyfs/lazyfs.hpp

Lines changed: 79 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,13 @@ class LazyFS : public Fusepp::Fuse<LazyFS> {
102102
/**
103103
* @brief Faults programmed in the configuration file.
104104
*/
105-
unordered_map<string,vector<cache::config::Fault*>>* faults;
105+
unordered_map<string,vector<faults::Fault*>>* faults;
106+
106107

107108
/**
108109
* @brief Faults of LazyFS crash injected during runtime.
109110
*
111+
* obsolete!
110112
*/
111113
std::unordered_map<string, unordered_set<string>> crash_faults;
112114

@@ -121,16 +123,47 @@ class LazyFS : public Fusepp::Fuse<LazyFS> {
121123
std::mutex write_lock;
122124

123125
/**
124-
* @brief Path of the current fault being injected.
126+
* @brief Current faults being injected.
125127
*/
126-
string path_injecting_fault;
128+
vector<string> injecting_fault;
127129

128130
/**
129-
* @brief Lock for path of current injected fault.
131+
* @brief Lock for current injected faults.
130132
*/
131-
std::mutex path_injecting_fault_lock;
133+
std::mutex injecting_fault_lock;
132134

133135
public:
136+
137+
/**
138+
* @brief Map of faults associated with each filesystem operation
139+
*
140+
*/
141+
// operation -> [((from_rgx, to_rgx), ...]
142+
std::unordered_map<string, vector<pair<std::regex, string>>> crash_faults_before_map;
143+
std::unordered_map<string, vector<pair<std::regex, string>>> crash_faults_after_map;
144+
145+
/**
146+
* @brief Map of allowed operations to have a crash fault
147+
*
148+
*/
149+
std::unordered_set<string> allow_crash_fs_operations = {"unlink",
150+
"truncate",
151+
"fsync",
152+
"write",
153+
"create",
154+
"access",
155+
"open",
156+
"read",
157+
"rename",
158+
"link",
159+
"symlink"};
160+
161+
/**
162+
* @brief Map of operations that have two paths
163+
*
164+
*/
165+
std::unordered_set<string> fs_op_multi_path = {"rename", "link", "symlink"};
166+
134167
/**
135168
* @brief Construct a new LazyFS object.
136169
*
@@ -149,7 +182,7 @@ class LazyFS : public Fusepp::Fuse<LazyFS> {
149182
cache::config::Config* config,
150183
std::thread* faults_handler_thread,
151184
void (*fht_worker) (LazyFS* filesystem),
152-
unordered_map<string,vector<cache::config::Fault*>>* faults);
185+
unordered_map<string,vector<faults::Fault*>>* faults);
153186

154187
/**
155188
* @brief Destroy the LazyFS object
@@ -158,9 +191,9 @@ class LazyFS : public Fusepp::Fuse<LazyFS> {
158191
~LazyFS ();
159192

160193
/**
161-
* @brief Get path of the fault currently being injected.
194+
* @brief Get faults currently being injected.
162195
*/
163-
string get_path_injecting_fault();
196+
vector<string> get_injecting_fault();
164197

165198
/**
166199
* @brief Fifo: (fault) Clear the cached contents
@@ -182,18 +215,18 @@ class LazyFS : public Fusepp::Fuse<LazyFS> {
182215

183216
/**
184217
* @brief Fifo: Reports which files have unsynced data.
185-
* @param path_to_exclude Path to be excluded from the report.
218+
* @param paths_to_exclude Paths to be excluded from the report.
186219
*
187220
*/
188-
void command_unsynced_data_report (string path_to_exclude);
221+
void command_unsynced_data_report (vector<string> paths_to_exclude);
189222

190223
/**
191224
* @brief Checks if a programmed reorder fault for the given path and operation exists. If so, updates the counter and returns the fault.
192225
* @param path Path of the file
193226
* @param op Operation ('write','fsync',...)
194227
* @return Pointer to the ReorderF object
195228
*/
196-
cache::config::ReorderF* get_and_update_reorder_fault(string path, string op);
229+
faults::ReorderF* get_and_update_reorder_fault(string path, string op);
197230

198231
/**
199232
* @brief Persists a write if a there is a programmed reorder fault for write in the given path and if the counter matches one of the writes to persist.
@@ -328,36 +361,6 @@ class LazyFS : public Fusepp::Fuse<LazyFS> {
328361
static int lfs_chmod (const char*, mode_t, struct fuse_file_info*);
329362
static int lfs_chown (const char*, uid_t, gid_t, fuse_file_info*);
330363

331-
/**
332-
* @brief Map of faults associated with each filesystem operation
333-
*
334-
*/
335-
// operation -> [((from_rgx, to_rgx), before?true:false), ...]
336-
std::unordered_map<string, vector<pair<std::regex, string>>> crash_faults_before_map;
337-
std::unordered_map<string, vector<pair<std::regex, string>>> crash_faults_after_map;
338-
339-
/**
340-
* @brief Map of allowed operations to have a crash fault
341-
*
342-
*/
343-
std::unordered_set<string> allow_crash_fs_operations = {"unlink",
344-
"truncate",
345-
"fsync",
346-
"write",
347-
"create",
348-
"access",
349-
"open",
350-
"read",
351-
"rename",
352-
"link",
353-
"symlink"};
354-
355-
/**
356-
* @brief Map of operations that have two paths
357-
*
358-
*/
359-
std::unordered_set<string> fs_op_multi_path = {"rename", "link", "symlink"};
360-
361364
/**
362365
* @brief Adds a crash fault to the faults map
363366
*
@@ -373,16 +376,46 @@ class LazyFS : public Fusepp::Fuse<LazyFS> {
373376
string crash_regex_to);
374377

375378
/**
376-
* @brief kills lazyfs with SIGINT if any fault condition verifies
379+
* @brief Adds a torn-seq fault to the faults map. Returns a vector with errors if any.
380+
*
381+
* @param path path of the fault
382+
* @param op system call
383+
* @param persist which parts of the write to persist
384+
* @return errors
385+
*/
386+
vector<string> add_torn_seq_fault(string path, string op, string persist);
387+
388+
/**
389+
* @brief Adds a torn-op fault to the faults map. Returns a vector with errors if any.
390+
*
391+
* @param path path of the fault
392+
* @param parts which parts of the write to persist
393+
* @param parts_bytes division of the write in bytes
394+
* @param persist which parts of the write to persist
395+
* @return errors
396+
*/
397+
vector<string> add_torn_op_fault(string path, string parts, string parts_bytes, string persist);
398+
399+
/**
400+
* @brief Kills lazyfs with SIGKILL if any fault condition verifies
377401
*
378-
* @param opname operation to check
379-
* @param optiming one of 'allow_crash_fs_operations'
402+
* @param opname one of 'allow_crash_fs_operations'
403+
* @param optiming timing for triggering fault operation ('before' or 'after' a given system call)
380404
* @param from_op_path source path specified in the operation
381405
* @param dest_op_path destination path specified in the operation
382406
* @param fault_type type of fault that triggered the crash
383407
*/
384-
void
385-
trigger_crash_fault (string opname, string optiming, string from_op_path, string to_op_path, string fault_type);
408+
void trigger_crash_fault (string opname, string optiming, string from_op_path, string to_op_path, string fault_type);
409+
410+
/**
411+
* @brief Triggers a clear fault if condition is verified.
412+
*
413+
* @param opname operation name
414+
* @param optiming timing for triggering fault operation ('before' or 'after')
415+
* @param from_op_path source path specified in the operation
416+
* @param dest_op_path destination path specified in the operation
417+
*/
418+
void trigger_configured_clear_fault (string opname, string optiming, string from_path, string to_path);
386419
};
387420

388421
} // namespace lazyfs

0 commit comments

Comments
 (0)