Whamcloud - gitweb
* obdfs/flushd.c: conditionalized number of C_DEBUG messages.
authorrzahir <rzahir>
Tue, 3 Jul 2001 01:01:24 +0000 (01:01 +0000)
committerrzahir <rzahir>
Tue, 3 Jul 2001 01:01:24 +0000 (01:01 +0000)
        * include/linux/obd_class.h: added obd_devicename member to
          struct obd_device (name is either ptr to dentry or uuid).
        * ext2obd/ext2_obd.c: setup() converts dentry into rdev number.
          class/class_obd.c: setup() converts name into obd_device dentry
          class/obdcontrol: setup() passes /dev/obd name into ioctl
          (used to be rdev number and if invalid rdev number was passed
           old ext2_obd.c would crash kernel when trying to read superblock).
        * class/obdcontrol: added "status, procsys, script, insmod, rmmod,
          lsmod, shell and close" commands for obdcontrol. This allows
          easier scripting from within obdcontrol. Introduced ability to
          maintain multiple open obd devices from a single obdcontrol
          session.  Device command toggles device context. Obdcontrol
          maintains multiple open file handles. "script <file>" command is
          useful for "sourcing" scripts without leaving obdcontrol.
          shell <command> allows any shell command to be executed from
          within obdcontrol.
        * class/proc_lustre.c: added support for /proc/lustre/obd/<n>/status.
          These are read-only /proc entries that track /dev/obd<n>
          internal state.
        * obdtrace/* & include/linux/obd_class.h: obd_trace a logical obd
          module useful for tracing and performance debug of the Lustre
          obd protocol stack. obdtrace module creates
          /proc/lustre/obd/<n>/stats file. Reading this /proc file shows
          per OBD performance statistics.  Any write to this /proc file
          resets the counters for this OBD.
        * scripts/obdtrace_demo.scr: Example of obdtrace that
          takes advantage of new obdcontrol functionality.
        * doc/obdtrace_demo.txt: shows obdtrace capabilities.

12 files changed:
lustre/include/linux/obd_class.h
lustre/include/linux/obd_support.h
lustre/include/linux/obd_trace.h [new file with mode: 0644]
lustre/obdclass/Makefile
lustre/obdclass/class_obd.c
lustre/obdclass/genops.c
lustre/obdclass/obdcontrol
lustre/obdclass/proc_lustre.c [new file with mode: 0644]
lustre/obdclass/sysctl.c
lustre/obdfs/flushd.c
lustre/scripts/mkobddevs [new file with mode: 0755]
lustre/scripts/obdtrace_demo.scr [new file with mode: 0644]

index 93a5338..2df81c8 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/obd_ext2.h>
 #include <linux/obd_snap.h>
+#include <linux/obd_trace.h>
 /* #include <linux/obd_fc.h> */
 #include <linux/obd_raid1.h>
 #include <linux/obd_rpc.h>
@@ -98,12 +99,19 @@ struct obd_conn {
         uint32_t oc_id;
 };
 
+typedef union {
+        struct dentry *dentry;   /* file system obd device names */
+        __u8           _uuid[16]; /* uuid obd device names */
+} obd_devicename;
+
 /* corresponds to one of the obdx */
 struct obd_device {
         struct obd_type *obd_type;
         int obd_minor;
         int obd_flags;
         int obd_refcnt; 
+        obd_devicename obd_fsname; 
+       struct proc_dir_entry *obd_proc_entry;
         int obd_multi_count;
         struct obd_conn obd_multi_conn[MAX_MULTI];
         unsigned int obd_gen_last_id;
@@ -113,11 +121,16 @@ struct obd_device {
                 struct ext2_obd ext2;
                 struct raid1_obd raid1;
                 struct snap_obd snap;
-                struct rpc_obd rpc;
+               struct trace_obd trace;
                 /* struct fc_obd fc; */
         } u;
 };
 
+extern struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device *obd);
+extern void proc_lustre_release_obd_device(struct obd_device *obd);
+extern void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd);
+
+
 /*
  *  ======== OBD Operations Declarations ===========
  */
@@ -449,7 +462,7 @@ int gen_multi_attach(struct obd_device *obddev, uint32_t len, void *data);
 int gen_multi_detach(struct obd_device *obddev);
 int gen_connect (struct obd_conn *conn);
 int gen_disconnect(struct obd_conn *conn);
-struct obd_client *gen_client(struct obd_conn *);
+struct obd_client *gen_client(const struct obd_conn *);
 int gen_cleanup(struct obd_device *obddev);
 int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst,
                   struct obd_conn *src_conn, struct obdo *src,
index a0b996c..cbe8325 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _OBD_SUPPORT
 #define _OBD_SUPPORT
+#include <linux/autoconf.h>
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
 
@@ -42,8 +43,9 @@ extern long obd_memory;
 #define D_INFO    0x200 /* general information, especially from interface.c */
 #define D_IOCTL   0x400 /* ioctl related information */
 #define D_BLOCKS  0x800 /* ext2 block allocation */
-#define D_RPC    0x1000 /* rpc communications */
+#define D_NET    0x1000 /* network communications */
 #define D_PUNCH  0x2000
+#define D_BUFFS  0x4000 /* print network buffers */
  
 #define CDEBUG(mask, format, a...)                                      \
         do {                                                            \
@@ -191,3 +193,4 @@ do {                                                    \
 
 
 #endif
+
diff --git a/lustre/include/linux/obd_trace.h b/lustre/include/linux/obd_trace.h
new file mode 100644 (file)
index 0000000..27b05c5
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * obdtrace (header file) - is useful for tracing and performance
+ * debug of the Lustre obd protocol stack. obdtrace is a transparent
+ * logical obd driver that prints commands their in- and outbound
+ * parameters.  obdtrace maintains statistics about number and latency
+ * of the obd commands that pass through it. As such it is also use
+ * for performance analysis.
+ *
+ * Copyright (c) 2001  Rumi Zahir <rumi.zahir@intel.com>
+ */
+
+#ifndef __OBD_TRACE_H
+#define __OBD_TRACE_H
+
+struct obd_device;
+struct obdtrace_opstats;
+
+struct trace_obd {
+  struct obdtrace_opstats *stats;
+};
+
+#endif
index cf82363..085cc91 100644 (file)
@@ -1,6 +1,6 @@
 
 MODULE = obdclass.o
 
-CFILES = genops.c class_obd.c sysctl.c 
+CFILES = genops.c proc_lustre.c class_obd.c sysctl.c 
 
 include ../make.rules
index 6940caa..0ee1298 100644 (file)
@@ -79,6 +79,9 @@ static int obd_class_open(struct inode * inode, struct file * file)
         CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
                obd_dev[dev].obd_refcnt);
 
+       obd_dev[dev].obd_proc_entry = 
+               proc_lustre_register_obd_device(&obd_dev[dev]);
+
         MOD_INC_USE_COUNT;
         EXIT;
         return 0;
@@ -101,6 +104,9 @@ static int obd_class_release(struct inode * inode, struct file * file)
                        obd_dev[dev].obd_refcnt);
         obd_dev[dev].obd_refcnt--;
 
+       if (obd_dev[dev].obd_proc_entry && (obd_dev[dev].obd_refcnt==0))
+               proc_lustre_release_obd_device(&obd_dev[dev]);
+
         CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
                obd_dev[dev].obd_refcnt);
         MOD_DEC_USE_COUNT;
@@ -154,6 +160,21 @@ static int getdata(int len, void **data)
         return 0;
 }
 
+
+static int obd_devicename_from_path(obd_devicename* whoami, 
+                                   char* user_string) 
+{
+  struct nameidata nd;
+  int err;
+
+  err = user_path_walk(user_string, &nd);
+  if (!err) { 
+    whoami->dentry = nd.dentry;
+    path_release(&nd);
+  }
+  return err;
+}
+
 /* to control /dev/obdNNN */
 static int obd_class_ioctl (struct inode * inode, struct file * filp, 
                             unsigned int cmd, unsigned long arg)
@@ -311,10 +332,12 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
         case OBD_IOC_SETUP: {
                 struct ioc_setup {
                         int setup_datalen;
-                        void *setup_data;
+                        char *setup_data;
                 } *setup;
+
                 setup = tmp_buf;
 
+
                 ENTRY;
                 /* have we attached a type to this device */
                 if (!(obddev->obd_flags & OBD_ATTACHED)) {
@@ -331,19 +354,23 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                         return -EBUSY;
                 }
 
-                /* get main structure */
-                err = copy_from_user(setup, (void *) arg, sizeof(*setup));
-                if (err) {
-                        EXIT;
-                        return err;
-                }
 
-                err = getdata(setup->setup_datalen, &setup->setup_data);
-                if (err) {
-                        EXIT;
-                        return err;
-                }
 
+               /* get main structure */
+               err = copy_from_user(setup, (void *) arg, sizeof(*setup));
+               if (err) {
+                 EXIT;
+                 return err;
+               }
+               
+               err = obd_devicename_from_path(&(obddev->obd_fsname),
+                                               (char*) setup->setup_data);
+               if (err) {
+                 memset(&(obddev->obd_fsname), 0, sizeof(obd_devicename));
+                 EXIT;
+                 return err;
+               }
+               
                 /* do the setup */
                 CDEBUG(D_PSDEV, "Setup %d, type %s\n", dev, 
                        obddev->obd_type->typ_name);
@@ -359,9 +386,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                         return 0;
                 }
 
-                err = OBP(obddev, setup)(obddev, setup->setup_datalen,
-                                         setup->setup_data);
-
+                err = OBP(obddev, setup)(obddev, 0, NULL);
+                          
                 if ( err )  {
                         obddev->obd_flags &= ~OBD_SET_UP;
                         EXIT;
@@ -372,8 +398,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                         obddev->obd_flags |= OBD_SET_UP;
                         EXIT;
                 }
-                if (setup->setup_data)
-                        OBD_FREE(setup->setup_data, setup->setup_datalen);
+
                 return err;
         }
         case OBD_IOC_CLEANUP: {
index 445b410..b1c88e6 100644 (file)
@@ -59,7 +59,7 @@ void obd_cleanup_obdo_cache(void)
 
 
 /* map connection to client */
-struct obd_client *gen_client(struct obd_conn *conn)
+struct obd_client *gen_client(const struct obd_conn *conn)
 {
         struct obd_device * obddev = conn->oc_dev;
         struct list_head * lh, * next;
index 94aea02..8747b2e 100755 (executable)
@@ -209,8 +209,18 @@ my $line;
 my $command;
 my $arg;
 
+my @procsysobd_objects = ('debug', 'index', 'reset', 'trace', 'vars');
+
 my %commands =
-    ('device' => {func => "Device", doc => "device <dev>: open another OBD device"},
+    ('status' => {func => "Status", doc => "status: show obd device status"},
+     'procsys' => {func => "Procsys", doc => "procsys <file> <value> (set /proc/sys/obd configuration)"},
+     'shell' => {func => "Shell", doc => "shell <shell-command>: execute shell-commands"},
+     'script' => {func => "Script", doc => "script <filename>: read and execute commands from a file"},
+     'insmod' => {func => "Insmod", doc => "insmod <module>: insert kernel module"},
+     'rmmod' => {func => "Rmmod", doc => "rmmod <module>: insert kernel module"},
+     'lsmod' => {func => "Lsmod", doc => "lsmod <module>: list kernel modules"},
+     'device' => {func => "Device", doc => "device <dev>: open another OBD device"},
+     'close' => {func => "Close", doc => "close <dev>: close OBD device"},
      'create' => {func => "Create", doc => "create [<num> [<mode> [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"},
@@ -254,7 +264,7 @@ my $term, $attribs;
 
 # Get going....
 
-Device($::device);
+#Device($::device);
 
 sub readl {
     if ( $file ) {
@@ -271,7 +281,8 @@ sub readl {
 if ( $file ) {
     while ( <STDIN> ) {
         print $_;
-        execute_line($_);
+        my $rc = execute_line($_);
+       if ($rc != 0) { last; }
     }
     exit 0;
 } else {
@@ -292,9 +303,17 @@ if ( $file ) {
 sub completeme {
     my ($text, $line, $start, $end) = @_;
     if (substr($line, 0, $start) =~ /^\s*$/) {
-        $attribs->{completion_word} = \@jcm_cmd_list;
-        return $term->completion_matches($text,
-                                         $attribs->{'list_completion_function'});
+       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'});
+       }
     }
 }
 
@@ -342,24 +361,173 @@ sub execute_line {
     return (&{$commands{$cmd}->{func}}(@cmdline));
 }
 
+my %opendevfds = ();
 
 # select the OBD device we talk to
 sub Device {
     my $device = shift;
 
-    if ($::client_id) {
-        print "Disconnecting active session ($::client_id)...";
-        Disconnect($::client_id);
+    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 "Openend 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 (<CMDF>) {
+       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;
     }
-    if (! $device ) {
-        $device = "/dev/obd0";
+    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");
+       }
     }
-    $::device = $device;
-    # Open the device, as we need an FD for the ioctl
-    sysopen(DEV_OBD, $device, 0) || die "Cannot open $device";
-    print "Device now $device\n";
+    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;
@@ -370,8 +538,8 @@ sub Attach {
     if ( ! $type ) {
         print "error: missing type\n";
 usage:
-        print "usage: attach {obdext2 | obdsnap | obdscsi}\n";
-        return;
+        print "usage: attach {obdext2 | obdsnap | obdscsi | obdtrace }\n";
+        return -1;
     }
 
     if ($type eq "obdscsi" ) {
@@ -391,7 +559,10 @@ usage:
         $datalen = 3 * 4;
     } elsif ($type eq "obdext2") {
         $data = pack("i", 4711);   # bogus data
-        $datalen = 0;
+        $datalen = 4;
+    } elsif ($type eq "obdtrace") {
+        $data = pack("i", 4711);   # bogus data
+        $datalen = 4;
     } else {
         print "error: unknown attach type $type\n";
         goto usage;
@@ -403,14 +574,21 @@ usage:
     print "type $type (len $len), datalen $datalen ($cl)\n";
     my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
 
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_ATTACH, $packed);
+    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;
     }
 }
 
@@ -418,14 +596,23 @@ usage:
 sub Detach {
     my $err = 0;
     my $data = "";
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_DETACH, $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;
     }
 }
 
@@ -446,15 +633,22 @@ sub TestExt2Iterator {
     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);
+    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;
     }
 }
 
@@ -462,7 +656,7 @@ sub TestExt2Iterator {
 sub SnapDelete { 
     if (!defined($::client_id)) {
         print "You must first ``connect''.\n";
-        return;
+        return -1;
     }
 
     my $err = 0;
@@ -478,14 +672,23 @@ sub SnapDelete {
 
     # 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.
-    my $rc = ioctl(DEV_OBD, &OBD_SNAP_DELETE, $packed);
+
+    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;
     }
 }
 
@@ -500,17 +703,17 @@ sub SnapRestore {
     # don't do anything until connected
     if (!defined($::client_id)) {
         print "You must first ``connect''.\n";
-        return;
+        return -1;
     }
 
     if ( ! $snaptable || ! defined $restoreto ) {
         print "Usage: snaprestore \"restore to slot\" \"snaptable\" \"tableno\"\n";
-        return;
+        return -1;
     }
 
     if ( ! -f $snaptable ) {
         print "Table $snaptable doesn't exist\n";
-        return;
+        return -1;
     }
    
     my $table = ReadSnapShotTable($snaptable);
@@ -518,13 +721,13 @@ sub SnapRestore {
     if ( ! defined $table->{0} || ! defined $restoretime ) {
         PrintSnapShotTable($table);
         print "No current or $restoreto slot in this table\n";
-        return;
+        return -1;
     }
 
     my $currentindex = $table->{0};
     if (  $table->{$restoretime} == $currentindex ) {
         print "You should not restore to the current snapshot\n";
-        return;
+        return -1;
     }
     
     # swap the entries for 0 and $restoreto
@@ -548,11 +751,16 @@ sub SnapRestore {
     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);
+    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;
@@ -562,9 +770,10 @@ sub SnapRestore {
         # set it in the kernel
         SnapSetTable($tableno, $snaptable);
         # PrintSnapShotTable($table);
-
+       return 0;
     } else {
         print "ioctl returned error code $rc.\n";
+       return -1;
     }
 }
 
@@ -594,15 +803,22 @@ sub SnapPrint {
     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);
+    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;
     }
 }
 
@@ -618,6 +834,7 @@ sub SnapSetTable {
 
     if ( ! -f $file ) {
         print "No such file $file\n";
+       return -1;
     }
 
     $table = ReadSnapShotTable($file);
@@ -627,7 +844,7 @@ sub SnapSetTable {
 
     if ( ! defined $table->{0} ) {
         print "No current snapshot in table! First make one\n";
-        return ;
+        return -1;
     }
     $data = pack("ii", $snaptableno, $snapcount);
     $datalen = 2 * 4;
@@ -641,15 +858,22 @@ sub SnapSetTable {
     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);
+    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;
     }
 }
 
@@ -698,6 +922,7 @@ sub SnapShotTable  {
     unless ( $ok eq "n" )  {
         WriteSnapShotTable($file, $table);
     }
+    return 0;
 }
 
 sub SnapFindTimeFromIdx {
@@ -766,15 +991,22 @@ sub Copy {
 
     # 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);
+    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;
     }
 }
 
@@ -789,15 +1021,22 @@ sub Migrate {
 
     # 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);
+    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;
     }
 }
 
@@ -809,14 +1048,21 @@ sub Format {
     my $datalen = 4;
 
     my $packed = pack("ip", $datalen, $data);
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_FORMATOBD, $packed);
+    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;
     }
 }
 
@@ -828,14 +1074,21 @@ sub Partition {
     my $datalen = 2 * 4;
 
     my $packed = pack("ip", $datalen, $data);
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_PARTITION, $packed);
+    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;
     }
 }
 
@@ -849,39 +1102,52 @@ sub Setup {
     # by type here
 
     if ($arg && !defined($::st = stat($arg))) {
-            print "$dev is not a valid device\n";
-            return;
+            print "$arg is not a valid device\n";
+            return -1;
     }
     
     if ( $arg ) {
-        $dev = $::st->rdev() unless $dev;
-        $data = pack("i", $dev);
-        $datalen = 4;
+        $data = $arg;
+        $datalen = length($arg)+1; # need null character also
     }
 
     my $packed = pack("ip", $datalen, $data);
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP, $packed);
+    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";
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_CLEANUP, $err);
+    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;
     }
 }
 
@@ -890,17 +1156,24 @@ sub Connect {
     my $rc;
 
     my $packed = "";
-    $rc = ioctl(DEV_OBD, &OBD_IOC_CONNECT, $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;
     }
 }
 
@@ -915,26 +1188,33 @@ sub Disconnect {
         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;
+        return -1;
     }
 
     my $packed = pack("L", $id);
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_DISCONNECT, $packed);
+    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;
+        return -1;
     }
 
     my $num = shift;
@@ -953,7 +1233,7 @@ sub Create {
 
     if (scalar($num) < 1 || defined($quiet) && $quiet ne "quiet") {
         print "usage: create [<number of objects> [<mode> [quiet]]]\n";
-        return;
+        return -1;
     }
 
     my $i;
@@ -972,7 +1252,11 @@ sub Create {
         $obdo->{valid} = &OBD_MD_FLMODE;
 
         my $packed = pack("I", $::client_id) . obdo_pack($obdo);
-        $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $packed);
+       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)) {
@@ -983,63 +1267,80 @@ sub Create {
 
     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";
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_SYNC, $err);
+    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;
+        return -1;
     }
 
     my $id = shift;
 
     if (!defined($id) || scalar($id) < 1) {
         print "usage: destroy <object number>\n";
-        return;
+        return -1;
     }
 
     print "Destroying object $id...\n";
     my $packed = pack("IL", $::client_id, $id);
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_DESTROY, $packed);
+    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;
+        return -1;
     }
 
     my $id = shift;
 
     if (!defined($id) || scalar($id) < 1) {
         print "invalid arguments; type \"help getattr\" for a synopsis\n";
-        return;
+        return -1;
     }
 
     # see Setattr
@@ -1047,29 +1348,36 @@ sub Getattr {
     $obdo->{id} = $id;
     $obdo->{valid} = &OBD_MD_FLALL;
     my $packed = pack("L", $::client_id) . obdo_pack($obdo);
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_GETATTR, $packed);
+    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;
+        return -1;
     }
 
     my $id = shift;
 
     if (!defined($id) || scalar($id) < 1) {
         print "invalid arguments; type \"help setattr\" for a synopsis\n";
-        return;
+        return -1;
     }
 
     # XXX we do not currently set all of the fields in the obdo
@@ -1108,21 +1416,28 @@ sub Setattr {
 
     printf "valid is %x, mode is %o\n", $obdo->{valid}, $obdo->{mode};
     my $packed = pack("L", $::client_id) . obdo_pack($obdo);
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_SETATTR, $packed);
+    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;
+        return -1;
     }
 
     my $id = shift;
@@ -1132,7 +1447,7 @@ sub Read {
     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;
+        return -1;
     }
 
     if (!defined($offset)) {
@@ -1153,29 +1468,37 @@ sub Read {
     my $packed = pack("L", $::client_id) . obdo_pack($obdo) .
                  pack("p LL LL", $buf, $count, $offset);
 
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_READ, $packed);
+    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;
+        return -1;
     }
 
     my $id = shift;
@@ -1185,7 +1508,7 @@ sub Read2 {
     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;
+        return -1;
     }
 
     if (!defined($offset)) {
@@ -1206,29 +1529,37 @@ sub Read2 {
     my $packed = pack("L", $::client_id) . obdo_pack($obdo) .
                  pack("p LL LL", $buf, $count, $offset);
 
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_READ2, $packed);
+    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";
-        } else {
+               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;
+        return -1;
     }
 
     my $id = shift;
@@ -1239,7 +1570,7 @@ sub Write {
     if (!defined($id) || scalar($id) < 1 || !defined($offset) ||
         scalar($offset) < 0) {
         print "invalid arguments; type \"help write\" for a synopsis\n";
-        return;
+        return -1;
     }
 
     if (!defined($text)) {
@@ -1256,28 +1587,36 @@ sub Write {
     my $packed = pack("L", $::client_id) . obdo_pack($obdo) .
                  pack("p LL LL", $text, $count, $offset);
 
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_WRITE, $packed);
+    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;
+        return -1;
     }
 
     my $id = shift;
@@ -1287,7 +1626,7 @@ sub Punch {
     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;
+        return -1;
     }
 
     print("Punching $count bytes starting at byte $start from object $id...\n");
@@ -1299,7 +1638,11 @@ sub Punch {
     my $packed = pack("L", $::client_id) . obdo_pack($obdo) .
                  pack("p LL LL", $buf, $start, $count);
 
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_PUNCH, $packed);
+    if (! defined $::dev_obd) {
+       print "No current device.\n";
+       return -1;
+    }
+    my $rc = ioctl($::dev_obd, &OBD_IOC_PUNCH, $packed);
 
     $retval = unpack("l", $packed);
 
@@ -1309,11 +1652,14 @@ sub Punch {
         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;
     }
 }
 
@@ -1322,7 +1668,7 @@ sub Preallocate {
 
     if (!defined($::client_id)) {
         print "You must first ``connect''.\n";
-        return;
+        return -1;
     }
 
     if (!defined($num) || scalar($num) < 1 || scalar($num) > 32) {
@@ -1333,10 +1679,15 @@ sub Preallocate {
     # client id, alloc, id[32]
     my $packed = pack("LLx128", $::client_id, $num);
 
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_PREALLOCATE, $packed);
+    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);
@@ -1347,27 +1698,36 @@ sub Preallocate {
             print $i . " ";
         }
         print "\nFinished (success)\n";
+       return 0;
     } else {
         print "ioctl returned error code $rc.\n";
+       return -1;
     }
 }
 
 sub Decusecount {
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_DEC_USE_COUNT, 0);
+    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;
+        return -1;
     }
 
     # struct statfs {
@@ -1386,10 +1746,15 @@ sub Statfs {
     my $packed = pack("LLLLLLLIILL6", $::client_id, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                       0, 0, 0, 0, 0, 0);
 
-    my $rc = ioctl(DEV_OBD, &OBD_IOC_STATFS, $packed);
+    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) =
@@ -1398,8 +1763,10 @@ sub Statfs {
               "$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;
     }
 }
 
@@ -1411,6 +1778,7 @@ sub Help {
     } else {
         print "Usage: " .  $commands{$cmd}->{doc} . "\n";
     }
+    return 0;
 }
 
 sub Quit {
diff --git a/lustre/obdclass/proc_lustre.c b/lustre/obdclass/proc_lustre.c
new file mode 100644 (file)
index 0000000..e9fe724
--- /dev/null
@@ -0,0 +1,235 @@
+/* proc_lustre.c manages /proc/lustre/obd. 
+ *
+ * OBD devices materialize in /proc as a directory:
+ *              /proc/lustre/obd/<number>
+ * when /dev/obd<number> is opened. When the device is closed, the 
+ * directory entry disappears. 
+ * 
+ * For each open OBD device, code in this file also creates a file
+ * named <status>. "cat /proc/lustre/obd/<number>/status" gives 
+ * information about the OBD device's configuration.
+ * The class driver manages the "status" entry.
+ *
+ * Other logical drivers can create their own entries. For example,
+ * the obdtrace driver creates /proc/lustre/obd/<obdid>/stats entry.
+ *
+ * This file defines three functions 
+ *               proc_lustre_register_obd_device()
+ *               proc_lustre_release_obd_device()
+ *               proc_lustre_remove_obd_entry() 
+ * that dynamically create/delete /proc/lustre/obd entries:
+ *
+ *     proc_lustre_register_obd_device() registers an obd device,
+ *     and, if this is the first OBD device, creates /proc/lustre/obd.
+ *
+ *     proc_lustre_release_obd_device() removes device information
+ *     from /proc/lustre/obd, and if this is the last OBD device
+ *     removes  /proc/lustre/obd.
+ *
+ *     proc_lustre_remove_obd_entry() removes a
+ *     /proc/lustre/obd/<obdid>/ entry by name. This is the only
+ *     function that is exported to other modules. 
+ *
+ * Copyright (c) 2001 Rumi Zahir <rumi.zahir@intel.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+
+#include <linux/obd_support.h>
+#include <linux/obd_class.h>
+
+
+#ifdef CONFIG_PROC_FS
+extern struct proc_dir_entry proc_root;
+
+static struct proc_dir_entry *proc_lustre_dir_entry = 0;
+static struct proc_dir_entry *proc_lustre_obd_dir_entry = 0;
+
+static struct proc_dir_entry *
+proc_lustre_mkdir(const char* dname, struct proc_dir_entry *parent)
+{
+       struct proc_dir_entry *child_dir_entry;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */
+       child_dir_entry = proc_mkdir(dname, parent);
+#else
+       child_dir_entry = create_proc_entry(dname,
+                                           S_IFDIR | S_IRUGO | S_IXUGO,
+                                           &proc_root);
+#endif
+       if (!child_dir_entry)
+               printk ("lustre: failed to create /proc  entry %s\n", dname);
+       
+       return child_dir_entry;
+}
+
+static int read_lustre_status(char *page, char **start, off_t offset,
+                             int count, int *eof, void *data)
+{
+       struct obd_device * obddev = (struct obd_device *) data;
+       int p;
+
+       p = sprintf(&page[0], "/dev/obd%d: ", obddev->obd_minor);
+       
+       if (obddev->obd_refcnt==0) { 
+               /* obd is unused */
+               p += sprintf(&page[p], "open but unused\n\0");
+       }
+       else {  /* obd in use */
+               p += sprintf(&page[p], "refcnt(%d)", obddev->obd_refcnt);
+               
+               if  (obddev->obd_flags & OBD_ATTACHED) {
+                       p += sprintf(&page[p], ", attached(%s)", 
+                                    obddev->obd_type->typ_name);
+               }
+               
+               if  (obddev->obd_flags & OBD_SET_UP) {
+                       struct dentry   *my_dentry;
+                       struct vfsmount *root_mnt;
+                       char *path;
+                       char *pathpage;
+                       
+                       if (!(pathpage = (char*) __get_free_page(GFP_KERNEL)))
+                               return -ENOMEM;
+               
+                       my_dentry = obddev->obd_fsname.dentry;
+                       root_mnt = mntget(current->fs->rootmnt);
+                       path = d_path(my_dentry,root_mnt,pathpage,PAGE_SIZE);
+
+                       p += sprintf(&page[p], ", setup(%s)", path);
+                       
+                       free_page((unsigned long) pathpage);
+               }
+               
+               /* print connections */
+               {
+                       struct list_head * lh;
+                       struct obd_client * cli=0;
+                       
+                       lh = &obddev->obd_gen_clients;
+                       while ((lh = lh->next) != &obddev->obd_gen_clients) {
+                               p += sprintf(&page[p],
+                                            ((cli==0) ? ", connections(" : ",") );
+                               cli = list_entry(lh, struct obd_client, cli_chain);
+                               p += sprintf(&page[p], "%d", cli->cli_id);
+                       } /* while */
+                       if (cli!=0) { /* there was at least one client */
+                               p += sprintf(&page[p], ")");
+                       }
+               }
+               
+               p += sprintf(&page[p], "\n\0");
+       }
+
+       /* Compute eof and return value */
+
+       if (offset + count >= p) {
+               *eof=1;
+               return (p - offset);
+       }
+       return count;
+}
+
+struct proc_dir_entry *
+proc_lustre_register_obd_device(struct obd_device *obd)
+{
+       char obdname[32];
+       struct proc_dir_entry *obd_dir;
+       struct proc_dir_entry *obd_status = 0;
+
+       if (!proc_lustre_dir_entry) {
+               proc_lustre_dir_entry = 
+                       proc_lustre_mkdir("lustre", &proc_root);
+               if (!proc_lustre_dir_entry)
+                       return 0;
+       
+               proc_lustre_obd_dir_entry = 
+                       proc_lustre_mkdir("obd", proc_lustre_dir_entry);
+               if (!proc_lustre_obd_dir_entry)
+                       return 0;
+       }
+
+       sprintf(obdname, "%d", obd->obd_minor);
+
+       obd_dir =  proc_lustre_mkdir(obdname, proc_lustre_obd_dir_entry);
+       
+        if (obd_dir) 
+               obd_status = create_proc_entry("status", S_IRUSR | S_IFREG, obd_dir);
+
+       if (obd_status) {
+               obd_status->read_proc = read_lustre_status;
+               obd_status->data = (void*) obd;
+       }
+
+       return obd_dir;
+}
+
+void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd)
+{
+       struct proc_dir_entry *obd_entry = 0;
+       struct proc_dir_entry *obd_dir = obd->obd_proc_entry;
+       
+       remove_proc_entry(name, obd_dir);
+
+       while (obd_dir->subdir==0) {
+               /* if we removed last entry in this directory,
+                * then remove parent directory unless this
+                * is /proc itself
+                */
+               if (obd_dir == &proc_root) 
+                       break;
+                       
+               obd_entry = obd_dir;
+               obd_dir = obd_dir->parent;
+       
+               /* If /proc/lustre/obd/XXX or /proc/lustre/obd or
+                * /proc/lustre are being removed, then reset 
+                * internal variables
+                */
+               
+               if (obd_entry == obd->obd_proc_entry) 
+                       obd->obd_proc_entry=0; /* /proc/lustre/obd/XXX */
+               else 
+                       if (obd_entry == proc_lustre_obd_dir_entry)
+                               proc_lustre_obd_dir_entry=0;
+                       else 
+                               if (obd_entry == proc_lustre_dir_entry) 
+                                       proc_lustre_dir_entry=0;
+
+               remove_proc_entry(obd_entry->name, obd_dir);
+       }
+}
+
+void proc_lustre_release_obd_device(struct obd_device *obd)
+{
+       proc_lustre_remove_obd_entry("status", obd);
+}
+
+
+#else  /* CONFIG_PROC_FS */
+
+struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device *obd)
+{
+       return 0;
+}
+
+void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd) {}
+void proc_lustre_release_obd_device(struct obd_device *obd) {}
+
+#endif   /* CONFIG_PROC_FS */
+                                  
+EXPORT_SYMBOL(proc_lustre_remove_obd_entry);
+
+
+
+
+
+
+
+
+
+
+
index 5feaccf..8e308b8 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <linux/autoconf.h>
 #include <linux/sysctl.h>
 #include <linux/sched.h>
@@ -25,8 +26,6 @@ static int obd_sctl_vars( ctl_table * table, int write, struct file *
 static int obd_sctl_reset( ctl_table * table, int write, struct file
                            * filp, void * buffer, size_t * lenp );
 
-
-
 #define OBD_SYSCTL 300
 
 #define OBD_DEBUG           1       /* control debugging */
@@ -45,7 +44,7 @@ static ctl_table obd_table[] = {
         {OBD_VARS, "vars", &vars[0], sizeof(int), 0644, NULL, &proc_dointvec},
         {OBD_INDEX, "index", &index, sizeof(int), 0644, NULL, &obd_sctl_vars},
         {OBD_RESET, "reset", NULL, 0, 0644, NULL, &obd_sctl_reset},
-        { 0 }
+       { 0 }
 };
 
 static ctl_table parent_table[] = {
@@ -104,3 +103,7 @@ int obd_sctl_vars (ctl_table * table, int write,
 
         return rc; 
 }
+
+
+
+
index b56cc8a..a1d0cb0 100644 (file)
@@ -310,7 +310,7 @@ int obdfs_flush_dirty_pages(unsigned long check_time)
         struct list_head *sl;
         int max = 0;
 
-        ENTRY;
+       /*        ENTRY; */
         sl = &obdfs_super_list;
         while ( (sl = sl->prev) != &obdfs_super_list ) {
                 struct obdfs_sb_info *sbi = 
@@ -323,7 +323,7 @@ int obdfs_flush_dirty_pages(unsigned long check_time)
 
                 max = ret > max ? ret : max;
         }
-        EXIT;
+        if (max) { EXIT; }
         return max;
 } /* obdfs_flush_dirty_pages */
 
@@ -387,21 +387,24 @@ static int pupdate(void *unused)
                         interval = 0;
                         if ( wrote < pupd_prm.ndirty )
                                 age >>= 1;
-                        CDEBUG(D_CACHE, "wrote %d, age %ld, interval %d\n",
+                        if (wrote) 
+                         CDEBUG(D_CACHE, "wrote %d, age %ld, interval %d\n",
                                 wrote, age, interval);
                 } else {
                         if ( wrote < pupd_prm.ndirty >> 1 &&
                              obdfs_cache_count < dirty_limit / 2) {
                                 interval = pupd_prm.interval;
                                 age = pupd_prm.age_buffer;
-                                CDEBUG(D_INFO,
+                                if (wrote) 
+                                 CDEBUG(D_INFO,
                                        "wrote %d, age %ld, interval %d\n",
                                        wrote, age, interval);
                         } else if (obdfs_cache_count > dirty_limit / 2) {
                                 interval >>= 1;
                                 if ( wrote < pupd_prm.ndirty )
                                         age >>= 1;
-                                CDEBUG(D_CACHE,
+                                if (wrote) 
+                                 CDEBUG(D_CACHE,
                                        "wrote %d, age %ld, interval %d\n",
                                        wrote, age, interval);
                         }
diff --git a/lustre/scripts/mkobddevs b/lustre/scripts/mkobddevs
new file mode 100755 (executable)
index 0000000..6dd8750
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh -x
+mknod -m 0600 /dev/obd0 c 186 0
+mknod -m 0600 /dev/obd1 c 186 1
+mknod -m 0600 /dev/obd2 c 186 2
+mknod -m 0600 /dev/obd3 c 186 3
+mknod -m 0600 /dev/obd4 c 186 4
+mknod -m 0600 /dev/obd5 c 186 5
+mknod -m 0600 /dev/obd6 c 186 6
+mknod -m 0600 /dev/obd7 c 186 7
diff --git a/lustre/scripts/obdtrace_demo.scr b/lustre/scripts/obdtrace_demo.scr
new file mode 100644 (file)
index 0000000..2bfc6d5
--- /dev/null
@@ -0,0 +1,56 @@
+# Print OS version
+shell uname -r
+# Insert Lustre kernel modules
+insmod class/obdclass.o
+procsys trace 0
+procsys debug 0
+insmod ext2obd/obdext2.o
+insmod obdtrace/obdtrace.o
+insmod obdfs/obdfs.o
+# Configure direct driver on /dev/obd0
+device /dev/obd0
+attach obdext2
+setup /dev/sda2
+# Configure obdtrace on /dev/obd1
+device /dev/obd1
+attach obdtrace
+setup /dev/obd0
+# What's the obd status
+status
+shell cat /proc/lustre/obd/1/stats
+# mount obd file system
+shell mkdir -p /mnt/obd
+shell mount -t obdfs -odevice=/dev/obd1 none /mnt/obd
+shell mount
+# Prepare a data set (tar file of current directory)
+shell rm -f /tmp/obdtrace_test.tar
+shell tar cf /tmp/obdtrace_test.tar .
+# make a directory on obd device
+shell mkdir -p /mnt/obd/obdtrace_test_dir
+# Unpack tarfile to obd device 
+shell tar -C /mnt/obd/obdtrace_test_dir -xf /tmp/obdtrace_test.tar
+shell rm -rf /mnt/obd/obdtrace_test_dir
+# Check obdtrace performance stats
+status
+shell cat /proc/lustre/obd/1/stats
+shell echo 0 >  /proc/lustre/obd/1/stats
+shell cat /proc/lustre/obd/1/stats
+# Umount file system
+shell umount /mnt/obd
+# Cleanup /tmp
+shell rm -f /tmp/obdtrace_test.tar
+# Dismantle /dev/obd1
+device /dev/obd1
+cleanup
+detach
+close
+# Dismantle /dev/obd0
+device /dev/obd0
+cleanup
+detach
+close
+# Remove all loaded kernel modules
+rmmod obdfs
+rmmod obdtrace
+rmmod obdext2
+rmmod obdclass