Whamcloud - gitweb
LU-16661 build: improve lustre.spec.in Requires 97/50397/14
authorAndreas Dilger <adilger@whamcloud.com>
Fri, 24 Mar 2023 02:31:59 +0000 (20:31 -0600)
committerOleg Drokin <green@whamcloud.com>
Wed, 26 Apr 2023 06:27:23 +0000 (06:27 +0000)
Add Suggests: bash-completion for lustre-client and lustre for
lctl and lfs sub-command completion.

Move perl from Requires to Recommends, since there are only some
uncommonly used tools (llstat, llobdstat) that are using perl.
Remove a couple of ancient obsolete test scripts that used perl.

lustre-iokit incorrectly Required perl instead of python3.

Set minimum kernel version for client to be 3.10 or later.

Change "netstat" to "ss" in tests to avoid dependency issues.
Fix sanity.sh and conf-sanity.sh tests for sles12sp5 issues.

Test-Parameters: trivial testlist=runtests clientdistro=sles12sp5
Test-Parameters: trivial testlist=runtests clientdistro=el9.1
Test-Parameters: trivial testlist=runtests clientdistro=sles15sp3
Fixes: 7521473bdd ("LU-16382 spec: add more dependencies for lustre-tests")
Fixes: fd734cffb3 ("b=18443 tests: remove obsolete tests scripts")
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Change-Id: I48c6819596c81cb044e983bc64f1edf1ee3ebbe5
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50397
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Arshad Hussain <arshad.hussain@aeoncomputing.com>
Reviewed-by: xinliang <xinliang.liu@linaro.org>
Reviewed-by: Alex Deiter <alex.deiter@gmail.com>
lustre-dkms.spec.in
lustre.spec.in
lustre/tests/conf-sanity.sh
lustre/tests/create.pl [deleted file]
lustre/tests/rename.pl [deleted file]
lustre/tests/sanity.sh

index 77b01b8..878b472 100644 (file)
@@ -102,8 +102,14 @@ Conflicts: @PACKAGE@-dkms
 Conflicts:     @PACKAGE@-all-dkms
 %endif
 %endif
-Requires:       gcc, make, perl
-Requires:       kernel-devel
+Requires:      gcc, make
+Requires:      kernel-devel >= 3.10
+%if 0%{?rhel} > 7 || 0%{?fedora} > 33 || 0%{?rhel} < 1
+Recommends:    perl
+Suggests:      bash-completion
+%else
+Requires:      perl
+%endif
 Provides:      %{kmod_name} = %{version}
 Provides:      @PACKAGE@-modules = %{version}
 %if %{with servers}
index 696aeca..aa0d2be 100644 (file)
@@ -223,6 +223,9 @@ BuildRequires: libtool pkgconfig(yaml-0.1) pkgconfig(zlib) pkgconfig(libnl-3.0)
 %if "%{_vendor}" == "redhat"
 BuildRequires: redhat-rpm-config
 BuildRequires: pkgconfig
+%if 0%{?rhel} > 7 || 0%{?fedora} > 33 || 0%{?rhel} < 1
+Suggests: bash-completion
+%endif
 %else
 %if "%{_vendor}" == "openEuler"
 BuildRequires: openEuler-rpm-config
@@ -273,7 +276,7 @@ BuildRequires: rpm-build >= 4.14.3
 %endif
 BuildRequires: %kernel_module_package_buildreqs
 # need to provide a /usr/lib/${uname -r)/build dir
-BuildRequires: kernel
+BuildRequires: kernel >= 3.10
 %if "%{_vendor}" == "redhat"
 %if %{with kabi}
 BuildRequires: kernel-abi-whitelists
@@ -403,11 +406,11 @@ Requires: %{requires_kmod_tests_name} = %{requires_kmod_version}
 %if %{with lustre_tests_lutf}
 Requires: python3 >= 3.6.0
 %endif
-Requires: attr, rsync, perl, lsof, /usr/bin/getconf
-Requires: /usr/sbin/getenforce, /usr/bin/netstat, acl, /usr/bin/killall, /usr/bin/ping, bc
+Requires: attr, rsync, lsof, /usr/bin/getconf
+Requires: /usr/sbin/getenforce, acl, /usr/bin/killall, /usr/bin/ping, bc
 # Of the supported targets, only rhel7 doesn't support Recommends.
-%if 0%{?rhel} > 7 || 0%{?rhel} < 1
-Recommends: dbench, iozone
+%if 0%{?rhel} > 7 || 0%{?fedora} > 33 || 0%{?rhel} < 1
+Recommends: perl, dbench, iozone
 # Either of these is sufficient
 Suggests: pdsh, clush
 %endif
@@ -438,7 +441,7 @@ to be used by the Lustre testing framework.
 %if %{with lustre_iokit}
 %package -n lustre-iokit
 Summary: Collection of benchmark tools for a cluster with the Lustre file system
-Requires: python3, sg3_utils
+Requires: perl, sg3_utils
 
 %description -n lustre-iokit
 This package includes five tools:
@@ -461,7 +464,7 @@ This script will collect IO stats on a defined set of nodes.
 
 ior-survey:
 A script to run the IOR benchmark. The latest version can be downloaded from
-http://www.llnl.gov/asci/purple/benchmarks/limited/ior/
+https://github.com/hpc/ior/
 
 mds-survey:
 This survey tests the local metadata performance using the echo_client to drive
index 187a90b..b0a8c10 100644 (file)
@@ -3452,8 +3452,8 @@ test_38() { # bug 14222
        do_facet $SINGLEMDS "od -Ax -td8 $mntpt/lov_objid"
        unmount_fstype $SINGLEMDS || error "umount failed (4)"
 
-       [ "$ERROR" = "y" ] &&
-               error "old and new files are different after sync" || true
+       [[ "$ERROR" != "y" ]] ||
+               error "old and new files are different after sync"
 
        log "files compared the same"
        cleanup || error "cleanup failed with $?"
@@ -3461,6 +3461,8 @@ test_38() { # bug 14222
 run_test 38 "MDS recreates missing lov_objid file from OST data"
 
 test_39() {
+       [[ -n "$(type -p perl)" ]] || skip_env "need perl for leak_finder.pl"
+
        PTLDEBUG=+malloc
        setup
        cleanup || error "cleanup failed with $?"
@@ -9513,7 +9515,7 @@ test_123aa() {
        [ -d $MOUNT/.lustre ] || setup
 
        # test old logid format until removal from llog_ioctl.c::str2logid()
-       if [ $MGS_VERSION -lt $(version_code 3.1.53) ]; then
+       if (( $MGS_VERSION < $(version_code 2.99.53) )); then
                do_facet mgs $LCTL dl | grep MGS
                do_facet mgs "$LCTL --device %MGS llog_print \
                              \\\\\\\$$FSNAME-client 1 10" ||
diff --git a/lustre/tests/create.pl b/lustre/tests/create.pl
deleted file mode 100644 (file)
index f740c18..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-#!/usr/bin/perl -w
-use strict;
-$|++;
-
-$ENV{PATH}="/bin:/usr/bin";
-$ENV{ENV}="";
-$ENV{BASH_ENV}="";
-use POSIX ":sys_wait_h";
-
-use diagnostics;
-use Getopt::Long;
-
-use vars qw(
-           $MAX_THREADS
-           $SCRIPT_NAME
-           );
-
-# Don't try to run more than this many threads concurrently.
-$MAX_THREADS = 16;
-
-$SCRIPT_NAME = "create.pl";
-
-# Initialize variables
-my $silent = 0;
-my $use_mcreate = 1; # should we use mcreate or open?
-my $num_files = 5;   # number of files to create
-my $iterations = 1;
-my $num_threads = 1;
-my $mountpt;
-my $num_mounts = -1;
-
-# Get options from the command line.
-GetOptions("silent!" => \$silent,
-           "use_mcreate=i" => \$use_mcreate,
-           "num_files=i" => \$num_files,
-          "mountpt=s" => \$mountpt,
-          "num_mounts=i" => \$num_mounts,
-          "iterations=i" => \$iterations,
-          "num_threads=i" => \$num_threads,
-          ) || die &usage;
-
-# Check for mandatory args.
-if (!$mountpt || 
-    !$num_mounts) {
-    die &usage;
-}
-
-if ($num_threads > $MAX_THREADS) {
-    print "\nMAX_THREADS is currently set to $MAX_THREADS.\n\n";
-    print "You will have to change this in the source\n";
-    print "if you really want to run with $num_threads threads.\n\n";
-    exit 1;
-}
-
-# Initialize rand() function.
-srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
-
-#########################################################################
-### MAIN
-
-for (my $i=1; $i<=$num_threads; $i++) {
-    my $status = &fork_and_create($i);
-    last if ($status != 0);
-}
-
-# Wait for all our threads to finish.
-my $child = 0;
-do {
-    $child = waitpid(-1, WNOHANG);
-} until $child > 0;
-sleep 1;
-
-exit 0;
-
-#########################################################################
-### SUBROUTINES
-
-sub usage () {
-    print "\nUsage: $0 [--silent] [--use_mcreate=n] [--num_files=n] [--iterations=n] [--num_threads=n] --mountpt=/path/to/lustre/mount --num_mounts=n\n\n";
-    print "\t--silent\tminimal output\n";
-    print "\t--use_mcreate=n\tuse mcreate to create files, default=1 (yes)\n";
-    print "\t--num_files=n\tnumber of files to create per iteration, default=5\n";
-    print "\t--iterations=n\tnumber of iterations to perform, default=1\n";
-    print "\t--num_threads=n\tnumber of thread to run, default=1\n";
-    print "\t--mountpt\tlocation of lustre mount\n";
-    print "\t--num_mounts=n\tnumber of lustre mounts to test across, default=-1 (single mount point without numeric suffix)\n\n";
-    print "example: $0 --mountpt=/mnt/lustre --num_mounts=2 --iterations=50\n";
-       print "         will perform 50 iterations in /mnt/lustre1 and /mnt/lustre2\n";
-    print "         $0 --mountpt=/mnt/lustre --num_mounts=-1 --iterations=50\n";
-    print "         will perform 50 iterations in /mnt/lustre only\n\n";
-    exit;
-}
-
-#########################################################################
-sub fork_and_create ($) {
-    my ($thread_num) = @_;
-    
-  FORK: {
-      if (my $pid = fork) {
-         # parent here
-         # child process pid is available in $pid
-         return 0;
-      } elsif (defined $pid) { # $pid is zero here if defined
-         my $current_iteration=1;
-         while ($current_iteration <= $iterations) {
-             for (my $i=1; $i<=$num_files; $i++) {
-                 my $which = "";
-                 if ($num_mounts > 0) {
-                     $which = int(rand() * $num_mounts) + 1;
-                 }
-                 my $d = int(rand() * $num_files);
-                 do_open("${mountpt}${which}/thread${thread_num}.${d}");
-                 
-                 if ($num_mounts > 0) {
-                     $which = int(rand() * $num_mounts) + 1;
-                 }
-                 $d = int(rand() * $num_files);
-                 my $path = "${mountpt}${which}/thread${thread_num}.${d}";
-                 print  "$SCRIPT_NAME - Thread $thread_num: Unlink $path start [" . $$."]...\n" if !$silent;
-                 if (unlink($path)) {
-                     print "$SCRIPT_NAME - Thread $thread_num: Unlink done [$$] $path: Success\n" if !$silent;
-                 } else {
-                     print "$SCRIPT_NAME - Thread $thread_num: Unlink done [$$] $path: $!\n"if !$silent;
-                 }
-             }
-             if (($current_iteration) % 100 == 0) {
-                 print "$SCRIPT_NAME - Thread $thread_num: " . $current_iteration . " operations [" . $$ . "]\n";
-             }
-             $current_iteration++;
-         }
-         
-         my $which = "";
-         if ($num_mounts > 0) {
-             $which = int(rand() * $num_mounts) + 1;
-         }
-         for (my $d = 0; $d < $num_files; $d++) {
-             my $path = "${mountpt}${which}/thread${thread_num}.${d}";
-             unlink("$path") if (-e $path);
-         }
-         
-         print "$SCRIPT_NAME - Thread $thread_num: Done.\n";
-         
-         exit 0;
-
-      } elsif ($! =~ /No more process/) {
-          # EAGAIN, supposedly recoverable fork error
-         sleep 5;
-         redo FORK;
-      } else {
-          # weird fork error
-         die "Can't fork: $!\n";
-      }
-  }
-
-}
-
-#########################################################################
-
-sub do_open ($) {
-    my ($path) = @_;;
-
-    if ($use_mcreate) {
-        my $tmp = `./mcreate $path`;
-        if ($tmp) {
-            print  "$SCRIPT_NAME - Creating $path [" . $$."]...\n" if !$silent;
-            $tmp =~ /.*error: (.*)\n/;
-            print  "$SCRIPT_NAME - Create done [$$] $path: $!\n" if !$silent;
-        } else {
-            print  "$SCRIPT_NAME - Create done [$$] $path: Success\n"if !$silent;
-        }
-    } else {
-        print  "$SCRIPT_NAME - Opening $path [" . $$."]...\n"if !$silent;
-        open(FH, ">$path") || die "open($path: $!";
-        print  "$SCRIPT_NAME - Open done [$$] $path: Success\n"if !$silent;
-        close(FH) || die;
-    }
-}
-
diff --git a/lustre/tests/rename.pl b/lustre/tests/rename.pl
deleted file mode 100644 (file)
index 3629553..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-#!/usr/bin/perl -w
-use strict;
-$|++;
-
-$ENV{PATH}="/bin:/usr/bin";
-$ENV{ENV}="";
-$ENV{BASH_ENV}="";
-
-use diagnostics;
-use Getopt::Long;
-use POSIX ":sys_wait_h";
-
-use vars qw(
-            $MAX_THREADS
-           $SCRIPT_NAME
-            );
-# Don't try to run more than this many threads concurrently.
-$MAX_THREADS = 16;
-
-$SCRIPT_NAME = "rename.pl";
-
-# Initialize variables
-my $silent = 0;
-my $create_files = 1; # should we create files or not?
-my $use_mcreate = 1;  # should we use mcreate or open?
-my $num_dirs = 3;     # number of directories to create
-my $num_files = 6;    # number of files to create
-my $iterations = 1;
-my $num_threads = 1;
-my $mountpt;
-my $num_mounts = -1;
-
-GetOptions("silent!"=> \$silent,
-          "use_mcreate=i" => \$use_mcreate,
-           "create_files=i" => \$create_files,
-          "use_mcreate=i" => \$use_mcreate,
-          "num_files=i" => \$num_files,
-          "num_dirs=i" => \$num_dirs,
-          "mountpt=s" => \$mountpt,
-           "num_mounts=i" => \$num_mounts,
-          "iterations=i" => \$iterations,
-           "num_threads=i" => \$num_threads,
-           ) || die &usage;
-
-# Check for mandatory args.
-if (!$mountpt ||
-    !$num_mounts) {
-    die &usage;
-}
-
-if ($num_threads > $MAX_THREADS) {
-    print "\nMAX_THREADS is currently set to $MAX_THREADS.\n\n";
-    print "You will have to change this in the source\n";
-    print "if you really want to run with $num_threads threads.\n\n";
-    exit 1;
-}
-
-# Initialize rand() function.
-srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
-
-#########################################################################
-### MAIN
-
-my $which = "";
-if ($num_mounts > 0) {
-    $which = int(rand() * $num_mounts) + 1;
-}
-
-# Create files and directories (if necessary)
-if ($create_files) {
-    for (my $i=1; $i<=$num_threads;$i++) {
-       for (my $j=0; $j<$num_dirs;$j++) {
-           my $path = "${mountpt}${which}/${i}.${j}";
-           mkdir $path, 0755 || die "Can't mkdir $path: $!\n";
-           for (my $k=0; $k<$num_files; $k++) {
-               my $filepath = "${path}/${k}";
-               &create_file($filepath);
-               if (! -e $filepath) {
-                   die "Error creating $filepath\n";
-               }
-           }
-       }
-    }
-}
-
-for (my $i=1; $i<=$num_threads; $i++) {
-    my $status = &fork_and_rename($i);
-    last if ($status != 0);
-}
-
-# Wait for all our threads to finish.
-# Wait for all our threads to finish.
-my $child = 0;
-do {
-    $child = waitpid(-1, 0);
-} until $child > 0;
-sleep 1;
-
-# Unlink files and directories (if necessary)
-if ($create_files) {
-    for (my $i=1; $i<=$num_threads;$i++) {
-       for (my $j=0; $j<$num_dirs;$j++) {
-           my $path = "${mountpt}${which}/${i}.${j}";
-           for (my $k=0; $k<=$num_files; $k++) {
-               my $filepath = "${path}/${k}";
-               unlink("$filepath") if (-e $filepath);
-           }
-           my $rc = rmdir $path;
-           print "$SCRIPT_NAME - rmdir $path failed: $!\n" if !$rc;        
-       }
-    }
-}
-
-exit 0;
-
-#########################################################################
-### SUBROUTINES
-
-sub usage () {
-    print "\nUsage: $0 [--silent] [--create_files=n] [--use_mcreate=n] [--num_dirs=n] [--num_files=n] [--iterations=n] [--num_threads=n] --num_mounts=n --mountpt=/path/to/lustre/mount\n\n";
-    print "\t--silent\tminimal output\n";
-    print "\t--create_files=n\create files at start, default=1 (yes)\n";
-    print "\t--use_mcreate=n\tuse mcreate to create files, default=1 (yes)\n";
-    print "\t--num_dirs=n\tnumber of directories to create per iteration, default=3\n";
-    print "\t--num_files=n\tnumber of files to create per directory, default=6\n";
-    print "\t--iterations=n\tnumber of iterations to perform, default=1\n";
-    print "\t--num_threads=n\tnumber of thread to run, default=1\n";
-    print "\t--mountpt\tlocation of lustre mount\n";
-    print "\t--num_mounts=n\tnumber of lustre mounts to test across, default=-1 (single mount point without numeric suffix)\n\n";
-    print "example: $0 --mountpt=/mnt/lustre --num_mounts=2 --iterations=50\n";
-       print "         will perform 50 iterations in /mnt/lustre1 and /mnt/lustre2\n";
-    print "         $0 --mountpt=/mnt/lustre --num_mounts=-1 --iterations=50\n";
-    print "         will perform 50 iterations in /mnt/lustre only\n\n";
-    exit;
-}
-
-
-#########################################################################
-sub create_file ($) {
-    my ($path) = @_;;
-    
-    if (-e $path) {
-       warn "$path already exists!\n";
-       return 1;
-    }
-
-    if ($use_mcreate) {
-        my $tmp = `./mcreate $path`;
-       if ($tmp =~ /.*error: (.*)\n/) {
-           die "Error mcreating $path: $!\n";
-       }
-    } else {
-        open(FH, ">$path") || die "Error opening $path: $!\n";
-        close(FH) || die;
-    }
-    return 0;
-}
-
-#########################################################################
-sub fork_and_rename ($) {
-    my ($thread_num) = @_;
-    
-  FORK: {
-      if (my $pid = fork) {
-          # parent here
-          # child process pid is available in $pid
-         return 0;
-      } elsif (defined $pid) { # $pid is zero here if defined
-         
-         my $current_iteration=1;
-          while ($current_iteration <= $iterations) {
-             for (my $i=0; $i<$num_files; $i++) {
-                 my $which = "";
-                 if ($num_mounts > 0) {
-                     $which = int(rand() * $num_mounts) + 1;
-                 }
-                 
-                 my $d = int(rand() * $num_dirs);
-                 my $f1 = int(rand() * $num_files);
-                 my $f2 = int(rand() * $num_files);
-                 my $path_f1 = "${mountpt}${which}/${thread_num}.${d}/${f1}";
-                 my $path_f2 = "${mountpt}${which}/${thread_num}.${d}/${f2}";
-                 
-                 print "$SCRIPT_NAME - Thread $thread_num: [$$] $path_f1 $path_f2 ...\n" if !$silent;
-                 my $rc = rename $path_f1, $path_f2;
-                 print "$SCRIPT_NAME - Thread $thread_num: [$$] done: $rc\n" if !$silent;
-             }
-             if (($current_iteration) % 100 == 0) {
-                 print "$SCRIPT_NAME - Thread $thread_num: " . $current_iteration . " operations [" . $$ . "]\n";
-                 
-             }
-             $current_iteration++;
-         }
-
-         print "$SCRIPT_NAME - Thread $thread_num: Done.\n";
-
-         exit 0;
-
-      } elsif ($! =~ /No more process/) {
-          # EAGAIN, supposedly recoverable fork error
-          sleep 5;
-          redo FORK;
-      } else {
-          # weird fork error
-          die "Can't fork: $!\n";
-      }
-  }
-    
-}
index f89263d..c58379a 100755 (executable)
@@ -6245,11 +6245,11 @@ test_53() {
 run_test 53 "verify that MDS and OSTs agree on pre-creation ===="
 
 test_54a() {
-       perl -MSocket -e ';' || skip "no Socket perl module installed"
+       LANG=C perl -MSocket -e ';' || skip "no Socket perl module installed"
 
-       $SOCKETSERVER $DIR/socket ||
+       LANG=C $SOCKETSERVER $DIR/socket ||
                error "$SOCKETSERVER $DIR/socket failed: $?"
-       $SOCKETCLIENT $DIR/socket ||
+       LANG=C $SOCKETCLIENT $DIR/socket ||
                error "$SOCKETCLIENT $DIR/socket failed: $?"
        $MUNLINK $DIR/socket || error "$MUNLINK $DIR/socket failed: $?"
 }
@@ -10964,27 +10964,24 @@ test_100() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run"
        [[ "$NETTYPE" =~ tcp ]] ||
                skip_env "TCP secure port test, not useful for NETTYPE=$NETTYPE"
+       [[ -n "$(type -p ss)" ]] || skip_env "ss not available"
        remote_ost_nodsh && skip "remote OST with nodsh"
        remote_mds_nodsh && skip "remote MDS with nodsh"
-       remote_servers ||
-               skip "useless for local single node setup"
+       remote_servers || skip "useless for local single node setup"
 
-       netstat -tna | ( rc=1; while read PROT SND RCV LOCAL REMOTE STAT; do
-               [ "$PROT" != "tcp" ] && continue
-               RPORT=$(echo $REMOTE | cut -d: -f2)
-               [ "$RPORT" != "$ACCEPTOR_PORT" ] && continue
+       ss -tna | ( rc=1; while read STATE SND RCV LOCAL REMOTE STAT; do
+               [[ "${REMOTE/*:/}" == "$ACCEPTOR_PORT" ]] || continue
 
                rc=0
-               LPORT=`echo $LOCAL | cut -d: -f2`
-               if [ $LPORT -ge 1024 ]; then
+               if (( ${LOCAL/*:/} >= 1024 )); then
                        echo "bad: $PROT $SND $RCV $LOCAL $REMOTE $STAT"
-                       netstat -tna
-                       error_exit "local: $LPORT > 1024, remote: $RPORT"
+                       ss -tna
+                       error "local: ${LOCAL/*:/} > 1024 remote: ${REMOTE/*:/}"
                fi
        done
-       [ "$rc" = 0 ] || error_exit "privileged port not found" )
+       (( $rc == 0 )) || error "privileged port not found" )
 }
-run_test 100 "check local port using privileged port ==========="
+run_test 100 "check local port using privileged port"
 
 function get_named_value()
 {
@@ -28354,22 +28351,38 @@ test_430c() {
        local start
 
        mkdir -p $DIR/$tdir
-       dd if=/dev/urandom of=$file bs=1k count=1 seek=5M
+       stack_trap "rm -f $file $file.tmp"
+       dd if=/dev/urandom of=$file bs=1k count=1 seek=5M || error "dd failed"
 
        # cp version 8.33+ prefers lseek over fiemap
-       if [[ $(cp --version | head -n1 | sed "s/[^0-9]//g") -ge 833 ]]; then
+       local ver=$(cp --version | awk '{ print $4; exit; }')
+       echo "cp $ver installed"
+       if (( $(version_code $ver) >= $(version_code 8.33) )); then
                start=$SECONDS
-               time cp $file /dev/null
-               (( SECONDS - start < 5 )) ||
+               time cp -v $file $file.tmp
+               (( SECONDS - start < 5 )) || {
+                       strace cp $file $file.tmp |&
+                               grep -E "open|read|seek|FIEMAP" |
+                               grep -A 100 $file
                        error "cp: too long runtime $((SECONDS - start))"
-
+               }
+       else
+               echo "cp test skipped due to $ver < 8.33"
        fi
        # tar version 1.29+ supports SEEK_HOLE/DATA
-       if [[ $(tar --version | head -n1 | sed "s/[^0-9]//g") -ge 129 ]]; then
+       ver=$(tar --version | awk '{ print $4; exit; }')
+       echo "tar $ver installed"
+       if (( $(version_code $ver) >= $(version_code 1.29) )); then
                start=$SECONDS
-               time tar cS $file - | cat > /dev/null
-               (( SECONDS - start < 5 )) ||
+               time tar cvf $file.tmp --sparse $file || error "tar $file failed"
+               (( SECONDS - start < 5 )) || {
+                       strace tar cf $file.tmp --sparse $file |&
+                               grep -E "open|read|seek|FIEMAP" |
+                               grep -A 100 $file
                        error "tar: too long runtime $((SECONDS - start))"
+               }
+       else
+               echo "tar test skipped due to $ver < 1.29"
        fi
 }
 run_test 430c "lseek: external tools check"