Whamcloud - gitweb
Numerous changes:
authorbraam <braam>
Tue, 11 Dec 2001 21:08:42 +0000 (21:08 +0000)
committerbraam <braam>
Tue, 11 Dec 2001 21:08:42 +0000 (21:08 +0000)
  - new control utility  - no Perl
  - filter obd halfway coded ; requires new patches to kernel
  - big cleanup in the class driver with better packed ioctls
  - macros to pack other things, like network packets

21 files changed:
lustre/demos/Makefile.in
lustre/include/linux/obd_class.h
lustre/include/linux/obd_filter.h [new file with mode: 0644]
lustre/include/linux/obd_support.h
lustre/include/linux/obdfs.h
lustre/obdclass/Makefile.am
lustre/obdclass/Makefile.in
lustre/obdclass/class_obd.c
lustre/obdclass/genops.c
lustre/obdfilter/Makefile.am [new file with mode: 0644]
lustre/obdfilter/filter.c [new file with mode: 0644]
lustre/obdfs/Makefile.am
lustre/obdfs/Makefile.in
lustre/obdfs/super.c
lustre/scripts/Makefile.in
lustre/utils/Makefile.am [new file with mode: 0644]
lustre/utils/Pack.pm [new file with mode: 0644]
lustre/utils/obdcontrol [moved from lustre/obdclass/obdcontrol with 88% similarity]
lustre/utils/obdctl.c [new file with mode: 0644]
lustre/utils/parser.c [new file with mode: 0644]
lustre/utils/parser.h [new file with mode: 0644]

index ca03afe..4a6aded 100644 (file)
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -77,7 +77,9 @@ docdir = @docdir@
 moduledir = @moduledir@
 modulefsdir = @modulefsdir@
 
-demo_SCRIPTS = baseclean.sh basesetup.sh obdfsclean.sh obdfssetup.sh   obdtest.sh snap3clean.sh snap3set.sh snapclean.sh snapdel.sh    snaprest.sh snaprestclean.sh snapsetup.sh snaptest.sh
+demo_SCRIPTS = baseclean.sh basesetup.sh obdfsclean.sh obdfssetup.sh \
+       obdtest.sh snap3clean.sh snap3set.sh snapclean.sh snapdel.sh \
+       snaprest.sh snaprestclean.sh snapsetup.sh snaptest.sh
 
 demo_DATA = config.sh
 EXTRA_DIST = $(demo_SCRIPTS) $(demo_DATA)
index 1cd173e..0314929 100644 (file)
  * See the file COPYING in this distribution
  */
 
+#ifndef __KERNEL__
+#include <stdint.h>
+#define __KERNEL__
+#include <linux/list.h>
+#undef __KERNEL__
+#else 
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/obd.h>
 
 #include <linux/obd_ext2.h>
+#include <linux/obd_filter.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>
+#endif
 
 
 /*
  *  ======== OBD type Declarations ===========
  */
+#define MIN(a,b) (((a)<(b)) ? (a): (b))
+#define MAX(a,b) (((a)>(b)) ? (a): (b))
+#define MKSTR(ptr) ((ptr))? (ptr) : ""
+
+static inline int size_round(int val)
+{
+       return (val + 3) & (~0x3);
+}
+
+static inline size_t round_strlen(char *str)
+{
+       return size_round(strlen(str) + 1);
+}
+
+#ifdef __KERNEL__
+static inline char *strdup(char *str)
+{
+       char *tmp = kmalloc(strlen(str) + 1, GFP_KERNEL);
+       if (tmp)
+               memcpy(tmp, str, strlen(str) + 1);
+               
+       return NULL;
+}
+#endif
+/* 
+ * copy sizeof(type) bytes from pointer to var and move ptr forward.
+ * return EFAULT if pointer goes beyond end
+ */
+#define UNLOGV(var,type,ptr,end) do {var = *(type *)ptr; ptr += sizeof(type); if (ptr > end ) return -EFAULT;} while (0)
+
+
+/* the following two macros convert to little endian */
+/* type must be 32 or 64 */
+#define LUNLOGV(var,type,ptr,end)                \
+do {                                            \
+        var = le_to_cpu##type(*(type *)ptr);         \
+        ptr += sizeof(type);                    \
+        if (ptr > end )                         \
+                return -EFAULT;                 \
+} while (0)
+
+/* now log values */
+#define LOGV(var,type,ptr)                      \
+do {                                            \
+        *((type *)ptr) = var;                   \
+        ptr += sizeof(type);                    \
+} while (0)
+
+/* and in network order */
+#define LLOGV(var,type,ptr)                     \
+do {                                            \
+        *((type *)ptr) = cpu_to_le##type(var);  \
+        ptr += sizeof(type);                    \
+} while (0)
+
+/* 
+ * set var to point at (type *)ptr, move ptr forward with sizeof(type)
+ * return from function with EFAULT if ptr goes beyond end
+ */
+#define UNLOGP(var,type,ptr,end) do {var = (type *)ptr; ptr += sizeof(type); if (ptr > end ) return -EFAULT; } while (0)
+
+/* 
+ * set var to point at (char *)ptr, move ptr forward by size_round(len);
+ * return from function with EFAULT if ptr goes beyond end
+ */
+#define UNLOGL(var,type,len,ptr,end) do {var = (type *)ptr; ptr += size_round(len * sizeof(type)); if (ptr > end ) return -EFAULT; } while (0)
+
+
+#define LOGL(var,len,ptr) do {memcpy((char *)ptr, (const char *)var, len); ptr += size_round(len);} while (0)
 
 typedef uint64_t        obd_id;
 typedef uint64_t        obd_gr;
@@ -37,6 +117,8 @@ typedef uint32_t        obd_rdev;
 typedef uint32_t        obd_flag;
 typedef uint32_t        obd_count;
 
+
+
 #define OBD_FL_INLINEDATA       (0x00000001UL)  
 #define OBD_FL_OBDMDEXISTS      (0x00000002UL)
 
@@ -66,6 +148,33 @@ struct obdo {
         struct obd_ops          *o_op;
 };
 
+
+struct obd_ioctl_data { 
+       uint32_t ioc_len;
+       uint32_t ioc_version;
+        uint32_t ioc_conn1;
+        uint32_t ioc_conn2;
+       struct obdo ioc_obdo1;
+       struct obdo ioc_obdo2;
+        obd_size         ioc_count;
+        obd_off          ioc_offset;
+       uint32_t         ioc_dev;
+
+       /* buffers the kernel will treat as user pointers */
+       uint32_t ioc_plen1;
+       char    *ioc_pbuf1;
+       uint32_t ioc_plen2;
+       char    *ioc_pbuf2;
+
+       /* two inline buffers */
+       uint32_t ioc_inllen1;
+       char    *ioc_inlbuf1;
+       uint32_t ioc_inllen2;
+       char    *ioc_inlbuf2;
+
+       char    ioc_bulk[0];
+};
+
 #define OBD_MD_FLALL    (~0UL)
 #define OBD_MD_FLID     (0x00000001UL)
 #define OBD_MD_FLATIME  (0x00000002UL)
@@ -113,6 +222,8 @@ typedef struct {
         __u8           _uuid[16]; /* uuid obd device names */
 } obd_devicename;
 
+
+#ifdef __KERNEL__
 /* corresponds to one of the obdx */
 struct obd_device {
         struct obd_type *obd_type;
@@ -120,8 +231,6 @@ struct obd_device {
         int obd_flags;
         int obd_refcnt; 
         obd_devicename obd_fsname; 
-       kdev_t obd_rdev;
-       char * obd_user_name;
        struct proc_dir_entry *obd_proc_entry;
         int obd_multi_count;
         struct obd_conn obd_multi_conn[MAX_MULTI];
@@ -130,6 +239,7 @@ struct obd_device {
         struct list_head obd_gen_clients;
         union {
                 struct ext2_obd ext2;
+                struct filter_obd filter;
                 struct raid1_obd raid1;
                 struct snap_obd snap;
                struct trace_obd trace;
@@ -141,7 +251,6 @@ extern struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device
 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 ===========
  */
@@ -158,9 +267,9 @@ struct obd_ops {
                           obd_count *vallen, void **val);
         int (*o_set_info)(struct obd_conn *, obd_count keylen, void *key,
                           obd_count vallen, void *val);
-        int (*o_attach)(struct obd_device *dev, obd_count len, void *data);
+        int (*o_attach)(struct obd_device *dev, struct obd_ioctl_data *data);
         int (*o_detach)(struct obd_device *dev);
-        int (*o_setup) (struct obd_device *dev, obd_count len, void *data);
+        int (*o_setup) (struct obd_device *dev, struct obd_ioctl_data *data);
         int (*o_cleanup)(struct obd_device *dev);
         int (*o_connect)(struct obd_conn *conn);
         int (*o_disconnect)(struct obd_conn *conn);
@@ -193,6 +302,8 @@ struct obd_ops {
 #define OBT(dev)        dev->obd_type->typ_ops
 #define OBP(dev,op)     dev->obd_type->typ_ops->o_ ## op
 
+#endif 
+
 /* This value is not arbitrarily chosen.  KIO_STATIC_PAGES from linux/iobuf.h */
 #define MAX_IOVEC       (KIO_STATIC_PAGES - 1)
 
@@ -217,6 +328,7 @@ static inline int obdo_has_obdmd(struct obdo *obdo)
                 obdo->o_obdflags & OBD_FL_OBDMDEXISTS);
 };
 
+#ifdef __KERNEL__
 /* support routines */
 extern kmem_cache_t *obdo_cachep;
 
@@ -301,52 +413,44 @@ static inline void obdo_from_iattr(struct obdo *oa, struct iattr *attr)
 }
 
 
-static __inline__ void obdo_cpy_md(struct obdo *dst, struct obdo *src)
+static inline void iattr_from_obdo(struct iattr *attr, struct obdo *oa)
 {
-        CDEBUG(D_INODE, "src obdo %Ld valid 0x%x, dst obdo %Ld\n",
-               src->o_id, src->o_valid, dst->o_id);
-        if ( src->o_valid & OBD_MD_FLATIME ) 
-                dst->o_atime = src->o_atime;
-        if ( src->o_valid & OBD_MD_FLMTIME ) 
-                dst->o_mtime = src->o_mtime;
-        if ( src->o_valid & OBD_MD_FLCTIME ) 
-                dst->o_ctime = src->o_ctime;
-        if ( src->o_valid & OBD_MD_FLSIZE ) 
-                dst->o_size = src->o_size;
-        if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
-                dst->o_blocks = src->o_blocks;
-        if ( src->o_valid & OBD_MD_FLBLKSZ )
-                dst->o_blksize = src->o_blksize;
-        if ( src->o_valid & OBD_MD_FLMODE ) 
-                dst->o_mode = src->o_mode;
-        if ( src->o_valid & OBD_MD_FLUID ) 
-                dst->o_uid = src->o_uid;
-        if ( src->o_valid & OBD_MD_FLGID ) 
-                dst->o_gid = src->o_gid;
-        if ( src->o_valid & OBD_MD_FLFLAGS ) 
-                dst->o_flags = src->o_flags;
-        /*
-        if ( src->o_valid & OBD_MD_FLOBDFLG ) 
-                dst->o_obdflags = src->o_obdflags;
-        */
-        if ( src->o_valid & OBD_MD_FLNLINK ) 
-                dst->o_nlink = src->o_nlink;
-        if ( src->o_valid & OBD_MD_FLGENER ) 
-                dst->o_generation = src->o_generation;
-        if ( src->o_valid & OBD_MD_FLINLINE &&
-             src->o_obdflags & OBD_FL_INLINEDATA) {
-                memcpy(dst->o_inline, src->o_inline, sizeof(src->o_inline));
-                dst->o_obdflags |= OBD_FL_INLINEDATA;
+        unsigned int ia_valid = oa->o_valid;
+
+        if (ia_valid & OBD_MD_FLATIME) {
+                attr->ia_atime = oa->o_atime;
+                attr->ia_valid |= ATTR_ATIME;
         }
-        if ( src->o_valid & OBD_MD_FLOBDMD &&
-             src->o_obdflags & OBD_FL_OBDMDEXISTS) {
-                memcpy(dst->o_obdmd, src->o_obdmd, sizeof(src->o_obdmd));
-                dst->o_obdflags |= OBD_FL_OBDMDEXISTS;
+        if (ia_valid & OBD_MD_FLMTIME) {
+                attr->ia_mtime = oa->o_mtime;
+                attr->ia_valid |= ATTR_MTIME;
+        }
+        if (ia_valid & OBD_MD_FLCTIME) {
+                attr->ia_ctime = oa->o_ctime;
+                attr->ia_valid |= ATTR_CTIME;
+        }
+        if (ia_valid & OBD_MD_FLSIZE) {
+                attr->ia_size = oa->o_size;
+                attr->ia_valid |= ATTR_SIZE;
+        }
+        if (ia_valid & OBD_MD_FLMODE) {
+                attr->ia_mode = oa->o_mode;
+                attr->ia_valid |= ATTR_MODE;
+                if (!in_group_p(oa->o_gid) && !capable(CAP_FSETID))
+                        attr->ia_mode &= ~S_ISGID;
+        }
+        if (ia_valid & OBD_MD_FLUID)
+        {
+                attr->ia_uid = oa->o_uid;
+                attr->ia_valid |= ATTR_UID;
+        }
+        if (ia_valid & OBD_MD_FLGID) {
+                attr->ia_gid = oa->o_gid;
+                attr->ia_valid |= ATTR_GID;
         }
-
-        dst->o_valid |= src->o_valid;
 }
 
+
 /* WARNING: the file systems must take care not to tinker with
    attributes they don't manage (such as blocks). */
 
@@ -411,6 +515,57 @@ static __inline__ void obdo_to_inode(struct inode *dst, struct obdo *src)
                 dst->i_generation = src->o_generation;
 }
 
+#endif 
+
+static __inline__ void obdo_cpy_md(struct obdo *dst, struct obdo *src)
+{
+#ifdef __KERNEL__
+        CDEBUG(D_INODE, "src obdo %Ld valid 0x%x, dst obdo %Ld\n",
+               src->o_id, src->o_valid, dst->o_id);
+#endif
+        if ( src->o_valid & OBD_MD_FLATIME ) 
+                dst->o_atime = src->o_atime;
+        if ( src->o_valid & OBD_MD_FLMTIME ) 
+                dst->o_mtime = src->o_mtime;
+        if ( src->o_valid & OBD_MD_FLCTIME ) 
+                dst->o_ctime = src->o_ctime;
+        if ( src->o_valid & OBD_MD_FLSIZE ) 
+                dst->o_size = src->o_size;
+        if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
+                dst->o_blocks = src->o_blocks;
+        if ( src->o_valid & OBD_MD_FLBLKSZ )
+                dst->o_blksize = src->o_blksize;
+        if ( src->o_valid & OBD_MD_FLMODE ) 
+                dst->o_mode = src->o_mode;
+        if ( src->o_valid & OBD_MD_FLUID ) 
+                dst->o_uid = src->o_uid;
+        if ( src->o_valid & OBD_MD_FLGID ) 
+                dst->o_gid = src->o_gid;
+        if ( src->o_valid & OBD_MD_FLFLAGS ) 
+                dst->o_flags = src->o_flags;
+        /*
+        if ( src->o_valid & OBD_MD_FLOBDFLG ) 
+                dst->o_obdflags = src->o_obdflags;
+        */
+        if ( src->o_valid & OBD_MD_FLNLINK ) 
+                dst->o_nlink = src->o_nlink;
+        if ( src->o_valid & OBD_MD_FLGENER ) 
+                dst->o_generation = src->o_generation;
+        if ( src->o_valid & OBD_MD_FLINLINE &&
+             src->o_obdflags & OBD_FL_INLINEDATA) {
+                memcpy(dst->o_inline, src->o_inline, sizeof(src->o_inline));
+                dst->o_obdflags |= OBD_FL_INLINEDATA;
+        }
+        if ( src->o_valid & OBD_MD_FLOBDMD &&
+             src->o_obdflags & OBD_FL_OBDMDEXISTS) {
+                memcpy(dst->o_obdmd, src->o_obdmd, sizeof(src->o_obdmd));
+                dst->o_obdflags |= OBD_FL_OBDMDEXISTS;
+        }
+
+        dst->o_valid |= src->o_valid;
+}
+
+
 /* returns FALSE if comparison (by flags) is same, TRUE if changed */
 static __inline__ int obdo_cmp_md(struct obdo *dst, struct obdo *src,
                                   obd_flag compare)
@@ -451,7 +606,7 @@ static __inline__ int obdo_cmp_md(struct obdo *dst, struct obdo *src,
 }
 
 
-
+#ifdef __KERNEL__
 int obd_register_type(struct obd_ops *ops, char *nm);
 int obd_unregister_type(char *nm);
 
@@ -482,60 +637,161 @@ int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst,
                   struct obd_conn *src_conn, struct obdo *src,
                   obd_size count, obd_off offset);
 
-
+#endif
 
 /*
  *  ======== OBD IOCL Declarations ===========
  */
-struct oic_generic {
-        uint32_t att_connid;
-        int      att_typelen;
-        void    *att_type;
-        int      att_datalen;
-        void    *att_data;
-};
 
+#define OBD_IOCTL_VERSION 0x00010001
 
-/* for preallocation */
-struct oic_prealloc_s {
-        uint32_t         conn_id;
-        uint32_t         alloc; /* user sets it to the number of inodes
-                                 * requesting to be preallocated.  kernel
-                                 * sets it to the actual number of
-                                 * succesfully preallocated inodes */
-        obd_id           ids[32]; /* actual inode numbers */
+struct obd_ioctl_hdr { 
+       uint32_t ioc_len;
+       uint32_t ioc_version;
 };
 
-/* for getattr, setattr, create, destroy */
-struct oic_attr_s {
-        uint32_t         conn_id;
-        struct obdo      obdo;
-};
+static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
+{
+       int len = sizeof(struct obd_ioctl_data);
+       len += size_round(data->ioc_inllen1);
+       len += size_round(data->ioc_inllen2);
+       return len;
+}
 
-/* for copy, migrate */
-struct ioc_mv_s {
-        uint32_t         src_conn_id;
-        struct obdo      src;
-        uint32_t         dst_conn_id;
-        struct obdo      dst;
-};
+static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
+{
+       if (data->ioc_len > (1<<30)) { 
+               printk("OBD ioctl: ioc_len larger than 1<<30\n");
+               return 1;
+       }
+       if (data->ioc_inllen1 > (1<<30)) { 
+               printk("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
+               return 1;
+       }
+       if (data->ioc_inllen2 > (1<<30)) { 
+               printk("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
+               return 1;
+       }
+       if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
+               printk("OBD ioctl: inlbuf1 pointer but 0 length\n");
+               return 1;
+       }
+       if (data->ioc_inlbuf2 && !data->ioc_inllen2) {
+               printk("OBD ioctl: inlbuf2 pointer but 0 length\n");
+               return 1;
+       }
+       if (data->ioc_pbuf1 && !data->ioc_plen1) {
+               printk("OBD ioctl: pbuf1 pointer but 0 length\n");
+               return 1;
+       }
+       if (data->ioc_pbuf2 && !data->ioc_plen2) {
+               printk("OBD ioctl: pbuf2 pointer but 0 length\n");
+               return 1;
+       }
+       if (obd_ioctl_packlen(data) != data->ioc_len ) {
+               printk("OBD ioctl: packlen exceeds ioc_len\n");
+               return 1;
+       }
+       if (data->ioc_inllen1 && 
+           data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { 
+               printk("OBD ioctl: inlbuf1 not 0 terminated\n");
+               return 1;
+       }
+       if (data->ioc_inllen2 && 
+           data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2 - 1] != '\0') { 
+               printk("OBD ioctl: inlbuf2 not 0 terminated\n");
+               return 1;
+       }
+       return 0;
+}
 
-/* for read/write */
-struct oic_rw_s {
-        uint32_t         conn_id;
-        struct obdo      obdo;
-        char            *buf;
-        obd_size         count;
-        obd_off          offset;
-};
+#ifndef __KERNEL__
+static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, int max)
+{
+       char *ptr;
+       struct obd_ioctl_data *overlay;
+       data->ioc_len = obd_ioctl_packlen(data);
+       data->ioc_version = OBD_IOCTL_VERSION;
+
+       if (*pbuf && obd_ioctl_packlen(data) > max) 
+               return 1;
+       if (*pbuf == NULL) { 
+               *pbuf = malloc(data->ioc_len);
+       }
+       if (!*pbuf)
+               return 1;
+       overlay = (struct obd_ioctl_data *)*pbuf;
+       memcpy(*pbuf, data, sizeof(*data));
+
+       ptr = overlay->ioc_bulk;
+       if (data->ioc_inlbuf1)
+               LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr);
+       if (data->ioc_inlbuf2)
+               LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr);
+       if (obd_ioctl_is_invalid(overlay))
+               return 1;
+
+       return 0;
+}
+#else
 
-/* for punch, sync */
-struct oic_range_s {
-        uint32_t         conn_id;
-        struct obdo      obdo;
-        obd_size         count;
-        obd_off          offset;
-};
+
+/* buffer MUST be at least the size of obd_ioctl_hdr */
+static inline int obd_ioctl_getdata(char *buf, char *end, void *arg)
+{
+       struct obd_ioctl_hdr *hdr;
+       struct obd_ioctl_data *data;
+       int err;
+       ENTRY;
+
+       hdr = (struct obd_ioctl_hdr *)buf;
+       data = (struct obd_ioctl_data *)buf;
+
+       err = copy_from_user(buf, (void *)arg, sizeof(*hdr));
+       if ( err ) {
+               EXIT;
+               return err;
+       }
+
+       if (hdr->ioc_version != OBD_IOCTL_VERSION) { 
+               printk("OBD: version mismatch kernel vs application\n");
+               return -EINVAL;
+       }
+
+       if (hdr->ioc_len + buf >= end) { 
+               printk("OBD: user buffer exceeds kernel buffer\n");
+               return -EINVAL;
+       }
+
+
+       if (hdr->ioc_len < sizeof(struct obd_ioctl_data)) { 
+               printk("OBD: user buffer too small for ioctl\n");
+               return -EINVAL;
+       }
+
+       err = copy_from_user(buf, (void *)arg, hdr->ioc_len);
+       if ( err ) {
+               EXIT;
+               return err;
+       }
+
+       if (obd_ioctl_is_invalid(data)) { 
+               printk("OBD: ioctl not correctly formatted\n");
+               return -EINVAL;
+       }
+
+       if (data->ioc_inllen1) { 
+               data->ioc_inlbuf1 = &data->ioc_bulk[0];
+       }
+
+       if (data->ioc_inllen2) { 
+               data->ioc_inlbuf2 = &data->ioc_bulk[0] + size_round(data->ioc_inllen1);
+       }
+
+       EXIT;
+       return 0;
+}
+#endif
 
 
 #define OBD_IOC_CREATE                 _IOR ('f',  3, long)
@@ -560,6 +816,7 @@ struct oic_range_s {
 #define OBD_IOC_COPY                   _IOWR('f', 22, long)
 #define OBD_IOC_MIGR                   _IOWR('f', 23, long)
 #define OBD_IOC_PUNCH                  _IOWR('f', 24, long)
+#define OBD_IOC_DEVICE                 _IOWR('f', 25, long)
 
 #define OBD_IOC_DEC_FS_USE_COUNT       _IO  ('f', 32      )
 
diff --git a/lustre/include/linux/obd_filter.h b/lustre/include/linux/obd_filter.h
new file mode 100644 (file)
index 0000000..6fb189f
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _OBD_FILTER_H
+#define _OBD_FILTER_H
+/*
+ * Copyright (C) 2001  Cluster File Systems, Inc.
+ *
+ * This code is issued under the GNU General Public License.
+ * See the file COPYING in this distribution
+ */
+
+
+#ifndef OBD_FILTER_DEVICENAME
+#define OBD_FILTER_DEVICENAME "obdfilter"
+#endif
+
+struct run_ctxt { 
+       struct vfsmount *pwdmnt;
+       struct dentry   *pwd;
+       mm_segment_t     fs;
+};
+
+struct filter_obd {
+       char *fo_fstype;
+        struct super_block * fo_sb;
+       struct vfsmount *fo_vfsmnt;
+       struct run_ctxt  fo_ctxt;
+       __u64 fo_lastino;
+};
+
+
+extern struct obd_ops filter_obd_ops;
+
+#endif
index 0d37002..c091236 100644 (file)
@@ -11,8 +11,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
-#define MIN(a,b) (((a)<(b)) ? (a): (b))
-#define MAX(a,b) (((a)>(b)) ? (a): (b))
+
 
 #define obd_unlock_page(page)   do {    if (PageLocked(page)) { \
                         UnlockPage(page);\
@@ -165,7 +164,7 @@ static inline void obd_iput(struct inode *inode)
 
 #define OBD_ALLOC(ptr, cast, size)                                      \
 do {                                                                    \
-        ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL);        \
+        ptr = kmalloc((unsigned long) size, GFP_KERNEL);        \
         obd_memory += size;                                             \
         CDEBUG(D_MALLOC, "kmalloced: %d at %x (tot %ld).\n",            \
                        (int) size, (int) ptr, obd_memory);             \
index ff959e2..5df8f03 100644 (file)
@@ -10,7 +10,7 @@
 
 
 #ifndef _OBDFS_H
-#define OBDFS_H
+#define _OBDFS_H
 #include <linux/obd_class.h>
 #include <linux/obdo.h>
 #include <linux/list.h>
index 428942d..f92cd00 100644 (file)
@@ -1,6 +1,3 @@
-bin_SCRIPTS = obdcontrol
-EXTRA_DIST = $(bin_SCRIPTS)
-
 MODULE = obdclass
 modulefs_DATA = obdclass.o
 EXTRA_PROGRAMS = obdclass
index 16dd2f7..45b7007 100644 (file)
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -85,9 +85,6 @@ docdir = @docdir@
 moduledir = @moduledir@
 modulefsdir = @modulefsdir@
 
-bin_SCRIPTS = obdcontrol
-EXTRA_DIST = $(bin_SCRIPTS)
-
 MODULE = obdclass
 modulefs_DATA = obdclass.o
 EXTRA_PROGRAMS = obdclass
@@ -103,8 +100,6 @@ obdclass_OBJECTS =  genops.o proc_lustre.o class_obd.o sysctl.o
 obdclass_LDADD = $(LDADD)
 obdclass_DEPENDENCIES = 
 obdclass_LDFLAGS = 
-SCRIPTS =  $(bin_SCRIPTS)
-
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 CCLD = $(CC)
@@ -154,25 +149,6 @@ obdclass: $(obdclass_OBJECTS) $(obdclass_DEPENDENCIES)
        @rm -f obdclass
        $(LINK) $(obdclass_LDFLAGS) $(obdclass_OBJECTS) $(obdclass_LDADD) $(LIBS)
 
-install-binSCRIPTS: $(bin_SCRIPTS)
-       @$(NORMAL_INSTALL)
-       $(mkinstalldirs) $(DESTDIR)$(bindir)
-       @list='$(bin_SCRIPTS)'; for p in $$list; do \
-         if test -f $$p; then \
-           echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-           $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-         else if test -f $(srcdir)/$$p; then \
-           echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
-           $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-         else :; fi; fi; \
-       done
-
-uninstall-binSCRIPTS:
-       @$(NORMAL_UNINSTALL)
-       list='$(bin_SCRIPTS)'; for p in $$list; do \
-         rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
-       done
-
 install-modulefsDATA: $(modulefs_DATA)
        @$(NORMAL_INSTALL)
        $(mkinstalldirs) $(DESTDIR)$(modulefsdir)
@@ -281,7 +257,7 @@ check-am: all-am
 check: check-am
 installcheck-am:
 installcheck: installcheck-am
-install-exec-am: install-binSCRIPTS
+install-exec-am:
 install-exec: install-exec-am
 
 install-data-am: install-modulefsDATA
@@ -290,14 +266,14 @@ install-data: install-data-am
 install-am: all-am
        @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
 install: install-am
-uninstall-am: uninstall-binSCRIPTS uninstall-modulefsDATA
+uninstall-am: uninstall-modulefsDATA
 uninstall: uninstall-am
-all-am: Makefile $(SCRIPTS) $(DATA)
+all-am: Makefile $(DATA)
 all-redirect: all-am
 install-strip:
        $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
 installdirs:
-       $(mkinstalldirs)  $(DESTDIR)$(bindir) $(DESTDIR)$(modulefsdir)
+       $(mkinstalldirs)  $(DESTDIR)$(modulefsdir)
 
 
 mostlyclean-generic:
@@ -333,10 +309,9 @@ maintainer-clean-am:  maintainer-clean-compile maintainer-clean-tags \
 maintainer-clean: maintainer-clean-am
 
 .PHONY: mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile uninstall-binSCRIPTS install-binSCRIPTS \
-uninstall-modulefsDATA install-modulefsDATA tags mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir \
-mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-compile uninstall-modulefsDATA install-modulefsDATA \
+tags mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \
+distdir mostlyclean-depend distclean-depend clean-depend \
 maintainer-clean-depend info-am info dvi-am dvi check check-am \
 installcheck-am installcheck install-exec-am install-exec \
 install-data-am install-data install-am install uninstall-am uninstall \
index bf57215..545f66b 100644 (file)
@@ -6,8 +6,7 @@
  *
  *              This program is free software; you can redistribute it and/or
  *              modify it under the terms of the GNU General Public License
- *              as published by the Free Software Foundation; either version
- *              2 of the License, or (at your option) any later version.
+ *              version 2 as published by the Free Software Foundation.
  * 
  *              Adapted to become the Linux 2.0 Coda pseudo device
  *              Peter  Braam  <braam@maths.ox.ac.uk> 
@@ -29,7 +28,6 @@
  */
 
 #define EXPORT_SYMTAB
-
 #include <linux/config.h> /* for CONFIG_PROC_FS */
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <asm/io.h>
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/poll.h>
 #include <asm/uaccess.h>
+#include <linux/miscdevice.h>
 
 #include <linux/obd_support.h>
 #include <linux/obd_class.h>
@@ -65,53 +63,26 @@ long obd_memory = 0;
 struct obd_device obd_dev[MAX_OBD_DEVICES];
 struct list_head obd_types;
 
-/* called when opening /dev/obdNNN */
+/*  opening /dev/obd */
 static int obd_class_open(struct inode * inode, struct file * file)
 {
-        int dev;
         ENTRY;
 
-        if (!inode)
-                return -EINVAL;
-        dev = MINOR(inode->i_rdev);
-        if (dev >= MAX_OBD_DEVICES)
-                return -ENODEV;
-        obd_dev[dev].obd_refcnt++;
-        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]);
-
+       file->private_data = NULL;
         MOD_INC_USE_COUNT;
         EXIT;
         return 0;
 }
 
-/* called when closing /dev/obdNNN */
+/*  closing /dev/obd */
 static int obd_class_release(struct inode * inode, struct file * file)
 {
-        int dev;
         ENTRY;
 
-        if (!inode)
-                return -EINVAL;
-        dev = MINOR(inode->i_rdev);
-        if (dev >= MAX_OBD_DEVICES)
-                return -ENODEV;
-        fsync_dev(inode->i_rdev);
-        if (obd_dev[dev].obd_refcnt <= 0)
-                printk(KERN_ALERT __FUNCTION__ ": refcount(%d) <= 0\n",
-                       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;
+       if (file->private_data)
+               file->private_data = NULL;
 
+        MOD_DEC_USE_COUNT;
         EXIT;
         return 0;
 }
@@ -155,337 +126,251 @@ static struct obd_type *obd_nm_to_type(char *nm)
         return type;
 }
 
-
-static int getdata(int len, void **data)
-{
-        void *tmp = NULL;
-
-        if (!len) {
-                *data = NULL;
-                return 0;
-        }
-
-        CDEBUG(D_MALLOC, "len %d, add %p\n", len, *data);
-
-        OBD_ALLOC(tmp, void *, len);
-        if ( !tmp )
-                return -ENOMEM;
-        
-        memset(tmp, 0, len);
-        if ( copy_from_user(tmp, *data, len)) {
-                OBD_FREE(tmp, len);
-                return -EFAULT;
-        }
-        *data = tmp;
-
-        return 0;
-}
-
-/* to control /dev/obdNNN */
+/* to control /dev/obd */
 static int obd_class_ioctl (struct inode * inode, struct file * filp, 
                             unsigned int cmd, unsigned long arg)
 {
-        struct obd_device *obddev;
         /* NOTE this must be larger than any of the ioctl data structs */
         char buf[1024];
-        void *tmp_buf = buf;
-        struct obd_conn conn;
-        int err, dev;
-        long int cli_id; /* connect, disconnect */
-
-        if (!inode) {
-                CDEBUG(D_IOCTL, "invalid inode\n");
-                return -EINVAL;
-        }
-
-        dev = MINOR(inode->i_rdev);
-        if (dev > MAX_OBD_DEVICES)
-                return -ENODEV;
-        obddev = &obd_dev[dev];
-        conn.oc_dev = obddev;
+       struct obd_ioctl_data *data;
+       struct obd_device *obd = filp->private_data;
+       struct obd_conn conn;
+        int err = 0;
+       ENTRY;
+
+       memset(buf, 0, sizeof(buf));
+
+       if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS) {
+               printk("OBD ioctl: No device\n");
+               return -EINVAL;
+       } 
+       if (obd_ioctl_getdata(buf, buf + 800, (void *)arg)) { 
+               printk("OBD ioctl: data error\n");
+               return -EINVAL;
+       }
+       data = (struct obd_ioctl_data *)buf;
 
         switch (cmd) {
         case TCGETS:
                 return -EINVAL;
+       case OBD_IOC_DEVICE: { 
+               CDEBUG(D_IOCTL, "\n");
+               if (data->ioc_dev >= MAX_OBD_DEVICES ||
+                   data->ioc_dev < 0) { 
+                       printk("OBD ioctl: DEVICE insufficient devices\n");
+                       return -EINVAL;
+               }
+               CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
+
+               filp->private_data = &obd_dev[data->ioc_dev];
+               EXIT;
+               return 0;
+       }
+
         case OBD_IOC_ATTACH: {
                 struct obd_type *type;
-                struct oic_generic *input = tmp_buf;
-                char *nm;
 
                 ENTRY;
                 /* have we attached a type to this device */
-                if ( obddev->obd_type || 
-                     (obddev->obd_flags & OBD_ATTACHED) ){
-                       char *name;
-                       if (obddev->obd_type->typ_name) 
-                               name = obddev->obd_type->typ_name; 
-                       else 
-                               name = "";
-                        CDEBUG(D_IOCTL,
-                               "OBD Device %d already attached to type %s.\n",
-                               dev, name);
-                        EXIT;
+                if ( obd->obd_type ||  (obd->obd_flags & OBD_ATTACHED) ){
+                        printk("OBD: Device %d already typed as  %s.\n",
+                               obd->obd_minor, MKSTR(obd->obd_type->typ_name));
                         return -EBUSY;
                 }
 
-                /* get data structures */
-                err = copy_from_user(input, (void *)arg, sizeof(*input));
-                if ( err ) {
-                        EXIT;
-                        return err;
-                }
-
-                err = getdata(input->att_typelen + 1, &input->att_type);
-                if ( err ) {
-                        EXIT;
-                        return err;
-                }
+               printk("-----> attach %s %s\n",  MKSTR(data->ioc_inlbuf1), 
+                      MKSTR(data->ioc_inlbuf2));
 
                 /* find the type */
-                nm = input->att_type;
-                type = obd_nm_to_type(nm);
-
-                OBD_FREE(input->att_type, input->att_typelen + 1);
+                type = obd_nm_to_type(data->ioc_inlbuf1);
                 if ( !type ) {
-                        printk(__FUNCTION__ ": unknown obd type dev %d\n",
-                               dev);
-                        EXIT;
+                        printk("OBD: unknown type dev %d\n", obd->obd_minor);
                         return -EINVAL;
                 }
-                obddev->obd_type = type;
-                
-                /* get the attach data */
-                err = getdata(input->att_datalen, &input->att_data);
-                if ( err ) {
-                        EXIT;
-                        return err;
-                }
 
-                INIT_LIST_HEAD(&obddev->obd_gen_clients);
-                obddev->obd_multi_count = 0;
-
-                CDEBUG(D_IOCTL, "Attach %d, datalen %d, type %s\n", 
-                       dev, input->att_datalen, obddev->obd_type->typ_name);
-                /* maybe we are done */
-                if ( !OBT(obddev) || !OBP(obddev, attach) ) {
-                        obddev->obd_flags |= OBD_ATTACHED;
-                        type->typ_refcnt++;
-                        CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
-                               type->typ_refcnt);
-                        if (input->att_data)
-                                OBD_FREE(input->att_data, input->att_datalen);
-                        MOD_INC_USE_COUNT;
-                        EXIT;
-                        return 0;
-                }
+                obd->obd_type = type;
+                obd->obd_multi_count = 0;
+                INIT_LIST_HEAD(&obd->obd_gen_clients);
 
                 /* do the attach */
-                err = OBP(obddev, attach)(obddev, input->att_datalen,
-                                          input->att_data);
-                if (input->att_data)
-                        OBD_FREE(input->att_data, input->att_datalen);
+                if ( OBT(obd) && OBP(obd, attach) ) {
+                       err = OBP(obd, attach)(obd, data);
+               }
 
                 if ( err ) {
-                        obddev->obd_flags &= ~OBD_ATTACHED;
-                        obddev->obd_type = NULL;
+                        obd->obd_flags &= ~OBD_ATTACHED;
+                        obd->obd_type = NULL;
                         EXIT;
                 } else {
-                        obddev->obd_flags |=  OBD_ATTACHED;
+                        obd->obd_flags |=  OBD_ATTACHED;
                         type->typ_refcnt++;
-                        CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
-                               type->typ_refcnt);
+                        printk("OBD: dev %d attached type %s\n", 
+                              obd->obd_minor, data->ioc_inlbuf1);
+                       obd->obd_proc_entry = 
+                               proc_lustre_register_obd_device(obd);
                         MOD_INC_USE_COUNT;
                         EXIT;
                 }
+
                 return err;
         }
 
         case OBD_IOC_DETACH: {
-
                 ENTRY;
-                if (obddev->obd_flags & OBD_SET_UP) {
-                        EXIT;
+                if (obd->obd_flags & OBD_SET_UP) {
+                        printk("OBD device %d still set up\n", obd->obd_minor);
                         return -EBUSY;
                 }
-                if (! (obddev->obd_flags & OBD_ATTACHED) ) {
-                        CDEBUG(D_IOCTL, "Device not attached\n");
-                        EXIT;
+                if (! (obd->obd_flags & OBD_ATTACHED) ) {
+                        printk("OBD device %d not attached\n", obd->obd_minor);
                         return -ENODEV;
                 }
-                if ( !list_empty(&obddev->obd_gen_clients) ) {
-                        CDEBUG(D_IOCTL, "Device has connected clients\n");
-                        EXIT;
+                if ( !list_empty(&obd->obd_gen_clients) ) {
+                        printk("OBD device %d has connected clients\n", obd->obd_minor);
                         return -EBUSY;
                 }
 
-                CDEBUG(D_PSDEV, "Detach %d, type %s\n", dev,
-                       obddev->obd_type->typ_name);
-                obddev->obd_flags &= ~OBD_ATTACHED;
-                obddev->obd_type->typ_refcnt--;
-                CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
-                       obddev->obd_type->typ_refcnt);
-                obddev->obd_type = NULL;
+               if (obd->obd_proc_entry)
+                       proc_lustre_release_obd_device(obd);
+
+                obd->obd_flags &= ~OBD_ATTACHED;
+                obd->obd_type->typ_refcnt--;
+                obd->obd_type = NULL;
                 MOD_DEC_USE_COUNT;
                 EXIT;
                 return 0;
         }
 
         case OBD_IOC_SETUP: {
-                struct ioc_setup {
-                        int setup_datalen;
-                       int setup_rdev;
-                        void *setup_data;
-                } *setup;
-
-                setup = tmp_buf;
-
-
                 ENTRY;
-                /* have we attached a type to this device */
-                if (!(obddev->obd_flags & OBD_ATTACHED)) {
-                        CDEBUG(D_IOCTL, "Device not attached\n");
-                        EXIT;
+                /* have we attached a type to this device? */
+                if (!(obd->obd_flags & OBD_ATTACHED)) {
+                        printk("Device %d not attached\n", obd->obd_minor);
                         return -ENODEV;
                 }
 
                 /* has this been done already? */
-                if ( obddev->obd_flags & OBD_SET_UP ) {
-                        CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
-                               dev, obddev->obd_type->typ_name);
-                        EXIT;
+                if ( obd->obd_flags & OBD_SET_UP ) {
+                        printk("Device %d already setup (type %s)\n",
+                               obd->obd_minor, obd->obd_type->typ_name);
                         return -EBUSY;
                 }
 
-               /* get main structure */
-               err = copy_from_user(setup, (void *) arg, sizeof(*setup));
-               if (err) {
-                 EXIT;
-                 return err;
-               }
-
-                /* get the attach data */
-                err = getdata(setup->setup_datalen, &setup->setup_data);
-                if ( err ) {
-                        EXIT;
-                        return err;
-                }
-               obddev->obd_rdev = setup->setup_rdev;
-               obddev->obd_user_name = (char *)setup->setup_data;
-
-                /* do the setup */
-                if ( !OBT(obddev) || !OBP(obddev, setup) ) {
-                        obddev->obd_type->typ_refcnt++;
-                        CDEBUG(D_PSDEV, "Dev %d refcount now %d\n",
-                               dev, obddev->obd_type->typ_refcnt);
-                        if (setup->setup_data)
-                                OBD_FREE(setup->setup_data,
-                                         setup->setup_datalen);
-                        obddev->obd_flags |= OBD_SET_UP;
-                        EXIT;
-                        return 0;
-                }
+                if ( OBT(obd) && OBP(obd, setup) )
+                       err = OBP(obd, setup)(obd, data);
 
-                CDEBUG(D_PSDEV, "Setup %d, type %s device %x, %s, len %d\n", dev, 
-                       obddev->obd_type->typ_name, setup->setup_rdev,
-                      obddev->obd_user_name, setup->setup_datalen);
+               if (!err) { 
+                       obd->obd_type->typ_refcnt++;
+                       obd->obd_flags |= OBD_SET_UP;
+                       EXIT;
+               }
 
-                err = OBP(obddev, setup)(obddev, 0, NULL);
-                          
-                if ( err )  {
-                        obddev->obd_flags &= ~OBD_SET_UP;
-                        EXIT;
-                } else {
-                        obddev->obd_type->typ_refcnt++;
-                        CDEBUG(D_PSDEV, "Dev %d refcount now %d\n",
-                               dev, obddev->obd_type->typ_refcnt);
-                        obddev->obd_flags |= OBD_SET_UP;
-                        EXIT;
-                }
-               // OBD_FREE(setup->setup_data, setup->setup_datalen);
                 return err;
         }
         case OBD_IOC_CLEANUP: {
                 ENTRY;
                 /* has this minor been registered? */
-                if (!obddev->obd_type) {
-                        CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
+                if (!obd->obd_type) {
+                        printk("OBD cleanup dev %d has no type.\n", 
+                              obd->obd_minor);
                         EXIT;
                         return -ENODEV;
                 }
 
-                if ( !obddev->obd_type->typ_refcnt ) {
-                        CDEBUG(D_IOCTL, "dev %d has refcount (%d)!\n",
-                               dev, obddev->obd_type->typ_refcnt);
-                        EXIT;
-                        return -EBUSY;
-                }
-
-                if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
-                     (!(obddev->obd_flags & OBD_ATTACHED))) {
-                        CDEBUG(D_IOCTL, "device not attached or set up\n");
+                if ( (!(obd->obd_flags & OBD_SET_UP)) ||
+                     (!(obd->obd_flags & OBD_ATTACHED))) {
+                        printk("OBD cleanup device %d not attached/set up\n",
+                              obd->obd_minor);
                         EXIT;
                         return -ENODEV;
                 }
 
-                if ( !OBT(obddev) || !OBP(obddev, cleanup) )
+                if ( !OBT(obd) || !OBP(obd, cleanup) )
                         goto cleanup_out;
 
                 /* cleanup has no argument */
-                err = OBP(obddev, cleanup)(obddev);
+                err = OBP(obd, cleanup)(obd);
                 if ( err ) {
                         EXIT;
                         return err;
                 }
 
         cleanup_out: 
-                obddev->obd_flags &= ~OBD_SET_UP;
-                obddev->obd_type->typ_refcnt--;
-                CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev,
-                       obddev->obd_type->typ_refcnt);
+                obd->obd_flags &= ~OBD_SET_UP;
+                obd->obd_type->typ_refcnt--;
                 EXIT;
                 return 0;
         }
+
         case OBD_IOC_CONNECT:
         {
-                if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
-                     (!(obddev->obd_flags & OBD_ATTACHED))) {
+                if ( (!(obd->obd_flags & OBD_SET_UP)) ||
+                     (!(obd->obd_flags & OBD_ATTACHED))) {
                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
                         return -ENODEV;
                 }
 
-                if ( !OBT(obddev) || !OBP(obddev, connect) )
+                if ( !OBT(obd) || !OBP(obd, connect) )
                         return -EOPNOTSUPP;
+
+               conn.oc_id = data->ioc_conn1;
+               conn.oc_dev = obd; 
                 
-                err = OBP(obddev, connect)(&conn);
+                err = OBP(obd, connect)(&conn);
+               CDEBUG(D_IOCTL, "assigned connection %d\n", conn.oc_id);
+               data->ioc_conn1 = conn.oc_id;
                 if ( err )
                         return err;
 
-                return copy_to_user((int *)arg, &conn.oc_id,
-                                    sizeof(uint32_t));
+                return copy_to_user((int *)arg, data, sizeof(*data));
         }
-        case OBD_IOC_DISCONNECT:
-                /* frees data structures */
-                /* has this minor been registered? */
-                if (!obddev->obd_type)
-                        return -ENODEV;
+        case OBD_IOC_DISCONNECT: { 
 
-                get_user(cli_id, (int *) arg);
-                conn.oc_id = cli_id;
+                if (!obd->obd_type)
+                        return -ENODEV;
 
-                if ( !OBT(obddev) || !OBP(obddev, disconnect))
+                if ( !OBT(obd) || !OBP(obd, disconnect))
                         return -EOPNOTSUPP;
                 
-                OBP(obddev, disconnect)(&conn);
+               conn.oc_id = data->ioc_conn1;
+               conn.oc_dev = obd;
+                OBP(obd, disconnect)(&conn);
                 return 0;
-               
-       case OBD_IOC_DEC_USE_COUNT:
+       }               
+
+       case OBD_IOC_DEC_USE_COUNT: { 
                MOD_DEC_USE_COUNT;
                return 0;
+       }
+
+        case OBD_IOC_CREATE: {
+                /* has this minor been registered? */
+                if ( !(obd->obd_flags & OBD_ATTACHED) ||
+                     !(obd->obd_flags & OBD_SET_UP)) {
+                        CDEBUG(D_IOCTL, "Device not attached or set up\n");
+                        return -ENODEV;
+                }
+                conn.oc_id = data->ioc_conn1;
+               conn.oc_dev = obd;
+
+                if ( !OBT(obd) || !OBP(obd, create) )
+                        return -EOPNOTSUPP;
+
+                err = OBP(obd, create)(&conn, &data->ioc_obdo1);
+                if (err) {
+                        EXIT;
+                        return err;
+                }
 
+                err = copy_to_user((int *)arg, data, sizeof(*data));
+                EXIT;
+                return err;
+        }
+#if 0
         case OBD_IOC_SYNC: {
                 struct oic_range_s *range = tmp_buf;
 
-                if (!obddev->obd_type)
+                if (!obd->obd_type)
                         return -ENODEV;
 
                 err = copy_from_user(range, (const void *)arg,  sizeof(*range));
@@ -495,14 +380,14 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                         return err;
                 }
                         
-                if ( !OBT(obddev) || !OBP(obddev, sync) ) {
+                if ( !OBT(obd) || !OBP(obd, sync) ) {
                         err = -EOPNOTSUPP;
                         EXIT;
                         return err;
                 }
 
                 /* XXX sync needs to be tested/verified */
-                err = OBP(obddev, sync)(&conn, &range->obdo, range->count,
+                err = OBP(obd, sync)(&conn, &range->obdo, range->count,
                                         range->offset);
 
                 if ( err ) {
@@ -512,42 +397,12 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                         
                 return put_user(err, (int *) arg);
         }
-        case OBD_IOC_CREATE: {
-                struct oic_attr_s *attr = tmp_buf;
-
-                err = copy_from_user(attr, (const void *)arg,  sizeof(*attr));
-                if (err) {
-                        EXIT;
-                        return err;
-                }
-
-                /* has this minor been registered? */
-                if ( !(obddev->obd_flags & OBD_ATTACHED) ||
-                     !(obddev->obd_flags & OBD_SET_UP)) {
-                        CDEBUG(D_IOCTL, "Device not attached or set up\n");
-                        return -ENODEV;
-                }
-                conn.oc_id = attr->conn_id;
-
-                if ( !OBT(obddev) || !OBP(obddev, create) )
-                        return -EOPNOTSUPP;
-
-                err = OBP(obddev, create)(&conn, &attr->obdo);
-                if (err) {
-                        EXIT;
-                        return err;
-                }
-
-                err = copy_to_user((int *)arg, attr, sizeof(*attr));
-                EXIT;
-                return err;
-        }
 
         case OBD_IOC_DESTROY: {
                 struct oic_attr_s *attr = tmp_buf;
                 
                 /* has this minor been registered? */
-                if (!obddev->obd_type)
+                if (!obd->obd_type)
                         return -ENODEV;
 
                 err = copy_from_user(attr, (int *)arg, sizeof(*attr));
@@ -556,11 +411,11 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                         return err;
                 }
 
-                if ( !OBT(obddev) || !OBP(obddev, destroy) )
+                if ( !OBT(obd) || !OBP(obd, destroy) )
                         return -EOPNOTSUPP;
 
                 conn.oc_id = attr->conn_id;
-                err = OBP(obddev, destroy)(&conn, &attr->obdo);
+                err = OBP(obd, destroy)(&conn, &attr->obdo);
                 EXIT;
                 return err;
         }
@@ -569,18 +424,18 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                 struct oic_attr_s *attr = tmp_buf;
 
                 /* has this minor been registered? */
-                if (!obddev->obd_type)
+                if (!obd->obd_type)
                         return -ENODEV;
 
                 err = copy_from_user(attr, (int *)arg, sizeof(*attr));
                 if (err)
                         return err;
 
-                if ( !OBT(obddev) || !OBP(obddev, setattr) )
+                if ( !OBT(obd) || !OBP(obd, setattr) )
                         return -EOPNOTSUPP;
                 
                 conn.oc_id = attr->conn_id;
-                err = OBP(obddev, setattr)(&conn, &attr->obdo);
+                err = OBP(obd, setattr)(&conn, &attr->obdo);
                 EXIT;
                 return err;
         }
@@ -594,7 +449,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
 
                 conn.oc_id = attr->conn_id;
                 ODEBUG(&attr->obdo);
-                err = OBP(obddev, getattr)(&conn, &attr->obdo);
+                err = OBP(obd, getattr)(&conn, &attr->obdo);
                 if ( err ) {
                         EXIT;
                         return err;
@@ -617,14 +472,14 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
 
                 conn.oc_id = rw_s->conn_id;
 
-                if ( !OBT(obddev) || !OBP(obddev, read) ) {
+                if ( !OBT(obd) || !OBP(obd, read) ) {
                         err = -EOPNOTSUPP;
                         EXIT;
                         return err;
                 }
 
 
-                err = OBP(obddev, read)(&conn, &rw_s->obdo, rw_s->buf, 
+                err = OBP(obd, read)(&conn, &rw_s->obdo, rw_s->buf, 
                                         &rw_s->count, rw_s->offset);
                 
                 ODEBUG(&rw_s->obdo);
@@ -651,7 +506,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
 
                 conn.oc_id = rw_s->conn_id;
 
-                if ( !OBT(obddev) || !OBP(obddev, write) ) {
+                if ( !OBT(obd) || !OBP(obd, write) ) {
                         err = -EOPNOTSUPP;
                         return err;
                 }
@@ -659,7 +514,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                 CDEBUG(D_INFO, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n",
                        rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
 
-                err = OBP(obddev, write)(&conn, &rw_s->obdo, rw_s->buf, 
+                err = OBP(obd, write)(&conn, &rw_s->obdo, rw_s->buf, 
                                          &rw_s->count, rw_s->offset);
                 ODEBUG(&rw_s->obdo);
                 if ( err ) {
@@ -676,24 +531,24 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                 struct oic_prealloc_s *prealloc = tmp_buf;
 
                 /* has this minor been registered? */
-                if (!obddev->obd_type)
+                if (!obd->obd_type)
                         return -ENODEV;
 
                 err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc));
                 if (err) 
                         return -EFAULT;
 
-                if ( !(obddev->obd_flags & OBD_ATTACHED) ||
-                     !(obddev->obd_flags & OBD_SET_UP)) {
+                if ( !(obd->obd_flags & OBD_ATTACHED) ||
+                     !(obd->obd_flags & OBD_SET_UP)) {
                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
                         return -ENODEV;
                 }
 
-                if ( !OBT(obddev) || !OBP(obddev, preallocate) )
+                if ( !OBT(obd) || !OBP(obd, preallocate) )
                         return -EOPNOTSUPP;
 
                 conn.oc_id = prealloc->conn_id;
-                err = OBP(obddev, preallocate)(&conn, &prealloc->alloc,
+                err = OBP(obd, preallocate)(&conn, &prealloc->alloc,
                                                prealloc->ids);
                 if ( err ) {
                         EXIT;
@@ -710,17 +565,17 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                 struct statfs buf;
 
                 /* has this minor been registered? */
-                if (!obddev->obd_type)
+                if (!obd->obd_type)
                         return -ENODEV;
 
                 tmp = (void *)arg + sizeof(unsigned int);
                 get_user(conn_id, (int *) arg);
 
-                if ( !OBT(obddev) || !OBP(obddev, statfs) )
+                if ( !OBT(obd) || !OBP(obd, statfs) )
                         return -EOPNOTSUPP;
 
                 conn.oc_id = conn_id;
-                err = OBP(obddev, statfs)(&conn, &buf);
+                err = OBP(obd, statfs)(&conn, &buf);
                 if ( err ) {
                         EXIT;
                         return err;
@@ -733,8 +588,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
         case OBD_IOC_COPY: {
                 struct ioc_mv_s *mvdata = tmp_buf;
 
-                if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
-                     (!(obddev->obd_flags & OBD_ATTACHED))) {
+                if ( (!(obd->obd_flags & OBD_SET_UP)) ||
+                     (!(obd->obd_flags & OBD_ATTACHED))) {
                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
                         return -ENODEV;
                 }
@@ -746,17 +601,17 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                         return err;
                 }
 
-                if ( !OBT(obddev) || !OBP(obddev, copy) )
+                if ( !OBT(obd) || !OBP(obd, copy) )
                         return -EOPNOTSUPP;
 
                 /* do the partition */
                 CDEBUG(D_INFO, "Copy %d, type %s dst %Ld src %Ld\n", dev, 
-                       obddev->obd_type->typ_name, mvdata->dst.o_id, 
+                       obd->obd_type->typ_name, mvdata->dst.o_id, 
                        mvdata->src.o_id);
 
                 conn.oc_id = mvdata->src_conn_id;
 
-                err = OBP(obddev, copy)(&conn, &mvdata->dst, 
+                err = OBP(obd, copy)(&conn, &mvdata->dst, 
                                         &conn, &mvdata->src, 
                                         mvdata->src.o_size, 0);
                 return err;
@@ -765,8 +620,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
         case OBD_IOC_MIGR: {
                 struct ioc_mv_s *mvdata = tmp_buf;
 
-                if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
-                     (!(obddev->obd_flags & OBD_ATTACHED))) {
+                if ( (!(obd->obd_flags & OBD_SET_UP)) ||
+                     (!(obd->obd_flags & OBD_ATTACHED))) {
                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
                         return -ENODEV;
                 }
@@ -779,16 +634,16 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
 
                 CDEBUG(D_INFO, "Migrate copying %d bytes\n", sizeof(*mvdata));
 
-                if ( !OBT(obddev) || !OBP(obddev, migrate) )
+                if ( !OBT(obd) || !OBP(obd, migrate) )
                         return -EOPNOTSUPP;
 
                 /* do the partition */
                 CDEBUG(D_INFO, "Migrate %d, type %s conn %d src %Ld dst %Ld\n",
-                       dev, obddev->obd_type->typ_name, mvdata->src_conn_id,
+                       dev, obd->obd_type->typ_name, mvdata->src_conn_id,
                        mvdata->src.o_id, mvdata->dst.o_id);
 
                 conn.oc_id = mvdata->src_conn_id;
-                err = OBP(obddev, migrate)(&conn, &mvdata->dst, &mvdata->src, 
+                err = OBP(obd, migrate)(&conn, &mvdata->dst, &mvdata->src, 
                                            mvdata->src.o_size, 0);
 
                 return err;
@@ -804,14 +659,14 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
 
                 conn.oc_id = rw_s->conn_id;
 
-                if ( !OBT(obddev) || !OBP(obddev, punch) ) {
+                if ( !OBT(obd) || !OBP(obd, punch) ) {
                         err = -EOPNOTSUPP;
                         return err;
                 }
 
                 CDEBUG(D_INFO, "PUNCH: conn %d, count %Ld, offset %Ld\n",
                        rw_s->conn_id, rw_s->count, rw_s->offset);
-                err = OBP(obddev, punch)(&conn, &rw_s->obdo, rw_s->count,
+                err = OBP(obd, punch)(&conn, &rw_s->obdo, rw_s->count,
                                          rw_s->offset);
                 ODEBUG(&rw_s->obdo);
                 if ( err ) {
@@ -885,6 +740,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                 EXIT;
                 return err;
         }
+#endif 
+       default:
+               return -EINVAL;
+
         }
 } /* obd_class_ioctl */
 
@@ -956,6 +815,12 @@ static struct file_operations obd_psdev_fops = {
 
 
 /* modules setup */
+#define OBD_MINOR 241
+static struct miscdevice obd_psdev = {
+        OBD_MINOR,
+        "obd_psdev",
+        &obd_psdev_fops
+};
 
 int init_obd(void)
 {
@@ -966,10 +831,9 @@ int init_obd(void)
         
         INIT_LIST_HEAD(&obd_types);
         
-        if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev", 
-                            &obd_psdev_fops)) {
-                printk(KERN_ERR __FUNCTION__ ": unable to get major %d\n", 
-                       OBD_PSDEV_MAJOR);
+       if ( (err = misc_register(&obd_psdev)) ) { 
+                printk(KERN_ERR __FUNCTION__ ": cannot register %d err %d\n", 
+                       OBD_MINOR, err);
                 return -EIO;
         }
 
@@ -1017,14 +881,14 @@ void cleanup_module(void)
         int i;
         ENTRY;
 
-        unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev");
+        misc_deregister(&obd_psdev);
         for (i = 0; i < MAX_OBD_DEVICES; i++) {
-                struct obd_device *obddev = &obd_dev[i];
-                if ( obddev->obd_type && 
-                     (obddev->obd_flags & OBD_SET_UP) &&
-                     OBT(obddev) && OBP(obddev, detach) ) {
+                struct obd_device *obd = &obd_dev[i];
+                if ( obd->obd_type && 
+                     (obd->obd_flags & OBD_SET_UP) &&
+                     OBT(obd) && OBP(obd, detach) ) {
                         /* XXX should this call generic detach otherwise? */
-                        OBP(obddev, detach)(obddev);
+                        OBP(obd, detach)(obd);
                 } 
         }
 
index 545b0c7..fc8770e 100644 (file)
@@ -12,6 +12,7 @@
 
 
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <asm/uaccess.h>
diff --git a/lustre/obdfilter/Makefile.am b/lustre/obdfilter/Makefile.am
new file mode 100644 (file)
index 0000000..fc10f59
--- /dev/null
@@ -0,0 +1,14 @@
+# Copyright (C) 2001  Cluster File Systems, Inc.
+#
+# This code is issued under the GNU General Public License.
+# See the file COPYING in this distribution
+
+MODULE = obdfilter
+modulefs_DATA = obdfilter.o
+EXTRA_PROGRAMS = obdfilter
+
+EXT2C = filter.c
+obdfilter_SOURCES = filter.c
+
+include $(top_srcdir)/Rules
+
diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c
new file mode 100644 (file)
index 0000000..ca9ee52
--- /dev/null
@@ -0,0 +1,816 @@
+/*
+ *  linux/fs/ext2_obd/ext2_obd.c
+ *
+ * Copyright (C) 1999  Stelias Computing, Inc.
+ * Copyright (C) 1999  Seagate Technology, Inc.
+ * Copyright (C) 2001  Cluster File Systems, Inc.
+ *
+ * This code is issued under the GNU General Public License.
+ * See the file COPYING in this distribution
+ *
+ * This is the object based disk driver based on ext2 
+ * written by Peter Braam <braam@clusterfs.com>, Phil Schwan <phil@off.net>
+ * Andreas Dilger <adilger@turbolinux.com>
+ *
+ */
+
+#define EXPORT_SYMTAB
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/locks.h>
+#include <linux/ext2_fs.h>
+#include <linux/quotaops.h>
+#include <asm/unistd.h>
+#include <linux/obd_support.h>
+#include <linux/obd_class.h>
+#include <linux/obd_ext2.h>
+
+
+
+extern struct obd_device obd_dev[MAX_OBD_DEVICES];
+long filter_memory;
+
+void push_ctxt(struct run_ctxt *save, struct run_ctxt *new)
+{ 
+       save->fs = get_fs();
+       save->pwd = dget(current->fs->pwd);
+       save->pwdmnt = mntget(current->fs->pwdmnt);
+
+       set_fs(new->fs);
+       set_fs_pwd(current->fs, new->pwdmnt, new->pwd);
+}
+
+void pop_ctxt(struct run_ctxt *saved)
+{
+       set_fs(saved->fs);
+       set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
+
+       dput(saved->pwd);
+       mntput(saved->pwdmnt);
+}
+
+static void filter_prep(struct obd_device *obddev)
+{
+       struct run_ctxt saved;
+       long rc;
+       int fd;
+       struct stat64 buf;
+       __u64 lastino = 0;
+
+       push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
+       rc = sys_mkdir("O", 0700);
+       rc = sys_mkdir("P", 0700);
+       rc = sys_mkdir("D", 0700);
+       if ( (fd = sys_open("D/status", O_RDWR | O_CREAT, 0700)) == -1 ) {
+               printk("OBD filter: cannot create status file\n");
+               goto out;
+       }
+       if ( (rc = sys_fstat64(fd, &buf, 0)) ) { 
+               printk("OBD filter: cannot stat status file\n");
+               goto out_close;
+       }
+       if (buf.st_size == 0) { 
+               rc = sys_write(fd, (char *)&lastino, sizeof(lastino));
+               if (rc != sizeof(lastino)) { 
+                       printk("OBD filter: error writing lastino\n");
+                       goto out_close;
+               }
+       } else { 
+               rc = sys_read(fd, (char *)&lastino, sizeof(lastino));
+               if (rc != sizeof(lastino)) { 
+                       printk("OBD filter: error writing lastino\n");
+                       goto out_close;
+               }
+       }
+       obddev->u.filter.fo_lastino = lastino;
+       
+ out_close:
+       rc = sys_close(fd);
+       if (rc) { 
+               printk("OBD filter: cannot close status file\n");
+       }
+ out:
+       pop_ctxt(&saved);
+}
+
+static void filter_post(struct obd_device *obddev)
+{
+       struct run_ctxt saved;
+       long rc;
+       int fd;
+
+       push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
+       if ( (fd = sys_open("D/status", O_RDWR | O_CREAT, 0700)) == -1 ) {
+               printk("OBD filter: cannot create status file\n");
+               goto out;
+       }
+       rc = sys_write(fd, (char *)&obddev->u.filter.fo_lastino, 
+                      sizeof(obddev->u.filter.fo_lastino));
+       if (rc != sizeof(sizeof(obddev->u.filter.fo_lastino)) ) { 
+               printk("OBD filter: error writing lastino\n");
+       }
+
+       rc = sys_close(fd);
+       if (rc) { 
+               printk("OBD filter: cannot close status file\n");
+       }
+ out:
+       pop_ctxt(&saved);
+}
+
+
+/* release per client resources */
+static int filter_disconnect(struct obd_conn *conn)
+{
+       /* XXX cleanup preallocated inodes */
+       return gen_disconnect(conn);
+} /* ext2obd_disconnect */
+
+
+
+
+/* 
+ *   to initialize a particular /dev/obdNNN to simulated OBD type
+ *   *data holds the device of the ext2 disk partition we will use. 
+ */ 
+static int filter_setup(struct obd_device *obddev, struct obd_ioctl_data* data)
+{
+       struct vfsmount *mnt;
+       int err; 
+        ENTRY;
+        
+       
+       mnt = do_kern_mount(data->ioc_inlbuf2, 0, 
+                           data->ioc_inlbuf1, NULL); 
+       err = PTR_ERR(mnt);
+       if (IS_ERR(mnt)) { 
+               EXIT;
+               return err;
+       }
+
+       obddev->u.filter.fo_sb = mnt->mnt_root->d_inode->i_sb;
+       if (!obddev->u.filter.fo_sb) {
+               EXIT;
+               return -ENODEV;
+       }
+
+       obddev->u.filter.fo_vfsmnt = mnt;
+       obddev->u.filter.fo_fstype = strdup(data->ioc_inlbuf2);
+
+       obddev->u.filter.fo_ctxt.pwdmnt = mnt;
+       obddev->u.filter.fo_ctxt.pwd = mnt->mnt_root;
+       obddev->u.filter.fo_ctxt.fs = KERNEL_DS;
+
+       filter_prep(obddev);
+       
+        MOD_INC_USE_COUNT;
+        EXIT; 
+        return 0;
+} 
+
+static int filter_cleanup(struct obd_device * obddev)
+{
+        struct super_block *sb;
+
+        ENTRY;
+
+        if ( !(obddev->obd_flags & OBD_SET_UP) ) {
+                EXIT;
+                return 0;
+        }
+
+        if ( !list_empty(&obddev->obd_gen_clients) ) {
+                printk(KERN_WARNING __FUNCTION__ ": still has clients!\n");
+                EXIT;
+                return -EBUSY;
+        }
+
+        sb = obddev->u.filter.fo_sb;
+        if (!obddev->u.filter.fo_sb){
+                EXIT;
+                return 0;
+        }
+       filter_post(obddev);
+
+       unlock_kernel();
+       mntput(obddev->u.filter.fo_vfsmnt); 
+        obddev->u.filter.fo_sb = 0;
+       kfree(obddev->u.filter.fo_fstype);
+
+       lock_kernel();
+
+
+        MOD_DEC_USE_COUNT;
+        EXIT;
+        return 0;
+}
+
+static struct inode *inode_from_obdo(struct obd_device *obddev, 
+                                    struct obdo *oa)
+{
+       char id[16];
+       struct super_block *sb;
+       struct inode *inode; 
+       struct run_ctxt saved;
+       struct stat64 st;
+
+       sb = obddev->u.filter.fo_sb;
+        if (!sb || !sb->s_dev) {
+                CDEBUG(D_SUPER, "fatal: device not initialized.\n");
+                EXIT;
+                return NULL;
+        }
+
+        if ( !oa->o_id ) {
+                CDEBUG(D_INODE, "fatal: invalid obdo %lu\n", (long)oa->o_id);
+                EXIT;
+                return NULL;
+        }
+
+       sprintf(id, "O/%Ld", oa->o_id);
+
+       push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
+       if (sys_stat64(id, &st, 0)) { 
+               EXIT;
+               return NULL;
+       }
+       pop_ctxt(&saved);
+
+        inode = iget(sb, st.st_ino);
+        if (!inode || inode->i_nlink == 0 || is_bad_inode(inode)) {
+                printk("from obdo - fatal: invalid inode %ld (%s).\n",
+                       (long)oa->o_id, inode ? inode->i_nlink ? "bad inode" :
+                       "no links" : "NULL");
+                if (inode)
+                        iput(inode);
+                EXIT;
+                return NULL;
+        }
+       return inode;
+}
+
+static inline void filter_from_inode(struct obdo *oa, struct inode *inode)
+{
+        ENTRY;
+
+        CDEBUG(D_INFO, "src inode %ld, dst obdo %ld valid 0x%08x\n",
+               inode->i_ino, (long)oa->o_id, oa->o_valid);
+        obdo_from_inode(oa, inode);
+
+        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+               obd_rdev rdev = kdev_t_to_nr(inode->i_rdev);
+                CDEBUG(D_INODE, "copying device %x from inode to obdo\n",
+                      rdev);
+                *((obd_rdev *)oa->o_inline) = rdev;
+                oa->o_obdflags |= OBD_FL_INLINEDATA;
+                oa->o_valid |= OBD_MD_FLINLINE;
+        }
+
+#if 0
+ else if (ext2obd_has_inline(inode)) {
+                CDEBUG(D_INFO, "copying inline from inode to obdo\n");
+                memcpy(oa->o_inline, inode->u.ext2_i.i_data,
+                       MIN(sizeof(inode->u.ext2_i.i_data),OBD_INLINESZ));
+                oa->o_obdflags |= OBD_FL_INLINEDATA;
+                oa->o_valid |= OBD_MD_FLINLINE;
+        }
+
+        if (ext2obd_has_obdmd(inode)) {
+                /* XXX this will change when we don't store the obdmd in data */
+                CDEBUG(D_INFO, "copying obdmd from inode to obdo\n");
+                memcpy(oa->o_obdmd, inode->u.ext2_i.i_data,
+                       MIN(sizeof(inode->u.ext2_i.i_data),OBD_INLINESZ));
+                oa->o_obdflags |= OBD_FL_OBDMDEXISTS;
+                oa->o_valid |= OBD_MD_FLOBDMD;
+        }
+#endif
+        EXIT;
+}
+
+static int filter_getattr(struct obd_conn *conn, struct obdo *oa)
+{
+        struct inode *inode;
+
+        ENTRY;
+        if ( !gen_client(conn) ) {
+                CDEBUG(D_IOCTL, "fatal: invalid client %u\n", conn->oc_id);
+                EXIT;
+                return -EINVAL;
+        }
+
+       if ( !(inode = inode_from_obdo(conn->oc_dev, oa)) ) { 
+               EXIT;
+               return -ENOENT;
+       }
+
+        filter_from_inode(oa, inode);
+        iput(inode);
+        EXIT;
+        return 0;
+} 
+
+static int filter_setattr(struct obd_conn *conn, struct obdo *oa)
+{
+       struct inode *inode;
+       struct iattr iattr;
+       int rc;
+       struct dentry de;
+
+        if (!gen_client(conn)) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                return -EINVAL;
+        }
+
+       inode = inode_from_obdo(conn->oc_dev, oa); 
+       if ( !inode ) { 
+               EXIT;
+               return -ENOENT;
+       }
+
+       iattr_from_obdo(&iattr, oa);
+       de.d_inode = inode;
+       if ( inode->i_op->setattr ) {
+               rc = inode->i_op->setattr(&de, &iattr);
+       } else { 
+               rc = inode_setattr(inode, &iattr);
+       }
+
+       iput(inode);
+       EXIT;
+       return rc;
+}
+
+static int filter_create (struct obd_conn* conn, struct obdo *oa)
+{
+       char name[64];
+       struct run_ctxt saved;
+       struct obd_device *obddev = conn->oc_dev;
+       struct iattr;
+       int rc;
+
+        if (!gen_client(conn)) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                return -EINVAL;
+        }
+
+       conn->oc_dev->u.filter.fo_lastino++;
+       oa->o_id = conn->oc_dev->u.filter.fo_lastino;
+       sprintf(name, "O/%Ld", oa->o_id);
+       push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
+       if (sys_mknod(name, 010644, 0)) { 
+               printk("Error mknod %s\n", name);
+               return -ENOENT;
+       }
+       pop_ctxt(&saved);
+
+       rc = filter_setattr(conn, oa); 
+       if ( rc ) { 
+               EXIT;
+               return -EINVAL;
+       }
+       
+        /* Set flags for fields we have set in ext2_new_inode */
+        oa->o_valid |= OBD_MD_FLID | OBD_MD_FLBLKSZ | OBD_MD_FLBLOCKS |
+                 OBD_MD_FLMTIME | OBD_MD_FLATIME | OBD_MD_FLCTIME |
+                 OBD_MD_FLUID | OBD_MD_FLGID;
+        return 0;
+}
+
+static int filter_destroy(struct obd_conn *conn, struct obdo *oa)
+{
+        struct obd_device * obddev;
+        struct obd_client * cli;
+        struct inode * inode;
+       struct run_ctxt saved;
+       char id[128];
+
+        if (!(cli = gen_client(conn))) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                EXIT;
+                return -EINVAL;
+        }
+
+        obddev = conn->oc_dev;
+       inode = inode_from_obdo(obddev, oa);
+
+       if (!inode) { 
+               EXIT;
+               return -ENOENT;
+       }
+
+        inode->i_nlink = 1;
+       inode->i_mode = 010000;
+       iput(inode);
+
+       sprintf(id, "O/%Ld", oa->o_id);
+       push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
+       if (sys_unlink(id)) { 
+               EXIT;
+               return -EPERM;
+       }
+       pop_ctxt(&saved);
+
+       EXIT;
+        return 0;
+}
+
+static int filter_read(struct obd_conn *conn, struct obdo *oa, char *buf,
+                        obd_size *count, obd_off offset)
+{
+        struct super_block *sb;
+        struct inode * inode;
+        struct file * f;
+        struct file fake_file;
+        struct dentry fake_dentry;
+        unsigned long retval;
+        int err;
+
+
+        if (!gen_client(conn)) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                EXIT;
+                return -EINVAL;
+        }
+
+        sb = conn->oc_dev->u.ext2.ext2_sb;
+       if ( !(inode = inode_from_obdo(conn->oc_dev, oa)) ) { 
+               EXIT;
+               return -ENOENT;
+       }
+
+        if (!S_ISREG(inode->i_mode)) {
+                iput(inode);
+                CDEBUG(D_INODE, "fatal: not regular file %ld (mode=%o).\n",
+                       inode->i_ino, inode->i_mode);
+                EXIT;
+                return -EINVAL;
+        }
+
+        memset(&fake_file, 0, sizeof(fake_file));
+        memset(&fake_dentry, 0, sizeof(fake_dentry));
+
+        f = &fake_file;
+        f->f_dentry = &fake_dentry;
+        f->f_dentry->d_inode = inode;
+       f->f_flags = O_LARGEFILE;
+        f->f_op = &ext2_file_operations;
+       inode->i_mapping->a_ops = &ext2_aops;
+
+        /* count doubles as retval */
+        retval = f->f_op->read(f, buf, *count, &offset);
+        iput(inode);
+        if ( retval >= 0 ) {
+                err = 0;
+                *count = retval;
+        } else {
+                err = retval;
+                *count = 0;
+        }
+
+        return err;
+} /* ext2obd_read */
+
+
+static int filter_write(struct obd_conn *conn, struct obdo *oa, char *buf, 
+                         obd_size *count, obd_off offset)
+{
+        int err;
+        struct super_block *sb;
+        struct inode * inode;
+        struct file fake_file;
+        struct dentry fake_dentry;
+        struct file * f;
+        unsigned long retval;
+
+        ENTRY;
+
+        if (!gen_client(conn)) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                EXIT;
+                return -EINVAL;
+        }
+
+        sb = conn->oc_dev->u.ext2.ext2_sb;
+       if ( !(inode = inode_from_obdo(conn->oc_dev, oa)) ) { 
+               EXIT;
+               return -ENOENT;
+       }
+
+        if (!S_ISREG(inode->i_mode)) {
+                CDEBUG(D_INODE, "fatal: not regular file.\n");
+                iput(inode);
+                EXIT;
+                return -EINVAL;
+        }
+
+        memset(&fake_file, 0, sizeof(fake_file));
+        memset(&fake_dentry, 0, sizeof(fake_dentry));
+
+        f = &fake_file;
+        f->f_dentry = &fake_dentry;
+        f->f_dentry->d_inode = inode;
+        f->f_op = &ext2_file_operations;
+       f->f_flags = O_LARGEFILE;
+       inode->i_mapping->a_ops = &ext2_aops;
+
+        /* count doubles as retval */
+       if (f->f_op->write)
+               retval = f->f_op->write(f, buf, *count, &(offset));
+       else 
+               retval = -EINVAL;
+        CDEBUG(D_INFO, "Result %ld\n", retval);
+
+        oa->o_valid = OBD_MD_FLBLOCKS | OBD_MD_FLCTIME | OBD_MD_FLMTIME;
+        obdo_from_inode(oa, inode);
+        iput(inode);
+
+        if ( retval >= 0 ) {
+                err = 0;
+                *count = retval;
+                EXIT;
+        } else {
+                err = retval;
+                *count = 0;
+                EXIT;
+        }
+
+        return err;
+} /* ext2obd_write */
+
+void ___wait_on_page(struct page *page)
+{
+        struct task_struct *tsk = current;
+        DECLARE_WAITQUEUE(wait, tsk);
+
+        add_wait_queue(&page->wait, &wait);
+        do {
+                run_task_queue(&tq_disk);
+                set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+                if (!PageLocked(page))
+                        break;
+                schedule();
+        } while (PageLocked(page));
+        tsk->state = TASK_RUNNING;
+        remove_wait_queue(&page->wait, &wait);
+}
+
+static inline int actor_from_kernel(char *dst, char *src, size_t len)
+{
+       ENTRY;
+       memcpy(dst, src, len);
+       EXIT;
+       return 0;
+}
+
+int kernel_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
+{
+       char *kaddr;
+       unsigned long count = desc->count;
+       ENTRY;
+       if (desc->buf == NULL) {
+               printk("ALERT: desc->buf == NULL\n");
+               desc->error = -EIO;
+               return -EIO;
+       }
+       
+       if (size > count)
+               size = count;
+
+       kaddr = kmap(page);
+       memcpy(desc->buf, kaddr + offset, size);
+       kunmap(page);
+       
+       desc->count = count - size;
+       desc->written += size;
+       desc->buf += size;
+       EXIT;
+       return size;
+}
+
+static int filter_pgcache_brw(int rw, struct obd_conn *conn, 
+                              obd_count num_oa,
+                              struct obdo **oa, 
+                              obd_count *oa_bufs, 
+                              struct page **pages,
+                              obd_size *count, 
+                              obd_off *offset, 
+                              obd_flag *flags)
+{
+        struct super_block      *sb;
+        int                      onum;          /* index to oas */
+        int                      pnum;          /* index to pages (bufs) */
+        unsigned long            retval;
+        int                      err;
+       struct file fake_file;
+       struct dentry fake_dentry; 
+       struct file *f;
+
+        ENTRY;
+
+        if (!gen_client(conn)) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                EXIT;
+                return -EINVAL;
+        }
+
+        sb = conn->oc_dev->u.ext2.ext2_sb;
+
+        pnum = 0; /* pnum indexes buf 0..num_pages */
+        for (onum = 0; onum < num_oa; onum++) {
+                struct inode    *inode;
+                int              pg;
+
+                if ( rw == READ ) 
+                        *flags &= ~OBD_BRW_CREATE;
+
+                if (! (inode = inode_from_obdo(conn->oc_dev, oa[onum])) ) {
+                        EXIT;
+                        return -ENOENT;
+                }
+
+               CDEBUG(D_INODE, "ino %ld, i_count %d\n", 
+                      inode->i_ino, atomic_read(&inode->i_count)); 
+               memset(&fake_file, 0, sizeof(fake_file));
+               memset(&fake_dentry, 0, sizeof(fake_dentry));
+               
+               f = &fake_file;
+               f->f_dentry = &fake_dentry;
+               f->f_dentry->d_inode = inode;
+               f->f_op = &ext2_file_operations;
+               f->f_flags = O_LARGEFILE;
+               inode->i_mapping->a_ops = &ext2_aops;
+
+               /* count doubles as retval */
+                for (pg = 0; pg < oa_bufs[onum]; pg++) {
+                       CDEBUG(D_INODE, "OP %d obdo no/pno: (%d,%d) (%ld,%ld) off count (%Ld,%Ld)\n", 
+                              rw, onum, pnum, inode->i_ino,
+                              (unsigned long)offset[pnum] >> PAGE_CACHE_SHIFT,
+                              offset[pnum], count[pnum]);
+                       if (rw == WRITE) { 
+                               loff_t off; 
+                               char *buffer;
+                               off = offset[pnum]; 
+                               buffer = kmap(pages[pnum]); 
+                               retval = do_generic_file_write
+                                       (f, buffer, count[pnum], &off, 
+                                        actor_from_kernel);
+                               kunmap(pages[pnum]);
+                               CDEBUG(D_INODE, "retval %ld\n", retval); 
+                       } else { 
+                               loff_t off; 
+                               read_descriptor_t desc;
+                               char *buffer = kmap(pages[pnum]);
+
+                               desc.written = 0;
+                               desc.count = count[pnum];
+                               desc.buf = buffer;
+                               desc.error = 0;
+                               off = offset[pnum]; 
+
+                               off = offset[pnum]; 
+                               if (off >= inode->i_size) {
+                                       memset(buffer, 0, PAGE_SIZE);
+                               } else {
+                                       do_generic_file_read
+                                               (f, &off, &desc, 
+                                                kernel_read_actor);
+                               } 
+                               kunmap(pages[pnum]);
+                               retval = desc.written;
+                               if ( !retval ) {
+                                       iput(inode);
+                                       retval = desc.error; 
+                                       EXIT;
+                                       goto ERROR;
+                               }
+                               CDEBUG(D_INODE, "retval %ld\n", retval); 
+                       }
+                       pnum++;
+               }
+               /* sizes and blocks are set by generic_file_write */
+               /* ctimes/mtimes will follow with a setattr call */ 
+
+                //oa[onum]->o_blocks = inode->i_blocks;
+                //oa[onum]->o_valid = OBD_MD_FLBLOCKS;
+               /* perform the setattr on the inode */
+               //ext2obd_to_inode(inode, oa[onum]);
+               //inode->i_size = oa[onum]->o_size;
+               //mark_inode_dirty(inode); 
+                iput(inode);
+       }
+       
+       EXIT;
+ ERROR:
+       err = (retval >= 0) ? 0 : retval;
+       return err;
+}
+
+static int filter_statfs (struct obd_conn *conn, struct statfs * statfs)
+{
+       struct super_block *sb;
+        int err;
+
+        ENTRY;
+
+        if (!gen_client(conn)) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                EXIT;
+                return -EINVAL;
+        }
+
+        sb = conn->oc_dev->u.filter.fo_sb;
+
+        err = sb->s_op->statfs(sb, statfs);
+        EXIT;
+        return err;
+} /* ext2obd_statfs */
+
+
+static int  filter_get_info(struct obd_conn *conn, obd_count keylen,
+                             void *key, obd_count *vallen, void **val)
+{
+        struct obd_device *obddev;
+        struct obd_client * cli;
+       ENTRY;
+
+        if (!(cli = gen_client(conn))) {
+                CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
+                return -EINVAL;
+        }
+
+        obddev = conn->oc_dev;
+        
+        if ( keylen == strlen("blocksize") &&
+             memcmp(key, "blocksize", keylen) == 0 ) {
+                *vallen = sizeof(int);
+                *val = (void *)obddev->u.filter.fo_sb->s_blocksize;
+               EXIT;
+                return 0;
+        }
+
+        if ( keylen == strlen("blocksize_bits") &&
+             memcmp(key, "blocksize_bits", keylen) == 0 ){
+                *vallen = sizeof(int);
+                *val = (void *)(int)obddev->u.filter.fo_sb->s_blocksize_bits;
+               EXIT;
+                return 0;
+        }
+
+        if ( keylen == strlen("root_ino") &&
+             memcmp(key, "root_ino", keylen) == 0 ){
+                *vallen = sizeof(int);
+                *val = (void *)(int)
+                       obddev->u.filter.fo_sb->s_root->d_inode->i_ino;
+               EXIT;
+                return 0;
+        }
+        
+        CDEBUG(D_IOCTL, "invalid key\n");
+        return -EINVAL;
+}
+
+
+struct obd_ops filter_obd_ops = {
+        o_iocontrol:   NULL,
+        o_get_info:    filter_get_info,
+        o_setup:       filter_setup,
+        o_cleanup:     filter_cleanup,
+        o_connect:     gen_connect,
+        o_disconnect:  filter_disconnect,
+        o_statfs:      filter_statfs,
+        o_getattr:     filter_getattr,
+        o_create:      filter_create,
+       o_setattr:     filter_setattr,
+        o_destroy:     filter_destroy,
+        o_read:        filter_read,
+        o_write:       filter_write,
+       o_brw:         filter_pgcache_brw,
+#if 0
+        o_preallocate: ext2obd_preallocate_inodes,
+        o_setattr:     ext2obd_setattr,
+        o_punch:       ext2obd_punch,
+        o_migrate:     ext2obd_migrate,
+        o_copy:        gen_copy_data,
+        o_iterate:     ext2obd_iterate
+#endif
+};
+
+
+#ifdef MODULE
+
+void init_module(void)
+{
+        printk(KERN_INFO "Filtering OBD driver  v0.001, braam@clusterfs.com\n");
+        obd_register_type(&filter_obd_ops, OBD_FILTER_DEVICENAME);
+}
+
+void cleanup_module(void)
+{
+        obd_unregister_type(OBD_FILTER_DEVICENAME);
+        CDEBUG(D_MALLOC, "FILTER mem used %ld\n", filter_memory);
+}
+
+#endif
index 2664496..b154c51 100644 (file)
@@ -6,7 +6,6 @@
 MODULE = obdfs
 modulefs_DATA = obdfs.o
 EXTRA_PROGRAMS = obdfs
-# obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
 obdfs_SOURCES =  rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
 
 include $(top_srcdir)/Rules
index 81f1805..84ba0b5 100644 (file)
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -93,7 +93,6 @@ modulefsdir = @modulefsdir@
 MODULE = obdfs
 modulefs_DATA = obdfs.o
 EXTRA_PROGRAMS = obdfs
-# obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
 obdfs_SOURCES = rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_CLEAN_FILES = 
index f569f30..031b8f3 100644 (file)
@@ -11,8 +11,6 @@
  *
  */
 
-#define EXPORT_SYMTAB
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
index 040cbb0..4e5fad9 100644 (file)
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am
new file mode 100644 (file)
index 0000000..90007fc
--- /dev/null
@@ -0,0 +1,10 @@
+bin_SCRIPTS = obdcontrol
+EXTRA_DIST = $(bin_SCRIPTS)
+
+CFLAGS:=-g -I. -I../include -Wall
+KFLAGS:=
+CPPFLAGS :=
+LDADD := -lreadline -ltermcap -lefence
+bin_PROGRAMS = obdctl
+obdctl_SOURCES = parser.c obdctl.c
+
diff --git a/lustre/utils/Pack.pm b/lustre/utils/Pack.pm
new file mode 100644 (file)
index 0000000..ad9f688
--- /dev/null
@@ -0,0 +1,172 @@
+package Pack;
+use Carp;
+use Exporter;
+@EXPORT = qw(LOGL, UNLOGL, LOGU32, UNLOGU32, LLOGU32, LUNLOGU32, LOGU64, UNLOGU64, LLOGU64, LUNLOGU64);
+
+sub round_len {
+    return ($_[0] + 3) & ~0x3;
+}
+
+sub roundq_len {
+    return ($_[0] + 3) & ~0x7;
+}
+
+# pack a string $_[2]
+#  at $offset ($_[1]) 
+#  in $buf ($_[0]) 
+#  padd to 32bit alignment move $_[1] forward
+
+sub LOGL{
+    my $len = length($_[2]);
+    my $rlen = round_len($len);
+    my $padd = $rlen + $off - length($_[0]);
+
+    if ($padd > 0) {
+        $_[0] .= pack "x$padd";
+    }
+    substr $_[0], $_[1], $len, $_[2];
+    $_[1] += $rlen;
+}
+
+# pack $_[2], a u32, into $_[0] at offset $_[1]
+sub LOGU32 {
+    if ($_[1] != round_len($_[1])) {
+        confess "packing I on non-word boundary";
+    } 
+    my $padd = 4 + $off - length($_[0]);
+
+    if ($padd > 0) {
+        $_[0] .= pack "L", $_[2];
+    } else {
+        substr $_[0], $_[1], $len, pack "L", $_[2];
+    }
+    $_[1] += 4;
+}
+
+# pack $_[2], a u32, into $_[0] at offset $_[1]
+# use little endian
+sub LLOGU32 {
+    if ($_[1] != round_len($_[1])) {
+        confess "packing V on non-word boundary";
+    } 
+    my $padd = 4 + $off - length($_[0]);
+
+    if ($padd > 0) {
+        $_[0] .= pack "V", $_[2];
+    } else {
+        substr $_[0], $_[1], $len, pack "V", $_[2];
+    }
+    $_[1] += 4;
+}
+
+sub LLOGU64 {
+    if ($_[1] != roundq_len($_[1])) {
+        confess "packing Q on non-word boundary";
+    } 
+    my $padd = 8 + $off - length($_[0]);
+
+    if ($padd > 0) {
+        $_[0] .= pack "VV", $_[3], $_[2];
+    } else {
+        substr $_[0], $_[1], $len, pack "VV", $_[3], $_[2];
+    }
+    $_[1] += 8;
+}
+
+sub LLOGU64 {
+    if ($_[1] != roundq_len($_[1])) {
+        confess "packing Q on non-word boundary";
+    } 
+    my $padd = 8 + $off - length($_[0]);
+
+    if ($padd > 0) {
+        $_[0] .= pack "LL", $_[3], $_[2];
+    } else {
+        substr $_[0], $_[1], $len, pack "LL", $_[3], $_[2];
+    }
+    $_[1] += 8;
+}
+
+sub UNLOGL { 
+    if (length($_[0]) < $_[1] + round_len($_[2]) ) {
+        confess "unpacking buf beyond string length";
+    }
+    
+    $_[3] = unpack "x$_[1]a$_[2]", $_[0];
+    $_[1] += round_len($_[2]);
+    return $_[3];
+}
+
+sub UNLOGU32 { 
+    if (length($_[0]) < $_[1] + 4) {
+        confess "unpacking u32 beyond string length";
+    }
+    
+    $_[2] = unpack "x$_[1]L", $_[0];
+    $_[1] += 4;
+    return $_[2];
+}
+
+sub LUNLOGU32 { 
+    if (length($_[0]) < $_[1] + 4) {
+        confess "lunpacking u32 beyond string length";
+    }
+    $_[2] = unpack "x$_[1]V", $_[0];
+    $_[1] += 4;
+    return $_[2];
+}
+
+sub UNLOGU64 {
+    if (length($_[0]) < $_[1] + 8) {
+        confess "unpacking u64 beyond string length";
+    }
+    
+    ($_[3], $_[2]) = unpack "x$_[1]LL", $_[0];
+    $_[1] += 8;
+    return ($_[2], $_[3]);
+}
+
+sub LUNLOGU64 {
+    if (length($_[0]) < $_[1] + 8) {
+        confess "lunpacking u64 beyond string length";
+    }
+    
+    ($_[3], $_[2]) = unpack "x$_[1]VV", $_[0];
+    $_[1] += 8;
+    return ($_[2], $_[3]);
+}
+
+sub test {
+    $buf = "";
+    $off = 0;
+    
+    LOGL($buf, $off, "moose");
+    print "off $off\n";
+    printf "len %d\n", length($buf);
+    LLOGU64($buf, $off, 0x01020304, 0x05060708);
+    print "off $off\n";
+    printf "len %d\n", length($buf);
+    LLOGU32($buf, $off, 0x01020304);
+    print "off $off\n";
+    printf "len %d\n", length($buf);
+    $off = 0;
+    UNLOGL($buf, $off, length("moose"), $str);
+    print "off $off $str\n";
+    LUNLOGU64($buf, $off, $high, $low);
+    printf "off $off high %x low %x\n", $high, $low;
+    LUNLOGU32($buf, $off, $low);
+    printf "off $off long %x\n", $low;
+    
+    $off = 0;
+    $str = UNLOGL($buf, $off, length("moose"));
+    print "assigned off $off $str\n";
+    ($high, $low) = LUNLOGU64($buf, $off);
+    printf "assigned off $off high %x low %x\n", $high, $low;
+    $low = LUNLOGU32($buf, $off, $low);
+    printf "assigned off $off long %x\n", $low;
+    
+    sysopen F, "/tmp/out", 2;
+    syswrite F, $buf, length($buf);
+}
+
+# test();
similarity index 88%
rename from lustre/obdclass/obdcontrol
rename to lustre/utils/obdcontrol
index f12a212..7a0d108 100755 (executable)
@@ -94,6 +94,7 @@ use Storable;
 use Carp;
 use Term::ReadLine;
 use IO::Handle;
+use Pack;
 
 
 # NOTE long long are layed out in ia32 memory as follows:
@@ -290,7 +291,7 @@ if ( $file ) {
     while ( <STDIN> ) {
         print $_;
         my $rc = execute_line($_);
-       if ($rc != 0) { last; }
+        if ($rc != 0) { last; }
     }
     exit 0;
 } else {
@@ -311,17 +312,17 @@ if ( $file ) {
 sub completeme {
     my ($text, $line, $start, $end) = @_;
     if (substr($line, 0, $start) =~ /^\s*$/) {
-       if ($] < 5.6) { # PErl version is less than 5.6.0
-           return (exists $commands{$text}) ? $text : 0;
+        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'});
-       }
+        }
+        else {
+            $attribs->{completion_word} = \@jcm_cmd_list;
+            return $term->completion_matches($text,
+                       $attribs->{'list_completion_function'});
+        }
     }
 }
 
@@ -374,32 +375,32 @@ sub Device {
     my $device = shift;
 
     if ( ! $device && ! $::device ) { # first time ever
-       $device = '/dev/obd0';
+        $device = '/dev/obd0';
     }
 
     if (($device) && ($::device ne $device)) {
-       local *NEW_OBD;
-       my $newfd;
+        local *NEW_OBD;
+        my $newfd;
 
-       if ($::client_id) {
-           print "Disconnecting active session ($::client_id)...";
-           Disconnect($::client_id);
-       }
+        if ($::client_id) {
+            print "Disconnecting active session ($::client_id)...";
+            Disconnect($::client_id);
+        }
 
-       if ($opendevfds{$device}) {
-           $::dev_obd = $opendevfds{$device};
+        if ($opendevfds{$device}) {
+            $::dev_obd = $opendevfds{$device};
+        }
+        else {
+            # Open the device, as we need an FD for the ioctl
+            if (!sysopen(NEW_OBD, $device, 0)) {
+                print "Cannot open $device. Did you insert the obdclass module ?\n";
+                return -1;
+            }
+            print "Opened device $device\n";
+            $opendevfds{$device} = *NEW_OBD;
+            $::dev_obd = *NEW_OBD;
         }
-       else {
-           # Open the device, as we need an FD for the ioctl
-           if (!sysopen(NEW_OBD, $device, 0)) {
-               print "Cannot open $device. Did you insert the obdclass module ?\n";
-               return -1;
-           }
-           print "Opened device $device\n";
-           $opendevfds{$device} = *NEW_OBD;
-           $::dev_obd = *NEW_OBD;
-       }
-       $::device = $device;    
+        $::device = $device;    
     }
     print "Current device is $::device\n";
     return 0;
@@ -410,35 +411,35 @@ sub Close {
     my $fd2close;
 
     if ( ! $device && ! $::device ) { # first time ever
-       print "Nothing to close\n";
-       return -1;
+        print "Nothing to close\n";
+        return -1;
     }
 
     if ( ! $device ) {
-       $device = $::device;
+        $device = $::device;
     }
 
     if ($::device eq $device) {
-       if ($::client_id) {
-           print "Disconnecting active session ($::client_id)...";
-           Disconnect($::client_id);
-       }
+        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";
+        close ($fd2close);
+        $opendevfds{$device} = undef;
+        print "Closed device $device\n";
     }
     else {
-       print "Device $device was not open\n";
-       return -1;
+        print "Device $device was not open\n";
+        return -1;
     }
     
     if ($::device eq $device) {
-       $::dev_obd = undef;
-       $::device = undef;
+        $::dev_obd = undef;
+        $::device = undef;
     }
     print "No current device. You just closed the current device ($device).\n";
     return 0; 
@@ -448,23 +449,23 @@ sub Script {
     my $cmdfilename = shift;
     my $rc = 0;
     if ( ! $cmdfilename )  {
-       print "please specify a command file name\n";
-       return -1;
+        print "please specify a command file name\n";
+        return -1;
     }
     if (! open(CMDF, $cmdfilename)) {
-       print "Cannot open $cmdfilename: $!\n";
-       return -1;
+        print "Cannot open $cmdfilename: $!\n";
+        return -1;
     }
     while (<CMDF>) {
-       if (/^#/) {
-           next;
-       }
+        if (/^#/) {
+            next;
+        }
         print "execute> $_";
-       $rc = execute_line($_);
-       if ($rc != 0) {
-           print "Something went wrong .......command exit status: $rc\n";
-           last;
-       }
+        $rc = execute_line($_);
+        if ($rc != 0) {
+            print "Something went wrong .......command exit status: $rc\n";
+            last;
+        }
     }
     close(CMDF);
     return $rc;
@@ -474,8 +475,8 @@ sub Shell {
     my $user_shell=$ENV{'SHELL'};
     print "% $user_shell -c '@_'\n";
     if ( ! @_ ) {
-       print "please specify a shell command\n";
-       return;
+        print "please specify a shell command\n";
+        return;
     }
     system("$user_shell -c '@_'");
     return ($? >> 8);
@@ -499,20 +500,20 @@ sub Procsys {
     my $value = shift;
 
     foreach $i (0 .. $#procsysobd_objects) {
-       my $sysobd = $procsysobd_objects[$i];
+        my $sysobd = $procsysobd_objects[$i];
 
-       if (defined $set_sysobd) {
-           if ($sysobd ne $set_sysobd) { next; }
+        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");
-       }
+            if (defined $value) { # set this one
+                system("echo \"$value\" > /proc/sys/obd/$sysobd");
+            }
+            system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd");
+            last;
+        }
+        else {
+            system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd");
+        }
     }
     return ($? >> 8);
 }
@@ -581,20 +582,20 @@ usage:
     my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data);
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -604,21 +605,21 @@ sub Detach {
     my $data = "";
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -640,21 +641,21 @@ sub TestExt2Iterator {
     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;
+        print "No current device.\n";
+        return -1;
     }
 
     my $rc = ioctl($::dev_obd, &OBD_EXT2_RUNIT, $packed);
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -680,21 +681,21 @@ sub SnapDelete {
     #     are deleted, the snapshot itself is also removed from the table.
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -758,15 +759,15 @@ sub SnapRestore {
     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;
+        print "No current device.\n";
+        return -1;
     }
 
     my $rc = ioctl($::dev_obd, &OBD_SNAP_RESTORE, $packed);
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Snaprestore finished (success)\n";
         delete $table->{$restoretime} if defined $restoretime;
@@ -776,10 +777,10 @@ sub SnapRestore {
         # set it in the kernel
         SnapSetTable($tableno, $snaptable);
         # PrintSnapShotTable($table);
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -810,21 +811,21 @@ sub SnapPrint {
     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;
+        print "No current device.\n";
+        return -1;
     }
 
     my $rc = ioctl($::dev_obd, &OBD_SNAP_PRINTTABLE, $packed);
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -840,7 +841,7 @@ sub SnapSetTable {
 
     if ( ! -f $file ) {
         print "No such file $file\n";
-       return -1;
+        return -1;
     }
 
     $table = ReadSnapShotTable($file);
@@ -865,21 +866,21 @@ sub SnapSetTable {
     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;
+        print "No current device.\n";
+        return -1;
     }
 
     my $rc = ioctl($::dev_obd, &OBD_SNAP_SETTABLE, $packed);
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -998,21 +999,21 @@ 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;
+        print "No current device.\n";
+        return -1;
     }
 
     my $rc = ioctl($::dev_obd, &OBD_IOC_COPY, $packed);
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1028,21 +1029,21 @@ 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;
+        print "No current device.\n";
+        return -1;
     }
 
     my $rc = ioctl($::dev_obd, &OBD_IOC_MIGR, $packed);
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1055,20 +1056,20 @@ sub Format {
 
     my $packed = pack("ip", $datalen, $data);
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1081,20 +1082,20 @@ sub Partition {
 
     my $packed = pack("ip", $datalen, $data);
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1120,41 +1121,41 @@ sub Setup {
 
     my $packed = pack("iip", $datalen, $::st->rdev(), $data);
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
 sub Cleanup {
     my $err = "0";
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
         $::client_id = 0;
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1164,23 +1165,23 @@ sub Connect {
 
     my $packed = "";
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         $::client_id = $id;
         print "Client ID     : $id\n";
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1200,21 +1201,21 @@ sub Disconnect {
 
     my $packed = pack("L", $id);
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         $::client_id = undef;
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1259,10 +1260,10 @@ sub Create {
         $obdo->{valid} = &OBD_MD_FLMODE;
 
         my $packed = pack("I", $::client_id) . obdo_pack($obdo);
-       if (! defined $::dev_obd) {
-           print "No current device.\n";
-           return -1;
-       }
+        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;
@@ -1274,33 +1275,33 @@ sub Create {
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
 sub Sync {
     my $err = "0";
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1320,20 +1321,20 @@ sub Destroy {
     print "Destroying object $id...\n";
     my $packed = pack("IL", $::client_id, $id);
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1356,21 +1357,21 @@ sub Getattr {
     $obdo->{valid} = &OBD_MD_FLALL;
     my $packed = pack("L", $::client_id) . obdo_pack($obdo);
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         $obdo = obdo_unpack($packed,  4); 
         obdo_print($obdo);
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1424,20 +1425,20 @@ sub Setattr {
     printf "valid is %x, mode is %o\n", $obdo->{valid}, $obdo->{mode};
     my $packed = pack("L", $::client_id) . obdo_pack($obdo);
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1476,8 +1477,8 @@ sub Read {
                  pack("p LL LL", $buf, $count, $offset);
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        print "No current device.\n";
+        return -1;
     }
     my $rc = ioctl($::dev_obd, &OBD_IOC_READ, $packed);
 
@@ -1485,20 +1486,20 @@ sub Read {
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        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;
+                return 0;
         } else {
                 print "Finished (error $retval)\n";
-               return $retval;
+                return $retval;
         }
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1537,8 +1538,8 @@ sub Read2 {
                  pack("p LL LL", $buf, $count, $offset);
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        print "No current device.\n";
+        return -1;
     }
     my $rc = ioctl($::dev_obd, &OBD_IOC_READ2, $packed);
 
@@ -1546,20 +1547,20 @@ sub Read2 {
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        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 {
+                return 0;
+         } else {
                 print "Finished (error $retval)\n";
-               return $retval;
+                return $retval;
         }
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1595,8 +1596,8 @@ sub Write {
                  pack("p LL LL", $text, $count, $offset);
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        print "No current device.\n";
+        return -1;
     }
     my $rc = ioctl($::dev_obd, &OBD_IOC_WRITE, $packed);
 
@@ -1604,19 +1605,19 @@ sub Write {
 
     if (!defined $rc) {
         print STDERR "ioctl failed: $!\n";
-       return -1;
+        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;
+                return 0;
         } else {
                 print "Finished (error $retval)\n";
-               return $retval;
+                return $retval;
         }
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1646,8 +1647,8 @@ sub Punch {
                  pack("p LL LL", $buf, $start, $count);
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        print "No current device.\n";
+        return -1;
     }
     my $rc = ioctl($::dev_obd, &OBD_IOC_PUNCH, $packed);
 
@@ -1659,14 +1660,14 @@ sub Punch {
         if ($retval >= 0) {
                 print "\nPunched $retval of an attempted $count bytes.\n";
                 print "Finished (success)\n";
-               return 0;
+                return 0;
         } else {
                 print "Finished (error $retval)\n";
-               return $retval;
+                return $retval;
         }
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1687,14 +1688,14 @@ sub Preallocate {
     my $packed = pack("LLx128", $::client_id, $num);
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         my $alloc = unpack("x4L", $packed);
         my @ids = unpack("x8L32", $packed);
@@ -1705,29 +1706,29 @@ sub Preallocate {
             print $i . " ";
         }
         print "\nFinished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
 sub Decusecount {
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        return -1;
     } elsif ($rc eq "0 but true") {
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
@@ -1754,14 +1755,14 @@ sub Statfs {
                       0, 0, 0, 0, 0, 0);
 
     if (! defined $::dev_obd) {
-       print "No current device.\n";
-       return -1;
+        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;
+        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) =
@@ -1770,10 +1771,10 @@ sub Statfs {
               "$bfree free ($bavail available).\n");
         print "$files files, " . ($files - $ffree) . " used, $ffree free.\n";
         print "Finished (success)\n";
-       return 0;
+        return 0;
     } else {
         print "ioctl returned error code $rc.\n";
-       return -1;
+        return -1;
     }
 }
 
diff --git a/lustre/utils/obdctl.c b/lustre/utils/obdctl.c
new file mode 100644 (file)
index 0000000..eebb238
--- /dev/null
@@ -0,0 +1,348 @@
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#define printk printf
+#include <linux/obd_class.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <string.h>
+
+#define __KERNEL__
+#include <linux/list.h>
+#undef __KERNEL__
+
+#include "parser.h"
+#include <stdio.h>
+
+int fd = -1;
+int connid = -1;
+char rawbuf[8192];
+char *buf = rawbuf;
+int max = 8192;
+
+#define IOCINIT(data) do { memset(&data, 0, sizeof(data)); data.ioc_version = OBD_IOCTL_VERSION; data.ioc_conn1 = connid; data.ioc_len = sizeof(data); if (fd < 0) { printf("No device open, use device\n"); return 1;}} while (0)
+
+/*
+    pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L", 
+    $obdo->{id}, 0, 
+    $obdo->{gr}, 0, 
+    $obdo->{atime}, 0, 
+    $obdo->{mtime}, 0 ,
+    $obdo->{ctime}, 0, 
+    $obdo->{size}, 0, 
+    $obdo->{blocks}, 0, 
+    $obdo->{blksize},
+    $obdo->{mode},
+    $obdo->{uid},
+    $obdo->{gid},
+    $obdo->{flags},
+    $obdo->{obdflags},
+    $obdo->{nlink},     
+    $obdo->{generation},        
+    $obdo->{valid},     
+    $obdo->{inline},
+    $obdo->{obdmd},
+    0, 0, # struct list_head 
+    0;  #  struct obd_ops 
+}
+
+*/
+
+char * obdo_print(struct obdo *obd)
+{
+       char buf[1024];
+
+       sprintf(buf, "id: %Ld\ngrp: %Ld\natime: %Ld\nmtime: %Ld\nctime: %Ld\nsize: %Ld\nblocks: %Ld\nblksize: %d\nmode: %o\nuid: %d\ngid: %d\nflags: %x\nobdflags: %x\nnlink: %d,\nvalid %x\n",
+               obd->o_id,
+               obd->o_gr,
+               obd->o_atime,
+               obd->o_mtime,
+               obd->o_ctime,
+               obd->o_size,
+               obd->o_blocks,
+               obd->o_blksize,
+               obd->o_mode,
+               obd->o_uid,
+               obd->o_gid,
+               obd->o_flags,
+               obd->o_obdflags,
+               obd->o_nlink,
+               obd->o_valid);
+       return strdup(buf);
+}
+
+
+static int jt_device(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int rc;
+
+       memset(&data, 0, sizeof(data));
+       if ( argc != 2 ) {
+               fprintf(stderr, "Usage: %s devno\n", argv[0]);
+               return 1;
+       }
+
+       data.ioc_dev = atoi(argv[1]);
+
+       if (obd_ioctl_pack(&data, &buf, max)) { 
+               printf("invalid ioctl\n"); 
+               return 1;
+       }
+
+       if (fd == -1) 
+               fd = open("/dev/obd", O_RDWR);
+       if (fd == -1) {
+               printf("Opening /dev/obd: %s\n", strerror(errno));
+               return 1;
+       }
+
+       rc = ioctl(fd, OBD_IOC_DEVICE , buf);
+       if (rc < 0) {
+               printf("Device: %x %s\n", OBD_IOC_DEVICE, strerror(errno));
+               return 1;
+       }
+
+       return 0;
+}
+
+static int jt_connect(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int rc;
+
+       IOCINIT(data);
+
+       if ( argc != 1 ) {
+               fprintf(stderr, "Usage: %s\n", argv[0]);
+               return 1;
+       }
+
+       rc = ioctl(fd, OBD_IOC_CONNECT , &data);
+       if (rc < 0) {
+               printf("Device: %x %s\n", OBD_IOC_CONNECT, strerror(errno));
+               return 1;
+       }
+       connid = data.ioc_conn1;
+
+       return 0;
+}
+
+
+
+static int jt_disconnect(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int rc;
+
+       IOCINIT(data);
+
+       if ( argc != 1 ) {
+               fprintf(stderr, "Usage: %s\n", argv[0]);
+               return 1;
+       }
+
+       rc = ioctl(fd, OBD_IOC_DISCONNECT , &data);
+       if (rc < 0) {
+               printf("Device: %x %s\n", OBD_IOC_DISCONNECT, strerror(errno));
+               return 1;
+       }
+       connid = -1;
+
+       return 0;
+}
+
+
+static int jt_detach(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int rc;
+
+       IOCINIT(data);
+
+       if ( argc != 1 ) {
+               fprintf(stderr, "Usage: %s\n", argv[0]);
+               return 1;
+       }
+
+       if (obd_ioctl_pack(&data, &buf, max)) { 
+               printf("invalid ioctl\n"); 
+               return 1;
+       }
+
+       rc = ioctl(fd, OBD_IOC_DETACH , buf);
+       if (rc < 0) {
+               printf("Detach: %s\n", strerror(errno));
+               return 1;
+       }
+       return 0;
+}
+
+static int jt_cleanup(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int rc;
+
+       IOCINIT(data);
+
+       if ( argc != 1 ) {
+               fprintf(stderr, "Usage: %s\n", argv[0]);
+               return 1;
+       }
+
+       rc = ioctl(fd, OBD_IOC_CLEANUP , &data);
+       if (rc < 0) {
+               printf("Detach: %s\n", strerror(errno));
+               return 1;
+       }
+       return 0;
+}
+
+static int jt_attach(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int rc;
+
+       IOCINIT(data);
+
+       if ( argc != 2 && argc != 3  ) {
+               fprintf(stderr, "Usage: %s type [data]\n", argv[0]);
+               return 1;
+       }
+
+       data.ioc_inllen1 =  strlen(argv[1]) + 1;
+       data.ioc_inlbuf1 = argv[1];
+       if ( argc == 3 ) { 
+               data.ioc_inllen2 = strlen(argv[2]) + 1;
+               data.ioc_inlbuf2 = argv[2];
+       }
+
+       printf("attach len %d addr %p type %s data %s\n", data.ioc_len, buf, 
+              MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2));
+
+       if (obd_ioctl_pack(&data, &buf, max)) { 
+               printf("invalid ioctl\n"); 
+               return 1;
+       }
+       printf("attach len %d addr %p raw %p type %s data %s and %s\n", data.ioc_len, buf, rawbuf,
+              MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2), &buf[516]);
+
+       rc = ioctl(fd, OBD_IOC_ATTACH , buf);
+       if (rc < 0) {
+               printf("Attach: %x %s\n", OBD_IOC_ATTACH, strerror(errno));
+               return 1;
+       }
+       return 0;
+}
+
+static int jt_setup(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int rc;
+
+       IOCINIT(data);
+
+       if ( argc != 2 && argc != 3  ) {
+               fprintf(stderr, "Usage: %s device [fstype]\n", argv[0]);
+               return 1;
+       }
+
+       data.ioc_inllen1 =  strlen(argv[1]) + 1;
+       data.ioc_inlbuf1 = argv[1];
+       if ( argc == 3 ) { 
+               data.ioc_inllen2 = strlen(argv[2]) + 1;
+               data.ioc_inlbuf2 = argv[2];
+       }
+
+       printf("attach len %d addr %p type %s data %s\n", data.ioc_len, buf, 
+              MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2));
+
+       if (obd_ioctl_pack(&data, &buf, max)) { 
+               printf("invalid ioctl\n"); 
+               return 1;
+       }
+       printf("attach len %d addr %p raw %p type %s data %s and %s\n", data.ioc_len, buf, rawbuf,
+              MKSTR(data.ioc_inlbuf1), MKSTR(data.ioc_inlbuf2), &buf[516]);
+
+       rc = ioctl(fd, OBD_IOC_SETUP , buf);
+       if (rc < 0) {
+               printf("Attach: %x %s\n", OBD_IOC_SETUP, strerror(errno));
+               return 1;
+       }
+       return 0;
+}
+
+
+static int jt_create(int argc, char **argv)
+{
+       struct obd_ioctl_data data;
+       int num = 1;
+       int silent = 0;
+       int i;
+       int rc;
+
+       IOCINIT(data);
+       if (argc > 1) { 
+               num = strtoul(argv[1], NULL, 0);
+       } else
+
+       if (argc > 2) { 
+               data.ioc_obdo1.o_mode = strtoul(argv[2], NULL, 0);
+       } else { 
+               data.ioc_obdo1.o_mode = 0100644;
+       }
+       data.ioc_obdo1.o_mode = OBD_MD_FLMODE;
+
+       if (argc > 3) { 
+               silent = strtoul(argv[3], NULL, 0);
+       }
+               
+       printf("Creating %d obdos\n", num);
+
+       for (i = 0 ; i<num ; i++) { 
+               rc = ioctl(fd, OBD_IOC_CREATE , &data);
+               if (rc < 0) {
+                       printf("Create: %x %s\n", OBD_IOC_CREATE, 
+                              strerror(errno));
+                       return 1;
+               }
+               printf("created obdo %Ld\n", data.ioc_obdo1.o_id);
+       }
+       return 0;
+}
+
+command_t list[] = {
+       {"device", jt_device, 0, "set current device (args device no)"},
+    {"attach", jt_attach, 0, "name the typed of device (args: type data"},
+    {"setup", jt_setup, 0, "setup device (args: blkdev, data"},
+    {"detach", jt_detach, 0, "detach the current device (arg: )"},
+    {"cleanup", jt_cleanup, 0, "cleanup the current device (arg: )"},
+    {"create", jt_create, 0, "create [count [mode [silent]]]"},
+    {"connect", jt_connect, 0, "connect - get a connection to device"},
+    {"disconnect", jt_disconnect, 0, "disconnect - break connection to device"},
+    {"help", Parser_help, 0, "help"},
+    {"exit", Parser_quit, 0, "quit"},
+    {"quit", Parser_quit, 0, "quit"},
+    { 0, 0, 0, NULL }
+};
+
+int main(int argc, char **argv)
+{
+
+       if (argc > 1) { 
+               return Parser_execarg(argc - 1, &argv[1], list);
+       }
+
+       Parser_init("obdctl > ", list);
+       Parser_commands();
+
+       return 0;
+}
+
diff --git a/lustre/utils/parser.c b/lustre/utils/parser.c
new file mode 100644 (file)
index 0000000..63eb906
--- /dev/null
@@ -0,0 +1,584 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stddef.h>
+#include <sys/param.h>
+#include <assert.h>
+
+#define        READLINE_LIBRARY
+#include <readline/readline.h>
+
+extern void using_history(void);
+extern void stifle_history(int);
+extern void add_history(char *);
+
+#include "parser.h"
+#define CMD_COMPLETE 0
+#define CMD_INCOMPLETE 1
+#define CMD_NONE 2
+#define CMD_AMBIG 3
+
+static command_t * top_level;     /* Top level of commands, initialized by
+                                   * InitParser                            */
+static command_t * match_tbl;     /* Command completion against this table */
+static char * parser_prompt = NULL;/* Parser prompt, set by InitParser      */
+static int done;                  /* Set to 1 if user types exit or quit   */
+
+
+/* static functions */
+static char *skipwhitespace(char *s);
+static char *skiptowhitespace(char *s);
+static command_t *find_cmd(char *name, command_t cmds[], char **next);
+static int process(char *s, char **next, command_t *lookup, command_t **result, char **prev);
+static char *command_generator(const char *text, int state);
+static char **command_completion(char *text, int start, int end);
+static void print_commands(char *str, command_t *table);
+
+static char * skipwhitespace(char * s) 
+{
+    char * t;
+    int    len;
+
+    len = (int)strlen(s);
+    for (t = s; t <= s + len && isspace(*t); t++);
+    return(t);
+}
+
+
+static char * skiptowhitespace(char * s) 
+{
+    char * t;
+
+    for (t = s; *t && !isspace(*t); t++);
+    return(t);
+}
+
+static int line2args(char *line, char **argv, int maxargs)
+{
+    char *arg;
+    int i = 0; 
+    
+    arg = strtok(line, " \t");
+    if ( arg ) {
+       argv[i] = arg;
+       i++;
+    } else 
+       return 0;
+
+    while( (arg = strtok(NULL, " \t")) && (i <= maxargs)) {
+       argv[i] = arg;
+       i++;
+    }
+    return i;
+}
+
+/* find a command -- return it if unique otherwise print alternatives */
+    
+static command_t *Parser_findargcmd(char *name, command_t cmds[])
+{
+       command_t *cmd;
+       int i;
+
+       for (i = 0; cmds[i].pc_name; i++) {
+               cmd = &cmds[i];
+
+               if (strlen(name) != strlen(cmd->pc_name))
+                       continue;
+
+               if (strlen(name) == strlen(cmd->pc_name)) {
+                       if (strcmp(name, cmd->pc_name) == 0) 
+                               return cmd;
+                       else
+                               continue;
+               }
+
+       }
+       return NULL;
+}
+
+int Parser_execarg(int argc, char **argv, command_t cmds[])
+{
+       command_t *cmd;
+       int i;
+
+        cmd = Parser_findargcmd(argv[0], cmds);
+       if ( cmd ) {
+               return (cmd->pc_func)(argc, argv);
+       } else {
+               printf("Try interactive use without arguments or use one of: ");
+               for (i=0 ; cmds[i].pc_name ; i++) {
+                       cmd = &cmds[i];
+                       printf("\"%s\" ", cmd->pc_name);
+               }
+               printf("as argument.\n");
+       }
+       return -1;
+}
+
+/* returns the command_t * (NULL if not found) corresponding to a
+   _partial_ match with the first token in name.  It sets *next to
+   point to the following token. Does not modify *name. */
+static command_t * find_cmd(char * name, command_t cmds[], char ** next) 
+{
+    int    i, len;
+    
+    if (!cmds || !name ) 
+        return NULL;
+    
+    /* This sets name to point to the first non-white space character,
+    and next to the first whitespace after name, len to the length: do
+    this with strtok*/
+    name = skipwhitespace(name);
+    *next = skiptowhitespace(name);
+    len = *next - name;
+    if (len == 0) 
+       return NULL;
+
+    for (i = 0; cmds[i].pc_name; i++) {
+       if (strncasecmp(name, cmds[i].pc_name, len) == 0) {
+           *next = skipwhitespace(*next);
+           return(&cmds[i]);
+       }
+    }
+    return NULL;
+}
+
+/* Recursively process a command line string s and find the command
+   corresponding to it. This can be ambiguous, full, incomplete,
+   non-existent. */
+static int process(char *s, char ** next, command_t *lookup,
+                  command_t **result, char **prev)
+{
+    *result = find_cmd(s, lookup, next);
+    *prev = s; 
+
+    /* non existent */
+    if ( ! *result ) 
+       return CMD_NONE;
+
+    /* found entry: is it ambigous, i.e. not exact command name and
+       more than one command in the list matches.  Note that find_cmd
+       points to the first ambiguous entry */
+    if ( strncasecmp(s, (*result)->pc_name, strlen((*result)->pc_name)) &&
+        find_cmd(s, (*result) + 1, next)) 
+       return CMD_AMBIG;
+
+    /* found a unique command: component or full? */
+    if ( (*result)->pc_func ) {
+       return CMD_COMPLETE;
+    } else {
+       if ( *next == '\0' ) {
+           return CMD_INCOMPLETE;
+       } else {
+           return process(*next, next, (*result)->pc_sub_cmd, result, prev);
+       }
+    }
+}
+
+static char * command_generator(const char * text, int state) 
+{
+    static int index,
+              len;
+    char       *name;
+
+    /* Do we have a match table? */
+    if (!match_tbl) 
+       return NULL;
+    
+    /* If this is the first time called on this word, state is 0 */
+    if (!state) {
+       index = 0;
+       len = (int)strlen(text);
+    }
+
+    /* Return the next name in the command list that paritally matches test */
+    while ( (name = (match_tbl + index)->pc_name) ) {
+       index++;
+
+       if (strncasecmp(name, text, len) == 0) {
+           return(strdup(name));
+       }
+    }
+
+    /* No more matches */
+    return NULL;
+}
+
+/* probably called by readline */
+static char **command_completion(char * text, int start, int end) 
+{
+    command_t  * table;
+    char       * pos;
+
+    match_tbl = top_level;
+    for (table = find_cmd(rl_line_buffer, match_tbl, &pos);
+        table;
+        table = find_cmd(pos, match_tbl, &pos)) {
+
+       if (*(pos - 1) == ' ') match_tbl = table->pc_sub_cmd;
+    }
+
+    return(rl_completion_matches(text, command_generator));
+}
+
+/* take a string and execute the function or print help */
+void execute_line(char * line) 
+{
+    command_t  *cmd, *ambig;
+    char *prev;
+    char *next, *tmp;
+    char *argv[MAXARGS];
+    int         i;
+
+    switch( process(line, &next, top_level, &cmd, &prev) ) {
+    case CMD_AMBIG:
+       fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line);
+       while( (ambig = find_cmd(prev, cmd, &tmp)) ) {
+           fprintf(stderr, "%s ", ambig->pc_name);
+           cmd = ambig + 1;
+       }
+       fprintf(stderr, "\n");
+       break;
+    case CMD_NONE:
+       fprintf(stderr, "No such command, type help\n");
+       break;
+    case CMD_INCOMPLETE:
+       fprintf(stderr,
+               "'%s' incomplete command.  Use '%s x' where x is one of:\n",
+               line, line);
+       fprintf(stderr, "\t");
+       for (i = 0; cmd->pc_sub_cmd[i].pc_name; i++) {
+           fprintf(stderr, "%s ", cmd->pc_sub_cmd[i].pc_name);
+       }
+       fprintf(stderr, "\n");
+       break;
+    case CMD_COMPLETE:
+       i = line2args(line, argv, MAXARGS);
+       (cmd->pc_func)(i, argv);
+       break;
+    }
+    
+    return;
+}
+
+/* this is the command execution machine */
+void Parser_commands(void) 
+{
+    char *line,
+        *s;
+
+    using_history();
+    stifle_history(HISTORY);
+
+    rl_attempted_completion_function = 
+           (rl_completion_func_t *)command_completion;
+    rl_completion_entry_function = (rl_compentry_func_t *)command_generator;
+    
+    while(!done) {
+       line = readline(parser_prompt);
+
+       if (!line) break;
+
+       s = skipwhitespace(line);
+
+       if (*s) {
+           add_history(s);
+           execute_line(s);
+       }
+
+       free(line);
+    }
+}
+
+
+/* sets the parser prompt */
+void Parser_init(char * prompt, command_t * cmds) 
+{
+    done = 0;
+    top_level = cmds;
+    if (parser_prompt) free(parser_prompt);
+    parser_prompt = strdup(prompt);
+}
+
+/* frees the parser prompt */
+void Parser_exit(int argc, char *argv[]) 
+{
+    done = 1;
+    free(parser_prompt);
+    parser_prompt = NULL;
+}
+
+/* convert a string to an integer */
+int Parser_int(char *s, int *val)
+{
+    int ret;
+
+    if (*s != '0')
+       ret = sscanf(s, "%d", val);
+    else if (*(s+1) != 'x')
+       ret = sscanf(s, "%o", val);
+    else {
+       s++;
+       ret = sscanf(++s, "%x", val);
+    }
+
+    return(ret);
+}
+
+
+    
+void Parser_qhelp(int argc, char *argv[]) {
+
+    printf("Available commands are:\n");
+       
+    print_commands(NULL, top_level);
+    printf("For more help type: help command-name\n");
+}
+
+int Parser_help(int argc, char **argv) 
+{
+    char line[1024];
+    char *next, *prev, *tmp;
+    command_t *result, *ambig;
+    int i;
+
+    if ( argc == 1 ) {
+       Parser_qhelp(argc, argv);
+       return 0;
+    }
+
+    line[0]='\0';
+    for ( i = 1 ;  i < argc ; i++ ) {
+       strcat(line, argv[i]);
+    }
+
+    switch ( process(line, &next, top_level, &result, &prev) ) {
+    case CMD_COMPLETE:
+       fprintf(stderr, "%s: %s\n",line, result->pc_help);
+       break;
+    case CMD_NONE:
+       fprintf(stderr, "%s: Unknown command.\n", line);
+       break;
+    case CMD_INCOMPLETE:
+       fprintf(stderr,
+               "'%s' incomplete command.  Use '%s x' where x is one of:\n",
+               line, line);
+       fprintf(stderr, "\t");
+       for (i = 0; result->pc_sub_cmd[i].pc_name; i++) {
+           fprintf(stderr, "%s ", result->pc_sub_cmd[i].pc_name);
+       }
+       fprintf(stderr, "\n");
+       break;
+    case CMD_AMBIG:
+       fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line);
+       while( (ambig = find_cmd(prev, result, &tmp)) ) {
+           fprintf(stderr, "%s ", ambig->pc_name);
+           result = ambig + 1;
+       }
+       fprintf(stderr, "\n");
+       break;
+    }
+    return 0;
+}  
+
+/*************************************************************************
+ * COMMANDS                                                             *
+ *************************************************************************/ 
+
+
+static void print_commands(char * str, command_t * table) {
+    command_t * cmds;
+    char       buf[80];
+
+    for (cmds = table; cmds->pc_name; cmds++) {
+       if (cmds->pc_func) {
+           if (str) printf("\t%s %s\n", str, cmds->pc_name);
+           else printf("\t%s\n", cmds->pc_name);
+       }
+       if (cmds->pc_sub_cmd) {
+           if (str) {
+               sprintf(buf, "%s %s", str, cmds->pc_name);
+               print_commands(buf, cmds->pc_sub_cmd);
+           } else {
+               print_commands(cmds->pc_name, cmds->pc_sub_cmd);
+           }
+       }
+    }
+}
+
+char *Parser_getstr(const char *prompt, const char *deft, char *res, 
+                   size_t len)
+{
+    char *line = NULL;
+    int size = strlen(prompt) + strlen(deft) + 8;
+    char *theprompt;
+    theprompt = malloc(size);
+    assert(theprompt);
+
+    sprintf(theprompt, "%s [%s]: ", prompt, deft);
+
+    line  = readline(theprompt);
+    free(theprompt);
+
+    if ( line == NULL || *line == '\0' ) {
+       strncpy(res, deft, len);
+    } else {
+       strncpy(res, line, len);
+    }
+
+    if ( line ) {
+       free(line);
+       return res;
+    } else {
+       return NULL;
+    }
+}
+
+/* get integer from prompt, loop forever to get it */
+int Parser_getint(const char *prompt, long min, long max, long deft, int base)
+{
+    int rc;
+    long result;
+    char *line;
+    int size = strlen(prompt) + 40;
+    char *theprompt = malloc(size);
+    assert(theprompt);
+    sprintf(theprompt,"%s [%ld, (0x%lx)]: ", prompt, deft, deft);
+
+    fflush(stdout);
+
+    do {
+       line = NULL;
+       line = readline(theprompt);
+       if ( !line ) {
+           fprintf(stdout, "Please enter an integer.\n");
+           fflush(stdout);
+           continue;
+       }
+       if ( *line == '\0' ) {
+           free(line);
+           result =  deft;
+           break;
+       }
+       rc = Parser_arg2int(line, &result, base);
+       free(line);
+       if ( rc != 0 ) {
+           fprintf(stdout, "Invalid string.\n");
+           fflush(stdout);
+       } else if ( result > max || result < min ) {
+           fprintf(stdout, "Error: response must lie between %ld and %ld.\n",
+                   min, max);
+           fflush(stdout);
+       } else {
+           break;
+       }
+    } while ( 1 ) ;
+
+    if (theprompt)
+       free(theprompt);
+    return result;
+
+}
+
+/* get boolean (starting with YyNn; loop forever */
+int Parser_getbool(const char *prompt, int deft)
+{
+    int result = 0;
+    char *line;
+    int size = strlen(prompt) + 8;
+    char *theprompt = malloc(size);
+    assert(theprompt);
+
+    fflush(stdout);
+    
+    if ( deft != 0 && deft != 1 ) {
+       fprintf(stderr, "Error: Parser_getbool given bad default (%d).\n",
+               deft);
+       assert ( 0 );
+    }
+    sprintf(theprompt, "%s [%s]: ", prompt, (deft==0)? "N" : "Y");
+
+    do {
+       line = NULL;
+       line = readline(theprompt);
+       if ( line == NULL ) {
+           result = deft;
+           break;
+       }
+       if ( *line == '\0' ) {
+           result = deft;
+           break;
+       }
+       if ( *line == 'y' || *line == 'Y' ) {
+           result = 1;
+           break;
+       }
+       if ( *line == 'n' || *line == 'N' ) {
+           result = 0;
+           break;
+       }
+       if ( line ) 
+           free(line);
+       fprintf(stdout, "Invalid string. Must start with yY or nN\n");
+       fflush(stdout);
+    } while ( 1 );
+
+    if ( line ) 
+       free(line);
+    if ( theprompt ) 
+       free(theprompt);
+    return result;
+}
+
+/* parse int out of a string or prompt for it */
+long Parser_intarg(const char *inp, const char *prompt, int deft,
+                 int min, int max, int base)
+{
+    long result;
+    int rc; 
+    
+    rc = Parser_arg2int(inp, &result, base);
+
+    if ( rc == 0 ) {
+       return result;
+    } else {
+       return Parser_getint(prompt, deft, min, max, base);
+    }
+}
+
+/* parse int out of a string or prompt for it */
+char *Parser_strarg(char *inp, const char *prompt, const char *deft,
+                   char *answer, int len)
+{
+    
+    if ( inp == NULL || *inp == '\0' ) {
+       return Parser_getstr(prompt, deft, answer, len);
+    } else 
+       return inp;
+}
+
+/* change a string into a number: return 0 on success. No invalid characters
+   allowed. The processing of base and validity follows strtol(3)*/
+int Parser_arg2int(const char *inp, long *result, int base)
+{
+    char *endptr;
+
+    if ( (base !=0) && (base < 2 || base > 36) )
+       return 1;
+
+    *result = strtol(inp, &endptr, base);
+
+    if ( *inp != '\0' && *endptr == '\0' )
+       return 0;
+    else 
+       return 1;
+}
+
+int Parser_quit(int argc, char **argv)
+{
+       argc = argc;
+       argv = argv;
+       exit(0);
+       return 0;
+}
diff --git a/lustre/utils/parser.h b/lustre/utils/parser.h
new file mode 100644 (file)
index 0000000..a35ab75
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _PARSER_H_
+#define _PARSER_H_
+
+#define HISTORY        100             /* Don't let history grow unbounded    */
+#define MAXARGS 100
+
+typedef struct parser_cmd {
+       char    *pc_name;
+       int     (* pc_func)(int, char **);
+       struct parser_cmd * pc_sub_cmd;
+       char *pc_help;
+} command_t;
+
+typedef struct argcmd {
+       char    *ac_name;
+       int      (*ac_func)(int, char **);
+       char     *ac_help;
+} argcmd_t;
+
+int  Parser_quit(int argc, char **argv);
+void Parser_init(char *, command_t *); /* Set prompt and load command list */
+void Parser_commands(void);                    /* Start the command parser */
+void Parser_qhelp(int, char **);       /* Quick help routine */
+int Parser_help(int, char **);         /* Detailed help routine */
+void Parser_exit(int, char **);                /* Shuts down command parser */
+int Parser_execarg(int argc, char **argv, command_t cmds[]);
+void execute_line(char * line);
+
+/* Converts a string to an integer */
+int Parser_int(char *, int *);
+
+/* Prompts for a string, with default values and a maximum length */
+char *Parser_getstr(const char *prompt, const char *deft, char *res, 
+                   size_t len);
+
+/* Prompts for an integer, with minimum, maximum and default values and base */
+int Parser_getint(const char *prompt, long min, long max, long deft,
+                 int base);
+
+/* Prompts for a yes/no, with default */
+int Parser_getbool(const char *prompt, int deft);
+
+/* Extracts an integer from a string, or prompts if it cannot get one */
+long Parser_intarg(const char *inp, const char *prompt, int deft,
+                  int min, int max, int base);
+
+/* Extracts a word from the input, or propmts if it cannot get one */
+char *Parser_strarg(char *inp, const char *prompt, const char *deft,
+                   char *answer, int len);
+
+/* Extracts an integer from a string  with a base */
+int Parser_arg2int(const char *inp, long *result, int base);
+
+
+#endif _PARSER_H_