[LTP] [PATCH] [dynamic debug] - Check interface and functionality

Cyril Hrubis chrubis@suse.cz
Tue Aug 22 15:09:53 CEST 2017


Hi!
> +# Test description: Test functionality of dynamic debug feature by enabling
> +#                   and disabling traces with available flags. Check that these
> +#                   settings don't cause issues by searching dmesg.
> +#
> +#                   This test handles changes of dynamic debug interface from
> +#                   commits 5ca7d2a6 (dynamic_debug: describe_flags with
> +#                   '=[pmflt_]*') and 8ba6ebf5 (Dynamic debug: Add more flags)
> +#
> +# Usage
> +# ./dynamic_debug01.sh
> +
> +TST_TESTFUNC=ddebug_test
> +TST_NEEDS_CMDS="awk"
> +TST_NEEDS_TMPDIR=1
> +TST_NEEDS_ROOT=1
> +TST_SETUP=setup
> +TST_CLEANUP=cleanup
> +
> +. tst_test.sh
> +
> +
> +DEBUGFS_WAS_MOUNTED=0
> +DEBUGFS_PATH=""
> +DEBUGFS_CONTROL=""
> +DYNDEBUG_STATEMENTS="./debug_statements"
> +EMPTY_FLAG=""
> +NEW_INTERFACE=0
> +
> +
> +mount_debugfs()
> +{
> +	if grep -q debugfs /proc/mounts ; then
> +		DEBUGFS_WAS_MOUNTED=1
> +		DEBUGFS_PATH=$(grep debugfs /proc/mounts | awk '{print $2}')
                                    ^
				  $(awk /debugfs/ '{print $2}' /proc/mounts)


> +		tst_res TINFO "debugfs already mounted at $DEBUGFS_PATH"
> +	else
> +		if ! grep -q debugfs /proc/filesystems ; then
> +			tst_res TCONF "debugfs not supported"
> +		fi
> +		DEBUGFS_PATH="$(pwd)/tst_debug"
                                  ^
				$PWD/tst_debug

Or we may as well use relative path i.e. just ./tst_debugfs/

> +		mkdir "$DEBUGFS_PATH"
> +		if mount -t debugfs xxx "$DEBUGFS_PATH" ; then
> +			tst_res TINFO "debugfs mounted at $DEBUGFS_PATH"
> +		else
> +			tst_res TFAIL "Unable to mount debugfs"
> +		fi
> +	fi
> +}
> +
> +setup()
> +{
> +	if tst_kvcmp -lt 2.6.30 ; then
> +		tst_brk TCONF "Dynamic debug is available since version 2.6.30"
> +	fi
> +
> +	mount_debugfs
> +	if [ ! -d "$DEBUGFS_PATH/dynamic_debug" ] ; then
> +		tst_res TBROK "Unable to find $DEBUGFS_PATH/dynamic_debug"
                ^
		tst_brk?
> +	fi
> +	DEBUGFS_CONTROL="$DEBUGFS_PATH/dynamic_debug/control"
> +	if [ ! -e "$DEBUGFS_CONTROL" ] ; then
> +		tst_res TBROK "Unable to find $DEBUGFS_CONTROL"
                ^
		here as well?
> +	fi
> +
> +	# Both patches with changes were backported to RHEL6 kernel 2.6.32-547
> +	if tst_kvcmp -ge '3.4 RHEL6:2.6.32-547' ; then
> +		NEW_INTERFACE=1
> +	fi
> +
> +	EMPTY_FLAG=$([ $NEW_INTERFACE -eq 1 ] && echo "=_" || echo "-")

Now, why don't we set empty flag to the old value on the top and set it
to the new value in the if that sets the NEW_INTERFACE variable.

We could even use the EMPTY_FLAG content in the conditions below, but I
guess that having NEW_INTERFACE variable is more readable.

> +	grep -v "^#" "$DEBUGFS_CONTROL" > "$DYNDEBUG_STATEMENTS"
> +}
> +
> +do_flag()
> +{
> +	FLAG="$1"
> +	OPTION_TO_SET="$2"
> +	OPTION_VALUE="$3"

It would be a sligtly better to declare these variables as local.

> +	if ! echo "$OPTION_TO_SET $OPTION_VALUE $FLAG" > \
> +		"$DEBUGFS_CONTROL" ; then
> +		tst_res TFAIL "Setting '$OPTION_TO_SET $OPTION_VALUE " \
> +			"$FLAG' failed with $?!"
> +	fi

We do have EXPECT_PASS and EXPECT_FAIL functions in the test library:

https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#expect_pass-and-expect_fail

> +}
> +
> +do_all_flags()
> +{
> +	OPTION="$1"
> +	ALL_INPUTS="$2"
> +
> +	echo "$ALL_INPUTS" | while read -r INPUT_LINE ; do

You can do just for input_line in $ALL_INPUTS; do here instead, the
newlines were converted to spaces once the output from the awk/sort/uniq
pipeline was assigned into a variable.

> +		do_flag "+p" "$OPTION" "$INPUT_LINE"
> +		if tst_kvcmp -ge 3.2 || [ $NEW_INTERFACE -eq 1 ] ; then
> +			do_flag "+flmt" "$OPTION" "$INPUT_LINE"
> +			do_flag "-flmt" "$OPTION" "$INPUT_LINE"
> +		fi
> +		do_flag "-p" "$OPTION" "$INPUT_LINE"
> +	done
> +
> +	if awk -v emp="$EMPTY_FLAG" '$3 != emp' "$DEBUGFS_CONTROL" \
> +		| grep -v -q "^#" ; then
> +		tst_res TFAIL "Failed to remove all set flags"
> +	fi
> +
> +}
> +
> +ddebug_test()
> +{
> +	dmesg > ./dmesg.old
> +
> +	DD_FUNCS=$(awk -F " |]" '{print $3}' "$DYNDEBUG_STATEMENTS" \
> +		| sort | uniq)
> +	DD_FILES=$(awk -F " |:" '{print $1}' "$DYNDEBUG_STATEMENTS" \
> +		| sort | uniq)
> +	DD_LINES=$(awk -F " |:" '{print $2}' "$DYNDEBUG_STATEMENTS" \
> +		| sort | uniq)
> +	DD_MODULES=$(awk -F [][] '{print $2}' "$DYNDEBUG_STATEMENTS" \
> +		| sort | uniq)
> +
> +	do_all_flags "func" "$DD_FUNCS"
> +	do_all_flags "file" "$DD_FILES"
> +	do_all_flags "line" "$DD_LINES"
> +	do_all_flags "module" "$DD_MODULES"
> +
> +	dmesg > ./dmesg.new
> +	sed -i -e 1,`wc -l < ./dmesg.old`d ./dmesg.new
> +	if grep -q -e "Kernel panic" -e "Oops" -e "general protection fault" \
> +		-e "general protection handler: wrong gs" -e "\(XEN\) Panic" \
> +		-e "fault" -e "warn" -e "BUG" ./dmesg.new ; then
> +		tst_res TFAIL "Issues found in dmesg!"
> +	else
> +		tst_res TPASS "Dynamic debug OK"
> +	fi
> +}
> +
> +cleanup()
> +{
> +	if [ $DEBUGFS_WAS_MOUNTED -eq 0 ] ; then
> +		tst_umount "$DEBUGFS_PATH"
> +	else
> +		FLAGS_SET=$(awk -v emp="$EMPTY_FLAG" '$3 != emp' \
> +			$DYNDEBUG_STATEMENTS)
> +		if [ "$FLAGS_SET" ] ; then
> +			FLAG_PREFIX=$([ $NEW_INTERFACE -eq 1 ] \
> +				&& echo "" || echo "+")
> +			echo "$FLAGS_SET" | while read -r FLAG_LINE ; do
> +				echo -n "$FLAG_LINE" \
> +					| awk -v prf="$FLAG_PREFIX" -F " |:" \
> +					'{print "file "$1" line "$2" "prf $4}' \
> +					> "$DEBUGFS_CONTROL"
> +			done
> +		fi
> +	fi

I wonder if we should attempt to restore the values even if debugfs
wasn't mounted and then umount it if it wasn't mounted once we are done.

On my machine I have 45 values set to =p by default, although debugfs is
mounted there...

> +}
> +
> +tst_run

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list