Merge pull request #9853 from ThomasWaldmann/fix-create-enospc-atomicity
Some checks failed
Lint / lint (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / security (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
CI / asan_ubsan (push) Has been cancelled
CI / native_tests (push) Has been cancelled
CI / vm_tests (NetBSD, false, netbsd, 10.1) (push) Has been cancelled
CI / vm_tests (OmniOS, false, omnios, r151056) (push) Has been cancelled
CI / vm_tests (OpenBSD, false, openbsd, 7.8) (push) Has been cancelled
CI / vm_tests (borg-freebsd-14-x86_64-gh, FreeBSD, true, freebsd, 14.3) (push) Has been cancelled
CI / windows_tests (push) Has been cancelled

create: do not wrap repository writes in backup_io("read") (silent data loss on ENOSPC)
This commit is contained in:
TW 2026-07-03 20:35:37 +02:00 committed by GitHub
commit 985cbc4178
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1434,15 +1434,18 @@ class FilesystemObjectProcessors:
changed_while_backup = False
if "chunks" not in item:
start_reading = time.time_ns()
with backup_io("read"):
self.process_file_chunks(
item,
cache,
self.stats,
self.show_progress,
backup_io_iter(self.chunker.chunkify(None, fd)),
)
self.stats.chunking_time = self.chunker.chunking_time
# Do NOT wrap this in backup_io("read"): the source-file reads are already
# guarded individually by backup_io_iter() below. Wrapping the whole call would
# also wrap add_chunk()'s *repository* writes, turning a critical repository IO
# failure (e.g. the repo running out of space during a pack flush) into a
# non-critical per-file BackupOSError. Borg would then only warn, skip the file,
# and still commit the archive -- referencing chunks that were never durably
# stored. An unwrapped repository OSError is critical and aborts create before
# archive.save() runs (see the BackupOSError docstring).
self.process_file_chunks(
item, cache, self.stats, self.show_progress, backup_io_iter(self.chunker.chunkify(None, fd))
)
self.stats.chunking_time = self.chunker.chunking_time
end_reading = time.time_ns()
with backup_io("fstat2"):
st2 = os.fstat(fd)