5 $ENV{PATH}="/bin:/usr/bin";
11 use POSIX ":sys_wait_h";
17 # Don't try to run more than this many threads concurrently.
20 # Initialize variables
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
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,
43 # Check for mandatory args.
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";
56 # Initialize rand() function.
57 srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
59 #########################################################################
63 if ($num_mounts > 0) {
64 $which = int(rand() * $num_mounts) + 1;
67 # Create files and directories (if necessary)
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);
77 die "Error creating $filepath\n";
84 for (my $i=1; $i<=$num_threads; $i++) {
85 my $status = &fork_and_rename($i);
86 last if ($status != 0);
89 # Wait for all our threads to finish.
90 # Wait for all our threads to finish.
93 $child = waitpid(-1, WNOHANG);
97 # Unlink files and directories (if necessary)
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);
106 my $rc = rmdir $path;
107 print "rmdir $path failed: $!\n" if !$rc;
114 #########################################################################
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";
136 #########################################################################
137 sub create_file ($) {
141 my $tmp = `./mcreate $path`;
142 if ($tmp =~ /.*error: (.*)\n/) {
143 die "Error mcreating $path: $!\n";
146 open(FH, ">$path") || die "Error opening $path: $!\n";
152 #########################################################################
153 sub fork_and_rename ($) {
154 my ($thread_num) = @_;
157 if (my $pid = fork) {
159 # child process pid is available in $pid
161 } elsif (defined $pid) { # $pid is zero here if defined
163 my $current_iteration=1;
164 while ($current_iteration <= $iterations) {
165 for (my $i=0; $i<$num_files; $i++) {
167 if ($num_mounts > 0) {
168 $which = int(rand() * $num_mounts) + 1;
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}";
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;
181 if (($current_iteration) % 100 == 0) {
182 print STDERR "Thread $thread_num: " . $current_iteration . " operations [" . $$ . "]\n";
185 $current_iteration++;
188 print "Thread $thread_num: Done.\n";
192 } elsif ($! =~ /No more process/) {
193 # EAGAIN, supposedly recoverable fork error
198 die "Can't fork: $!\n";