diff --git a/lib/model/sharedpullerstate.go b/lib/model/sharedpullerstate.go index ce5ae5f8b..1c048536c 100644 --- a/lib/model/sharedpullerstate.go +++ b/lib/model/sharedpullerstate.go @@ -158,8 +158,27 @@ func (s *sharedPullerState) tempFile() (io.WriterAt, error) { // Truncate sets the size of the file. This creates a sparse file or a // space reservation, depending on the underlying filesystem. if err := fd.Truncate(s.file.Size); err != nil { - s.failLocked("dst truncate", err) - return nil, err + // The truncate call failed. That can happen in some cases when + // space reservation isn't possible or over some network + // filesystems... This generally doesn't matter. + + if s.reused > 0 { + // ... but if we are attempting to reuse a file we have a + // corner case when the old file is larger than the new one + // and we can't just overwrite blocks and let the old data + // linger at the end. In this case we attempt a delete of + // the file and hope for better luck next time, when we + // should come around with s.reused == 0. + + fd.Close() + + if remErr := s.fs.Remove(s.tempName); remErr != nil { + l.Debugln("failed to remove temporary file:", remErr) + } + + s.failLocked("dst truncate", err) + return nil, err + } } }