-
Notifications
You must be signed in to change notification settings - Fork 43
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
Avoid overwriting files that are unchanged? #269
Comments
While this issue seems related to #242 I think what I'm asking for is a reliable way to apply an update from the store via an index diff? (since I can have the destination indexed in advance) Redundant writes should be preventable with information Example (base vs update)# Initial content:
$ ls -l /root-fs
total 4
-rw-r--r-- 1 root root 24 Sep 11 09:00 file
$ ls -l /root-fs-b
total 4
-rw-r--r-- 1 root root 24 Sep 11 09:00 file
# Initial store + seed index:
$ desync tar --no-time -s store -i existing.caidx /root-fs
# An update (create a new index + update store):
$ touch /root-fs-b/new-file
$ desync tar --no-time -s store -i update-b.caidx /root-fs-b
# Compare existing index vs updated index:
desync info --format plain --store store --seed existing.caidx update-b.caidx
Blob size: 377
Size of deduplicated chunks not in seed: 377
Size of deduplicated chunks not in seed nor cache: 377
Total chunks: 1
Unique chunks: 1
Chunks in store: 1
Chunks in seed: 0
Chunks in cache: 0
Chunks not in seed nor cache: 1
Chunk size min: 16384
Chunk size avg: 65536
Chunk size max: 262144
$ desync mtree -s store -i existing.caidx
#mtree v1.0
. type=dir mode=0755 uid=0 gid=0 time=0. 0
file type=file mode=0644 uid=0 gid=0 size=24 time=0.000000000 sha512256digest=97b0fc819edb24745c11422b30476acf214a8459d888fb5dda857ee9bb195a5e
$ desync mtree -s store -i update-b.caidx
#mtree v1.0
. type=dir mode=0755 uid=0 gid=0 time=0. 0
file type=file mode=0644 uid=0 gid=0 size=24 time=0.000000000 sha512256digest=97b0fc819edb24745c11422b30476acf214a8459d888fb5dda857ee9bb195a5e
new-file type=file mode=0644 uid=0 gid=0 size=0 time=0.000000000 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a References (not useful to maintainers)These are more for myself since I discovered them while searching issues 😅
Diffing between index filesWith these two index files, # A diff between the two:
$ diff <(desync mtree -s store -i existing.caidx) <(desync mtree -s store -i update-b.caidx)
3a4
> new-file type=file mode=0644 uid=0 gid=0 size=0 time=0.000000000 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
# Just the unique digests from the diff output:
$ diff <(desync mtree -s store -i existing.caidx) <(desync mtree -s store -i update-b.caidx) \
| grep -oP 'sha512256digest=\K.+' | sort -u
c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a It seems that basic file metadata is encoded for each file from the |
This comment was marked as resolved.
This comment was marked as resolved.
Thanks for letting me know about the typos. Fixed them
As for only overwriting files that are different, it'd be possible to unpack every file from the archive into a tempfile somewhere, then compare the content to what's on disk, and replace the old file with the tempfile if it's different. This would require extra space (as much as the size of the largest file) and would likely be slower. However, I can think of valid use-cases for this. For example if the target is on a flash drive and the goal is to reduce wear on it. Or when the target FS is very slow, one could unpack the tempfiles into memory first and not use the slow FS. |
Yes, the intent was that if the file itself had not changed in content, nor the other metadata like permissions and ownership (although I don't think that's relevant to mtime, only the file content?) I would expect that the mtime is not updated. This is for a scenario where I wanted to sync the delta but with mtime ignored (as the newer version may have already generated existing content with a new mtime but otherwise no difference). I tried to point this concern out in the "context" section I provided where a Docker image layer will duplicate storage required for a file (a new layer contains the copy) just by attributes like ownership, permissions or mtime being updated. There are package managers that let you install your own root fs target. If after this point you wanted to add some new packages however, by overlaying that root-fs with a modified variant, the mtime update makes that layer much bigger than it needs to be. I learned about I suppose |
I'm not able to reproduce it. Here's what I tried: Create a source-tree:
Query the mtime of the file inside it and make a catar:
The mtime is shown as Then unpack the archive and display the mtime of the file:
It too shows Are you able to make a simple repro for what you're seeing? |
I provided one at the very top of the report under "Reproduction" header. It uses Docker, that should provide you an environment with the same conditions to reproduce. Just to re-iterate since I think you missed the context with your last reply, the mtime is not stored in the archive as I do not want to modify files that otherwise unchanged beyond mtime, yet mtime is still updated. When I say mtime is updated/changed, I mean that it becomes the time of extraction due to |
That's exactly what's happening currently, and it does not matter it there's an mtime in the archive or not. Files are always overwritten. Having said that, if you include the mtime during tar, then untar will set the mtime of the extracted file to that value (after extracting it). The file would still have been written, but the mtime may be the same if the source-file during tar wasn't changed. So in your use-case, perhaps including the mtime will help? |
The 2nd archive would be generated at a different mtime, so no I don't think it would help. I could perhaps pre-process mtime to 0 before archiving with desync and see if the overwritten files still result in duplicate data in the new OCI image layer. The inode isn't changed with desync like it is with casync, so perhaps it would otherwise be identical. I can alternatively use something like rsync for this, I just liked the other perks that a solution like desync had to offer but dealing with a directory tree of files is a bit of a friction point it seems 😅 |
One thing I could do is add an option to |
I think that was my expectation with No rush to resolve this any time soon, it's mostly to document awareness and see if any other users chime in with similar needs. My use-case may depend on a less naive extraction process as discussed at #242 to skip writes for files with no actual difference in their content. In my scenario with Docker layers, it was for using the
|
Is it not possible for
desync
to avoid modifying files that have no difference?There is no blocks/chunks to update, yet the
mtime
is modified each time I run theuntar
command? (desync untar
appears to be the equivalent ofcasync extract
for a directory tree?)UPDATE: See follow-up comment. At a glance I think
desync
could diff between two index (caidx
) files for before/after, to filter out files with no change in their content digest (and perhaps the other metadata attributes) asdesync mtree
/desync info
can derive information from a common store dir andcaidx
files?Context
I am new to
casync
/desync
, there's a lot of options/commands and jargon to ingest, so perhaps I've misunderstood something. I've looked over existing issues and this may be a duplicate of #242 or just overlap with it.In my scenario, I wanted to sync changes from the archive (src) to the target (dest) based on file content (not concerned with file metadata changes at this point). The impression I had was
desync
could effectively detect only what needs to be updated from an index/store. The linked issue suggests this is a problem withuntar
and needing support for providing a seed.mtime
or other metadata related changes is problematic within Docker images. Similar to the linked issue, I'm interested in updating a filesystem root with only the subset of changes from the archive (typically much smaller than the existing destination target).When all files are modified redundantly, the new Docker layer will duplicate that file content in full which is undesirable.
Reproduction
Related issue with
casync
: systemd/casync#264 (comment)It does manage to avoid replacing the inode unlike
casync
which is an improvement I think? However I'd rather it not unnecessarily modify files.The text was updated successfully, but these errors were encountered: