mbox series

[0/2,V10] btrfs-progs: allocation_hint disk property

Message ID cover.1641491043.git.kreijack@inwind.it (mailing list archive)
Headers show
Series btrfs-progs: allocation_hint disk property | expand

Message

Goffredo Baroncelli Jan. 6, 2022, 5:49 p.m. UTC
From: Goffredo Baroncelli <kreijack@inwind.it>

This patches set is the userspace portion of the serie
"[PATCH V10] btrfs: allocation_hint mode".

Look this patches set for further information.

G.Baroncelli

Goffredo Baroncelli (2):
  btrfs-progs: new "allocation_hint" property.
  Update man page for allocator_hint property.

 Documentation/btrfs-property.asciidoc |  17 +++
 cmds/property.c                       | 202 ++++++++++++++++++++++++++
 kernel-shared/ctree.h                 |  13 ++
 3 files changed, 232 insertions(+)

Comments

Goffredo Baroncelli Jan. 6, 2022, 5:52 p.m. UTC | #1
Below the script that I use to test this patch

----
#!/bin/bash

#size of disk, smaller -> faster
MAXSIZE=$((1*1024*1024*1024))
MNT=mnt
BTRFS=./btrfs-hint
UUID=292afefb-6e8c-4fb3-9d12-8c4ecb1f237c

cleanup_all() {
	while losetup | egrep loop; do
		umount $MNT
		losetup -D
		sleep 1s
	done
}

raise() {
	echo 1>&2 "$@"
	exit 100
}

xmount() {
	mount -o allocation_hint=1 "$1" "$2"
	#mount  "$1" "$2"
}

create_loops() {
	[ -n "$1" ] || {
		raise "Create_loops, missing an argument"
	}

	cleanup_all
	
	size=$MAXSIZE
	[ -n "$2" ] && size=$2
	ret=""
	for i in $(seq "$1"); do
		disk=disk-$i.img
		rm -rf $disk
		truncate -s $size $disk
		losetup /dev/loop$i $disk
		ret="$ret /dev/loop$i"
	done

	echo "$ret"
}


fill_1_file() {
	fn=$MNT/giant-file-$1
	if [ -n "$2" ]; then
		size=count=$(($2 / 16 / 1024 / 1024 ))
	else
		size=
	fi
	dd if=/dev/zero of=$fn bs=16M oflag=direct $size
	ls -l $fn | awk '{ print $5 }'
}

dump_bg_data() {
	$BTRFS fi us -b $MNT | awk '
		/^$/    { flag=0 }
		        { if(flag) print $0 }
		/^Data/ { flag=1 }
	'
}

dump_bg_metadata() {
	$BTRFS fi us -b $MNT | awk '
		/^$/        { flag=0 }
		            { if(flag) print $0 }
		/^Metadata/ { flag=1 }
	'
}

# check if a disk conrain data and/or metadata
check_data_bg() {
	res=$(dump_bg_data)
	while [ -n "$1" ]; do
		if ! echo $res | egrep -q $1 ; then
			btrfs fil us $MNT
			raise "Data BG should contains $1"
		fi
		shift
	done
}

check_data_not_bg() {
	res=$(dump_bg_data)
	while [ -n "$1" ]; do
		if echo $res | egrep -q $1 ; then
			btrfs fil us $MNT
			raise "Data BG should not contains $1"
		fi
		shift
	done
}

check_metadata_bg() {
	res=$(dump_bg_metadata)
	while [ -n "$1" ]; do
		if ! echo $res | egrep -q $1 ; then
			btrfs fil us $MNT
			raise "Metadata BG should contains $1"
		fi
		shift
	done
}

check_metadata_not_bg() {
	res=$(dump_bg_metadata)
	while [ -n "$1" ]; do
		if echo $res | egrep -q $1 ; then
			btrfs fil us $MNT
			raise "Metadata BG should not contains $1"
		fi
		shift
	done
}


test_default_raid1() {
	loops=$(create_loops 4)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	loop2=$(echo $loops | awk '{ print $3 }')
	loop3=$(echo $loops | awk '{ print $4 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -draid1 -mraid1 $loops
	xmount $loop0 $MNT
	
	size=$(fill_1_file x $(($MAXSIZE / 2)) )

	check_data_bg $loop0 $loop1 $loop2 $loop3
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 || raise "Data BG should contains $loop0"
	#echo $res | egrep $loop1 || raise "Data BG should contains $loop1"
	#echo $res | egrep $loop2 || raise "Data BG should contains $loop2"
	#echo $res | egrep $loop3 || raise "Data BG should contains $loop3"

	size1=$(fill_1_file y )

	size=$(($size + $size1))

	[ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] || raise "File too small: check mnt/"
	[ $size -lt $(($MAXSIZE * 2 * 3 / 2 )) ] || raise "File too big: check mnt/"

	cleanup_all
}

test_default_single() {
	loops=$(create_loops 2)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -dsingle -msingle $loops
	xmount $loop0 $MNT
	
	size=$(fill_1_file x $(($MAXSIZE / 2)) )

	check_data_bg $loop0 $loop1
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 || raise "Data BG should contains $loop0"
	#echo $res | egrep $loop1 || raise "Data BG should contains $loop1"

	size1=$(fill_1_file y )

	size=$(($size + $size1))

	[ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] || raise "File too small: check mnt/"
	[ $size -lt $(($MAXSIZE * 2 * 3 / 2 )) ] || raise "File too big: check mnt/"

	cleanup_all
}

test_single_preferred_data() {
	loops=$(create_loops 2)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -dsingle -msingle $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop1 allocation_hint DATA_PREFERRED
	
	$BTRFS balance start --full-balance $MNT

	size=$(fill_1_file x $(($MAXSIZE / 2)) )

	check_data_bg $loop1
	check_data_not_bg $loop0
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop3"

	cleanup_all
}

test_single_preferred_metadata_slow() {
	loops=$(create_loops 2)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -dsingle -msingle $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop1 allocation_hint DATA_PREFERRED
	
	$BTRFS balance start --full-balance $MNT

	fnsize=2048
	for i in $(seq $(( $MAXSIZE / $fnsize * 700 / 1000))); do
		dd if=/dev/zero of=$MNT/fn-$i bs=$fnsize count=1
	done

	#BTRFS fi us $MNT

	check_metadata_bg  $loop0
	check_metadata_not_bg  $loop1
	#res=$(dump_bg_metadata)
	#echo $res | egrep $loop0 &>/dev/null || raise "Metadata BG should contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null && raise "Metadata BG should not contains $loop3"

	cleanup_all
}



test_raid1_preferred_data() {
	loops=$(create_loops 4)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	loop2=$(echo $loops | awk '{ print $3 }')
	loop3=$(echo $loops | awk '{ print $4 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -draid1 -mraid1 $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop1 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop2 allocation_hint DATA_PREFERRED
	$BTRFS prop set $loop3 allocation_hint DATA_PREFERRED
	
	$BTRFS balance start --full-balance $MNT

	size=$(fill_1_file x $(($MAXSIZE / 2)) )

	check_data_bg  $loop2 $loop3
	check_data_not_bg $loop0 $loop1
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not contains $loop1"
	#echo $res | egrep $loop2 &>/dev/null || raise "Data BG should contains $loop2"
	#echo $res | egrep $loop3 &>/dev/null || raise "Data BG should contains $loop3"

	cleanup_all
}

test_raid1_preferred_metadata_slow() {
	loops=$(create_loops 4)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	loop2=$(echo $loops | awk '{ print $3 }')
	loop3=$(echo $loops | awk '{ print $4 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -draid1 -mraid1 $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop1 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop2 allocation_hint DATA_PREFERRED
	$BTRFS prop set $loop3 allocation_hint DATA_PREFERRED
	
	$BTRFS balance start --full-balance $MNT

	fnsize=2048
	for i in $(seq $(( $MAXSIZE / $fnsize * 700 / 1000))); do
		dd if=/dev/zero of=$MNT/fn-$i bs=$fnsize count=1
	done

	#BTRFS fi us $MNT

	check_metadata_bg $loop0 $loop1
	check_metadata_not_bg $loop2 $loop3
	#res=$(dump_bg_metadata)
	#echo $res | egrep $loop0 &>/dev/null || raise "Metadata BG should contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null || raise "Metadata BG should contains $loop1"
	#echo $res | egrep $loop2 &>/dev/null && raise "Metadata BG should not contains $loop2"
	#echo $res | egrep $loop3 &>/dev/null && raise "Metadata BG should not contains $loop3"

	cleanup_all
}

test_raid1_data_only() {
	loops=$(create_loops 4)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	loop2=$(echo $loops | awk '{ print $3 }')
	loop3=$(echo $loops | awk '{ print $4 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -draid1 -mraid1 $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_ONLY
	$BTRFS prop set $loop1 allocation_hint METADATA_ONLY
	$BTRFS prop set $loop2 allocation_hint DATA_ONLY
	$BTRFS prop set $loop3 allocation_hint DATA_ONLY
	
	$BTRFS balance start --full-balance $MNT

	size=$(fill_1_file x  )

	[ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] && raise "File too big: check mnt/"
	[ $size -lt $(($MAXSIZE * 2 / 3 )) ] && raise "File too small: check mnt/"

	check_data_bg $loop2 $loop3
	check_data_not_bg $loop0 $loop1
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not contains $loop1"
	#echo $res | egrep $loop2 &>/dev/null || raise "Data BG should contains $loop2"
	#echo $res | egrep $loop3 &>/dev/null || raise "Data BG should contains $loop3"

	cleanup_all
}

test_single_data_only() {
	loops=$(create_loops 2)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -dsingle -msingle $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_ONLY
	$BTRFS prop set $loop1 allocation_hint DATA_ONLY
	
	$BTRFS balance start --full-balance $MNT

	size=$(fill_1_file x  )

	[ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] && raise "File too big: check mnt/"
	[ $size -lt $(($MAXSIZE * 2 / 3 )) ] && raise "File too small: check mnt/"

	check_data_bg $loop1
	check_data_not_bg $loop0
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop3"

	cleanup_all
}


test_single_data_bouncing() {
	loops=$(create_loops 2)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -dsingle -msingle $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_ONLY
	$BTRFS prop set $loop1 allocation_hint DATA_ONLY
	
	$BTRFS balance start --full-balance $MNT

	size=$(fill_1_file x  $(($MAXSIZE * 2 / 4 )))

	[ $size -gt $(($MAXSIZE * 2 / 3 )) ] && raise "File too big: check mnt/"
	[ $size -lt $(($MAXSIZE * 1 / 3 )) ] && raise "File too small: check mnt/"

	check_data_bg $loop1
	check_data_not_bg $loop0
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop1"

	$BTRFS balance start --full-balance $MNT

	check_data_bg $loop1
	check_data_not_bg $loop0
	#res=$(dump_bg_data)
	#echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0"
	#echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop1"


	$BTRFS prop set $loop1 allocation_hint METADATA_ONLY
	$BTRFS prop set $loop0 allocation_hint DATA_ONLY

	$BTRFS balance start --full-balance $MNT

	check_data_bg $loop0
	check_data_not_bg $loop1
	#res=$(dump_bg_data)
	#echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not contains $loop1"
	#echo $res | egrep $loop0 &>/dev/null || raise "Data BG should contains $loop0"
	cleanup_all
}

test_single_progressive_fill_data() {

	xsize=$MAXSIZE

	loops=$(create_loops 4 $xsize)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	loop2=$(echo $loops | awk '{ print $3 }')
	loop3=$(echo $loops | awk '{ print $4 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -dsingle -msingle $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_ONLY
	$BTRFS prop set $loop1 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop2 allocation_hint DATA_PREFERRED
	$BTRFS prop set $loop3 allocation_hint DATA_ONLY
	$BTRFS balance start --full-balance $MNT	
	
	# fill $loop3
	
	size=$(fill_1_file x  $(( $xsize / 3 )))

	for i in 1 2 3; do
		check_data_bg $loop3
		check_data_not_bg $loop1 $loop2 $loop0
		$BTRFS balance start --full-balance $MNT
	done
		
	# fill $loop3 then $loop2

     	size=$(fill_1_file y  $(( $xsize )))

	for i in 1 2 3; do
		check_data_bg $loop3 $loop2
		check_data_not_bg $loop1 $loop0
		$BTRFS balance start --full-balance $MNT
	done
		
	# fill $loop3 then $loop2, then $loop1

     	size=$(fill_1_file z  $(( $xsize )))

	for i in 1 2 3; do
		check_data_bg $loop3 $loop2 $loop1
		check_data_not_bg $loop0
		$BTRFS balance start --full-balance $MNT
	done

	# fill the disk

     	size=$(fill_1_file w  )

	# when the disk is filled not balance is possible
	check_data_bg $loop3 $loop2 $loop1
	check_data_not_bg $loop0

	cleanup_all
}

test_raid1_progressive_fill_data() {

	xsize=$MAXSIZE

	loops=$(create_loops 5 $xsize)
	loop0=$(echo $loops | awk '{ print $1 }')
	loop1=$(echo $loops | awk '{ print $2 }')
	loop2=$(echo $loops | awk '{ print $3 }')
	loop3=$(echo $loops | awk '{ print $4 }')
	loop4=$(echo $loops | awk '{ print $5 }')
	$BTRFS dev scan -u
	mkfs.btrfs -U $UUID -dRAID1 -msingle $loops
	xmount $loop0 $MNT

	$BTRFS prop set $loop0 allocation_hint METADATA_ONLY
	$BTRFS prop set $loop1 allocation_hint METADATA_PREFERRED
	$BTRFS prop set $loop2 allocation_hint DATA_PREFERRED
	$BTRFS prop set $loop3 allocation_hint DATA_ONLY
	$BTRFS prop set $loop4 allocation_hint DATA_ONLY
	$BTRFS balance start --full-balance $MNT	
	
	# fill $loop3 $loop4
	
	size=$(fill_1_file x  $(( $xsize / 6 )))

	for i in 1 2 3; do
		check_data_bg $loop3 $loop4
		check_data_not_bg $loop1 $loop0 $loop2
		$BTRFS balance start --full-balance $MNT
	done
		
	# fill $loop3, $loop4 then $loop2, $loop1

     	size=$(fill_1_file y  $(( $xsize )))

	for i in 1 2 3; do
		check_data_bg $loop3 $loop2 $loop1 $loop4
		check_data_not_bg  $loop0
		$BTRFS balance start --full-balance $MNT
	done
		
	cleanup_all
}



SETV=""
SETX=""

while true; do
	if [ "$1" = "-x" ]; then
		SETX="set -x"
		shift
	elif [ "$1" = "-v" ]; then
		SETV="-v"
		shift
	elif [ "$1" = "--list" ]; then
		declare -F | awk '{ print $3 }' | egrep ^test_ | sort
		exit
     elif [ "$1" = "cleanup" ]; then
	    cleanup_all

	    exit
     elif [ "$1" = "makeraid1" ]; then
	    loops=$(create_loops 4)
	    loop0=$(echo $loops | awk '{ print $1 }')
	    mkfs.btrfs -U $UUID -draid1 -mraid1 $loops
	    xmount $loop0 $MNT

	    exit
	else
		break
	fi
done

cleanup_all &>/dev/null
cleanup_all &>/dev/null

ARG="$1"

$SETX

[ -z "$ARG" ] && ARG="."
declare -F | awk '{ print $3 }' | egrep ^test_ | sort |
	egrep $SETV "$ARG" | while read func; do

	echo -n "TEST '$func' "
	(
		$SETX
		$func >.out.log 2>.err.log
	)|| raise "Error !!!; read .out.log, .err.log"
	echo "OK"
done

----