{"id":40667571,"url":"https://github.com/dsrhaslab/lazyfs","last_synced_at":"2026-01-21T09:14:59.547Z","repository":{"id":37715552,"uuid":"480401263","full_name":"dsrhaslab/lazyfs","owner":"dsrhaslab","description":"LazyFS: A FUSE Filesystem with an internal dedicated page cache, which can be used to simulate data loss on unsynced writes","archived":false,"fork":false,"pushed_at":"2025-07-08T11:00:03.000Z","size":6577,"stargazers_count":161,"open_issues_count":3,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-07-08T11:42:57.651Z","etag":null,"topics":["data-loss-prevention","filesystem","fuse","storage"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dsrhaslab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-11T13:51:21.000Z","updated_at":"2025-07-03T12:57:48.000Z","dependencies_parsed_at":"2024-07-31T16:48:51.836Z","dependency_job_id":"611fc77e-17dc-4338-a1f3-3852ea72c10b","html_url":"https://github.com/dsrhaslab/lazyfs","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/dsrhaslab/lazyfs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsrhaslab%2Flazyfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsrhaslab%2Flazyfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsrhaslab%2Flazyfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsrhaslab%2Flazyfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dsrhaslab","download_url":"https://codeload.github.com/dsrhaslab/lazyfs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsrhaslab%2Flazyfs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28630944,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-loss-prevention","filesystem","fuse","storage"],"created_at":"2026-01-21T09:14:59.431Z","updated_at":"2026-01-21T09:14:59.529Z","avatar_url":"https://github.com/dsrhaslab.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LazyFS\n\n\u003ch1 align=\"center\"\u003e\n    \u003cimg src=\".media/LazyFS.png\" width=\"60%\"\u003e\n    \u003cbr\u003e\n    \u003cimg src=\"https://img.shields.io/badge/C++-17-yellow.svg?style=flat\u0026logo=c%2B%2B\" /\u003e\n    \u003ca href=\"https://github.com/dsrhaslab/lazyfs/actions/workflows/build.yaml\"\u003e\n        \u003cimg src=\"https://github.com/dsrhaslab/lazyfs/actions/workflows/build.yaml/badge.svg\" /\u003e\n    \u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/status-research%20prototype-green.svg\" /\u003e\n    \u003ca href=\"https://opensource.org/licenses/BSD-3-Clause\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/License-MIT-blue.svg\" /\u003e\n    \u003c/a\u003e\n\u003c/h1\u003e\n\nA 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 unsynced data.\n\nPlease cite the [following paper](https://www.vldb.org/pvldb/vol17/p3017-ramos.pdf) if you use LazyFS:\n\n```bibtex\n@article{\n    author = {Ramos, Maria and Azevedo, Jo\\~{a}o and Kingsbury, Kyle and Pereira, Jos\\'{e} and Esteves, T\\^{a}nia and Macedo, Ricardo and Paulo, Jo\\~{a}o},\n    title = {When Amnesia Strikes: Understanding and Reproducing Data Loss Bugs with Fault Injection},\n    year = {2024},\n    issue_date = {July 2024},\n    publisher = {VLDB Endowment},\n    volume = {17},\n    number = {11},\n    issn = {2150-8097},\n    url = {https://doi.org/10.14778/3681954.3681980},\n    doi = {10.14778/3681954.3681980},\n    journal = {Proc. VLDB Endow.},\n    month = jul,\n    pages = {3017–3030},\n    numpages = {14}\n}\n```\n\n\u003c!--- \u003e **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. --\u003e\n\n## Installation\n\nLazyFS was tested with ext4 (with the default mount options) as the underlying file system (FUSE backend), in both Debian 11 (bullseye) and Ubuntu 20.04 (focal) environment. It is C++17 compliant and requires the following packages to be installed:\n\n-   `CMake` and `g++`:\n\n```bash\nsudo apt install g++ cmake\n\n# The following versions are used during development:\n# cmake: 3.16.3\n# g++: 9.4.0\n```\n\n-   `FUSE 3`:\n\n```bash\nsudo apt install libfuse3-dev libfuse3-3 fuse3\n```\n\nFUSE requires the option `allow_other` as a startup argument so that other users can read and write files, besides the user owning the file system. For that, you must uncomment/add the following line on the configuration file `/etc/fuse.conf`:\n\n```bash\nuser_allow_other\n```\n\nCompile and install the caching library `libpcache`, which will be attached to **LazyFS**:\n\n```bash\ncd libs/libpcache \u0026\u0026 ./build.sh \u0026\u0026 cd -\n```\n\nFinally, build `lazyfs`:\n\n```bash\ncd lazyfs \u0026\u0026 ./build.sh \u0026\u0026 cd -\n```\n\n## Running and Injecting faults\n\n**LazyFS** uses a [toml](https://toml.io/en/) configuration file to set up the cache and a named pipe to append fault commands:\n\n```toml\n[faults]\nfifo_path=\"/tmp/faults.fifo\"\n# fifo_path_completed=\"/tmp/faults_completed.fifo\"\n\n[cache]\napply_eviction=false\n\n[cache.simple]\ncustom_size=\"0.5GB\"\nblocks_per_page=1\n\n# [cache.manual]\n# io_block_size=4096\n# page_size=4096\n# no_pages=10\n\n[file system]\nlog_all_operations=false\nlogfile=\"/tmp/lazyfs.log\"\n\n[[injection]]\ntype=\"torn-seq\"\nop=\"write\"\nfile=\"output.txt\"\npersist=[1,4]\noccurrence=2\n\n[[injection]]\ntype=\"torn-op\"\nfile=\"output1.txt\"\noccurrence=5\nparts=3 #or parts_bytes=[4096,3600,1260]\npersist=[1,3]\n\n[[injection]]\ntype=\"clear\"\nfrom=\"f1.txt\"\ntiming=\"before\"\nop=\"fsync\"\noccurrence=6\ncrash=true\n```\n\nI 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:\n\n-   **apply_eviction**: Whether the cache should behave like the real page cache, evicting pages when the cache fills to the maximum.\n\n-   **[cache.simple]** or **[cache.manual]**: To setup the cache size and internal organization. For now, you could just follow the example using the **custom_size** in (Gb/Mb/Kb) and the **number of blocks in each page** (you can just leave 1 as default). For manual configurations, comment out the simple configuration and uncoment/change the example above to suit your needs.\n\n**Optionally**, users can specify a set of predefined `injection` faults before LazyFS starts running. These faults are introduced as additional features, namely:\n\n-   **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.\n-   **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.\n-   **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.\n\nIn torn-seq and torn-op faults, configure parameter `file` with the absolute path using the root directory of LazyFS.\n\nOther parameters:\n\n- **fifo_path**: The absolute path where the faults FIFO should be created.\n- **fifo_path_completed**: If we plan to inject the clear cache fault synchronously, it is necessary to determine the completion of the `lazyfs::clear-cache` command execution. By specifying this parameter, a message will be written to another FIFO (`finished::clear-cache`), so that users can set up a reader process that waits before making any post-fault consistency checks.\n- **log_all_operations**: Whether to log all file system operations that LazyFS receives.\n- **logfile**: The log file for LazyFS's outputs. Fault acknowledgment is sent to `stdout` or to the `logfile`.\n\n\nTo **run the file system**, one could use the **mount-lazyfs.sh** script, which calls FUSE with the correct parameters:\n\n- `-m` : FUSE mount directory.\n- `-r` : FUSE root directory.\n- `-f` : Foreground mode.\n- `-s` : FUSE single thread mode.\n\n```bash\ncd lazyfs/\n\n# Running LazyFS in the foreground (add '-f/--foregound')\n\n./scripts/mount-lazyfs.sh -c config/default.toml -m /tmp/lazyfs.mnt -r /tmp/lazyfs.root -f -s\n\n# Running LazyFS in the background\n\n./scripts/mount-lazyfs.sh -c config/default.toml -m /tmp/lazyfs.mnt -r /tmp/lazyfs.root -s\n\n# Umount with\n\n./scripts/umount-lazyfs.sh -m /tmp/lazyfs.mnt/\n\n# Display help\n\n./scripts/mount-lazyfs.sh --help\n./scripts/umount-lazyfs.sh --help\n```\n\nFinally, one can control LazyFS by echoing the following commands to the configured FIFO:\n\n-   **Clear cache** - clears all unsynced data:\n\n    ```bash\n    echo \"lazyfs::clear-cache\" \u003e /tmp/faults.fifo\n    ```\n\n-   **Checkpoint** - checkpoints all unsynced data by calling `write` to the underlying file system (without `fsync`):\n\n    ```bash\n    echo \"lazyfs::cache-checkpoint\" \u003e /tmp/faults.fifo\n    ```\n\n    \u003e Note: Any subsequent failure is outside of the test control.\n\n-   **Show usage** - displays the current cache usage (percentage of pages allocated):\n\n    ```bash\n    echo \"lazyfs::display-cache-usage\" \u003e /tmp/faults.fifo\n    ```\n\n-   **Report unsynced data,** which displays the inodes that have data in cache:\n\n    ```bash\n    echo \"lazyfs::unsynced-data-report\" \u003e /my/path/faults.fifo\n    ```\n\n-   **Kill the filesystem,** which is triggered by an operation, a timing and a path regex:\n\n    Here **timing** should be one of `before` or `after`, and **op** should be a valid system call name (e.g. `write` or `read`).\n\n    - In the case of operations that have a source path only (e.g. `create`, `open`, `read`, `write`, ...)\n\n        ```bash\n        echo \"lazyfs::crash::timing=...::op=...::from_rgx=...\" \u003e /my/path/faults.fifo\n        ```\n\n        Here, `from_rgx` is required (do not specify to_rgx).\n\n    - For `rename`, `link` and `symlink`, one is able to specify the destination path:\n\n        ```bash\n        echo \"lazyfs::crash::timing=...::op=...::from_rgx=...::to_rgx=...\" \u003e /my/path/faults.fifo\n        ```\n\n        Here, only one of `from_rgx` or `to_rgx` is required.\n\n    Example 1:\n\n    ```bash\n    echo \"lazyfs::crash::timing=before::op=write::from_rgx=file1\" \u003e /my/path/faults.fifo\n    ```\n\n    \u003e Kills LazyFS before executing a write operation to the file pattern 'file1'.\n\n    Example 2:\n\n    ```bash\n    echo \"lazyfs::crash::timing=before::op=link::from_rgx=file1::to_rgx=file2\" \u003e /my/path/faults.fifo\n    ```\n\n    \u003e Kills LazyFS before executing a rename operation from the file pattern 'file1' to the file pattern 'file2'.\n\n    Example 3:\n\n    ```bash\n    echo \"lazyfs::crash::timing=before::op=rename::to_rgx=fileabd\" \u003e /my/path/faults.fifo\n    ```\n\n    \u003e Kills LazyFS before executing a link operation to the file pattern 'fileabd'.\n\n-   **Kill the filesystem** after injecting `torn-op` or `torn-seq`faults:\n\n    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` ).\n\n    -   ```bash\n        echo \"lazyfs::torn-op::file=...::persist=...::parts=...::occurrence=...\" \u003e /my/path/faults.fifo\n        ```\n\n    -   ```bash\n        echo \"lazyfs::torn-seq::op=...::file=...::persist=...::occurrence=...\" \u003e /my/path/faults.fifo\n        ```\n\nAfter a LazyFS crash, the mount directory may be left in an undefined state. In that case, run:\n\n```bash\nfusermount -uz \u003cmount-directory\u003e\n```\n\nLazyFS 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`.\n\n## Contact\n\nFor additional information regarding possible improvements and collaborations please open an issue or contact: [@devzizu](https://github.com/devzizu), [@mj-ramos](https://github.com/mj-ramos) and [@dsrhaslab](https://github.com/dsrhaslab).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsrhaslab%2Flazyfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdsrhaslab%2Flazyfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsrhaslab%2Flazyfs/lists"}