Whamcloud - gitweb
New direcotory layout:
authorbraam <braam>
Tue, 2 Nov 1999 19:12:27 +0000 (19:12 +0000)
committerbraam <braam>
Tue, 2 Nov 1999 19:12:27 +0000 (19:12 +0000)
  subdirs for different clients and file systems
  documentation, tests and lib subdirectories.

14 files changed:
lustre/include/linux/inofs.h [new file with mode: 0644]
lustre/include/linux/obd_rpc.h
lustre/include/linux/obd_support.h
lustre/include/linux/obdfs.h
lustre/obdclass/Makefile [new file with mode: 0644]
lustre/obdfs/Makefile
lustre/obdfs/dir.c
lustre/obdfs/file.c
lustre/obdfs/namei.c
lustre/obdfs/notes.txt [deleted file]
lustre/obdfs/rw.c
lustre/obdfs/super.c
lustre/tests/test.c [new file with mode: 0755]
lustre/tests/test2.c [new file with mode: 0755]

diff --git a/lustre/include/linux/inofs.h b/lustre/include/linux/inofs.h
new file mode 100644 (file)
index 0000000..74d9ac3
--- /dev/null
@@ -0,0 +1,74 @@
+/* object based disk file system
+ * 
+ * This software is licensed under the GPL.  See the file COPYING in the
+ * top directory of this distribution for details.
+ * 
+ * Copyright (C), 1999, Stelias Computing Inc
+ *
+ *
+ */
+
+
+#ifndef _INOFS_H
+#define INOFS_H
+#include <linux/obd_class.h>
+
+/* super.c */
+void inofs_read_inode(struct inode *inode);
+
+
+/* file.c */
+ssize_t inofs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos);
+
+
+/* rw.c */
+struct page *inofs_getpage(struct inode *inode, unsigned long offset, int create, int locked);
+int inofs_writepage(struct file *file, struct page *page);
+int inofs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf);
+
+/* namei.c */
+struct dentry *inofs_lookup(struct inode * dir, struct dentry *dentry);
+int inofs_create (struct inode * dir, struct dentry * dentry, int mode);
+int inofs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+int inofs_rmdir(struct inode *dir, struct dentry *dentry);
+int inofs_unlink(struct inode *dir, struct dentry *dentry);
+int inofs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev);
+int inofs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
+int inofs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry);
+int inofs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry);
+/* dir.c */
+int inofs_readdir(struct file * filp, void * dirent, filldir_t filldir);
+int inofs_check_dir_entry (const char * function, struct inode * dir,
+                         struct ext2_dir_entry_2 * de,
+                         struct page * page,
+                          unsigned long offset);
+
+struct inofs_sb_info {
+       struct obd_conn_info osi_conn_info;
+       struct super_block *osi_super;
+       struct obd_device *osi_obd;
+       struct obd_ops *osi_ops;
+};
+
+void inofs_sysctl_init(void);
+void inofs_sysctl_clean(void);
+
+struct inofs_inode_info;
+
+extern struct file_operations inofs_file_ops;
+extern struct inode_operations inofs_inode_ops;
+
+static inline struct obd_ops *iops(struct inode *i)
+{
+       struct inofs_sb_info *sbi = (struct inofs_sb_info *) i->i_sb->u.generic_sbp;
+       return sbi->osi_ops;
+}
+
+#define NOLOCK 0
+#define LOCKED 1
+
+
+#define INOFS_SUPER_MAGIC 0x4711
+
+#endif
+
index 43d7bc3..b103bd1 100644 (file)
@@ -31,34 +31,9 @@ enum obd_stat {
 };
 
 
 };
 
 
-
-#define OBD_PROGRAM            100003
-#define OBD_VERSION            2
-#define OBDPROC_NULL           0
-#define OBDPROC_GETATTR                1
-#define OBDPROC_SETATTR                2
-#define OBDPROC_ROOT           3
-#define OBDPROC_LOOKUP         4
-#define OBDPROC_READLINK       5
-#define OBDPROC_READ           6
-#define OBDPROC_WRITECACHE     7
-#define OBDPROC_WRITE          8
-#define OBDPROC_CREATE         9
-#define OBDPROC_REMOVE         10
-#define OBDPROC_RENAME         11
-#define OBDPROC_LINK           12
-#define OBDPROC_SYMLINK                13
-#define OBDPROC_MKDIR          14
-
-
-
 extern struct rpc_program obd_program;
 
 
 extern struct rpc_program obd_program;
 
 
-
-
-
-
 struct obd_target {
        struct sockaddr_in tgt_addr;
        int tgt_flags;
 struct obd_target {
        struct sockaddr_in tgt_addr;
        int tgt_flags;
@@ -71,9 +46,11 @@ struct obd_target {
 
 
 struct rpc_obd {
 
 
 struct rpc_obd {
-       struct rpc_clnt *       client;         /* RPC client handle */
-       struct sockaddr_in     addr;
+       struct rpc_clnt *       handle;         /* RPC client handle */
+       struct sockaddr_in      addr;
        int                     flags;          /* various flags */
        int                     flags;          /* various flags */
+       int                     timeo;
+       int                     retrans;
        int                     rsize;          /* read size */
        int                     wsize;          /* write size */
        unsigned int            bsize;          /* server block size */
        int                     rsize;          /* read size */
        int                     wsize;          /* write size */
        unsigned int            bsize;          /* server block size */
@@ -81,4 +58,26 @@ struct rpc_obd {
 };
 
 
 };
 
 
+#define OBD_PROGRAM            300001
+#define OBD_VERSION            1
+#define OBDPROC_NULL           0
+#define OBDPROC_ECHOINT                1
+
+#ifdef  OBD_NEED_XDR_TYPES
+
+struct obd_echoint_in {
+       __u32                   in;
+};
+
+struct obd_echoint_out {
+       __u32                   out;
+};
+
+
+#endif /* OBD_NEED_XDR_TYPES */
+
+
+int obd_proc_echoint(struct rpc_obd *target, __u32 in, __u32 *out);
+
+
 #endif
 #endif
index 68f12ca..db2081a 100644 (file)
@@ -30,6 +30,7 @@ extern int obd_print_entry;
 #define D_INFO      512 /* general information, especially from interface.c */
 #define D_IOCTL    1024 /* ioctl related information */
 #define D_BLOCKS   2048 /* ext2 block allocation */
 #define D_INFO      512 /* general information, especially from interface.c */
 #define D_IOCTL    1024 /* ioctl related information */
 #define D_BLOCKS   2048 /* ext2 block allocation */
+#define D_RPC      4096 /* ext2 block allocation */
  
 #ifdef SIM_OBD_DEBUG
 #define CDEBUG(mask, format, a...)                                     \
  
 #ifdef SIM_OBD_DEBUG
 #define CDEBUG(mask, format, a...)                                     \
index 2abcb8f..3af1251 100644 (file)
@@ -11,7 +11,7 @@
 
 #ifndef _OBDFS_H
 #define OBDFS_H
 
 #ifndef _OBDFS_H
 #define OBDFS_H
-#include <../obd/linux/obd_class.h>
+#include <linux/obd_class.h>
 
 /* super.c */
 void obdfs_read_inode(struct inode *inode);
 
 /* super.c */
 void obdfs_read_inode(struct inode *inode);
diff --git a/lustre/obdclass/Makefile b/lustre/obdclass/Makefile
new file mode 100644 (file)
index 0000000..fdd8f6a
--- /dev/null
@@ -0,0 +1,7 @@
+include ../config.mk
+
+MODULE = obdclass.o
+
+CFILES = genops.c class_obd.c sysctl.c 
+
+include ../make.rules
\ No newline at end of file
index f677548..afb45cf 100644 (file)
@@ -4,64 +4,7 @@
 
 include ../config.mk
 
 
 include ../config.mk
 
-MODDIR = $(PREFIX)/lib/modules/$(UTS_RELEASE)
+MODULE = obdfs.o
+CFILES=file.c dir.c sysctl.c super.c rw.c namei.c # symlink.c
 
 
-ifndef CFLAGS
-# Don't remove "-O2" or bad things will happen!
-KFLAGS = -O2 -Wall -Wstrict-prototypes  -pipe -I../obd
-endif
-
-CPPFLAGS = $(PCDEBUG) -D__KERNEL__ -DMODULE -I../include \
-          -I. -I$(LINUX)/include $(SMPFLAG)
-COFLAGS = -kv
-
-ifeq ($(CONFIG_MODVERSIONS),"y")
-CFLAGS= $(KFLAGS) $(MFLAG)
-else 
-CFLAGS= $(KFLAGS)
-endif
-
-SRCS=file.c dir.c sysctl.c super.c rw.c namei.c # symlink.c
-OBJS=$(SRCS:%.c=%.o)
-
-MODULES = obdfs.o
-
-all:   ../.prereq.ok kcheck $(MODULES) 
-
-showvar:
-       @echo CFLAGS $(CFLAGS)
-       @echo CPPFLAGS $(CPPFLAGS)
-       @echo MODDIR $(MODDIR)
-       @echo UTS_RELEASE $(UTS_RELEASE)
-       @echo SRCS $(SRCS)
-       @echo OBJS $(OBJS)
-
-clean:
-       rm -f core core.* *.o *.d .*.o *.s *.a *~ .depend .depfiles/*.d
-
-MODDIR = $(PREFIX)/lib/modules/$(UTS_RELEASE)
-
-install: $(MODULES) ../.prereq.ok kcheck
-       -mkdir -p $(MODDIR)/fs
-       install -o root -g root -m 644 $(MODULES) $(MODDIR)/fs/
-
-# Stuff to automatically maintain dependency files
-
-.c.o:
-       $(CC) -MD $(CFLAGS) $(CPPFLAGS) -c $<
-       @mkdir -p .depfiles ; mv $*.d .depfiles
-
-kcheck:
-       @. ../config.out ; \
-       if [ "$$CHECK" != "" ] ; then \
-           if [ "`cksum < $$CHECK`" != "$$CKSUM" ] ; then \
-               /bin/echo -n "Kernel configuration has changed." ; \
-               /bin/echo "  Please re-run 'make config'." ; \
-               exit 1 ; \
-           fi ; \
-       fi
-
-obdfs.o: $(OBJS)
-       $(LD) -m "`ld --help | awk '/supported emulations/ {print $$4}'`" -r -o $@ $(OBJS)
-
--include $(SRCS:%.c=.depfiles/%.d)
+include ../make.rules
\ No newline at end of file
index fb171ad..14150a9 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/locks.h>
 #include <linux/quotaops.h>
 #include <linux/iobuf.h>
 #include <linux/locks.h>
 #include <linux/quotaops.h>
 #include <linux/iobuf.h>
-#include "obdfs.h"
+#include <linux/obdfs.h>
 #include <linux/obd_support.h>
 
 #if 0
 #include <linux/obd_support.h>
 
 #if 0
index e3d629f..20910f4 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/smp_lock.h>
 
 #include <linux/obd_support.h>
 #include <linux/smp_lock.h>
 
 #include <linux/obd_support.h>
-#include "obdfs.h"
+#include <linux/obdfs.h>
 
 static inline void remove_suid(struct inode *inode)
 {
 
 static inline void remove_suid(struct inode *inode)
 {
index 316a17a..6bb405a 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/iobuf.h>
 
 #include <linux/obd_support.h>
 #include <linux/iobuf.h>
 
 #include <linux/obd_support.h>
-#include "obdfs.h"
+#include <linux/obdfs.h>
 
 /*
  * define how far ahead to read directories while searching them.
 
 /*
  * define how far ahead to read directories while searching them.
diff --git a/lustre/obdfs/notes.txt b/lustre/obdfs/notes.txt
deleted file mode 100644 (file)
index cd177d5..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-Considerations for an API between OBD's and OBDFS
-
-
-OBDFS 
-
-Methods needed:
-
-struct super_operations {
-       void (*read_inode) (struct inode *);
-       void (*write_inode) (struct inode *);
-       void (*put_inode) (struct inode *);
-       void (*delete_inode) (struct inode *);
-       int (*notify_change) (struct dentry *, struct iattr *);
-       void (*put_super) (struct super_block *);
-       void (*write_super) (struct super_block *);
-       int (*statfs) (struct super_block *, struct statfs *, int);
-*      int (*remount_fs) (struct super_block *, int *, char *);
-       void (*clear_inode) (struct inode *);
-*      void (*umount_begin) (struct super_block *);
-};
-
-
-read_inode:
-
-Called from function iget(ino, dev) - through get_new_inode.
-Typically called only when a VFS inode is instantiated by FS, i.e.
-upon lookup, create, mkdir, or upon mounting for the / inode.
-
-  -  executed for new inodes and for existing inodes
-  -  for new inodes, avoid traffic to disk
-
-E.g:
-
-lookup("name in dir-inode")
-{
-       get data from dir-inode; 
-       find ino of "name" in this data;
-       iget(sb(dev), ino); 
-       ---> calls read_inode 
-            ----> obd_getattr(obj-no = ino)
-}
-
-create("name in dir-inode") 
-{
-       get ino for name from pre-alloced obj-no's
-        ---> may call obd_prealloc_ids(hint)
-
-       iget(sb(dev), ino)
-       ---> call read_inode 
-            ---> do not contact OBD, fill in from FS
-
-       change data from dir-inode, to contain ("name, ino");
-}
-
-mkdir("name in dir-inode")
-{
-       as above
-}
-
-read_super(dev, data)
-{
-       struct obdfs_sb *sb = ... ;
-       obd_connect(dev, &sb->obdfs_conn_info);
-
-       iget(sb, sb->obdfs_conn_info->conn_ino);
-
-
-}
-
-We currently have:
-
-struct obd_conn_info {
-       unsigned int conn_id;
-       unsigned long conn_ino;
-       unsigned long conn_blocksize;
-       unsigned char conn_blocksize_bits;
-};
-
-read_inode(inode)
-{
-       struct iattr attr;
-
-       
-       if ( inode in inode_attr cache ) {
-               get_attr_from_cache(inode, &attr);
-       } else {
-               obd_getattr(conn_id, inode->i_ino, &attr);
-       }               
-
-       inode_setattr(inode, &attr);
-}
-
-Write_inode is called from the bdflush (sync_dev) routines, through
-write_inode, sync_inode, sync_list, sync_inodes etc:
-
-void sync_dev(kdev_t dev)
-{
-       sync_buffers(dev, 0);
-       sync_supers(dev);
-       sync_inodes(dev);
-       sync_buffers(dev, 0);
-       DQUOT_SYNC(dev);
-       /*
-        * FIXME(eric) we need to sync the physical devices here.
-        * This is because some (scsi) controllers have huge amounts of
-        * cache onboard (hundreds of Mb), and we need to instruct
-        * them to commit all of the dirty memory to disk, and we should
-        * not return until this has happened.
-        *
-        * This would need to get implemented by going through the assorted
-        * layers so that each block major number can be synced, and this
-        * would call down into the upper and mid-layer scsi.
-        */
-}
-
-This sync_inodes function is responsible (for "block" disk file
-systems) for copying the modified inode metadata into the buffer
-cache.  The sync_buffers call which follows sync_inodes is responsible
-for writing back this meta data.  For OBD's this is different.
-
-I expect the following routine to be there:
-
-sync_inode_pages(dev,0);
-sync_supers(dev);
-sync_inode_metadata(dev);
-
-
-The statfs function should return simple summary information available 
-on the disk: %free, total space, etc.    May require a new obd_command.
-
-Similarly write_super would instruct the disk to commit any pending
-data.  This is called from do_unmount just before put_super (the
-latter breaks down the vm super block  structure).  
-
-Write_super should: 
-- undo pre-allocated inode numbers
-
-The disk itself also needs a cleanup function.
-
-struct file_operations {
-       loff_t (*llseek) (struct file *, loff_t, int);
-       ssize_t (*read) (struct file *, char *, size_t, loff_t *);
-       ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
-       int (*readdir) (struct file *, void *, filldir_t);
-       unsigned int (*poll) (struct file *, struct poll_table_struct *);
-       int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
-       int (*mmap) (struct file *, struct vm_area_struct *);
-       int (*open) (struct inode *, struct file *);
-       int (*flush) (struct file *);
-       int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, struct dentry *);
-       int (*fasync) (int, struct file *, int);
-       int (*check_media_change) (kdev_t dev);
-       int (*revalidate) (kdev_t dev);
-       int (*lock) (struct file *, int, struct file_lock *);
-};
-
-
-struct inode_operations {
-       struct file_operations * default_file_ops;
-       int (*create) (struct inode *,struct dentry *,int);
-       struct dentry * (*lookup) (struct inode *,struct dentry *);
-       int (*link) (struct dentry *,struct inode *,struct dentry *);
-       int (*unlink) (struct inode *,struct dentry *);
-       int (*symlink) (struct inode *,struct dentry *,const char *);
-       int (*mkdir) (struct inode *,struct dentry *,int);
-       int (*rmdir) (struct inode *,struct dentry *);
-       int (*mknod) (struct inode *,struct dentry *,int,int);
-       int (*rename) (struct inode *, struct dentry *,
-                       struct inode *, struct dentry *);
-       int (*readlink) (struct dentry *, char *,int);
-       struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int);
-       /*
-        * the order of these functions within the VFS template has been
-        * changed because SMP locking has changed: from now on all get_block,
-        * readpage, writepage and flushpage functions are supposed to do
-        * whatever locking they need to get proper SMP operation - for
-        * now in most cases this means a lock/unlock_kernel at entry/exit.
-        * [The new order is also slightly more logical :)]
-        */
-       /*
-        * Generic block allocator exported by the lowlevel fs. All metadata
-        * details are handled by the lowlevel fs, all 'logical data content'
-        * details are handled by the highlevel block layer.
-        */
-       int (*get_block) (struct inode *, long, struct buffer_head *, int);
-
-       int (*readpage) (struct file *, struct page *);
-       int (*writepage) (struct file *, struct page *);
-       int (*flushpage) (struct inode *, struct page *, unsigned long);
-
-       void (*truncate) (struct inode *);
-       int (*permission) (struct inode *, int);
-       int (*smap) (struct inode *,int);
-       int (*revalidate) (struct dentry *);
-};
-
-
index bceef44..1e2b2a2 100644 (file)
@@ -28,9 +28,9 @@
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 
-#include <../obd/linux/obd_support.h>
-#include <../obd/linux/obd_sim.h>
-#include <obdfs.h>
+#include <linux/obd_support.h>
+#include <linux/obd_sim.h>
+#include <linux/obdfs.h>
 
 int console_loglevel;
 
 
 int console_loglevel;
 
index f007e91..7524d53 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/obd_support.h>
 #include <linux/obd_class.h>
 #include <linux/obd_sim.h>  /* XXX for development/debugging only */
 #include <linux/obd_support.h>
 #include <linux/obd_class.h>
 #include <linux/obd_sim.h>  /* XXX for development/debugging only */
-#include <obdfs.h>
+#include <linux/obdfs.h>
 
 /* VFS super_block ops */
 static struct super_block *obdfs_read_super(struct super_block *, void *, int);
 
 /* VFS super_block ops */
 static struct super_block *obdfs_read_super(struct super_block *, void *, int);
diff --git a/lustre/tests/test.c b/lustre/tests/test.c
new file mode 100755 (executable)
index 0000000..c79a640
--- /dev/null
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <asm/statfs.h>
+#include <unistd.h>
+
+#define OBD_IOC_CREATE                 _IOR('f', 3, long)
+#define OBD_IOC_SETUP                  _IOW('f', 4, long)
+#define OBD_IOC_SYNC                   _IOR('f', 16, long)
+#define OBD_IOC_DESTROY                _IOW('f', 6, long)
+#define OBD_IOC_STATFS                _IORW('f', 15, long)
+
+#define LOOP_DEVICE "/dev/loop0"
+#define OBD_DEVICE "/dev/obd"
+
+int main (int argc, char * argv[])
+{
+       int fd, rc, err = -1;
+       struct stat stat_buf;
+       struct statfs stfs;
+
+
+       if (argc < 2) {
+               printf("syntax: %s command [argument]\n", argv[0]);
+               printf("Where command is one of \"setup\", \"create\", \"destroy\", or \"sync\".\n");
+               exit(1);
+       }
+       if (stat(LOOP_DEVICE, &stat_buf)) {
+               printf("Couldn't stat(" LOOP_DEVICE ").\n");
+               exit(1);
+       }
+       printf("Device: %u\n", (unsigned int) stat_buf.st_rdev);
+
+       fd = open (OBD_DEVICE, O_RDONLY);
+       if (fd == -1) {
+               printf("Couldn't open " OBD_DEVICE ".\n");
+               exit(1);
+       }
+
+       if (!strcmp(argv[1], "setup")) {
+               rc = ioctl(fd, OBD_IOC_SETUP, &stat_buf.st_rdev);
+               fprintf(stderr, "rc = %d, errno = %d\n", rc, errno);
+       } else if (!strcmp(argv[1], "create")) {
+               int iter, i;
+
+               if (argc < 3) {
+                       printf("create requires a nonzero argument.\n");
+                       exit(1);
+               }
+
+               iter = atoi(argv[2]);
+               if (iter < 1) {
+                       printf("create requires a nonzero argument.\n");
+                       exit(1);
+               }
+               printf("creating %d objects...\n", iter);
+
+               for (i = 0; i < iter; i++) {
+                       if ((rc = ioctl(fd, OBD_IOC_CREATE, &err))) {
+                               fprintf(stderr, "Error; aborting.\n");
+                               break;
+                       }
+                       if ((rc = ioctl(fd, OBD_IOC_DESTROY, &err))) {
+                               fprintf(stderr, "Error; aborting.\n");
+                               break;
+                       }
+               }
+               fprintf(stderr, "rc = %d, errno = %d, err = %d\n",
+                       rc, errno, err);
+       } else if (!strcmp(argv[1], "sync")) {
+               rc = ioctl(fd, OBD_IOC_SYNC, &err);
+               fprintf(stderr, "rc = %d, errno = %d, err = %d\n",
+                       rc, errno, err);
+       } else if (!strcmp(argv[1], "destroy")) {
+               int ino;
+
+               if (argc < 3) {
+                       printf("destroy requires a nonzero inode number.\n");
+                       exit(1);
+               }
+
+               ino = atoi(argv[2]);
+               if (ino < 1) {
+                       printf("destroy requires a nonzero inode number.\n");
+                       exit(1);
+               }
+
+               rc = ioctl(fd, OBD_IOC_DESTROY, &ino);
+               fprintf(stderr, "rc = %d, errno = %d\n", rc, errno);
+       } else {
+               printf("Invalid command, run with no arguments for help.\n");
+       }
+       close(fd);
+
+       return 0;
+}
diff --git a/lustre/tests/test2.c b/lustre/tests/test2.c
new file mode 100755 (executable)
index 0000000..4d486af
--- /dev/null
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+/* Beware when setting FSROOT that I've not made any attempts to avoid buffer
+ * overruns below--this is a test program, it's a static buffer. */
+#define FSROOT "/mnt"
+#define OBD_ITERATIONS 10000
+
+int main (int argc, char * argv[])
+{
+       int fd, rc, err = -1;
+       struct stat stat_buf;
+
+       if (argc < 2) {
+               printf("syntax: %s command\n", argv[0]);
+               printf("Where command is one of \"setup\" or \"create\".\n");
+               exit(1);
+       }
+
+       if (!strcmp(argv[1], "setup")) {
+               printf("This is silly.\n");
+       } else if (!strcmp(argv[1], "create")) {
+               int i, iter;
+
+               if (argc < 3) {
+                       printf("create requires a nonzero argument.\n");
+                       exit(1);
+               }
+
+               iter = atoi(argv[2]);
+
+               if (iter < 1) {
+                       printf("create requires a nonzero argument.\n");
+                       exit(1);
+               }
+               printf("creating %d files...\n", iter);
+
+               for (i = 0; i < iter; i++) {
+                       fd = creat(FSROOT "/foo123", S_IRWXU);
+                       close(fd);
+                       unlink(FSROOT "/foo123");
+               }
+       } else {
+               printf("Invalid command, run with no arguments for help.\n");
+       }
+
+       return 0;
+}