fix(runtime): avoid Copy to RAM worker panic
This commit is contained in:
@@ -401,8 +401,7 @@ func copyFileLarge(ctx context.Context, src, dst string, logFunc func(string)) e
|
|||||||
copied += int64(n)
|
copied += int64(n)
|
||||||
if shouldLogCopyProgress(copied, total, lastLogged) {
|
if shouldLogCopyProgress(copied, total, lastLogged) {
|
||||||
lastLogged = copied
|
lastLogged = copied
|
||||||
pct := int(float64(copied) / float64(total) * 100)
|
maybeLogCopyProgress(logFunc, copied, total)
|
||||||
logFunc(fmt.Sprintf(" %s / %s (%d%%)", humanBytes(copied), humanBytes(total), pct))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -415,6 +414,14 @@ func copyFileLarge(ctx context.Context, src, dst string, logFunc func(string)) e
|
|||||||
return out.Sync()
|
return out.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func maybeLogCopyProgress(logFunc func(string), copied, total int64) {
|
||||||
|
if logFunc == nil || total <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pct := int(float64(copied) / float64(total) * 100)
|
||||||
|
logFunc(fmt.Sprintf(" %s / %s (%d%%)", humanBytes(copied), humanBytes(total), pct))
|
||||||
|
}
|
||||||
|
|
||||||
func shouldLogCopyProgress(copied, total, lastLogged int64) bool {
|
func shouldLogCopyProgress(copied, total, lastLogged int64) bool {
|
||||||
if total <= 0 || copied <= 0 {
|
if total <= 0 || copied <= 0 {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -272,3 +272,7 @@ func TestDetachInstallMedium(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMaybeLogCopyProgressAllowsNilLogger(t *testing.T) {
|
||||||
|
maybeLogCopyProgress(nil, copyProgressLogStep, copyProgressLogStep)
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ The Linux ABI defines `LOOP_CHANGE_FD` as `0x4C06` and
|
|||||||
`ioctlLoopChangeFD`, so every fallback reassociation called the wrong ioctl
|
`ioctlLoopChangeFD`, so every fallback reassociation called the wrong ioctl
|
||||||
and received `EINVAL`.
|
and received `EINVAL`.
|
||||||
|
|
||||||
|
The follow-up live run exposed another independent failure: copying the
|
||||||
|
remaining medium tree passes a nil progress callback to `copyFileLarge`, but
|
||||||
|
the copier called that callback unconditionally after each progress interval.
|
||||||
|
The worker therefore panicked immediately after logging "Copying remaining
|
||||||
|
medium files...", and the parent task only reported `exit status 1`.
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
- Use the correct `LOOP_CHANGE_FD` request number, `0x4C06`, and protect it
|
- Use the correct `LOOP_CHANGE_FD` request number, `0x4C06`, and protect it
|
||||||
@@ -40,6 +46,8 @@ and received `EINVAL`.
|
|||||||
- Eject the original device without unmounting the new RAM bind mount.
|
- Eject the original device without unmounting the new RAM bind mount.
|
||||||
- Preserve a complete RAM copy after any failure that occurs after loop
|
- Preserve a complete RAM copy after any failure that occurs after loop
|
||||||
reassociation begins, so retry never deletes a file backing a live loop.
|
reassociation begins, so retry never deletes a file backing a live loop.
|
||||||
|
- Progress reporting is optional; bulk copies without a logger must never
|
||||||
|
panic.
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user