Whamcloud - gitweb
4ea020f2c0a9b796d7cbc0f8481616b6974fcce0
[fs/lustre-release.git] / lustre / tests / rename.pl
1 #!/usr/bin/perl -w
2 use strict;
3 $|++;
4
5 $ENV{PATH}="/bin:/usr/bin";
6 $ENV{ENV}="";
7 $ENV{BASH_ENV}="";
8
9 use diagnostics;
10 use Getopt::Long;
11 use POSIX ":sys_wait_h";
12
13 use vars qw(
14             $MAX_THREADS
15             );
16  
17 # Don't try to run more than this many threads concurrently.
18 $MAX_THREADS = 16;
19
20 # Initialize variables
21 my $silent = 0;
22 my $create_files = 1; # should we create files or not?
23 my $use_mcreate = 1;  # should we use mcreate or open?
24 my $num_dirs = 3;     # number of directories to create
25 my $num_files = 6;    # number of files to create
26 my $iterations = 1;
27 my $num_threads = 1;
28 my $mountpt;
29 my $num_mounts = -1;
30
31 GetOptions("silent!"=> \$silent,
32            "use_mcreate=i" => \$use_mcreate,
33            "create_files=i" => \$create_files,
34            "use_mcreate=i" => \$use_mcreate,
35            "num_files=i" => \$num_files,
36            "num_dirs=i" => \$num_dirs,
37            "mountpt=s" => \$mountpt,
38            "num_mounts=i" => \$num_mounts,
39            "iterations=i" => \$iterations,
40            "num_threads=i" => \$num_threads,
41            ) || die &usage;
42
43 # Check for mandatory args.
44 if (!$mountpt ||
45     !$num_mounts) {
46     die &usage;
47 }
48
49 if ($num_threads > $MAX_THREADS) {
50     print "\nMAX_THREADS is currently set to $MAX_THREADS.\n\n";
51     print "You will have to change this in the source\n";
52     print "if you really want to run with $num_threads threads.\n\n";
53     exit 1;
54 }
55
56 # Initialize rand() function.
57 srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
58
59 #########################################################################
60 ### MAIN
61
62 my $which = "";
63 if ($num_mounts > 0) {
64     $which = int(rand() * $num_mounts) + 1;
65 }
66
67 # Create files and directories (if necessary)
68 if ($create_files) {
69     for (my $i=1; $i<=$num_threads;$i++) {
70         for (my $j=0; $j<$num_dirs;$j++) {
71             my $path = "${mountpt}${which}/${i}.${j}";
72             mkdir $path, 0755 || die "Can't mkdir $path: $!\n";
73             for (my $k=0; $k<$num_files; $k++) {
74                 my $filepath = "${path}/${k}";
75                 &create_file($filepath);
76                 if (! -e $filepath) {
77                     die "Error creating $filepath\n";
78                 }
79             }
80         }
81     }
82 }
83
84 for (my $i=1; $i<=$num_threads; $i++) {
85     my $status = &fork_and_rename($i);
86     last if ($status != 0);
87 }
88
89 # Wait for all our threads to finish.
90 # Wait for all our threads to finish.
91 my $child = 0;
92 do {
93     $child = waitpid(-1, WNOHANG);
94 } until $child > 0;
95 sleep 1;
96
97 # Unlink files and directories (if necessary)
98 if ($create_files) {
99     for (my $i=1; $i<=$num_threads;$i++) {
100         for (my $j=0; $j<$num_dirs;$j++) {
101             my $path = "${mountpt}${which}/${i}.${j}";
102             for (my $k=0; $k<=$num_files; $k++) {
103                 my $filepath = "${path}/${k}";
104                 unlink("$filepath") if (-e $filepath);
105             }
106             my $rc = rmdir $path;
107             print "rmdir $path failed: $!\n" if !$rc;       
108         }
109     }
110 }
111
112 exit 0;
113
114 #########################################################################
115 ### SUBROUTINES
116
117 sub usage () {
118     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";
119     print "\t--silent\tminimal output\n";
120     print "\t--create_files=n\create files at start, default=1 (yes)\n";
121     print "\t--use_mcreate=n\tuse mcreate to create files, default=1 (yes)\n";
122     print "\t--num_dirs=n\tnumber of directories to create per iteration, default=3\n";
123     print "\t--num_files=n\tnumber of files to create per directory, default=6\n";
124     print "\t--iterations=n\tnumber of iterations to perform, default=1\n";
125     print "\t--num_threads=n\tnumber of thread to run, default=1\n";
126     print "\t--mountpt\tlocation of lustre mount\n";
127     print "\t--num_mounts=n\tnumber of lustre mounts to test across, default=-1 (single mount point without numeric suffix)\n\n";
128     print "example: $0 --mountpt=/mnt/lustre --num_mounts=2 --iterations=50\n";
129     print "         will perform 50 interations in /mnt/lustre1 and /mnt/lustre2\n";
130     print "         $0 --mountpt=/mnt/lustre --num_mounts=-1 --iterations=50\n";
131     print "         will perform 50 iterations in /mnt/lustre only\n\n";
132     exit;
133 }
134
135
136 #########################################################################
137 sub create_file ($) {
138     my ($path) = @_;;
139     
140     if ($use_mcreate) {
141         my $tmp = `./mcreate $path`;
142         if ($tmp =~ /.*error: (.*)\n/) {
143             die "Error mcreating $path: $!\n";
144         }
145     } else {
146         open(FH, ">$path") || die "Error opening $path: $!\n";
147         close(FH) || die;
148     }
149     return 0;
150 }
151
152 #########################################################################
153 sub fork_and_rename ($) {
154     my ($thread_num) = @_;
155     
156   FORK: {
157       if (my $pid = fork) {
158           # parent here
159           # child process pid is available in $pid
160           return 0;
161       } elsif (defined $pid) { # $pid is zero here if defined
162           
163           my $current_iteration=1;
164           while ($current_iteration <= $iterations) {
165               for (my $i=0; $i<$num_files; $i++) {
166                   my $which = "";
167                   if ($num_mounts > 0) {
168                       $which = int(rand() * $num_mounts) + 1;
169                   }
170                   
171                   my $d = int(rand() * $num_dirs);
172                   my $f1 = int(rand() * $num_files);
173                   my $f2 = int(rand() * $num_files);
174                   my $path_f1 = "${mountpt}${which}/${thread_num}.${d}/${f1}";
175                   my $path_f2 = "${mountpt}${which}/${thread_num}.${d}/${f2}";
176                   
177                   print "Thread $thread_num: [$$] $path_f1 $path_f2 ...\n" if !$silent;
178                   my $rc = rename $path_f1, $path_f2;
179                   print "Thread $thread_num: [$$] done: $rc\n" if !$silent;
180               }
181               if (($current_iteration) % 100 == 0) {
182                   print STDERR "Thread $thread_num: " . $current_iteration . " operations [" . $$ . "]\n";
183                   
184               }
185               $current_iteration++;
186           }
187
188           print "Thread $thread_num: Done.\n";
189
190           exit 0;
191
192       } elsif ($! =~ /No more process/) {
193           # EAGAIN, supposedly recoverable fork error
194           sleep 5;
195           redo FORK;
196       } else {
197           # weird fork error
198           die "Can't fork: $!\n";
199       }
200   }
201     
202 }