Whamcloud - gitweb
LU-797 tests: improve test_23b of ost-pools.sh
[fs/lustre-release.git] / lustre / tests / rename.pl
index 3ba9368..dd6b5dc 100644 (file)
-#!/usr/bin/perl
+#!/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";
 
-sub usage () {
-    print "Usage: $0 <mount point prefix> <iterations>\n";
-    print "example: $0 --count=2 /mnt/lustre 50\n";
-    print "         will test in /mnt/lustre1 and /mnt/lustre2\n";
-    print "         $0 --count=0 /mnt/lustre 50\n";
-    print "         will test in /mnt/lustre only\n";
-    exit;
-}
-my ($j, $k, $d, $f1, $f2, $path, $silent);
-my $count = 0;
-my $create = 10;
+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,
-           "count=i" => \$count,
-           "create=i" => \$create);
+          "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;
 
-my $mtpt = shift || usage();
-my $i = shift || usage();
-my $total = $i;
-my $files = 6;
-my $dirs = 3;
-my $mcreate = 0; # should we use mcreate or open?
+# Check for mandatory args.
+if (!$mountpt ||
+    !$num_mounts) {
+    die &usage;
+}
 
-my $which = "";
-if ($count > 0) {
-    $which = int(rand() * $count) + 1;
+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;
 }
 
-$k = $dirs;
-if ($create == 0) {
-    $k = 0;
+# Initialize rand() function.
+srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
+
+#########################################################################
+### MAIN
+
+my $which = "";
+if ($num_mounts > 0) {
+    $which = int(rand() * $num_mounts) + 1;
 }
-while ($k--) {
-    $path = "$mtpt$which/$k";
-    my $rc = mkdir $path, 0755;
-    print "mkdir $path failed: $!\n" if !$rc;
-    $j = $files;
-    while ($j--) {
-        `./mcreate $path/$j`;
+
+# 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";
+               }
+           }
+       }
     }
 }
 
-while ($i--) {
-    my $which = "";
-    if ($count > 0) {
-        $which = int(rand() * $count) + 1;
-    }
-    $d = int(rand() * $dirs);
-    $f1 = int(rand() * $files);
-    $f2 = int(rand() * $files);
-    print "[$$] $mtpt$which/$d/$f1 $mtpt$which/$d/$f2 ...\n" if !$silent;
-    my $rc = rename "$mtpt$which/$d/$f1", "$mtpt$which/$d/$f2";
-    print "[$$] done: $rc\n" if !$silent;
-    if (($total - $i) % 100 == 0) {
-        print STDERR "[" . $$ . "]" . ($total - $i) . " operations\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;        
+       }
     }
 }
 
-$k = $dirs;
-if ($create == 0) {
-    $k = 0;
+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 interations 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;
 }
-while ($k--) {
-    $path = "$mtpt$which/$k";
-    $j = $files;
-    while ($j--) {
-        unlink "$path/$j";
+
+
+#########################################################################
+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;
     }
-    my $rc = rmdir $path;
-    print "rmdir $path failed: $!\n" if !$rc;
+    return 0;
 }
 
-print "Done.\n";
+#########################################################################
+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";
+      }
+  }
+    
+}