-
Notifications
You must be signed in to change notification settings - Fork 557
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
rbd: cleanup inconsistent state in reserveSnap()
after a failure
#4946
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -388,6 +388,18 @@ func (ri *rbdImage) repairImageID(ctx context.Context, j *journal.Connection, fo | |
func reserveSnap(ctx context.Context, rbdSnap *rbdSnapshot, rbdVol *rbdVolume, cr *util.Credentials) error { | ||
var err error | ||
|
||
// restore original values in case of an error | ||
origReservedID := rbdSnap.ReservedID | ||
origRbdSnapName := rbdSnap.RbdSnapName | ||
origVolID := rbdSnap.VolID | ||
defer func() { | ||
if err != nil { | ||
rbdSnap.ReservedID = origReservedID | ||
rbdSnap.RbdSnapName = origRbdSnapName | ||
rbdSnap.VolID = origVolID | ||
} | ||
}() | ||
|
||
journalPoolID, imagePoolID, err := util.GetPoolIDs(ctx, rbdSnap.Monitors, rbdSnap.JournalPool, rbdSnap.Pool, cr) | ||
if err != nil { | ||
return err | ||
|
@@ -405,6 +417,17 @@ func reserveSnap(ctx context.Context, rbdSnap *rbdSnapshot, rbdVol *rbdVolume, c | |
ctx, rbdSnap.JournalPool, journalPoolID, rbdSnap.Pool, imagePoolID, | ||
rbdSnap.RequestName, rbdSnap.NamePrefix, rbdVol.RbdImageName, kmsID, rbdSnap.ReservedID, rbdVol.Owner, | ||
"", encryptionType) | ||
defer func() { | ||
// only undo the reservation when an error occurred | ||
if err == nil { | ||
return | ||
} | ||
|
||
undoErr := undoSnapReservation(ctx, rbdSnap, cr) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be and is already called outside after reserveSnap() calls ? https://github.com/ceph/ceph-csi/blob/devel/internal/rbd/controllerserver.go#L1194 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is not sufficient in case |
||
if undoErr != nil { | ||
log.WarningLog(ctx, "failed undoing reservation of snapshot %q: %v", rbdSnap, undoErr) | ||
} | ||
}() | ||
if err != nil { | ||
return err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nixpanic any specific reason to preserve and restore these values? i assume if the reservation is done properly these values will be set and not overridden to any values isnt it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are these two calls that overwrite the attributes in any case (success of error):
and
So, if something goes wrong, it looks nicer to reset the attributes that may have been modified by a failing call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting those attributes only at the end of the function is tricky too,
undoSnapReservation()
expects them to be set in order to clean things up in the journal.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nixpanic the ReserveID and RbdSnapName names are not set earlier its only set by calling the
j.ReserveName
function, IMO we dont need to preserve anything and also calling the defer incase of error should be enough. same goes for volID as well.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Madhu-1 if they are not expected to be set, shall I add a check and error message in case they are not an empty string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently we dont have any case where they are set before calling this function. there are callers doing undo reservation and that will fail or not required
we updated the current code to do undo internally if something fails.
Doesnt hurt to have this code but this will result in extra error/logs when we try to call the Undo function multiple times.
Let me know what do you prefer
reserveSnap
internal functionThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current PR as it is shows what a function should do/restore. There are no callers that will call
undoSnapReservation()
in casereserveSnap()
fails, so there should not be additional logs for that.When a function returns an error, there should be no need for the caller to undo whatever internals the function may, or may not, have done. Everything internal to the function should stay there. For the more complex cases, a special
undo
function can be returned, similar to whatManager.getGroupUUID()
does.Merging the current PR as it is should be fine IMHO, @Madhu-1, but I am also fine with improving it some way you recommend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/ceph/ceph-csi/blob/devel/internal/rbd/controllerserver.go#L1194
https://github.com/ceph/ceph-csi/blob/devel/internal/rbd/controllerserver.go#L1194 might trigger an additional log
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it would not. In case there is an error returned by
reserveSnap()
, thedefer
whereundoSnapReservation()
is called will never be reached.