# BTRFS

- [BTRFS](#btrfs)
  - [Naming Conventions](#naming-conventions)
  - [Creating an Array](#creating-an-array)
  - [Converting an Array Between RAID Versions](#converting-an-array-between-raid-versions)
  - [Mounting the Array](#mounting-the-array)
  - [Adding Disks](#adding-disks)
  - [Replacing a Disk](#replacing-a-disk)
  - [Scrubbing the Array](#scrubbing-the-array)
  - [Creating Subvolumes](#creating-subvolumes)
  - [Monitoring Usage](#monitoring-usage)
  - [Monitoring Disk Health](#monitoring-disk-health)
  - [Defragmenting and Compressing](#defragmenting-and-compressing)
  - [Converting ext4 to btrfs](#converting-ext4-to-btrfs)
  - [Error Kata](#error-kata)

Oracle [has decent docs here](https://docs.oracle.com/en/operating-systems/oracle-linux/8/btrfs/btrfs-ResizingaBtrfsFileSystem.html)

You'll also want to [read about btrfs compression](https://thelinuxcode.com/enable-btrfs-filesystem-compression/)

## Naming Conventions

`poolX` is my naming convention for data pools. `pool0` is the first pool you create.

`backupX` is my naming convention for backup pools. `backup0` is hte first backup pool you create. 

## Creating an Array

```bash
# At any point you can check the status of an array by referencing any member
btrfs filesystem show /dev/vdb
```

```bash
# Raid0
mkfs.btrfs --data raid0 --metadata raid0 /dev/vdb /dev/vdc
btrfs device scan

# Raid1
mkfs.btrfs --data raid1 --metadata raid1 /dev/vdb /dev/vdc
btrfs device scan

# Raid1c3
mkfs.btrfs --data raid1c3 --metadata raid1c3 /dev/vdb /dev/vdc /dev/vdd
btrfs device scan

# Raid10
mkfs.btrfs --data raid10 --metadata raid10 /dev/vdb /dev/vdc /dev/vdd /dev/vde
btrfs device scan
```

Label your arrays for easier identification in btrfs filesystem information commands

```bash
btrfs filesystem label /btrfs/pool0 pool0
```

## Converting an Array Between RAID Versions

```bash
# Convert to raid1
# -dconvert == "data convert"
# -mconvert == "metadata convert"
btrfs balance start -dconvert=raid1 -mconvert=raid1 /btrfs/pool0
btrfs balance status
```

## Mounting the Array

One off

```bash
# Create a mount point
mkdir /btrfs/pool0

# List the filesystem UUID
lsblk --fs

# Mount the top level subvolume
mount UUID=xxxxx-xxxxx-xxxxx /btrfs/pool0 -o subvolid=5

# Mount with better SSD support
mount UUID=xxxxx-xxxxx-xxxxx /btrfs/pool0 -o subvolid=5,ssd

# Mount with auto defragmentation for HDD support
mount UUID=xxxxx-xxxxx-xxxxx /btrfs/pool0 -o subvolid=5,autodefrag

# Mount a subvolume
mount UUID=xxxxx-xxxxx-xxxxx /btrfs/pool0 -o subvol=home

# Inspect
btrfs filesystem show /btrfs/pool0
```

In fstab

```conf
UUID=btrfs_uuid  /btrfs/pool0  btrfs  defaults 0 0
```

## Adding Disks

```bash
# Add a disk
btrfs device add /dev/vdd /btrfs/pool0

# Balance the array
btrfs balance start /btrfs/pool0

# Watch the expansion
btrfs filesystem usage /btrfs/pool0
```

## Replacing a Disk

```bash
# Remove a disk from the array
# This may take a while, as btrfs will rebalance the array during this process
btrfs device remove /dev/vdb /btrfs/pool0

# You can watch the device "used" data drain with
watch btrfs filesystem show /btrfs/pool0/

# Add the new device
# Again, this may take a while while btrfs rebalances.
btrfs device add /dev/vdg /btrfs/pool0
```

## Scrubbing the Array

```bash
# Start a scrub to check for errors
# -B prevents the process from going to the background
# -d prints stats for each device
btrfs scrub start -Bd /btrfs/pool0

# Check the status of a scrub
btrfs scrub status /btrfs/pool0

# Watch for disk failures
dmesg | grep btrfs
```

## Creating Subvolumes

```bash
# Create a new subvolume (make sure to mount /btrfs as subvolid=5)
btrfs subvolume create /btrfs/pool0

# List all subvolumes under a path
btrfs subvolume list -o /btrfs/pool0

# Delete a subvolume
btrfs subvolume delete /btrfs/pool0
```

## Monitoring Usage

```bash
# Quick info for all btrfs arrays
btrfs filesystem show

# Show usage for a specific array
btrfs filesystem usage /btrfs/pool0

# Quick command to filter for data used
btrfs filesystem usage /btrfs/pool0 | grep 'Data.*Used'
```

## Monitoring Disk Health

<https://www.dotlinux.net/blog/how-to-configure-smartd-and-be-notified-of-hard-disk-problems-via-email/#installing-smartd-smartmontools>

```bash
# btrfs device stats shows any errors
# Grep for any line not ending in "0"
btrfs device stats /btrfs/pool0 | grep -vE ' 0$'

# Show the device IDs for the mounted filesystem
btrfs filesystem show /btrfs/pool0

# Delete a device (with ID 8, for example)
btrfs device delete 8 /btrfs/pool0

# Add a device to the array
btrfs device add /dev/vdi1 /btrfs/pool0

# Rebalance the array
btrfs balance start --background --full-balance /btrfs/pool0

# Check the status
btrfs balance status /btrfs/pool0
```

## Defragmenting and Compressing

```bash
# Defrag a filesystem
btrfs filesystem defragment /btrfs/pool0

# Defrag and apply compression
# zstd:20 is currently the best compression algorithm
btrfs filesystem defragment -c zstd:20 /btrfs/pool0
```

## Converting ext4 to btrfs

```bash
# Unmount and then run btrfs-convert
umount /path/to/mount
btrfs-convert /dev/sdX1
```

## Error Kata

After unplanned shutdowns, power loss, physically moving the server, or whenever
you feel like it, it's generally a good idea to scrub your btrfs pools for
errors and check your device stats.

```bash
export POOL=pool1
# Find any device stat with a number > 0
# This means there's an error
btrfs device stats /btrfs/${POOL} | grep -vE ' 0$'

# If you find an error, grab the smartctl details to check for disk error
# Scrub the btrfs pool to check for other hidden errors
lsblk -fs
smartctl -a /dev/<dev>
btrfs scrub start -Bd /btrfs/pool0
btrfs scrub status /btrfs/${POOL}

# Check the filesystem status after a scrub 
btrfs filesystem show /btrfs/${POOL}
```
