Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix [#163]: uses reflinking on CoW filesystems like btrfs #164

Merged
merged 1 commit into from
Jan 5, 2024

Conversation

taukakao
Copy link
Member

@taukakao taukakao commented Dec 16, 2023

TL;DR:

Current behavior:

  1. Make new empty folder called /part-future/.system.new
  2. Copy entire image contents to /part-future/.system.new
  3. Atomically swap /part-future/.system and /part-future/.system.new

This PR (only on btrfs and other CoW filesystems):

  1. Copy /part-future/.system to /part-future/.system.new (Takes up no additional space because of CoW)
  2. Apply only changes from image to /part-future/.system.new
  3. Atomically swap /part-future/.system and /part-future/.system.new

Details:

Currently, ABRoot just copies the entire root from the mounted image to a new folder in the future partition called /.system.new

This can be improved on CoW filesystems like btrfs by using reflink copying.

In this implementation, the /part-future/.system.new folder is reflink copied from the /part-future/.system folder. Rsync will then make the changes needed to mirror the image.
This means that most of the data can be reflinked instead of copied which has a couple of important benefits:

  1. The root needs less space:
    Currently, during an abroot operation, the copied .system.new will take up roughly as much space as each of the .system folders in a and b.
    With this approach, the .system.new folder will just take up space for the needed changes.
  2. This reduces disk writes:
    Since only the changes are copied there are way less disk write operations which is especially important on SSD drives which have limited write cycles.
  3. This greatly reduces the time an abroot operation takes:
    I made a quick (but very unscientific) comparison in a VM: (cloned to be identical across tests)
    • without modifications: 5 min 10 sec
    • with reflinking and the -c rsync flag for checksum comparing: 2 min 24 sec
    • with the default rsync behaviour: 52 sec
      (This was the time it took to run abroot pkg apply with netris as a new package)

The whole thing has one minor caveat: Files which have exactly the same modification time and size will not be synced, since this is the default behavior of rsync. I can not think about a realistic scenario in which that would happen tho.
If this tiny risk is unacceptable tho then I would still prefer using this approch but with the -c (checksum) rsync flag. Files will be compared by their checksum. This requires all files to be read to compute their checksum before copying tho so it takes a lot longer (in my tests still less then with the current approach on small changes)

I want to mention a couple of things:

  1. This is not file system dependent. The behavior on other file systems will be the same as before.
  2. This does not affect atomicity. The original .system folder in the future partition is still kept until it is swapped with the new one.

A version to test can be downloaded here: https://github.com/taukakao/ABRoot/releases/tag/reflink-system-fast
(All bugs that I've encountered are present in the current abroot as well)

@taukakao
Copy link
Member Author

fixes #163

@taukakao taukakao force-pushed the reflink-system branch 5 times, most recently from 96e34da to 878e42e Compare December 16, 2023 22:12
@mirkobrombin
Copy link
Member

Looks good to me.
How will this behave once VDO support is implemented?
It would be good to support both options since ABRoot is a distro agnostic tool.

@taukakao
Copy link
Member Author

taukakao commented Dec 16, 2023

How will this behave once VDO support is implemented?

I don't know much about VDO but I don't see why this would be a problem.
There's still a btrfs filesystem ontop of VDO, so this would still work the same way.
It would also probably still have a performance benefit since data doesn't need to be unnecessarily read in.

Also, if something doesn't work it will still fall back to the default behavior.

@taukakao taukakao force-pushed the reflink-system branch 2 times, most recently from e62b2a8 to 6cab83b Compare December 22, 2023 20:19
@taukakao taukakao force-pushed the reflink-system branch 2 times, most recently from 204b545 to ab424fc Compare January 5, 2024 14:33
@taukakao taukakao requested a review from mirkobrombin January 5, 2024 14:42
This improves the time it takes to write the changes to disk.
@mirkobrombin mirkobrombin merged commit ebc0756 into Vanilla-OS:main Jan 5, 2024
2 checks passed
@taukakao taukakao deleted the reflink-system branch April 13, 2024 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants