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: cleanup volume dir if create volume failed #2865

Merged
merged 1 commit into from Apr 10, 2024

Conversation

zjumoon01
Copy link

Volume path should be cleaned up if create volume failed.

Otherwise, the volume will be created failed again next time with a 'file exists' error on os.Mkdir.

@AkihiroSuda
Copy link
Member

How to test this?

@zjumoon01
Copy link
Author

How to test this?

This scene is quite rare. There is no space left on device, and a directory is just deleted.

step1
#nerdctl volume create v2
FATA[0000] mkdir /var/lib/nerdctl/1935db59/volumes/default/v2/_data: no space left on device

step2
Cleanup my disk and release some space.
Create volume again.
#nerdctl volume create v2
FATA[0000] mkdir /var/lib/nerdctl/1935db59/volumes/default/v2: file exists

Look into /var/lib/nerdctl/1935db59/volumes/default/v2, it's an empty dir

#nerdctl volume ls
FATA[0000] volume "v2" not found: not found

@AkihiroSuda
Copy link
Member

This case is quite rare, so I expect the user to just run nerdctl volume rm

@zjumoon01
Copy link
Author

This case is quite rare, so I expect the user to just run nerdctl volume rm

Volume is not created successfully. The creation process was only halfway complete.
volume rm also got 'not found' error.

#nerdctl volume rm v2
FATA[0000] volume "v2" not found: not found

In fact, get function is called before remove function.
Get function in volume store only check volume dataPath

@AkihiroSuda AkihiroSuda added this to the v2.0.0 milestone Mar 8, 2024
@AkihiroSuda AkihiroSuda requested review from a team March 11, 2024 01:20
if err := os.Mkdir(volPath, 0700); err != nil {
return err
}
defer func() {
if err != nil {
os.Remove(volPath)
Copy link
Member

Choose a reason for hiding this comment

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

Volume path should be cleaned up if create volume failed.

cleanup doesn't seem to happen for errors outside of this fn?

Copy link
Author

Choose a reason for hiding this comment

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

cleanup is called in this fn for the two errors, json.MarshalIndent and os.WriteFile
Creation is done after this fn is completed. No other new errors outside of it. If some action added after lockutil.WithDirLock(vs.dir, fn) in future, cleanup will be moved out of this fn.

Copy link
Member

Choose a reason for hiding this comment

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

cleanup is called in this fn for the two errors, json.MarshalIndent and os.WriteFile

cleanup seems to fail if that dir isn't empty

in future, cleanup will be moved out of this fn.

should be documented

Copy link
Author

@zjumoon01 zjumoon01 Mar 11, 2024

Choose a reason for hiding this comment

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

cleanup seems to fail if that dir isn't empty

dir is empty as expected if writing json file failed. Or use os.RemoveAll instead ?

should be documented

OK, should I add some comments?

Copy link
Member

Choose a reason for hiding this comment

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

RemoveAll can be dangerous, so I don't prefer it

Copy link
Member

Choose a reason for hiding this comment

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

dir is empty as expected if writing json file failed.

https://pkg.go.dev/os#WriteFile

Since WriteFile requires multiple system calls to complete, a failure mid-operation can leave the file in a partially written state.

Copy link
Author

Choose a reason for hiding this comment

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

How about these steps in cleanup ?
step 1. check json file exists and remove it
step 2. remove volume data path dir
step 3. remove volume path dir

Copy link
Member

Choose a reason for hiding this comment

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

the path was created on multiple steps so I beleive that cleanup should follow the same pattern and be cleaned on multiple steps

Copy link
Author

Choose a reason for hiding this comment

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

How about these steps in cleanup ?
step 1. check json file exists and remove it

fixed
Use stat to check json file exist
Also add some comments.

defer func() {
if err != nil {
// ignore cleanup error
if _, serr := os.Stat(volFilePath); serr == nil || !os.IsNotExist(serr) {
Copy link
Member

Choose a reason for hiding this comment

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

If stat returns error for the file, it should print error and shouldn't continue cleanup.

Copy link
Member

Choose a reason for hiding this comment

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

it should print error and shouldn't continue cleanup.

volFilePath does not exist and volDataPath exists => we should continue cleanup

just drop stat and log remove error should be fine

Copy link
Author

Choose a reason for hiding this comment

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

If stat returns error for the file, it should print error and shouldn't continue cleanup.

Fixed.

if err := os.Mkdir(volDataPath, 0755); err != nil {
return err
}
defer func() {
if err != nil {
// ignore cleanup error
Copy link
Member

Choose a reason for hiding this comment

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

error shouldn't be ignored. can we print log for this?

Copy link
Author

Choose a reason for hiding this comment

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

error shouldn't be ignored. can we print log for this?

volFilePath, volDataPath and volPath are removed in cleanup. It looks like complicated if we print all the remove error log. How about only printing stat error which will abort cleanup function

Copy link
Author

Choose a reason for hiding this comment

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

error shouldn't be ignored. can we print log for this?

I don't print log for cleanup error as some other cleanup functions defer os.Remove in the code.
Of course, I can also add some logs for these remove errors

pkg/mountutil/volumestore/volumestore.go Outdated Show resolved Hide resolved
defer func() {
if err != nil {
// ignore cleanup error
if _, serr := os.Stat(volFilePath); serr == nil || !os.IsNotExist(serr) {
Copy link
Member

Choose a reason for hiding this comment

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

it should print error and shouldn't continue cleanup.

volFilePath does not exist and volDataPath exists => we should continue cleanup

just drop stat and log remove error should be fine

pkg/mountutil/volumestore/volumestore.go Outdated Show resolved Hide resolved
Copy link
Member

@ktock ktock left a comment

Choose a reason for hiding this comment

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

LGTM on green

@zjumoon01
Copy link
Author

LGTM on green

@ktock Could you please rerun the integration test? The failure is not likely related with nerdctl/volume

@djdongjin
Copy link
Member

@zjumoon01 can you rebase to get the latest change in main? The cosign-related CI errors should be fixed now #2896.

@zjumoon01
Copy link
Author

@zjumoon01 can you rebase to get the latest change in main? The cosign-related CI errors should be fixed now #2896.

I rebased, but CI failed again caused by 'run container error' in TestVolumeRemove. Do you have any ideas ?

Volume path should be cleaned up if create volume failed.
Otherwise, the same volume will be created failed again
next time with a 'file exists' error on os.Mkdir.

Signed-off-by: baijia <baijia.wr@antgroup.com>
Copy link
Member

@fahedouch fahedouch left a comment

Choose a reason for hiding this comment

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

Thanks

@fahedouch fahedouch merged commit d53bfe7 into containerd:main Apr 10, 2024
21 of 22 checks passed
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.

None yet

5 participants