btrfs will compress every file changed since it was mounted if you use:
mount -o compress-force=lzo /dev/btrfsdev /mnt/btrfsmnt
If you want to see to it that ALL files get compressed this way, I've got a little script I wrote to do it...
du -ht +$((1024*1024)) "$HOME" |\
sed -rn 's/^[^/]*(.*)/btrfs fi defrag -fvclzo "\1"/p' |\
sudo sh -n
The above only works on my $HOME
directory - but you can use it on anything or everything as you like. It's also got the -n
operand fed to sh
as is so you can see for yourself what sh
is currently not
doing before removing it to tell it to do it.
Anyway, first it queries du
for files in human-readable
format (probably redundant here since we strip that in the next step anyway) that are larger than 1MB
or $((1024*1024)).
It |pipes
its info to sed
which strips off everything before the leading /, "quotes"
the filename, builds the btrfs filesystem defragment -verbose -flush-to-disk -compress-lzo \filename
command and hands it over a |pipe
to sudo sh
to execute.
Again, it won't do anything so long as sh --no-execute
is in effect, though.
I think some very recent btrfs
userspace tool builds do defragment entire directories recursively, but if so it's a pretty new thing, so I've always had to do stuff like this.
Currently, btrfs does not support n-way mirrors.
Btrfs does have a special replace subcommand:
btrfs replace start /dev/left /dev/new_device /mnt/foo
Reading between the lines of the btrfs-replace
man page, this command should be able to use both existing legs - e.g. for situations where both legs have read errors - but both error sets are disjoint.
The btrfs replace command is executed in the background - you can check its status via the status
subcommand, e.g.:
btrfs replace status /mnt/foo
45.4% done, 0 write errs, 0 uncorr. read errs
Alternatively, one can also add a device to raid-1 filesytem and then delete an existing leg:
btrfs dev add /dev/mapper/new_device /mnt/foo
btrfs dev delete /dev/mapper/right /mnt/foo
The add
should return fast, since it justs adds the device (issue a btrfs fi show
to confirm).
The following delete
should trigger a balancing between the remaining devices such that each extend is available on each remaining device. Thus, the command is potentially very long running. This method also works to deal with the situation described in the question.
In comparison with btrfs replace
the add/delete cycle spams the syslog with low-level info messages. Also, it takes much longer to finish (e.g. 2-3 times longer, in my test system with 3 TB SATA drives, 80 % FS usage).
Finally, after the actual replacement, if the newer devices are larger than the original devices, you will need to issue a btrfs fi resize
on each device to utilize the entire disk space available. For the replace
example at the top, this looks like something like:
btrfs fi resize <devid>:max /mnt/foo
where devid
stands for the device id which btrfs fi show
returns.
Best Answer
Kernel 5.1 added ZSTD level support. I tested it with rc1 today using a mount option compress=zstd:12 in /etc/fstab. The default level is 3. To be clear: The change affects only files that are written after this mount command. Some benchmark results: https://lkml.org/lkml/2019/1/28/1930