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