Différences entre les versions de « Btrfs »

De Wiki Seb35
Aller à la navigation Aller à la recherche
 
(23 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
I tried to have a root filesystem into btrfs for a [https://www.gandi.net Gandi] server, and succeed after a number of trial-error. Here are my steps if it can be useful to others.
I tried to have a root filesystem into btrfs for a [https://www.gandi.net Gandi] server, and succeed after a number of trial-error. Here are my steps if it can be useful to others. For an introduction, see [https://en.wikipedia.org/wiki/Btrfs Wikipedia article] and/or [https://btrfs.wiki.kernel.org the dedicated wiki].


WARNING: this is EXPERIMENTAL and could cause DATA LOSS.
WARNING: this could cause DATA LOSS, be sure you have backups (possibly Gandi snapshots).


== Create the server ==
This was updated on 2020-09-24 for Debian 10 buster + GandiV5, and on 2022-02-02 for Debian 11 bullseye + GandiV5. An [{{fullurl:Btrfs|oldid=658077}} older version] was for Debian 9 jessie or Ubuntu 18.04 LTS + GandiV4.


On https://v4.gandi.net, create a new server [https://v4.gandi.net/admin/iaas/vm/create] with e.g. 1 proc, 256 Mio RAM, 1 system disk, Ubuntu 18.04 LTS or Debian 9.
== Manual procedure ==


Update the packages:
=== Create the server ===
apt update && apt upgrade -y


On https://v4.gandi.net, stop the server, open the page about the system disk, clone the system disk with another name, and attach this cloned disk to the server, start the server.
On [https://admin.gandi.net GandiV5], create a new server with e.g. 1 proc, 256 MiB RAM, 1 system disk of 5 GiB, Debian 10 buster or Debian 11 bullseye.


== Convert to btrfs ==
For Debian 10 buster (only), define backports (btrfs-progs must contain btrfs-convert, see [https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=870286 this Debian bug]) (this is not needed for Debian 11):
echo 'deb https://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/debian-backports.list


:''Mostly from [https://btrfs.wiki.kernel.org/index.php/Conversion_from_Ext3]''
Install btrfs-progs:
apt update && apt install -t buster-backports btrfs-progs # Debian 10 buster
apt update && apt install btrfs-progs # Debian 11 bullseye


The package btrfs-progs currently does not contain btrfs-convert ([https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=870286 this Debian bug]) because the risk of data loss is too great. Then we need to compile btrfs-progs.
On GandiV5 :
# stop the server,
# open the page about the system disk in Volumes,
# clone the system disk with another (definitive) name (e.g. the current disk is "sys-myserver", you can define the copied disk as "myserver"),
# start the server,
# wait until the server is started,
# attach this cloned disk to the server.


Install dependencies (''Ubuntu 18.04 LTS''):
ATTENTION: really start the server before attaching the cloned disk, else the root filesystem might be the cloned disk given they have the same UUID and /etc/fstab is using the UUID to select the root filesystem (it could be workarounded by setting /dev/xvda1 in /etc/fstab before stopin the server).
apt install gcc g++ libblkid-dev liblzo2-dev zlib1g-dev libzstd-dev asciidoc xmlto libattr1-dev pkg-config python3-dev python3-setuptools libext2fs-dev


OR Install dependencies (''Debian 9''):
=== Convert to btrfs ===
apt install gcc g++ libblkid-dev liblzo2-dev zlib1g-dev libzstd-dev asciidoc xmlto libattr1-dev pkg-config python3-dev python3-setuptools e2fslibs-dev


Download and compile btrfs-progs ([https://btrfs.wiki.kernel.org/index.php/Changelog changelog], [https://www.kernel.org/pub/linux/kernel/people/kdave/btrfs-progs/ releases]):
:''Mostly from [https://btrfs.wiki.kernel.org/index.php/Conversion_from_Ext3]''
wget https://mirrors.edge.kernel.org/pub/linux/kernel/people/kdave/btrfs-progs/btrfs-progs-v4.20.1.tar.gz
tar xfz btrfs-progs-v4.20.1.tar.gz
cd btrfs-progs-v4.20.1
./configure --with-convert=ext2
make
make install
cd ..
rm -rf btrfs-progs-v4.20.1 btrfs-progs-v4.20.1.tar.gz


Display the active root filesystem, and you will be able to deduce what is the cloned filesystem:
Display the active root filesystem, and you will be able to deduce what is the cloned filesystem:
  ls /dev/xvd*
  ls /dev/xvd*
  mount|grep xvd
  mount|grep xvd
  blkid -o value -s TYPE /dev/xvda1 # and the same for others
  blkid
 
Copy the result of <code>blkid</code> in some text file on your computer (will be used later).


Let’s say /dev/xvdb1 is the clone filesystem, we convert it to btrfs: ([https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-convert man 8 btrfs-convert])
Let’s say /dev/xvdb1 is the clone filesystem, we convert it to btrfs: ([https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-convert man 8 btrfs-convert])
  fsck.ext4 -f /dev/xvdb1
  fsck.ext4 -f /dev/xvdb1 # optional
  btrfs-convert -p /dev/xvdb1
  btrfs-convert -p /dev/xvdb1


Here, I obtained the following error:
Here, I obtained the following error:
  root@test:~# btrfs-convert -p /dev/xvda1
  root@test:~# btrfs-convert -p /dev/xvdb1
  create btrfs filesystem:
  create btrfs filesystem:
  blocksize: 4096
  blocksize: 4096
Ligne 73 : Ligne 73 :
  btrfs-convert -n -d -p /dev/xvdb1
  btrfs-convert -n -d -p /dev/xvdb1


Or, if still unsuccessful, try to add free space, or if still unsuccessfull, [https://github.com/kdave/btrfs-progs/issues/123#issuecomment-455877070 re-compile btrfs-progs in version 4.17.1] (this last try worked for me for 50 Gio disk with 24 Gio free space, expanded after its original size was 30 Gio (=4 Gio free space)).
Or, if still unsuccessful, try to add free space, or if still unsuccessfull, [https://github.com/kdave/btrfs-progs/issues/123#issuecomment-455877070 re-compile btrfs-progs in version 4.17.1] (this last try worked for me for 50 Gio disk with 24 Gio free space on Debian 9 jessie, expanded after its original size was 30 Gio (=4 Gio free space)).


Then, mount the filesystem and delete the old ext4 snapshot:
Then, mount the filesystem and delete the old ext4 snapshot:
Ligne 81 : Ligne 81 :
  btrfs balance start /mnt # could take hours
  btrfs balance start /mnt # could take hours


== Promote as root filesystem ==
=== Promote as root filesystem ===


:''Mostly from [https://help.ubuntu.com/community/btrfs#Install_as_Root_on_earlier_Ubuntu_versions]''
:''Mostly from [https://help.ubuntu.com/community/btrfs#Install_as_Root_on_earlier_Ubuntu_versions]''


Enter the chrooted system:
Edit the /etc/fstab of the btrfs system:
uuid=`blkid|grep -P '^/dev/xvdb1: '|grep -o -P ' UUID="[0-9a-f-]+" '|cut -d'"' -f2`
sed -i -E 's/^UUID=[0-9a-f-]+ *\/ .*$/UUID=$uid \/              btrfs    defaults 0      1/' /mnt/etc/fstab
 
Update Grub in a chrooted system:
  for i in dev dev/pts proc sys; do mount --bind /$i /mnt/$i; done
  for i in dev dev/pts proc sys; do mount --bind /$i /mnt/$i; done
  chroot /mnt
  chroot /mnt update-grub
  blkid|grep xvdb1
  for i in dev/pts dev proc sys; do umount /mnt/$i; done
  vi /etc/fstab
umount /mnt
 
Quit:
exit
 
=== Define the cooked disk as boot disk ===
 
In Gandi V5 interface, stop the server, detach the old root disk and define the cooked disk as "Use to start".
 
Launch the server (it should correctly start, even if the /boot directory is on the main partition / (some old documents said it didn’t work because grub didn’t know the btrfs filesystem, but it is fixed now)).
 
df -hT
 
It should show something like:
/dev/xvda1    btrfs      50G  32G  19G  63% /
 
Delete the old root disk.
 
You can delete the packages grub-efi-amd64, grub-efi-amd64-bin, grub-pc, grub-pc-bin since they are not used, but keep /etc/default/grub with Gandi customisations:
  cp -a /etc/default/grub /root/grub
apt-get purge -y grub-efi-amd64 grub-efi-amd64-bin grub-pc grub-pc-bin
mv /root/grub /etc/default/grub
apt-mark manual grub-common grub2-common
update-grub # to check it still work and you should reboot now to be sure it reboots correctly
 
== Scripted procedure ==
 
This script automates the conversion, with a slightly-modified procedure.
 
On [https://admin.gandi.net GandiV5], create a new server with e.g. 1 proc, 256 MiB RAM, 1 system disk of 5 GiB, Debian 11 bullseye.


Edit the root filesystem with: (the UUID is from the command blkid)
On GandiV5 :
UUID=a74f5787-aee1-4981-b7e6-fbd3cb6ac919 /              btrfs    defaults 0      1
# stop the server,
# open the page about the system disk in Volumes,
# clone the system disk with another (definitive) name (e.g. the current disk is "sys-myserver", you can define the copied disk as "myserver"),
# start the server,
# wait until the server is started,
# attach this cloned disk to the server.


(in vi, type "dd" to remove a line, "i" to enter in edit mode, Esc to quit edit mode, ":x" to save and quit.)
ATTENTION: really start the server before attaching the cloned disk, else the root filesystem might be the cloned disk given they have the same UUID and /etc/fstab is using the UUID to select the root filesystem (it could be workarounded by setting /dev/xvda1 in /etc/fstab before stopin the server).


vi /etc/grub.d/00_header
# Launch this script as root: (<code>vi convert_gandiroot_to_btrfs.sh</code> + <code>chmod +x convert_gandiroot_to_btrfs.sh</code> + (<code>./convert_gandiroot_to_btrfs.sh</code>)
#: The script takes about 3 minutes to convert a 1.4 GiB disk.
<syntaxhighlight lang="shell">
#!/bin/sh


Comment the line:
set -e
#if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi


Update grub:
fs_type=`mount|grep -F ' on / '|grep -o -E ' type [a-z0-9]+ '|cut -d' ' -f3`
grub-install /dev/xvdb
blkid=`blkid|grep -F ' LABEL="gandiroot" '`
update-grub
nb_fs_gandiroot=`echo "$blkid"|cut -d: -f2-|uniq -c|tr -s ' '|cut -d' ' -f2`
if [ "$fs_type" != 'ext4' -o ! "$nb_fs_gandiroot" = 2 ]; then
    echo 'It is not possible to convert the disk. There should be two identical devices labeled "gandiroot" formatted in ext4'
    exit 2
fi
fs_gandiroot_ext4=`echo "$blkid"|head -n1|cut -d: -f1`
fs_gandiroot_btrfs=`echo "$blkid"|tail -n1|cut -d: -f1`


Quit:
echo
exit
echo "Current root filesystem: $fs_gandiroot_ext4 (ext4)"
for i in dev dev/pts proc sys; do umount /mnt/$i; done
echo "Future root filesystem: $fs_gandiroot_btrfs (currently ext4, will be btrfs)"
umount /mnt
 
exit
set -v
 
apt-get update
 
apt-get install -y btrfs-progs
 
fsck.ext4 -f "$fs_gandiroot_btrfs"
 
btrfs-convert -p "$fs_gandiroot_btrfs"
 
mount "$fs_gandiroot_btrfs" /mnt
 
btrfs subvolume delete -C /mnt/ext2_saved
 
btrfs filesystem defragment -r /mnt
 
btrfs balance start /mnt
 
new_uuid=`blkid|grep -P "^$fs_gandiroot_btrfs: "|grep -o -P ' UUID="[0-9a-f-]+" '|cut -d'"' -f2`
 
sed -i -E "s/^UUID=[0-9a-f-]+ *\/ .*$/UUID=$new_uuid \/              btrfs    defaults 0      1/" /mnt/etc/fstab
 
for i in dev dev/pts proc sys; do mount --bind /$i /mnt/$i; done
 
chroot /mnt update-grub
 
for i in dev/pts dev proc sys; do umount /mnt/$i; done


== Define the cooked disk as boot disk ==
umount /mnt


In Gandi V4 interface, stop the server, select the cooked disk as boot disk of this server (or detach the cooked disk and attach it as boot disk on another server).
</syntaxhighlight>


Launch the server (it should correctly start, even if the /boot directory is on the main partition / (some old documents said it didn’t work because grub didn’t know the btrfs filesystem, but it is fixed now)).
In Gandi V5 interface, stop the server, detach the old root disk and define the cooked disk as "Use to start".


Launch the server and execute:
  df -hT
  df -hT


It should show something like:
It should show something like:
  /dev/xvda1    btrfs      50G   32G   19G 63% /
  /dev/xvda1    btrfs      5G   1.4G   3.5G 28% /
 
Delete the old root disk.
 
== Troubleshootings ==
 
* During a conversion, the root filesystem was mounted read-only in btrfs; it was probably because I didn’t change the options "rw,noatime,errors=remount-ro" to "defaults"
 
== External links ==
 
* [https://wiki.xen.org/wiki/PvGrub2 PvGrub2 on Xen wiki]

Version actuelle datée du 15 juin 2023 à 17:48

I tried to have a root filesystem into btrfs for a Gandi server, and succeed after a number of trial-error. Here are my steps if it can be useful to others. For an introduction, see Wikipedia article and/or the dedicated wiki.

WARNING: this could cause DATA LOSS, be sure you have backups (possibly Gandi snapshots).

This was updated on 2020-09-24 for Debian 10 buster + GandiV5, and on 2022-02-02 for Debian 11 bullseye + GandiV5. An older version was for Debian 9 jessie or Ubuntu 18.04 LTS + GandiV4.

Manual procedure

Create the server

On GandiV5, create a new server with e.g. 1 proc, 256 MiB RAM, 1 system disk of 5 GiB, Debian 10 buster or Debian 11 bullseye.

For Debian 10 buster (only), define backports (btrfs-progs must contain btrfs-convert, see this Debian bug) (this is not needed for Debian 11):

echo 'deb https://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/debian-backports.list

Install btrfs-progs:

apt update && apt install -t buster-backports btrfs-progs # Debian 10 buster
apt update && apt install btrfs-progs # Debian 11 bullseye

On GandiV5 :

  1. stop the server,
  2. open the page about the system disk in Volumes,
  3. clone the system disk with another (definitive) name (e.g. the current disk is "sys-myserver", you can define the copied disk as "myserver"),
  4. start the server,
  5. wait until the server is started,
  6. attach this cloned disk to the server.

ATTENTION: really start the server before attaching the cloned disk, else the root filesystem might be the cloned disk given they have the same UUID and /etc/fstab is using the UUID to select the root filesystem (it could be workarounded by setting /dev/xvda1 in /etc/fstab before stopin the server).

Convert to btrfs

Mostly from [1]

Display the active root filesystem, and you will be able to deduce what is the cloned filesystem:

ls /dev/xvd*
mount|grep xvd
blkid

Copy the result of blkid in some text file on your computer (will be used later).

Let’s say /dev/xvdb1 is the clone filesystem, we convert it to btrfs: (man 8 btrfs-convert)

fsck.ext4 -f /dev/xvdb1 # optional
btrfs-convert -p /dev/xvdb1

Here, I obtained the following error:

root@test:~# btrfs-convert -p /dev/xvdb1
create btrfs filesystem:
	blocksize: 4096
	nodesize:  16384
	features:  extref, skinny-metadata (default)
creating ext2 image file
creating btrfs metadata
Unable to find block group for 0 27081]
Unable to find block group for 0
Unable to find block group for 0
ctree.c:2245: split_leaf: BUG_ON `1` triggered, value 1
btrfs-convert(+0x11b5a)[0x559c159c1b5a]
btrfs-convert(+0x1589b)[0x559c159c589b]
btrfs-convert(btrfs_search_slot+0x269)[0x559c159c6401]
btrfs-convert(btrfs_insert_empty_items+0x92)[0x559c159c7b3c]
btrfs-convert(btrfs_record_file_extent+0x1bc)[0x559c159d46b4]
btrfs-convert(record_file_blocks+0x14a)[0x559c159bfe92]
btrfs-convert(+0x10349)[0x559c159c0349]
btrfs-convert(+0x1135f)[0x559c159c135f]
btrfs-convert(main+0x1f59)[0x559c159bdefb]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7f4c11c3bb97]
btrfs-convert(_start+0x2a)[0x559c159bb5ca]
Aborted

According to [2] and [3], it can be worked around: (this command could take some hours, depending on disk size and number of files)

btrfs-convert -d -p /dev/xvdb1

or even:

btrfs-convert -n -d -p /dev/xvdb1

Or, if still unsuccessful, try to add free space, or if still unsuccessfull, re-compile btrfs-progs in version 4.17.1 (this last try worked for me for 50 Gio disk with 24 Gio free space on Debian 9 jessie, expanded after its original size was 30 Gio (=4 Gio free space)).

Then, mount the filesystem and delete the old ext4 snapshot:

mount /dev/xvdb1 /mnt
btrfs subvolume delete /mnt/ext2_saved
btrfs filesystem defrag -r /mnt # could take dozen of minuts
btrfs balance start /mnt # could take hours

Promote as root filesystem

Mostly from [4]

Edit the /etc/fstab of the btrfs system:

uuid=`blkid|grep -P '^/dev/xvdb1: '|grep -o -P ' UUID="[0-9a-f-]+" '|cut -d'"' -f2`
sed -i -E 's/^UUID=[0-9a-f-]+ *\/ .*$/UUID=$uid \/               btrfs    defaults 0       1/' /mnt/etc/fstab

Update Grub in a chrooted system:

for i in dev dev/pts proc sys; do mount --bind /$i /mnt/$i; done
chroot /mnt update-grub
for i in dev/pts dev proc sys; do umount /mnt/$i; done
umount /mnt

Quit:

exit

Define the cooked disk as boot disk

In Gandi V5 interface, stop the server, detach the old root disk and define the cooked disk as "Use to start".

Launch the server (it should correctly start, even if the /boot directory is on the main partition / (some old documents said it didn’t work because grub didn’t know the btrfs filesystem, but it is fixed now)).

df -hT

It should show something like:

/dev/xvda1     btrfs      50G   32G   19G  63% /

Delete the old root disk.

You can delete the packages grub-efi-amd64, grub-efi-amd64-bin, grub-pc, grub-pc-bin since they are not used, but keep /etc/default/grub with Gandi customisations:

cp -a /etc/default/grub /root/grub
apt-get purge -y grub-efi-amd64 grub-efi-amd64-bin grub-pc grub-pc-bin
mv /root/grub /etc/default/grub
apt-mark manual grub-common grub2-common
update-grub # to check it still work and you should reboot now to be sure it reboots correctly

Scripted procedure

This script automates the conversion, with a slightly-modified procedure.

On GandiV5, create a new server with e.g. 1 proc, 256 MiB RAM, 1 system disk of 5 GiB, Debian 11 bullseye.

On GandiV5 :

  1. stop the server,
  2. open the page about the system disk in Volumes,
  3. clone the system disk with another (definitive) name (e.g. the current disk is "sys-myserver", you can define the copied disk as "myserver"),
  4. start the server,
  5. wait until the server is started,
  6. attach this cloned disk to the server.

ATTENTION: really start the server before attaching the cloned disk, else the root filesystem might be the cloned disk given they have the same UUID and /etc/fstab is using the UUID to select the root filesystem (it could be workarounded by setting /dev/xvda1 in /etc/fstab before stopin the server).

  1. Launch this script as root: (vi convert_gandiroot_to_btrfs.sh + chmod +x convert_gandiroot_to_btrfs.sh + (./convert_gandiroot_to_btrfs.sh)
    The script takes about 3 minutes to convert a 1.4 GiB disk.
#!/bin/sh

set -e

fs_type=`mount|grep -F ' on / '|grep -o -E ' type [a-z0-9]+ '|cut -d' ' -f3`
blkid=`blkid|grep -F ' LABEL="gandiroot" '`
nb_fs_gandiroot=`echo "$blkid"|cut -d: -f2-|uniq -c|tr -s ' '|cut -d' ' -f2`
if [ "$fs_type" != 'ext4' -o ! "$nb_fs_gandiroot" = 2 ]; then
    echo 'It is not possible to convert the disk. There should be two identical devices labeled "gandiroot" formatted in ext4'
    exit 2
fi
fs_gandiroot_ext4=`echo "$blkid"|head -n1|cut -d: -f1`
fs_gandiroot_btrfs=`echo "$blkid"|tail -n1|cut -d: -f1`

echo
echo "Current root filesystem: $fs_gandiroot_ext4 (ext4)"
echo "Future root filesystem: $fs_gandiroot_btrfs (currently ext4, will be btrfs)"

set -v

apt-get update

apt-get install -y btrfs-progs

fsck.ext4 -f "$fs_gandiroot_btrfs"

btrfs-convert -p "$fs_gandiroot_btrfs"

mount "$fs_gandiroot_btrfs" /mnt

btrfs subvolume delete -C /mnt/ext2_saved

btrfs filesystem defragment -r /mnt

btrfs balance start /mnt

new_uuid=`blkid|grep -P "^$fs_gandiroot_btrfs: "|grep -o -P ' UUID="[0-9a-f-]+" '|cut -d'"' -f2`

sed -i -E "s/^UUID=[0-9a-f-]+ *\/ .*$/UUID=$new_uuid \/               btrfs    defaults 0       1/" /mnt/etc/fstab

for i in dev dev/pts proc sys; do mount --bind /$i /mnt/$i; done

chroot /mnt update-grub

for i in dev/pts dev proc sys; do umount /mnt/$i; done

umount /mnt

In Gandi V5 interface, stop the server, detach the old root disk and define the cooked disk as "Use to start".

Launch the server and execute:

df -hT

It should show something like:

/dev/xvda1     btrfs      5G   1.4G   3.5G  28% /

Delete the old root disk.

Troubleshootings

  • During a conversion, the root filesystem was mounted read-only in btrfs; it was probably because I didn’t change the options "rw,noatime,errors=remount-ro" to "defaults"

External links