Whamcloud - gitweb
A couple days of changes--much improvement.
authorpschwan <pschwan>
Sat, 5 Jun 1999 19:02:00 +0000 (19:02 +0000)
committerpschwan <pschwan>
Sat, 5 Jun 1999 19:02:00 +0000 (19:02 +0000)
lustre/include/linux/presto.h
lustre/include/linux/sym_obd.h
lustre/obdclass/obdcontrol [new file with mode: 0755]
lustre/obdclass/sysctl.c [new file with mode: 0644]

index a6ead3d..98e5976 100755 (executable)
@@ -1,17 +1,6 @@
 #ifndef __PRESTO_H_
 #define __PRESTO_H_ 1
 
 #ifndef __PRESTO_H_
 #define __PRESTO_H_ 1
 
-/* super.c */
-#if 0
-extern struct super_block * ext2_read_super (struct super_block * sb, 
-                                            void * data,
-                                            int silent);
-#endif
-extern struct file_system_type presto_fs_type;
-extern int init_presto_fs(void);
-
-int presto_ispresto(struct inode *);
-
 struct bottomfs {
        struct super_operations *bottom_sops;
 
 struct bottomfs {
        struct super_operations *bottom_sops;
 
@@ -26,137 +15,8 @@ struct bottomfs {
 };
 extern struct bottomfs *the_bottom;
 
 };
 extern struct bottomfs *the_bottom;
 
-/* inode.c */
-void presto_read_inode(struct inode *inode);
-int presto_notify_change(struct dentry *de, struct iattr *iattr);
-
-/* dcache.c */
-extern struct dentry_operations presto_dentry_operations;
-
-/* dir.c */
-extern struct inode_operations presto_dir_iops;
-extern struct inode_operations presto_file_iops;
-extern struct inode_operations presto_sym_iops;
-extern struct file_operations presto_dir_fops;
-extern struct file_operations presto_file_fops;
-extern struct file_operations presto_sym_fops;
-
-void presto_setup_file_ops(struct inode *);
-void presto_setup_symlink_ops(struct inode *);
-
-int presto_lookup(struct inode * dir, struct dentry *dentry);
-int presto_dir_open(struct inode *inode, struct file *file);
-int presto_file_open(struct inode *inode, struct file *file);
-int presto_file_release(struct inode *inode, struct file *file);
-
-int presto_mkdir(struct inode *inode, struct dentry *, int mode);
-int presto_create(struct inode *inode, struct dentry *, int mode);
-int presto_unlink(struct inode *inode, struct dentry *);
-int presto_rmdir(struct inode *inode, struct dentry *);
-int presto_symlink(struct inode *, struct dentry *, const char *);
-int presto_rename(struct inode *old_dir, struct dentry *old_dentry,
-                 struct inode *new_dir, struct dentry *new_dentry);
-
-int lento_journal(char *page);
-
-/* intermezzo.c */
-#define PRESTO_ATTR            0x00000001 /* attributes cached */
-#define PRESTO_DATA            0x00000002 /* data cached */
-#define PRESTO_VOLROOT          0x00000004 /* this dentry is root of volume */
-#define PRESTO_HASPERMIT        0x00000008 /* we have a permit to WB */
-
-#define EISVOLROOT              0x2001
-
-int presto_chk(struct dentry *dentry, int flag);
-void presto_set(struct dentry *dentry, int flag);
-void presto_permit(struct inode *);
-int presto_mark_dentry(const char *path, int and_bits, int or_bits);
-
-/* journal.c */
-
-#define JOURNAL_PAGE  PAGE_SIZE
-
-
-#define PRESTO_CREATE  1
-#define PRESTO_MKDIR   2
-#define PRESTO_UNLINK  3
-#define PRESTO_RMDIR   4
-#define PRESTO_CLOSE   5
-#define PRESTO_SYMLINK 6
-#define PRESTO_RENAME  7
-#define PRESTO_SETATTR 8
-#define PRESTO_LINK    9
-
-void journal_create(struct inode *dirinode, struct inode *fileinode, int len, const char *name, int mode);
-void journal_symlink(struct inode *inode, int len, const char *name, const char *target);
-void journal_mkdir(struct inode *inode, int len, const char *name, int mode);
-void journal_unlink(struct inode *inode, int len, const char *name);
-void journal_rmdir(struct inode *inode, int len, const char *name);
-void journal_rename(struct inode *old_dir, struct inode *old_file,
-                   struct inode *new_dir, int new_len, const char *new_name);
-void journal_setattr(struct inode *, int uid, int gid, int fsize, int atime,
-                    int mtime, int ctime, int mode, unsigned int flags,
-                    unsigned int valid);
-void journal_close(struct inode *inode);
-void journal_link(struct inode *src, struct inode *tpdiri, 
-                 struct inode *ti, int len, const char *name);
-void journal_fetch(void);
-
 /* sysctl.c */
 void presto_sysctl_init(void);
 void presto_sysctl_clean(void);
 
 /* sysctl.c */
 void presto_sysctl_init(void);
 void presto_sysctl_clean(void);
 
-/* global variables */
-extern int presto_debug;
-extern int presto_print_entry;
-
-/* debugging masks */
-#define D_SUPER     1   /* print results returned by Venus */ 
-#define D_INODE     2   /* print entry and exit into procedure */
-#define D_FILE      4   
-#define D_CACHE     8   /* cache debugging */
-#define D_MALLOC    16  /* print malloc, de-alloc information */
-#define D_JOURNAL   32
-#define D_UPCALL    64  /* up and downcall debugging */
-#define D_PSDEV    128  
-#define D_PIOCTL   256
-#define D_SPECIAL  512
-#define D_TIMING  1024
-#define D_DOWNCALL 2048
-#if 0
-#define CDEBUG(mask, format, a...)                                \
-  do {                                                            \
-  if (presto_debug & mask) {                                        \
-    printk("(%s,l. %d): ",  __FUNCTION__, __LINE__);              \
-    printk(format, ## a); }                                       \
-} while (0) ;                            
-#else
-#define CDEBUG(mask, format, a...) ;
-#endif
-
-#define ENTRY    \
-    if(presto_print_entry) printk("Process %d entered %s\n",current->pid,__FUNCTION__)
-
-#define EXIT    \
-    if(presto_print_entry) printk("Process %d leaving %s\n",current->pid,__FUNCTION__)
-
-
-#define PRESTO_ALLOC(ptr, cast, size)                                       \
-do {                                                                      \
-    if (size <= 4096) {                                                    \
-        ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL);            \
-                CDEBUG(D_MALLOC, "kmalloced: %x at %x.\n", (int) size, (int) ptr);\
-     }  else {                                                             \
-        ptr = (cast)vmalloc((unsigned long) size);                        \
-       CDEBUG(D_MALLOC, "vmalloced: %x at %x.\n", (int) size, (int) ptr);}\
-    if (ptr == 0) {                                                       \
-        printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__);  \
-    }                                                                     \
-    memset( ptr, 0, size );                                                   \
-} while (0)
-
-
-#define PRESTO_FREE(ptr,size) do {if (size <= 4096) { kfree_s((ptr), (size)); CDEBUG(D_MALLOC, "kfreed: %x at %x.\n", (int) size, (int) ptr); } else { vfree((ptr)); CDEBUG(D_MALLOC, "vfreed: %x at %x.\n", (int) size, (int) ptr);} } while (0)
-
 #endif
 #endif
index 10f2b53..87c86b2 100755 (executable)
@@ -9,22 +9,99 @@
 /*
  * Debug code
  */
 /*
  * Debug code
  */
+/* global variables */
+extern int obd_debug_level;
+extern int obd_print_entry;
+
+/* debugging masks */
+#define D_PSDEV       1 /* debug information from psdev.c */
+#define D_UNUSED1     2
+#define D_UNUSED2     4
+#define D_UNUSED3     8
+#define D_UNUSED4    16
+#define D_UNUSED5    32
+#define D_UNUSED6    64
+#define D_MALLOC    128 /* print malloc, free information */
+#define D_CACHE     256 /* cache-related items */
+#define D_INFO      512 /* general information, especially from interface.c */
+#define D_IOCTL    1024 /* ioctl related information */
+#define D_BLOCKS   2048 /* ext2 block allocation */
 #ifdef SYM_OBD_DEBUG
 #ifdef SYM_OBD_DEBUG
-#      define obd_debug(f, a...)       { \
-                                       printk ("SYM OBD DEBUG (%s, %d): %s:", \
-                                               __FILE__, __LINE__, __FUNCTION__); \
-                                       printk (f, ## a); \
-                                       }
-#else
-#      define obd_debug(f, a...)       /**/
-#endif
+#define CDEBUG(mask, format, a...)                                     \
+        do {                                                           \
+       if (obd_debug_level & mask) {                                   \
+               printk("(%s,l. %d): ",  __FUNCTION__, __LINE__);        \
+               printk(format, ## a); }                                 \
+       } while (0);
+
+#define ENTRY                                                                \
+        if (obd_print_entry)                                                 \
+                printk("Process %d entered %s\n", current->pid, __FUNCTION__)
+
+#define EXIT                                                                 \
+        if (obd_print_entry)                                                 \
+                printk("Process %d leaving %s\n", current->pid, __FUNCTION__)
+
+#else /* SYM_OBD_DEBUG */
+
+#       define CDEBUG(mask, format, a...) ;
+#       define ENTRY ;
+#       define EXIT ;
+
+#endif /* SYM_OBD_DEBUG */
+
+
+
+#define OBD_ALLOC(ptr, cast, size)                                     \
+do {                                                                   \
+       if (size <= 4096) {                                             \
+               ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL);  \
+                CDEBUG(D_MALLOC, "kmalloced: %x at %x.\n",             \
+                      (int) size, (int) ptr);                          \
+       } else {                                                        \
+               ptr = (cast)vmalloc((unsigned long) size);              \
+               CDEBUG(D_MALLOC, "vmalloced: %x at %x.\n",              \
+                      (int) size, (int) ptr);                          \
+       }                                                               \
+       if (ptr == 0) {                                                 \
+               printk("kernel malloc returns 0 at %s:%d\n",            \
+                      __FILE__, __LINE__);                             \
+       }                                                               \
+       memset(ptr, 0, size);                                           \
+} while (0)
+
+#define OBD_FREE(ptr,size)                             \
+do {                                                   \
+       if (size <= 4096) {                             \
+               kfree_s((ptr), (size));                 \
+               CDEBUG(D_MALLOC, "kfreed: %x at %x.\n", \
+                      (int) size, (int) ptr);          \
+       } else {                                        \
+               vfree((ptr));                           \
+               CDEBUG(D_MALLOC, "vfreed: %x at %x.\n", \
+                      (int) size, (int) ptr);          \
+       }                                               \
+} while (0)
+
 
 /*
  * ioctl commands
  */
 
 /*
  * ioctl commands
  */
+struct ioc_prealloc {
+       long alloc; /* user sets it to the number of inodes requesting to be
+                    * preallocated.  kernel sets it to the actual number of
+                    * succesfully preallocate inodes */
+       long inodes[32]; /* actual inode numbers */
+};
+
 #define OBD_IOC_CREATE                 _IOR('f', 3, long)
 #define OBD_IOC_SETUP                  _IOW('f', 4, long)
 #define OBD_IOC_SYNC                   _IOR('f', 5, long)
 #define OBD_IOC_CREATE                 _IOR('f', 3, long)
 #define OBD_IOC_SETUP                  _IOW('f', 4, long)
 #define OBD_IOC_SYNC                   _IOR('f', 5, long)
+#define OBD_IOC_DESTROY                _IOW('f', 6, long)
+
+#define OBD_IOC_DEC_USE_COUNT          _IO('f', 8)
+
 
 /* balloc.c */
 int obd_new_block (const struct inode * inode, unsigned long goal,
 
 /* balloc.c */
 int obd_new_block (const struct inode * inode, unsigned long goal,
@@ -33,9 +110,23 @@ void obd_free_blocks (const struct inode * inode, unsigned long block,
                       unsigned long count);
 unsigned long obd_count_free_blocks (struct super_block * sb);
 int ext2_group_sparse(int group);
                       unsigned long count);
 unsigned long obd_count_free_blocks (struct super_block * sb);
 int ext2_group_sparse(int group);
+struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+                                            unsigned int block_group,
+                                            struct buffer_head ** bh);
+
+
+/* bitmap.c */
+unsigned long ext2_count_free(struct buffer_head * map, unsigned int numchars);
 
 /* fsync.c */
 
 /* fsync.c */
-int obd_sync_file(struct file * file, struct dentry *dentry);
+extern int obd_sync_file(struct file * file, struct dentry *dentry);
+
+/* ialloc.c */
+extern void ext2_free_inode (struct inode * inode);
+extern struct inode * ext2_new_inode (const struct inode * dir, int mode,
+                                    int * err);
+extern unsigned long ext2_count_free_inodes (struct super_block * sb);
+extern void ext2_check_inodes_bitmap (struct super_block * sb);
 
 /* inode.c */
 void obd_read_inode (struct inode * inode);
 
 /* inode.c */
 void obd_read_inode (struct inode * inode);
@@ -50,11 +141,8 @@ struct buffer_head * obd_getblk (struct inode * inode, long block,
                                  int create, int * err);
 
 /* interface.c */
                                  int create, int * err);
 
 /* interface.c */
-extern struct inode * obd_inode_new (int inode_hint, int * err);
-extern void obd_inode_destroy (struct inode * inode);
-extern unsigned long obd_count_free_inodes (struct super_block * sb);
-extern void obd_check_inodes_bitmap (struct super_block * sb);
-unsigned long obd_count_free_inodes (struct super_block * sb);
+extern int obd_create (struct super_block * sb, int inode_hint, int * err);
+extern void obd_unlink (struct inode * inode);
 
 /* ioctl.c */
 int obd_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 
 /* ioctl.c */
 int obd_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
@@ -69,6 +157,10 @@ int obd_remount (struct super_block * sb, int * flags, char * data);
 struct super_block * obd_read_super (struct super_block * sb, void * data,
                                     int silent);
 
 struct super_block * obd_read_super (struct super_block * sb, void * data,
                                     int silent);
 
+/* sysctl.c */
+extern void obd_sysctl_init (void);
+extern void obd_sysctl_clean (void);
+
 /* truncate.c */
 void obd_truncate (struct inode * inode);
 
 /* truncate.c */
 void obd_truncate (struct inode * inode);
 
diff --git a/lustre/obdclass/obdcontrol b/lustre/obdclass/obdcontrol
new file mode 100755 (executable)
index 0000000..6967bdc
--- /dev/null
@@ -0,0 +1,264 @@
+#!/usr/bin/perl
+
+#use strict;
+BEGIN { require "asm/errno.ph" };
+BEGIN { require "asm/ioctl.ph" };
+
+# p2ph generated invalid macros for ioctl stuff, so I override some of it here
+eval 'sub OBD_IOC_CREATE () { &_IOC(2, ord(\'f\'), 3, 4);}' unless
+  defined(&OBD_IOC_CREATE);
+eval 'sub OBD_IOC_SETUP () { &_IOC(1, ord(\'f\'), 4, 4);}' unless
+  defined(&OBD_IOC_SETUP);
+eval 'sub OBD_IOC_SYNC () { &_IOC(2, ord(\'f\'), 5, 4);}' unless
+  defined(&OBD_IOC_SYNC);
+eval 'sub OBD_IOC_DESTROY () { &_IOC(1, ord(\'f\'), 6, 4);}' unless
+  defined(&OBD_IOC_DESTROY);
+eval 'sub OBD_IOC_DEC_USE_COUNT () { &_IOC(0, ord(\'f\'), 8, 0);}' unless
+  defined(&OBD_IOC_DEC_USE_COUNT);
+
+use Getopt::Long;
+use File::stat;
+use Storable;
+use Carp;
+use Term::ReadLine;
+use IO::Handle;
+
+my ($device, $filesystem);
+# startup options (I'll replace these when I have some to replace with)
+GetOptions("device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions";
+
+$device = "/dev/obd" unless $device;
+$filesystem = "/dev/loop0" unless $filesystem;
+
+# get a console for the app
+my $term = new Term::ReadLine 'obdcontrol ';
+my $attribs = $term->Attribs;
+$term->ornaments('md,me,,');   # bold face prompt
+
+# make sure stdout is not buffered
+STDOUT->autoflush(1);
+
+my $line;
+my $command;
+my $arg;
+
+my %commands =
+    ('create' => {func => "Create", doc => "create: creates a new inode"},
+     'setup' => {func => "Setup", doc => "setup: initializes the environment"},
+     'sync' => {func => "Sync", doc => "sync: flushes buffers to disk"},
+     'destroy' => {func => "Destroy", doc => "setup: destroys an inode"},
+     'dec_use_count' => {func => "Decusecount", doc => "decreases the module use count so that it can be unmounted following an oops"},
+     '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;
+
+$attribs->{attempted_completion_function} = \&completeme;
+#------------------------------------------------------------------------------
+# Open the device, as we need an FD for the ioctl
+sysopen(DEV_OBD, $device, 0);
+
+if (!defined($::st = stat($filesystem))) {
+    die "Unable to stat $filesystem.\n";
+}
+
+# Get on with the show
+process_line();
+
+#------------------------------------------------------------------------------
+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'});
+    }
+}
+
+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 @arg = split(' ', $line);
+    my $word = shift @arg;
+
+    my $cmd = find_command($word);
+    unless ($cmd) {
+       printf STDERR "$word: No such command, or not unique.\n";
+       return (-1);
+    }
+
+    if ($cmd eq "help" || $cmd eq "exit" || $cmd eq "quit") {
+       return (&{$commands{$cmd}->{func}}(@arg));
+    }
+
+    # Call the function.
+    return (&{$commands{$cmd}->{func}}(@arg));
+}
+
+sub Setup {
+    my $err = 0;
+    my $packed = pack("L", $::st->rdev());
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP, $packed);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Create {
+    my $arg = shift;
+    my $quiet = shift;
+    my $err = "0";
+    my $rc;
+
+    if (defined($quiet) && !($quiet eq "quiet")) {
+       print "syntax: create [number of objects [quiet]]\n";
+       return;
+    }
+
+    if (!defined($arg) || scalar($arg) < 2) {
+       print "Creating 1 object...\n";
+       $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
+       if (!defined($quiet)) {
+           my $ino = unpack("L", $err);
+           print "Created object #$ino.\n";
+       }
+    } else {
+       my $i;
+
+       print "Creating " . scalar($arg) . " objects...\n";
+       for ($i = 0; $i < scalar($arg); $i++) {
+           $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $err);
+           if (!($rc eq "0 but true") || $err < 0) {
+               last;
+           } elsif (!defined($quiet)) {
+               my $ino = unpack("L", $err);
+               print "Created object #$ino.\n";
+           }
+       }
+    }
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Sync {
+    my $err = "0";
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_SYNC, $err);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Destroy {
+    my $arg = shift;
+
+    if (!defined($arg) || scalar($arg) < 1) {
+       print "destroy requires the object number to destroy.\n";
+       return;
+    }
+
+    print "Destroying object $arg...\n";
+    my $packed = pack("L", $arg);
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_DESTROY, $packed);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Preallocate {
+    my $arg = shift;
+
+    if (!defined($arg) || scalar($arg) < 1 || scalar($arg) > 32) {
+       $arg = 32;
+    }
+
+    print "Preallocating $arg inodes...\n";
+    my $packed = pack("Lx128", $arg); # alloc, inodes[32]
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_PREALLOCATE, $packed);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       my $alloc = unpack("L", $packed);
+       my @inodes = unpack("L32", $packed);
+       my $i;
+
+       print "Got $alloc inodes: ";
+       for ($i = 1; $i <= $alloc; ++$i) {
+           print $inodes[$i] . " ";
+       }
+       print "\nFinished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Decusecount {
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_DEC_USE_COUNT, NULL);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Help {
+    my $arg = shift;
+
+    if ( !$arg || !$commands{$arg} ) {
+       print "Comands: ", join( ' ', @jcm_cmd_list), "\n";
+    } else {
+       print "Usage: " .  $commands{$arg}->{doc} . "\n";
+    }
+}
+
+sub Quit {
+    exit;
+}
diff --git a/lustre/obdclass/sysctl.c b/lustre/obdclass/sysctl.c
new file mode 100644 (file)
index 0000000..c221e7a
--- /dev/null
@@ -0,0 +1,108 @@
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <linux/swapctl.h>
+#include <linux/proc_fs.h>
+#include <linux/malloc.h>
+#include <linux/stat.h>
+#include <linux/ctype.h>
+#include <asm/bitops.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/utsname.h>
+
+#include <linux/sym_obd.h>
+#include <linux/presto.h>
+#include <linux/obd_psdev.h>
+#include <linux/presto_upcall.h>
+
+struct ctl_table_header *obd_table_header = NULL;
+
+static int vars[2];
+static int index = 0;
+
+static int obd_sctl_vars( ctl_table * table, int write, struct file *
+                         filp, void * buffer, size_t * lenp );
+static int obd_sctl_reset( ctl_table * table, int write, struct file
+                          * filp, void * buffer, size_t * lenp );
+
+
+
+#define OBD_SYSCTL 1
+
+#define OBD_DEBUG          1       /* control debugging */
+#define OBD_ENTRY          2       /* control enter/leave pattern */
+#define OBD_TIMEOUT         3       /* timeout on upcalls to become intrble */
+#define OBD_HARD            4       /* mount type "hard" or "soft" */
+#define OBD_VARS            5       
+#define OBD_INDEX           6
+#define OBD_RESET           7
+
+#define OBD_VARS_SLOT       2
+
+static ctl_table obd_table[] = {
+       {OBD_DEBUG, "debug", &obd_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
+       {OBD_ENTRY, "trace", &obd_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
+       {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 }
+};
+
+static ctl_table jukebox_table[] = {
+       {OBD_SYSCTL, "obd",    NULL, 0, 0555, obd_table},
+       {0}
+};
+
+
+void obd_sysctl_init (void)
+{
+#ifdef CONFIG_SYSCTL
+       if ( !obd_table_header )
+               obd_table_header = register_sysctl_table(jukebox_table, 0); 
+#endif
+}
+
+void obd_sysctl_clean (void)
+{
+#ifdef CONFIG_SYSCTL
+       if ( obd_table_header )
+               unregister_sysctl_table(obd_table_header);
+       obd_table_header = NULL;
+#endif
+}
+
+int obd_sctl_reset (ctl_table * table, int write, 
+                   struct file * filp, void * buffer, 
+                   size_t * lenp)
+{
+       if ( write ) {
+               /* do something here */
+               vars[0]=0;
+               vars[1]=0;
+       }
+
+       *lenp = 0;
+       return 0;
+}
+
+int obd_sctl_vars (ctl_table * table, int write, 
+                  struct file * filp, void * buffer, 
+                  size_t * lenp)
+{
+       int rc;
+
+       rc = proc_dointvec(table, write, filp, buffer, lenp);
+
+       if ( rc ) 
+               return rc;
+
+       if ( index < 0 || index > 1 ) {
+               printk("Index illegal!\n");
+               index = 0;
+       } else {
+               obd_table[OBD_VARS_SLOT].data = &vars[index];
+       }
+
+       return rc; 
+}