From f0414c73924d07cc84c086a4b34663901cf17041 Mon Sep 17 00:00:00 2001 From: braam Date: Tue, 5 Mar 2002 01:00:36 +0000 Subject: [PATCH] - add obdecho directory - numerous small fixes to obdclass -- yippeah Andreas is back - test_getattr (jt_multi_getattr) tells obdctl to fire many getattr requests. - build this code, run obd/tests/llecho.sh and play with it --- lustre/include/linux/obd_class.h | 15 +- lustre/obdclass/class_obd.c | 23 +- lustre/obdecho/.cvsignore | 8 + lustre/obdecho/Makefile.am | 14 + lustre/obdecho/echo.c | 75 ++ lustre/tests/llecho.sh | 55 ++ lustre/tests/llmount.sh | 4 +- lustre/utils/Makefile.am | 3 - lustre/utils/obdcontrol | 1798 -------------------------------------- lustre/utils/obdctl.c | 37 +- 10 files changed, 216 insertions(+), 1816 deletions(-) create mode 100644 lustre/obdecho/.cvsignore create mode 100644 lustre/obdecho/Makefile.am create mode 100644 lustre/obdecho/echo.c create mode 100644 lustre/tests/llecho.sh delete mode 100755 lustre/utils/obdcontrol diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 29d55ea..6420950 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -204,7 +204,7 @@ static inline int obd_check_conn(struct obd_conn *conn) return 0; } -#define OBT(dev) dev->obd_type->typ_ops +#define OBT(dev) dev->obd_type #define OBP(dev,op) dev->obd_type->typ_ops->o_ ## op #define OBD_CHECK_SETUP(conn) \ @@ -263,6 +263,19 @@ static inline int obd_set_info(struct obd_conn *conn, obd_count keylen, void *ke return rc; } +static inline int obd_setup(struct obd_device *obd, int datalen, void *data) +{ + struct obd_conn conn; + int rc; + conn.oc_dev = obd; + + OBD_CHECK_OP((&conn),setup); + + rc = OBP(conn.oc_dev, setup)(obd, datalen, data); + EXIT; + return rc; +} + static inline int obd_cleanup(struct obd_device *obd) { struct obd_conn conn; diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index c5984f2..4e8b6d0 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -266,7 +266,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, } if ( OBT(obd) && OBP(obd, setup) ) - err = OBP(obd, setup)(obd, sizeof(*data), data); + err = obd_setup(obd, sizeof(*data), data); if (!err) { obd->obd_type->typ_refcnt++; @@ -279,16 +279,21 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, case OBD_IOC_CLEANUP: { ENTRY; - err = obd_cleanup(obd); - if ( err ) { - EXIT; - return err; + /* have we attached a type to this device? */ + if (!(obd->obd_flags & OBD_ATTACHED)) { + CERROR("Device %d not attached\n", obd->obd_minor); + return -ENODEV; } - obd->obd_flags &= ~OBD_SET_UP; - obd->obd_type->typ_refcnt--; - EXIT; - return 0; + if ( OBT(obd) && OBP(obd, cleanup) ) + err = obd_cleanup(obd); + + if (!err) { + obd->obd_flags &= ~OBD_SET_UP; + obd->obd_type->typ_refcnt--; + EXIT; + } + return err; } case OBD_IOC_CONNECT: diff --git a/lustre/obdecho/.cvsignore b/lustre/obdecho/.cvsignore new file mode 100644 index 0000000..e530020 --- /dev/null +++ b/lustre/obdecho/.cvsignore @@ -0,0 +1,8 @@ +.Xrefs +config.log +config.status +configure +Makefile +Makefile.in +.deps +TAGS diff --git a/lustre/obdecho/Makefile.am b/lustre/obdecho/Makefile.am new file mode 100644 index 0000000..bd6308f --- /dev/null +++ b/lustre/obdecho/Makefile.am @@ -0,0 +1,14 @@ +# Copyright (C) 2001 Cluster File Systems, Inc. +# +# This code is issued under the GNU General Public License. +# See the file COPYING in this distribution + +DEFS:= +MODULE = obdecho +modulefs_DATA = obdecho.o +EXTRA_PROGRAMS = obdecho + +obdecho_SOURCES = echo.c + +include $(top_srcdir)/Rules + diff --git a/lustre/obdecho/echo.c b/lustre/obdecho/echo.c new file mode 100644 index 0000000..dad0dec --- /dev/null +++ b/lustre/obdecho/echo.c @@ -0,0 +1,75 @@ +/* + * linux/fs/ext2_obd/ext2_obd.c + * + * Copyright (C) 2001 Cluster File Systems, Inc. + * + * This code is issued under the GNU General Public License. + * See the file COPYING in this distribution + * + * by Peter Braam + */ + +#define EXPORT_SYMTAB + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_SUBSYSTEM S_ECHO + +#include +#include +#include + +extern struct obd_device obd_dev[MAX_OBD_DEVICES]; +static struct obdo OA; +static obd_count GEN; + +static int echo_getattr(struct obd_conn *conn, struct obdo *oa) +{ + memcpy(oa, &OA, sizeof(*oa)); + oa->o_mode = ++GEN; + + return 0; +} + +/* +static int echo_setattr(struct obd_conn *conn, struct obdo *oa) +{ + memcpy(&OA, oa, sizeof(*oa)); + + return 0; +} +*/ + +struct obd_ops echo_obd_ops = { + o_connect: gen_connect, + o_disconnect: gen_disconnect, + o_getattr: echo_getattr, +// o_setattr: echo_setattr, +}; + + +static int __init obdecho_init(void) +{ + printk(KERN_INFO "Echo OBD driver v0.001, braam@clusterfs.com\n"); + + return obd_register_type(&echo_obd_ops, OBD_ECHO_DEVICENAME); +} + +static void __exit obdecho_exit(void) +{ + obd_unregister_type(OBD_ECHO_DEVICENAME); +} + +MODULE_AUTHOR("Peter J. Braam "); +MODULE_DESCRIPTION("Lustre Testing Echo OBD driver v1.0"); +MODULE_LICENSE("GPL"); + +module_init(obdecho_init); +module_exit(obdecho_exit); diff --git a/lustre/tests/llecho.sh b/lustre/tests/llecho.sh new file mode 100644 index 0000000..bbe0179 --- /dev/null +++ b/lustre/tests/llecho.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +SRCDIR="`dirname $0`" +. $SRCDIR/common.sh + +mknod /dev/portals c 10 240 + +insmod $R/usr/src/portals/linux/oslib/portals.o || exit -1 +insmod $R/usr/src/portals/linux/socknal/ksocknal.o || exit -1 + +$R/usr/src/portals/linux/utils/acceptor 1234 & + +insmod $R/usr/src/obd/class/obdclass.o || exit -1 +insmod $R/usr/src/obd/rpc/ptlrpc.o || exit -1 +insmod $R/usr/src/obd/ost/ost.o || exit -1 +insmod $R/usr/src/obd/osc/osc.o || exit -1 +insmod $R/usr/src/obd/obdecho/obdecho.o || exit -1 + +$R/usr/src/obd/utils/obdctl modules > $R/tmp/ogdb +echo "The GDB module script is in /tmp/ogdb. Press enter to continue" +read + +$R/usr/src/portals/linux/utils/ptlctl < /proc/sys/portals/debug +echo 8191 > /proc/sys/portals/trace + +$R/usr/src/obd/utils/obdctl < /proc/sys/obd/debug -echo 8291 > /proc/sys/obd/trace +echo 8191 > /proc/sys/portals/debug +echo 8191 > /proc/sys/portals/trace $R/usr/src/obd/utils/obdctl <{id}, 0, - $obdo->{gr}, 0, - $obdo->{atime}, 0, - $obdo->{mtime}, 0 , - $obdo->{ctime}, 0, - $obdo->{size}, 0, - $obdo->{blocks}, 0, - $obdo->{blksize}, - $obdo->{mode}, - $obdo->{uid}, - $obdo->{gid}, - $obdo->{flags}, - $obdo->{obdflags}, - $obdo->{nlink}, - $obdo->{generation}, - $obdo->{valid}, - $obdo->{inline}, - $obdo->{obdmd}, - 0, 0, # struct list_head - 0; # struct obd_ops -} - -sub obdo_unpack { - my $buf = shift; - my $offset = shift; - my $obdo; - ($obdo->{id}, - $obdo->{gr}, - $obdo->{atime}, - $obdo->{mtime}, - $obdo->{ctime}, - $obdo->{size}, - $obdo->{blocks}, - $obdo->{blksize}, - $obdo->{mode}, - $obdo->{uid}, - $obdo->{gid}, - $obdo->{flags}, - $obdo->{obdflags}, - $obdo->{nlink}, - $obdo->{generation}, - $obdo->{valid}, - $obdo->{inline}, - $obdo->{obdmd}) = unpack "x${offset}Lx4 Lx4 Lx4 Lx4 Lx4 Lx4 Lx4 L L L L L L L L L a60 a60", $buf; - $obdo; -} - -sub obdo_print { - - my $obdo = shift; - - printf "id: %d\ngrp: %d\natime: %s\nmtime: %s\nctime: %s\nsize: %d\nblocks: %d\nblksize: %d\nmode: %o\nuid: %d\ngid: %d\nflags: %x\nobdflags: %x\nnlink: %d\nvalid: %x\ninline: %s\nobdmd: %s\n", - $obdo->{id}, - $obdo->{gr}, - $obdo->{atime}, - $obdo->{mtime}, - $obdo->{ctime}, - $obdo->{size}, - $obdo->{blocks}, - $obdo->{blksize}, - $obdo->{mode}, - $obdo->{uid}, - $obdo->{gid}, - $obdo->{flags}, - $obdo->{obdflags}, - $obdo->{nlink}, - $obdo->{valid}, - $obdo->{inline}, - $obdo->{obdmd}; -} - - -my ($file); - -GetOptions("f!" => \$file, "device=s" => \$::device, ) || die "Getoptions"; - - -# get a console for the app - -my $line; -my $command; -my $arg; - -my @procsysobd_objects = ('debug', 'index', 'reset', 'trace', 'vars'); - -my %commands = - ('status' => {func => "Status", doc => "status: show obd device status"}, - 'procsys' => {func => "Procsys", doc => "procsys (set /proc/sys/obd configuration)"}, - 'shell' => {func => "Shell", doc => "shell : execute shell-commands"}, - 'script' => {func => "Script", doc => "script : read and execute commands from a file"}, - 'insmod' => {func => "Insmod", doc => "insmod : insert kernel module"}, - 'rmmod' => {func => "Rmmod", doc => "rmmod : insert kernel module"}, - 'lsmod' => {func => "Lsmod", doc => "lsmod : list kernel modules"}, - 'device' => {func => "Device", doc => "device : open another OBD device"}, - 'close' => {func => "Close", doc => "close : close OBD device"}, - 'create' => {func => "Create", doc => "create [ [ [quiet]]]: create new object(s) (files, unless mode is given)"}, - 'attach' => {func => "Attach", doc => "attach { obdext2 | obdsnap snapdev snapidx tableno | obdscsi adapter bus tid lun }: attach this minor device to the specified driver" }, - 'detach' => {func => "Detach", doc => "detach this minor device"}, - 'testext2iterator' => {func => "TestExt2Iterator", doc => "test ext2 iterator function"}, - 'snapset' => {func => "SnapSetTable", doc => "snapset : set the table (created with snaptable) as table #tableno" }, - 'snapprint' => {func => "SnapPrint", doc => "snapprint : output the contents of table #tableno to the syslog"}, - 'snapdelete' => {func => "SnapDelete", doc => "snapdelete: delete connected snap obd objects from disk"}, - 'snaprestore' => {func => "SnapRestore", doc => "snaprestore : restore connected old snap objects to be current"}, - 'snaptable' => {func => "SnapShotTable", doc => "snaptable: build a snapshot table (interactive)"}, - 'copy' => {func => "Copy", doc => "copy : copy objects"}, - 'migrate' => {func => "Migrate", doc => "migrate : migrate data from one object to another"}, -# FIXME: obsolete? - 'partition' => {func => "Partition", doc => "partition : create a partition"}, -# FIXME: obsolete? - 'format' => {func => "Format", doc => "format : format a partition"}, - 'setup' => {func => "Setup", doc => "setup [type]: link this OBD device to the underlying device (default type obdext2)"}, - 'connect' => {func => "Connect", doc => "connect: allocates client ID for this session"}, - 'disconnect' => {func => "Disconnect", doc => "disconnect [id]: frees client resources"}, - 'sync' => {func => "Sync", doc => "sync: flushes buffers to disk"}, - 'destroy' => {func => "Destroy", doc => "destroy : destroys an object"}, - 'cleanup' => {func => "Cleanup", doc => "cleanup the minor obd device"}, -# FIXME: obsolete? - 'dec_use_count' => {func => "Decusecount", doc => "decreases the module use count so that the module can be removed following an oops"}, - 'read' => {func => "Read", doc => "read [offset]: read data from object"}, -# FIXME: obsolete? - 'fsread' => {func => "Read2", doc => "read [offset]: read data from object"}, - 'write' => {func => "Write", doc => "write : write data to object"}, - 'punch' => {func => "Punch", doc => "punch : punch a hole in object"}, - 'setattr' => {func => "Setattr", doc => "setattr [mode [uid [gid [size [atime [mtime [ctime]]]]]]]: sets object attributes"}, - 'getattr' => {func => "Getattr", doc => "getattr : displays object attributes"}, - 'preallocate' => {func => "Preallocate", doc => "preallocate [num]: requests preallocation of num objects."}, - 'statfs' => {func => "Statfs", doc => "statfs: filesystem status information"}, - 'help' => {func => \&Help, doc => "help: this message"}, - 'quit' => {func => \&Quit, doc => "see \"exit\""}, - 'exit' => {func => \&Quit, doc => "see \"quit\""} - ); - -# -# setup completion function -# -my @jcm_cmd_list = keys %commands; - -my $term, $attribs; - - -# Get going.... - -Device($::device); - -sub readl { - if ( $file ) { - my $str = ; - chop($str); - return $str; - } else { - return $term->readline(@_); - } -} - - - -if ( $file ) { - while ( ) { - print $_; - my $rc = execute_line($_); - if ($rc != 0) { last; } - } - exit 0; -} else { - $term = new Term::ReadLine 'obdcontrol '; - $attribs = $term->Attribs; - $attribs->{attempted_completion_function} = \&completeme; - $term->ornaments('md,me,,'); # bold face prompt - - # make sure stdout is not buffered - STDOUT->autoflush(1); - - - # Get on with the show - process_line(); -} - -#------------------------------------------------------------------------------ -sub completeme { - my ($text, $line, $start, $end) = @_; - if (substr($line, 0, $start) =~ /^\s*$/) { - if ($] < 5.6) { # PErl version is less than 5.6.0 - return (exists $commands{$text}) ? $text : 0; -#Above line doesn't perform command completion, but -#perl5.005 Term-ReadLine lacks support for completion matching -#and perl5.6.0 requires glibc2.2.2 that won't run under Redhat6.2......sigh. - } - else { - $attribs->{completion_word} = \@jcm_cmd_list; - return $term->completion_matches($text, - $attribs->{'list_completion_function'}); - } - } -} - -sub find_command { - my $given = shift; - my $name; - my @completions = completeme($given, $given, 0, length($given)); - if ($#completions == 0) { - $name = shift @completions; - } - - return $name; -} - -# start making requests -sub process_line { - foo: - $line = $term->readline("obdcontrol > "); - execute_line($line); - goto foo; -} - -sub execute_line { - my $line = shift; - - my @cmdline = split(' ', $line); - my $word = shift @cmdline; - - return 0 unless ($word); - - my $cmd; - if ( $file ) { - $cmd = $word; - } else { - $cmd = find_command($word); - } - unless ($cmd) { - printf STDERR "$word: No such command, or not unique.\n"; - return (-1); - } - - # Call the function. - return (&{$commands{$cmd}->{func}}(@cmdline)); -} - -my %opendevfds = (); - -# select the OBD device we talk to -sub Device { - my $device = shift; - - if ( ! $device && ! $::device ) { # first time ever - $device = '/dev/obd0'; - } - - if (($device) && ($::device ne $device)) { - local *NEW_OBD; - my $newfd; - - if ($::client_id) { - print "Disconnecting active session ($::client_id)..."; - Disconnect($::client_id); - } - - if ($opendevfds{$device}) { - $::dev_obd = $opendevfds{$device}; - } - else { - # Open the device, as we need an FD for the ioctl - if (!sysopen(NEW_OBD, $device, 0)) { - print "Cannot open $device. Did you insert the obdclass module ?\n"; - return -1; - } - print "Opened device $device\n"; - $opendevfds{$device} = *NEW_OBD; - $::dev_obd = *NEW_OBD; - } - $::device = $device; - } - print "Current device is $::device\n"; - return 0; -} - -sub Close { - my $device = shift; - my $fd2close; - - if ( ! $device && ! $::device ) { # first time ever - print "Nothing to close\n"; - return -1; - } - - if ( ! $device ) { - $device = $::device; - } - - if ($::device eq $device) { - if ($::client_id) { - print "Disconnecting active session ($::client_id)..."; - Disconnect($::client_id); - } - } - - $fd2close = $opendevfds{$device}; - if ($fd2close) { # XXXX something wrong in this if statement - close ($fd2close); - $opendevfds{$device} = undef; - print "Closed device $device\n"; - } - else { - print "Device $device was not open\n"; - return -1; - } - - if ($::device eq $device) { - $::dev_obd = undef; - $::device = undef; - } - print "No current device. You just closed the current device ($device).\n"; - return 0; -} - -sub Script { - my $cmdfilename = shift; - my $rc = 0; - if ( ! $cmdfilename ) { - print "please specify a command file name\n"; - return -1; - } - if (! open(CMDF, $cmdfilename)) { - print "Cannot open $cmdfilename: $!\n"; - return -1; - } - while () { - if (/^#/) { - next; - } - print "execute> $_"; - $rc = execute_line($_); - if ($rc != 0) { - print "Something went wrong .......command exit status: $rc\n"; - last; - } - } - close(CMDF); - return $rc; -} - -sub Shell { - my $user_shell=$ENV{'SHELL'}; - print "% $user_shell -c '@_'\n"; - if ( ! @_ ) { - print "please specify a shell command\n"; - return; - } - system("$user_shell -c '@_'"); - return ($? >> 8); -} - -sub Status { - my $oldfh = select(STDOUT); - $| = 1; - - system('cat /proc/lustre/obd/*/status'); - my $rc = ($? >> 8); - - select($oldfh); - $| = 0; - - return $rc; -} - -sub Procsys { - my $set_sysobd = shift; - my $value = shift; - - foreach $i (0 .. $#procsysobd_objects) { - my $sysobd = $procsysobd_objects[$i]; - - if (defined $set_sysobd) { - if ($sysobd ne $set_sysobd) { next; } - - if (defined $value) { # set this one - system("echo \"$value\" > /proc/sys/obd/$sysobd"); - } - system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd"); - last; - } - else { - system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd"); - } - } - return ($? >> 8); -} - -sub Insmod { - my $module = shift; - system("insmod $module"); - return ($? >> 8); -} - -sub Rmmod { - my $module = shift; - system("rmmod $module"); - return ($? >> 8); -} - -sub Lsmod { - my $module = shift; - system("lsmod $module"); - return ($? >> 8); -} - -sub Attach { - my $err = 0; - my $type = shift; - my $data; - my $datalen = 0; - - if ( ! $type ) { - print "error: missing type\n"; -usage: - print "usage: attach {obdext2 | obdsnap | obdscsi | obdtrace }\n"; - return -1; - } - - if ($type eq "obdscsi" ) { - my $adapter = shift; - my $bus = shift; - my $tid = shift; - my $lun = shift; - - $data = pack("iiii", $adapter, $bus, $tid, $lun); - $datalen = 4 * 4; - } elsif ($type eq "obdsnap" ) { - my $snapdev = shift; - my $snapidx = shift; - my $tableno = shift; - - $data = pack("iii", $snapdev, $snapidx, $tableno); - $datalen = 3 * 4; - } elsif ($type eq "obdext2") { - $data = pack("i", 4711); # bogus data - $datalen = 4; - } elsif ($type eq "obdtrace") { - $data = pack("i", 4711); # bogus data - $datalen = 4; - } else { - print "error: unknown attach type $type\n"; - goto usage; - } - - my $len = length($type); - my $cl = length($data); - - print "type $type (len $len), datalen $datalen ($cl)\n"; - my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_ATTACH, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - - -sub Detach { - my $err = 0; - my $data = ""; - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_IOC_DETACH, $data); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - - -sub TestExt2Iterator { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; - } - - my $err = 0; - my $type = "obdext2"; - - $data = pack("i", 4711); # bogus data - $datalen = 4; - - my $len = length($type); - my $cl = length($data); - print "type $type (len $len), datalen $datalen ($cl)\n"; - my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_EXT2_RUNIT, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - - -sub SnapDelete { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $err = 0; - my $type = "obdsnap"; - - $data = pack("i", 4711); # bogus data - $datalen = 4; - - my $len = length($type); - my $cl = length($data); - print "type $type (len $len), datalen $datalen ($cl)\n"; - my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); - - # XXX We need to fix this up so that after the objects in this snapshot - # are deleted, the snapshot itself is also removed from the table. - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_SNAP_DELETE, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - - -# this routine does the whole job -sub SnapRestore { - my $restoreto = shift; - my $snaptable = shift; - my $tableno = shift; - my $restoretime; - - # don't do anything until connected - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - if ( ! $snaptable || ! defined $restoreto ) { - print "Usage: snaprestore \"restore to slot\" \"snaptable\" \"tableno\"\n"; - return -1; - } - - if ( ! -f $snaptable ) { - print "Table $snaptable doesn't exist\n"; - return -1; - } - - my $table = ReadSnapShotTable($snaptable); - $restoretime = FindSnapInTable($table, $restoreto); - if ( ! defined $table->{0} || ! defined $restoretime ) { - PrintSnapShotTable($table); - print "No current or $restoreto slot in this table\n"; - return -1; - } - - my $currentindex = $table->{0}; - if ( $table->{$restoretime} == $currentindex ) { - print "You should not restore to the current snapshot\n"; - return -1; - } - - # swap the entries for 0 and $restoreto - my $tmp = $table->{$restoretime}; - $table->{$restoretime} = $table->{0}; - $table->{0} = $tmp; - # PrintSnapShotTable($table); - - # write it back - WriteSnapShotTable($snaptable, $table); - - # set it in the kernel - SnapSetTable($tableno, $snaptable); - - # ready for the ioctl - my $err = 0; - my $type = "obdsnap"; - $data = pack("i", $currentindex); # slot of previous current snapshot - $datalen = 4; - - my $len = length($type); - my $cl = length($data); - my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_SNAP_RESTORE, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Snaprestore finished (success)\n"; - delete $table->{$restoretime} if defined $restoretime; - # write it back - WriteSnapShotTable($snaptable, $table); - - # set it in the kernel - SnapSetTable($tableno, $snaptable); - # PrintSnapShotTable($table); - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub FindSnapInTable { - my $table = shift; - my $snapno =shift; - - foreach my $restoretime ( keys %{$table} ) { - if ( $table->{$restoretime} == $snapno) { - print "Found key $restoretime for snapno $snapno\n"; - return $restoretime; - } - } - undef; -} - - -sub SnapPrint { - my $err = 0; - my $type = "obdsnap"; - my $snaptableno = shift; - - $data = pack("i", $snaptableno); - $datalen = 4; - - my $len = length($type); - my $cl = length($data); - print "type $type (len $len), datalen $datalen ($cl)\n"; - my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_SNAP_PRINTTABLE, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub SnapSetTable { - my $err = 0; - my $type = "obdsnap"; - my $snaptableno = shift; - my $file = shift; - my $snapcount; - my $table = {}; - my $data; - my $datalen = 0; - - if ( ! -f $file ) { - print "No such file $file\n"; - return -1; - } - - $table = ReadSnapShotTable($file); - - $snapcount = keys %{$table}; - print "Snapcount $snapcount\n"; - - if ( ! defined $table->{0} ) { - print "No current snapshot in table! First make one\n"; - return -1; - } - $data = pack("ii", $snaptableno, $snapcount); - $datalen = 2 * 4; - foreach my $time (sort keys %{$table}) { - # XXX we should change to pack LL instead of I for times - $data .= pack("Ii", $time, $table->{$time}); - $datalen += 8; - } - - my $len = length($type); - my $cl = length($data); - print "type $type (len $len), datalen $datalen ($cl)\n"; - my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_SNAP_SETTABLE, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - - -sub SnapShotTable { - - my $file = &readl("enter file name: "); - if ( ! -f $file ) { - `touch $file`; - } - my $table = ReadSnapShotTable($file); - - again: - PrintSnapShotTable($table); - my $action = &readl("Add, Delete or Quit [adq]: "); - goto done if ($action =~ "^q.*" ); - goto add if ($action =~ "^a.*"); - goto del if ($action =~ "^d.*"); - goto again; - - add: - my $idx = &readl("enter index where you want this snapshot: "); - my $time = &readl("enter time or 'now' or 'current': "); - my $oldtime = SnapFindTimeFromIdx($idx, $table); - if (defined $oldtime) { - print "This already exists, first clean up\n"; - goto again; - } - - if ( $time eq 'now' ) { - $time = time; - } elsif ( $time eq 'current' ) { - $time = 0; - } - $table->{$time} = $idx; - goto again; - - del: - $didx = &readl("Enter index to delete: "); - my $deltime = SnapFindTimeFromIdx($didx, $table); - delete $table->{$deltime} if defined $deltime; - goto again; - - done: - my $ok = &readl("OK with new table? [Yn]: "); - unless ( $ok eq "n" ) { - WriteSnapShotTable($file, $table); - } - return 0; -} - -sub SnapFindTimeFromIdx { - my $idx = shift; - my $table = shift; - - foreach my $time ( keys %{$table} ) { - if ( $table->{$time} == $idx ) { - return $time; - } - } - undef; -} - -sub PrintSnapShotTable { - my $table = shift; - my $time; - - foreach $time ( sort keys %{$table} ) { - my $stime = localtime($time); - if ( ! $time ) { - $stime = "current"; - } - printf "Time: %s -- Index %d\n", $stime, $table->{$time}; - } -} - -sub ReadSnapShotTable { - - my $file = shift; - my $table = {}; - - open FH, "<$file"; - while ( ) { - my ($time, $index) = split ; - $table->{$time} = $index; - } - close FH; - - PrintSnapShotTable($table); - - return $table; -} - -sub WriteSnapShotTable { - my $file = shift; - my $table = shift; - - open FH, ">$file"; - foreach my $time ( sort keys %{$table} ) { - print FH "$time $table->{$time}\n"; - } - close FH; -} - -sub Copy { - my $err = 0; - my $src_obdo; - my $dst_obdo; - - # Note: _copy IOCTL takes parameters as dst, src. - # Copy function takes parameters as src, dst. - $src_obdo->{id} = shift; - $dst_obdo->{id} = shift; - $src_obdo->{valid} = &OBD_MD_FLALL; - - # XXX need to fix copy so we can have 2 client IDs here - my $packed = pack("L", $::client_id) . obdo_pack($dst_obdo) . pack("L", $::client_id) . obdo_pack($src_obdo); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_IOC_COPY, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Migrate { - my $err = 0; - - # Note: _migr IOCTL takes parameters as dst, src. - # Migrate function takes parameters as src, dst. - $src_obdo->{id} = shift; - $dst_obdo->{id} = shift; - $src_obdo->{valid} = &OBD_MD_FLALL; - - # We pack a dummy connection ID here - my $packed = pack("L", $::client_id) . obdo_pack($dst_obdo) . pack("L", $::client_id) . obdo_pack($src_obdo); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - - my $rc = ioctl($::dev_obd, &OBD_IOC_MIGR, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - - -sub Format { - my $err = 0; - my $size = shift; - my $data = pack("i", $size); - my $datalen = 4; - - my $packed = pack("ip", $datalen, $data); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_FORMATOBD, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Partition { - my $err = 0; - my $partno = shift; - my $size = shift; - my $data = pack("ii", $partno, $size); - my $datalen = 2 * 4; - - my $packed = pack("ip", $datalen, $data); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_PARTITION, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Setup { - my $err = 0; - my $arg = shift; - my $data; - my $datalen = 0; - - # XXX we need a getinfo ioctl to validate parameters - # by type here - - if ($arg && !defined($::st = stat($arg))) { - print "$arg is not a valid device\n"; - return -1; - } - - printf "setting up %s, device %x\n", $arg, $::st->rdev(); - if ( $arg ) { - $data = $arg; - $datalen = length($arg)+1; # need null character also - } - - my $packed = pack("iip", $datalen, $::st->rdev(), $data); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_SETUP, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Cleanup { - my $err = "0"; - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_CLEANUP, $err); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - $::client_id = 0; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - - -sub Connect { - my $rc; - - my $packed = ""; - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - $rc = ioctl($::dev_obd, &OBD_IOC_CONNECT, $packed); - $id = unpack("I", $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - $::client_id = $id; - print "Client ID : $id\n"; - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Disconnect { - my $id = shift; - - if (!defined($id)) { - $id = $::client_id; - } - - if (!defined($id)) { - print "syntax: disconnect [client ID]\n"; - print "When client ID is not given, the last valid client ID to be returned by a\n"; - print "connect command this session is used; there is no such ID.\n"; - return -1; - } - - my $packed = pack("L", $id); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_DISCONNECT, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - $::client_id = undef; - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Create { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $num = shift; - my $mode = shift; - my $quiet = shift; - my $rc; - my $prealloc = 0; - - if (!defined($num)) { - $num = 1; - } - - if (!defined($mode)) { - $mode = 0100644; # create a file (rw-r--r--) if not specified - } - - if (scalar($num) < 1 || defined($quiet) && $quiet ne "quiet") { - print "usage: create [ [ [quiet]]]\n"; - return -1; - } - - my $i; - my $id = 0; # can't currently request IDs - - print "Creating " . scalar($num) . " object"; - if (scalar($num) > 1) { - print "s"; - } - print "\n"; - - for ($i = 0; $i < scalar($num); $i++) { - my $obdo; - $obdo->{id} = $id; - $obdo->{mode} = scalar($mode); - $obdo->{valid} = &OBD_MD_FLMODE; - - my $packed = pack("I", $::client_id) . obdo_pack($obdo); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - $rc = ioctl($::dev_obd, &OBD_IOC_CREATE, $packed); - if ($rc ne "0 but true") { - last; - } elsif (!defined($quiet)) { - $obdo = obdo_unpack($packed, 4); - print "Created object #$obdo->{id}.\n"; - } - } - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Sync { - my $err = "0"; - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_SYNC, $err); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Destroy { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $id = shift; - - if (!defined($id) || scalar($id) < 1) { - print "usage: destroy \n"; - return -1; - } - - print "Destroying object $id...\n"; - my $packed = pack("IL", $::client_id, $id); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_DESTROY, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Getattr { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $id = shift; - - if (!defined($id) || scalar($id) < 1) { - print "invalid arguments; type \"help getattr\" for a synopsis\n"; - return -1; - } - - # see Setattr - my $obdo; - $obdo->{id} = $id; - $obdo->{valid} = &OBD_MD_FLALL; - my $packed = pack("L", $::client_id) . obdo_pack($obdo); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_GETATTR, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - $obdo = obdo_unpack($packed, 4); - obdo_print($obdo); - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Setattr { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $id = shift; - - if (!defined($id) || scalar($id) < 1) { - print "invalid arguments; type \"help setattr\" for a synopsis\n"; - return -1; - } - - # XXX we do not currently set all of the fields in the obdo - my $obdo; - $obdo->{id} = $id; - $obdo->{mode} = oct(shift); - $obdo->{uid} = shift; - $obdo->{gid} = shift; - $obdo->{size} = shift; - $obdo->{atime} = shift; - $obdo->{mtime} = shift; - $obdo->{ctime} = shift; - $obdo->{valid} = 0; - - if (defined($obdo->{atime})) { - $obdo->{valid} |= &OBD_MD_FLATIME; - } - if (defined($obdo->{mtime})) { - $obdo->{valid} |= &OBD_MD_FLMTIME; - } - if (defined($obdo->{ctime})) { - $obdo->{valid} |= &OBD_MD_FLCTIME; - } - if (defined($obdo->{size})) { - $obdo->{valid} |= &OBD_MD_FLSIZE; - } - if (defined($obdo->{mode})) { - $obdo->{valid} |= &OBD_MD_FLMODE; - } - if (defined($obdo->{uid})) { - $obdo->{valid} |= &OBD_MD_FLUID; - } - if (defined($obdo->{gid})) { - $obdo->{valid} |= &OBD_MD_FLGID; - } - - printf "valid is %x, mode is %o\n", $obdo->{valid}, $obdo->{mode}; - my $packed = pack("L", $::client_id) . obdo_pack($obdo); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_SETATTR, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Read { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $id = shift; - my $count = shift; - my $offset = shift; - - if (!defined($id) || scalar($id) < 1 || !defined($count) || - $count < 1 || (defined($offset) && $offset < 0)) { - print "invalid arguments; type \"help read\" for a synopsis\n"; - return -1; - } - - if (!defined($offset)) { - $offset = 0; - } - - print("Reading $count bytes starting at byte $offset from object " . - "$id...\n"); - - # "allocate" a large enough buffer - my $buf = sprintf("%${count}s", " "); - die "suck" if (length($buf) != $count); - - my $obdo; - $obdo->{id} = $id; - - # the perl we're using doesn't support pack type Q, and offset is 64 bits - my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $buf, $count, $offset); - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_READ, $packed); - - $retval = unpack("l", $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print substr($buf, 0, $retval); - print "\nRead $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - return 0; - } else { - print "Finished (error $retval)\n"; - return $retval; - } - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Read2 { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $id = shift; - my $count = shift; - my $offset = shift; - - if (!defined($id) || scalar($id) < 1 || !defined($count) || - $count < 1 || (defined($offset) && $offset < 0)) { - print "invalid arguments; type \"help read\" for a synopsis\n"; - return -1; - } - - if (!defined($offset)) { - $offset = 0; - } - - print("Reading $count bytes starting at byte $offset from object " . - "$id...\n"); - - # "allocate" a large enough buffer - my $buf = sprintf("%${count}s", " "); - die "suck" if (length($buf) != $count); - - my $obdo; - $obdo->{id} = $id; - - # the perl we're using doesn't support pack type Q, and offset is 64 bits - my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $buf, $count, $offset); - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_READ2, $packed); - - $retval = unpack("l", $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print substr($buf, 0, $retval); - print "\nRead $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - return 0; - } else { - print "Finished (error $retval)\n"; - return $retval; - } - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Write { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $id = shift; - my $offset = shift; - my $text = join(' ', @_); - my $count = length($text); - - if (!defined($id) || scalar($id) < 1 || !defined($offset) || - scalar($offset) < 0) { - print "invalid arguments; type \"help write\" for a synopsis\n"; - return -1; - } - - if (!defined($text)) { - $text = ""; - $count = 0; - } - - print("Writing $count bytes starting at byte $offset to object $id...\n"); - - my $obdo; - $obdo->{id} = $id; - - # the perl we're using doesn't support pack type Q - my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $text, $count, $offset); - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_WRITE, $packed); - - $retval = unpack("l", $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print "\nWrote $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - return 0; - } else { - print "Finished (error $retval)\n"; - return $retval; - } - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Punch { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - my $id = shift; - my $start = shift; - my $count = shift; - - if (!defined($id) || scalar($id) < 1 || !defined($start) || - scalar($start) < 0 || !defined($count) || scalar($count) < 0) { - print "invalid arguments; type \"help punch\" for a synopsis\n"; - return -1; - } - - print("Punching $count bytes starting at byte $start from object $id...\n"); - - my $obdo; - $obdo->{id} = $id; - - # the perl we're using doesn't support pack type Q - my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $buf, $start, $count); - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_PUNCH, $packed); - - $retval = unpack("l", $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print "\nPunched $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - return 0; - } else { - print "Finished (error $retval)\n"; - return $retval; - } - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Preallocate { - my $num = shift; - - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - if (!defined($num) || scalar($num) < 1 || scalar($num) > 32) { - $num = 32; - } - - print "Preallocating $num objects...\n"; - # client id, alloc, id[32] - my $packed = pack("LLx128", $::client_id, $num); - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_PREALLOCATE, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - my $alloc = unpack("x4L", $packed); - my @ids = unpack("x8L32", $packed); - my $i; - - print "Got $alloc objects: "; - foreach $i (@ids) { - print $i . " "; - } - print "\nFinished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Decusecount { - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_DEC_USE_COUNT, 0); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Statfs { - if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return -1; - } - - # struct statfs { - # long f_type; - # long f_bsize; - # long f_blocks; - # long f_bfree; - # long f_bavail; - # long f_files; - # long f_ffree; - # __kernel_fsid_t f_fsid; (64 bits) - # long f_namelen; - # long f_spare[6]; - # }; - - my $packed = pack("LLLLLLLIILL6", $::client_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0); - - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } - my $rc = ioctl($::dev_obd, &OBD_IOC_STATFS, $packed); - - if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; - return -1; - } elsif ($rc eq "0 but true") { - # skip both the conn_id and the fs_type in the buffer - my ($bsize, $blocks, $bfree, $bavail, $files, $ffree) = - unpack("x4x4LLLLLL", $packed); - print("$bsize byte blocks: $blocks, " . ($blocks - $bfree) . " used, " . - "$bfree free ($bavail available).\n"); - print "$files files, " . ($files - $ffree) . " used, $ffree free.\n"; - print "Finished (success)\n"; - return 0; - } else { - print "ioctl returned error code $rc.\n"; - return -1; - } -} - -sub Help { - my $cmd = shift; - - if ( !$cmd || !$commands{$cmd} ) { - print "Comands: ", join( ' ', @jcm_cmd_list), "\n"; - } else { - print "Usage: " . $commands{$cmd}->{doc} . "\n"; - } - return 0; -} - -sub Quit { - if ($::client_id) { - print "Disconnecting active session ($::client_id)..."; - Disconnect($::client_id); - } - exit; -} diff --git a/lustre/utils/obdctl.c b/lustre/utils/obdctl.c index 979a665..656f0fd 100644 --- a/lustre/utils/obdctl.c +++ b/lustre/utils/obdctl.c @@ -390,13 +390,42 @@ static int jt_destroy(int argc, char **argv) return rc; } +static int jt_multi_getattr(int argc, char **argv) +{ + struct obd_ioctl_data data; + int count, i; + int rc; + + IOCINIT(data); + if (argc == 2) { + count = strtoul(argv[1], NULL, 0); + data.ioc_obdo1.o_valid = 0xffffffff; + data.ioc_obdo1.o_id = 2; + printf("getting %d attrs (testing only)\n", count); + } else { + printf("usage %s id\n", argv[0]); + return 0; + } + + for (i = 0 ; i < count; i++) { + rc = ioctl(fd, OBD_IOC_GETATTR , &data); + if (rc) { + printf("Error: %s on i=%d\n", strerror(rc), i); + break; + } else { + printf("attr number %d\n", i); + } + } + return 0; +} + static int jt_getattr(int argc, char **argv) { struct obd_ioctl_data data; int rc; IOCINIT(data); - if (argc != 1) { + if (argc == 2) { data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0); data.ioc_obdo1.o_valid = 0xffffffff; printf("getting attr for %Ld\n", data.ioc_obdo1.o_id); @@ -419,10 +448,11 @@ static int jt_modules(int argc, char **argv) { char *modules[] = {"portals", "ksocknal", "obdclass", "ptlrpc", "obdext2", "ost", "osc", "mds", "mdc", "llight", - NULL}; + "obdecho", NULL}; char *paths[] = {"portals/linux/oslib", "portals/linux/socknal", "obd/class", "obd/rpc", "obd/ext2obd", "obd/ost", - "obd/osc", "obd/mds", "obd/mdc", "obd/llight", NULL}; + "obd/osc", "obd/mds", "obd/mdc", "obd/llight", + "obd/obdecho", NULL}; char *path = ".."; char *kernel = "linux"; int i; @@ -469,6 +499,7 @@ command_t list[] = { {"cleanup", jt_cleanup, 0, "cleanup the current device (arg: )"}, {"create", jt_create, 0, "create [count [mode [silent]]]"}, {"destroy", jt_destroy, 0, "destroy id"}, + {"test_getattr", jt_multi_getattr, 0, "test_getattr count [silent]"}, {"getattr", jt_getattr, 0, "getattr id"}, {"setattr", jt_setattr, 0, "setattr id mode"}, {"connect", jt_connect, 0, "connect - get a connection to device"}, -- 1.8.3.1