Home / Alt manpages / btrfs-restore(8)

  • btrfs-restore(8)
  • Admin command
  • linux

Recover Files from a Damaged Btrfs Image with btrfs restore

You will finish with a cautious workflow for salvaging files from a damaged Btrfs filesystem image into a separate directory. The examples use btrfs-progs 6.6.3, installed here as btrfs restore. Allow thirty minutes for a small image and longer for a large or badly damaged filesystem. Recovery is an investigation: a successful command does not prove that every file is complete or current.

You need a readable Btrfs device or image, enough free space for the recovered data, and a destination that is not the source filesystem. The image must not be mounted for this operation. Ordinary listing and dry-run commands usually need no elevated privilege when your account can read the source. Use sudo only when the device permissions require it.

1. Protect the source and prepare a destination

Do not start by writing into the damaged filesystem. btrfs restore does not modify the filesystem image, but the destination is still changed as files are recovered. If the source is a block device, identify it carefully and keep it unmounted:

$ lsblk -f
$ findmnt /dev/DEVICE
$ mkdir -p /path/to/recovery

Replace /dev/DEVICE and /path/to/recovery with real paths. The findmnt command should produce no entry for the source device. Stop if the destination is on the same filesystem you are trying to rescue, or if it does not have enough free space.

Checkpoint

Record the exact source and destination before continuing. A typo in the source path can turn a recovery attempt into a test of a different disk.

2. List the available subvolume roots

Start with the read-only root listing. It shows tree roots that can be passed to -r later:

$ btrfs restore --list-roots /path/to/damaged-image
Tree      5  FS tree
Tree      256  FS tree
Tree      257  FS tree

The exact lines depend on the image, and a damaged image may report warnings or fewer roots. The useful values are the object IDs in the first column. Do not copy the sample numbers unless they appear in your own output. A non-zero exit status means this inspection failed; capture its diagnostics before trying recovery options.

3. Run a dry run before writing files

Use --dry-run with a destination. The command lists files that it would recover and does not write recovered data:

$ btrfs restore --dry-run --verbose /path/to/damaged-image /path/to/recovery
We have a good chance of reading ...
... files listed here are image-dependent ...

Do not treat the sample lines as guaranteed output. Your image may produce different names, warnings or no usable file list. The point of this pass is to see whether metadata can be read far enough to identify files. If it lists the wrong root or only a small part of the tree, return to the root list and try an explicit root ID.

Checkpoint

Continue only when the dry run reaches data you actually need. A dry run is not a completeness check, but it avoids filling the destination with an unexamined attempt.

4. Restore a selected subvolume

Choose a root object ID from your own --list-roots output, then restore it into a dedicated directory:

$ ROOT_ID=257
$ mkdir -p /path/to/recovery/root-257
$ btrfs restore --root "$ROOT_ID" --verbose /path/to/damaged-image /path/to/recovery/root-257

--root limits the operation to a subvolume whose object ID is the supplied value. Without it, the command uses its normal filesystem-tree selection and may inspect more than the tree you intended. The destination directory is created or populated by the command; choose a new one for each trial so that results from different roots are not confused.

When the command exits, check both its status and the recovered files:

$ printf 'restore status: %s\n' "$?"
restore status: 0
$ find /path/to/recovery/root-257 -type f -print | head

A zero status means the command reported success, not that every file was recovered. Compare important files against another copy, open them with an appropriate tool, and keep the source unchanged until those checks are complete.

5. Add file metadata deliberately

The basic restore focuses on file data. Add --metadata when owner, mode and timestamps matter, and --xattr when extended attributes matter:

$ btrfs restore --metadata --xattr \
    --root "$ROOT_ID" /path/to/damaged-image /path/to/recovery/root-257-metadata

These options change the attributes written in the destination, not the source image. Check the result with stat and, where relevant, getfattr. Ownership restoration may be limited by the account running the command, so use elevated privileges only if preserving numeric ownership is necessary and the destination is trusted.

Symbolic links and snapshots are not included by every default selection. Use --symlinks for symbolic links and --snapshots to include snapshots:

$ btrfs restore --symlinks --snapshots \
    /path/to/damaged-image /path/to/recovery/with-links

These flags can create more destination entries than a data-only attempt. Inspect the destination before handing it to another program. To limit names, --path-regex accepts a regular expression in the required full-path form. For example, this selects paths below /home/alice/Documents:

$ btrfs restore --path-regex \
    '^/(|home(|/alice(|/Documents(|/.*))))$' \
    /path/to/damaged-image /path/to/recovery/documents

The expression must describe the complete path and its parent directories. It is not a simple substring filter, and the manual warns that it is awkward for one deeply nested file. Use -c only when case-insensitive matching is required for that regular expression.

7. Retry around damaged metadata

If the normal attempt stops on errors, try --ignore-errors in a new destination:

$ btrfs restore --ignore-errors --verbose \
    /path/to/damaged-image /path/to/recovery/ignore-errors

This asks the program to continue, so the output may contain incomplete files or files from an older available version. It is a salvage attempt, not a repair. Keep the first result and the command diagnostics; do not overwrite one recovery with another unless you have compared them.

For damaged tree structures, the installed command also accepts -t for a root-tree byte offset, -f for a subvolume-root byte offset, and -u for superblock mirror 0, 1 or 2. These values are image-specific. Do not guess them. Obtain a candidate from a trusted inspection of the same image and record which value produced each result.

8. Handle repeats safely

By default, existing files and directories in the destination are not an invitation to merge blindly. If you deliberately want to repeat a run into an existing destination, --overwrite permits overwriting files and directories there:

$ btrfs restore --overwrite /path/to/damaged-image /path/to/recovery/retry

This can destroy a better copy already in the destination. Prefer a new destination directory. If you used --overwrite accidentally, stop and preserve what remains; there is no restore-specific undo command. Recovering again into a new directory cannot reconstruct files already overwritten in the old destination, so keep independent copies when the data matters.

Done means

  • Source protected. The image or device was identified, kept unmounted and left unchanged.
  • Destination separate. It has enough space and a clear record of which attempt created it.
  • Roots checked. You listed them and took any --root value from real output, not a guess.
  • Dry run reviewed. It showed whether the files you need were readable before a full restore.
  • Files verified. Recovered files were checked for presence, content and any metadata that matters.
  • Overwrite avoided. Retries used separate destinations unless replacement was genuinely intended.