diff --git a/docs/faq.rst b/docs/faq.rst index abf8fed23..a6fb31edb 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -1159,6 +1159,44 @@ It may be useful to set ``BORG_RELOCATED_REPO_ACCESS_IS_OK=yes`` to avoid the prompts when renaming multiple repositories or in a non-interactive context such as a script. See :doc:`deployment` for an example. +The repository quota size is reached, what can I do? +---------------------------------------------------- + +The simplest solution is to increase or disable the quota and resume the backup: + +:: + + borg config /path/to/repo storage_quota 0 + +If you are bound to the quota, you have to free repository space. The first to +try is running :ref:`borg_compact` to free unused backup space (see also +:ref:`separate_compaction`): + +:: + + borg compact /path/to/repo + +If your repository is already compacted, run :ref:`borg_prune` or +:ref:`borg_delete` to delete archives that you do not need anymore, and then run +``borg compact`` again. + +My backup disk is full, what can I do? +-------------------------------------- + +Borg cannot work if you really have zero free space on the backup disk, so the +first thing you must do is deleting some files to regain free disk space. See +:ref:`about_free_space` for further details. + +Some Borg commands that do not change the repository might work under disk-full +conditions, but generally this should be avoided. If your backup disk is already +full when Borg starts a write command like `borg create`, it will abort +immediately and the repository will stay as-is. + +If you run a backup that stops due to a disk running full, Borg will roll back, +delete the new new segment file and thus freeing disk space automatically. There +may be a checkpoint archive left that has been saved before the disk got full. +You can keep it to speed up the next backup or delete it to get back more disk +space. Miscellaneous ############# diff --git a/docs/internals/frontends.rst b/docs/internals/frontends.rst index 7ef96c788..056fa98ac 100644 --- a/docs/internals/frontends.rst +++ b/docs/internals/frontends.rst @@ -90,12 +90,14 @@ progress_percent can have this property set to *true*. message A formatted progress message, this will include the percentage and perhaps other information + (absent for finished == true) current - Current value (always less-or-equal to *total*) + Current value (always less-or-equal to *total*, absent for finished == true) info Array that describes the current item, may be *null*, contents depend on *msgid* + (absent for finished == true) total - Total value + Total value (absent for finished == true) time Unix timestamp (float) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index af14815d9..5754a02cf 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -26,6 +26,8 @@ repositories contain data blocks and a manifest tracking which blocks are in eac archive. If some data hasn't changed from one backup to another, Borg can simply reference an already uploaded data chunk (deduplication). +.. _about_free_space: + Important note about free space ------------------------------- diff --git a/src/borg/_hashindex.c b/src/borg/_hashindex.c index 7236cfdce..7cd4cf31a 100644 --- a/src/borg/_hashindex.c +++ b/src/borg/_hashindex.c @@ -664,11 +664,11 @@ hashindex_compact(HashIndex *index) while(idx < index->num_buckets) { /* Phase 1: Find some empty slots */ start_idx = idx; - while((BUCKET_IS_EMPTY(index, idx) || BUCKET_IS_DELETED(index, idx)) && idx < index->num_buckets) { + while((idx < index->num_buckets) && (BUCKET_IS_EMPTY(index, idx) || BUCKET_IS_DELETED(index, idx))) { idx++; } - /* everything from start_idx to idx is empty or deleted */ + /* everything from start_idx to idx-1 (inclusive) is empty or deleted */ count = empty_slot_count = idx - start_idx; begin_used_idx = idx; @@ -682,7 +682,7 @@ hashindex_compact(HashIndex *index) /* Phase 2: Find some non-empty/non-deleted slots we can move to the compact tail */ - while(!(BUCKET_IS_EMPTY(index, idx) || BUCKET_IS_DELETED(index, idx)) && empty_slot_count && idx < index->num_buckets) { + while(empty_slot_count && (idx < index->num_buckets) && !(BUCKET_IS_EMPTY(index, idx) || BUCKET_IS_DELETED(index, idx))) { idx++; empty_slot_count--; } diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 17cf970ca..3c141234f 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -3147,10 +3147,13 @@ class Archiver: # borg mount mount_epilog = process_epilog(""" - This command mounts an archive as a FUSE filesystem. This can be useful for - browsing an archive or restoring individual files. Unless the ``--foreground`` - option is given the command will run in the background until the filesystem - is ``umounted``. + This command mounts an archive as a FUSE filesystem. This can be useful + for browsing an archive or restoring individual files. When restoring, + take into account that the current FUSE implementation does not support + special fs flags and ACLs. + + Unless the ``--foreground`` option is given the command will run in the + background until the filesystem is ``umounted``. The command ``borgfs`` provides a wrapper for ``borg mount``. This can also be used in fstab entries: diff --git a/src/borg/platform/base.py b/src/borg/platform/base.py index 3cfd82974..d6f2aae8f 100644 --- a/src/borg/platform/base.py +++ b/src/borg/platform/base.py @@ -239,13 +239,18 @@ class SaveFile: safe_unlink(self.tmp_fname) # with-body has failed, clean up tmp file return # continue processing the exception normally - # tempfile.mkstemp always uses owner-only file permissions for the temp file, - # but as we'll rename it to the non-temp permanent file now, we need to respect - # the umask and change the file mode to what a normally created file would have. - # thanks to the crappy os.umask api, we can't query the umask without setting it. :-( - umask = os.umask(UMASK_DEFAULT) - os.umask(umask) - os.chmod(self.tmp_fname, mode=0o666 & ~ umask) + try: + # tempfile.mkstemp always uses owner-only file permissions for the temp file, + # but as we'll rename it to the non-temp permanent file now, we need to respect + # the umask and change the file mode to what a normally created file would have. + # thanks to the crappy os.umask api, we can't query the umask without setting it. :-( + umask = os.umask(UMASK_DEFAULT) + os.umask(umask) + os.chmod(self.tmp_fname, mode=0o666 & ~ umask) + except OSError: + # chmod might fail if the fs does not support it. + # this is not harmful, the file will still have permissions for the owner. + pass try: os.replace(self.tmp_fname, self.path) # POSIX: atomic rename