#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;
};
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);
-/* 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
/*
* 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
-# 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
*/
+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_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,
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 */
-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);
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,
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);
--- /dev/null
+#!/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;
+}
--- /dev/null
+#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;
+}