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

gadget, osutil: use atomic file copy, adjust tests #9103

Merged

Conversation

bboozzoo
Copy link
Collaborator

@bboozzoo bboozzoo commented Aug 6, 2020

The regular CopyFile() call can only overwrite the destination location in
place. Add a new helper that wraps the destination path with AtomicFile, to
obtain a 2 stage write & commit (or cancel) behavior.

Use the CopyFileAtomic helper in gadget for moving file data around.
Update the tests to match slightly changed semantics.

The regular CopyFile() call can only overwrite the destination location in
place. Add a new helper that wraps the destination path with AtomicFile, to
obtain a 2 stage write & commit (or cancel) behavior.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Use the CopyFileAtomic helper for moving file data around. Update the tests
to match slightly changed semantics.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
@bboozzoo bboozzoo added the UC20 label Aug 6, 2020
@mvo5 mvo5 added this to the 2.45 milestone Aug 6, 2020
Copy link
Contributor

@mvo5 mvo5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks for working on this. Some comments inline though.

// TODO try to preserve ownership and permission bits
if err := osutil.CopyFile(src, dst, copyFlags); err != nil {

// dst is a reflection of src, no additional flags are needed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand this comment - but maybe I just need more tea?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite sure it needs a better comment, which I'll add

@@ -2021,7 +2021,8 @@ func (s *mountedfilesystemTestSuite) TestMountedUpdaterRollbackRestoreFails(c *C
{target: "foo", content: "written"},
{target: "some-dir/foo", content: "written"},
})
// make rollback fail when restoring
// the file exists, rollback will try to restore it, but make the file
// non-modifiable directly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this updated comment, but even though the file is 0000 rollback will restore it, yes? Maybe the comment could mention this too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add.

osutil/cp.go Outdated
// destination. The destination path is always overwritten. The destination and
// the owning directory are synced after copy completes. Pass additional flags
// for AtomicFile wrapping the destination.
func CopyFileAtomic(src, dst string, flags AtomicWriteFlags) (err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It slightly bothers me slightly that "CopyFileAtomic" takes different flags than "CopyFile()". OTOH maybe the perfect should not be the enemy of the good and we can always tweak/fix further as needed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that we cannot really make any use of the flags. CopyFlagSync is meaningless because we always sync, CopyFlagOverwrite is racy unless we try to open the dst file with O_CREAT|O_EXCL next to AtomicFile, lastly CopyFlagPreserveAll cannot be implemented right now without calling cp under the hood. In that sense, the semantics are more like AtomicFile, so instead passing CopyFlags, it's taking AtomicWriteFlags.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this should be called AtomicCopyFile. Regarding needeing cp, we could use it if needed and cp to a random file name and then AtomicRename that to the final name, it's not our current use case I think though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other possible naming would be AtomicWriteFileCopy, in that case though src and dst would have to be swapped I think

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like AtomicWriteFileCopy() and we can always consolidate into CopyFile() with the Atomic flag later, maybe a XXX: should we merge into CopyFIle with new AtomicCopyFile or similar.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Copy link
Contributor

@mvo5 mvo5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Samueles ideas

this makes it a bit clearer that ATM some aspects of the behavior are
closer to the AtomicWrite* family

for consistency this involved also swapping argument order
Copy link
Member

@anonymouse64 anonymouse64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Copy link
Member

@cmatsuoka cmatsuoka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM.

@cmatsuoka cmatsuoka merged commit 70a6760 into snapcore:master Aug 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants