Whamcloud - gitweb
A couple days of changes--much improvement.
[fs/lustre-release.git] / lustre / obdclass / obdcontrol
1 #!/usr/bin/perl
2
3 #use strict;
4 BEGIN { require "asm/errno.ph" };
5 BEGIN { require "asm/ioctl.ph" };
6
7 # p2ph generated invalid macros for ioctl stuff, so I override some of it here
8 eval 'sub OBD_IOC_CREATE () { &_IOC(2, ord(\'f\'), 3, 4);}' unless
9   defined(&OBD_IOC_CREATE);
10 eval 'sub OBD_IOC_SETUP () { &_IOC(1, ord(\'f\'), 4, 4);}' unless
11   defined(&OBD_IOC_SETUP);
12 eval 'sub OBD_IOC_SYNC () { &_IOC(2, ord(\'f\'), 5, 4);}' unless
13   defined(&OBD_IOC_SYNC);
14 eval 'sub OBD_IOC_DESTROY () { &_IOC(1, ord(\'f\'), 6, 4);}' unless
15   defined(&OBD_IOC_DESTROY);
16 eval 'sub OBD_IOC_DEC_USE_COUNT () { &_IOC(0, ord(\'f\'), 8, 0);}' unless
17   defined(&OBD_IOC_DEC_USE_COUNT);
18
19 use Getopt::Long;
20 use File::stat;
21 use Storable;
22 use Carp;
23 use Term::ReadLine;
24 use IO::Handle;
25
26 my ($device, $filesystem);
27 # startup options (I'll replace these when I have some to replace with)
28 GetOptions("device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions";
29
30 $device = "/dev/obd" unless $device;
31 $filesystem = "/dev/loop0" unless $filesystem;
32
33 # get a console for the app
34 my $term = new Term::ReadLine 'obdcontrol ';
35 my $attribs = $term->Attribs;
36 $term->ornaments('md,me,,');    # bold face prompt
37
38 # make sure stdout is not buffered
39 STDOUT->autoflush(1);
40
41 my $line;
42 my $command;
43 my $arg;
44
45 my %commands =
46     ('create' => {func => "Create", doc => "create: creates a new inode"},
47      'setup' => {func => "Setup", doc => "setup: initializes the environment"},
48      'sync' => {func => "Sync", doc => "sync: flushes buffers to disk"},
49      'destroy' => {func => "Destroy", doc => "setup: destroys an inode"},
50      'dec_use_count' => {func => "Decusecount", doc => "decreases the module use count so that it can be unmounted following an oops"},
51      'help' => {func => \&Help,  doc => "help: this message"},
52      'quit' => {func => \&Quit,  doc => "see \"exit\""},
53      'exit' => {func => \&Quit,  doc => "see \"quit\""}
54     );
55
56 #
57 #       setup completion function
58 #
59 my @jcm_cmd_list = keys %commands;
60
61 $attribs->{attempted_completion_function} = \&completeme;
62 #------------------------------------------------------------------------------
63 # Open the device, as we need an FD for the ioctl
64 sysopen(DEV_OBD, $device, 0);
65
66 if (!defined($::st = stat($filesystem))) {
67     die "Unable to stat $filesystem.\n";
68 }
69
70 # Get on with the show
71 process_line();
72
73 #------------------------------------------------------------------------------
74 sub completeme {
75     my ($text, $line, $start, $end) = @_;
76     if (substr($line, 0, $start) =~ /^\s*$/) {
77         $attribs->{completion_word} = \@jcm_cmd_list;
78         return $term->completion_matches($text,
79                                          $attribs->{'list_completion_function'});
80     }
81 }
82
83 sub find_command {
84     my $given = shift;
85     my $name;
86     my @completions = completeme($given, $given, 0, length($given));
87     if ($#completions == 0) {
88         $name = shift @completions;
89     }
90
91     return $name;
92 }
93
94 # start making requests
95 sub process_line {
96   foo:
97     $line = $term->readline("obdcontrol > ");
98     execute_line($line);
99     goto foo;
100 }
101
102 sub execute_line {
103     my $line = shift;
104
105     my @arg = split(' ', $line);
106     my $word = shift @arg;
107
108     my $cmd = find_command($word);
109     unless ($cmd) {
110         printf STDERR "$word: No such command, or not unique.\n";
111         return (-1);
112     }
113
114     if ($cmd eq "help" || $cmd eq "exit" || $cmd eq "quit") {
115         return (&{$commands{$cmd}->{func}}(@arg));
116     }
117
118     # Call the function.
119     return (&{$commands{$cmd}->{func}}(@arg));
120 }
121
122 sub Setup {
123     my $err = 0;
124     my $packed = pack("L", $::st->rdev());
125     my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP, $packed);
126
127     if (!defined $rc) {
128         print STDERR "ioctl failed: $!\n";
129     } elsif ($rc eq "0 but true") {
130         print "Finished (success)\n";
131     } else {
132         print "ioctl returned error code $rc.\n";
133     }
134 }
135
136 sub Create {
137     my $arg = shift;
138     my $quiet = shift;
139     my $err = "0";
140     my $rc;
141
142     if (defined($quiet) && !($quiet eq "quiet")) {
143         print "syntax: create [number of objects [quiet]]\n";
144         return;
145     }
146
147     if (!defined($arg) || scalar($arg) < 2) {
148         print "Creating 1 object...\n";
149         $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
150         if (!defined($quiet)) {
151             my $ino = unpack("L", $err);
152             print "Created object #$ino.\n";
153         }
154     } else {
155         my $i;
156
157         print "Creating " . scalar($arg) . " objects...\n";
158         for ($i = 0; $i < scalar($arg); $i++) {
159             $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
160             if (!($rc eq "0 but true") || $err < 0) {
161                 last;
162             } elsif (!defined($quiet)) {
163                 my $ino = unpack("L", $err);
164                 print "Created object #$ino.\n";
165             }
166         }
167     }
168
169     if (!defined $rc) {
170         print STDERR "ioctl failed: $!\n";
171     } elsif ($rc eq "0 but true") {
172         print "Finished (success)\n";
173     } else {
174         print "ioctl returned error code $rc.\n";
175     }
176 }
177
178 sub Sync {
179     my $err = "0";
180     my $rc = ioctl(DEV_OBD, &OBD_IOC_SYNC, $err);
181
182     if (!defined $rc) {
183         print STDERR "ioctl failed: $!\n";
184     } elsif ($rc eq "0 but true") {
185         print "Finished (success)\n";
186     } else {
187         print "ioctl returned error code $rc.\n";
188     }
189 }
190
191 sub Destroy {
192     my $arg = shift;
193
194     if (!defined($arg) || scalar($arg) < 1) {
195         print "destroy requires the object number to destroy.\n";
196         return;
197     }
198
199     print "Destroying object $arg...\n";
200     my $packed = pack("L", $arg);
201     my $rc = ioctl(DEV_OBD, &OBD_IOC_DESTROY, $packed);
202
203     if (!defined $rc) {
204         print STDERR "ioctl failed: $!\n";
205     } elsif ($rc eq "0 but true") {
206         print "Finished (success)\n";
207     } else {
208         print "ioctl returned error code $rc.\n";
209     }
210 }
211
212 sub Preallocate {
213     my $arg = shift;
214
215     if (!defined($arg) || scalar($arg) < 1 || scalar($arg) > 32) {
216         $arg = 32;
217     }
218
219     print "Preallocating $arg inodes...\n";
220     my $packed = pack("Lx128", $arg); # alloc, inodes[32]
221     my $rc = ioctl(DEV_OBD, &OBD_IOC_PREALLOCATE, $packed);
222
223     if (!defined $rc) {
224         print STDERR "ioctl failed: $!\n";
225     } elsif ($rc eq "0 but true") {
226         my $alloc = unpack("L", $packed);
227         my @inodes = unpack("L32", $packed);
228         my $i;
229
230         print "Got $alloc inodes: ";
231         for ($i = 1; $i <= $alloc; ++$i) {
232             print $inodes[$i] . " ";
233         }
234         print "\nFinished (success)\n";
235     } else {
236         print "ioctl returned error code $rc.\n";
237     }
238 }
239
240 sub Decusecount {
241     my $rc = ioctl(DEV_OBD, &OBD_IOC_DEC_USE_COUNT, NULL);
242
243     if (!defined $rc) {
244         print STDERR "ioctl failed: $!\n";
245     } elsif ($rc eq "0 but true") {
246         print "Finished (success)\n";
247     } else {
248         print "ioctl returned error code $rc.\n";
249     }
250 }
251
252 sub Help {
253     my $arg = shift;
254
255     if ( !$arg || !$commands{$arg} ) {
256         print "Comands: ", join( ' ', @jcm_cmd_list), "\n";
257     } else {
258         print "Usage: " .  $commands{$arg}->{doc} . "\n";
259     }
260 }
261
262 sub Quit {
263     exit;
264 }