-# 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.
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)
* 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;
typedef uint32_t obd_flag;
typedef uint32_t obd_count;
+
+
#define OBD_FL_INLINEDATA (0x00000001UL)
#define OBD_FL_OBDMDEXISTS (0x00000002UL)
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)
__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;
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];
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;
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 ===========
*/
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);
#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)
obdo->o_obdflags & OBD_FL_OBDMDEXISTS);
};
+#ifdef __KERNEL__
/* support routines */
extern kmem_cache_t *obdo_cachep;
}
-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). */
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)
}
-
+#ifdef __KERNEL__
int obd_register_type(struct obd_ops *ops, char *nm);
int obd_unregister_type(char *nm);
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)
#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 )
--- /dev/null
+#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
#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);\
#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); \
#ifndef _OBDFS_H
-#define OBDFS_H
+#define _OBDFS_H
#include <linux/obd_class.h>
#include <linux/obdo.h>
#include <linux/list.h>
-bin_SCRIPTS = obdcontrol
-EXTRA_DIST = $(bin_SCRIPTS)
-
MODULE = obdclass
modulefs_DATA = obdclass.o
EXTRA_PROGRAMS = obdclass
-# 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.
moduledir = @moduledir@
modulefsdir = @modulefsdir@
-bin_SCRIPTS = obdcontrol
-EXTRA_DIST = $(bin_SCRIPTS)
-
MODULE = obdclass
modulefs_DATA = obdclass.o
EXTRA_PROGRAMS = obdclass
obdclass_LDADD = $(LDADD)
obdclass_DEPENDENCIES =
obdclass_LDFLAGS =
-SCRIPTS = $(bin_SCRIPTS)
-
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@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)
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
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:
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 \
*
* 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>
*/
#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>
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;
}
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));
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 ) {
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));
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;
}
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;
}
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;
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);
conn.oc_id = rw_s->conn_id;
- if ( !OBT(obddev) || !OBP(obddev, write) ) {
+ if ( !OBT(obd) || !OBP(obd, write) ) {
err = -EOPNOTSUPP;
return err;
}
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 ) {
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;
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;
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;
}
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;
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;
}
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;
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 ) {
EXIT;
return err;
}
+#endif
+ default:
+ return -EINVAL;
+
}
} /* obd_class_ioctl */
/* modules setup */
+#define OBD_MINOR 241
+static struct miscdevice obd_psdev = {
+ OBD_MINOR,
+ "obd_psdev",
+ &obd_psdev_fops
+};
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;
}
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);
}
}
#include <linux/mm.h>
+#include <linux/pagemap.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
--- /dev/null
+# 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
+
--- /dev/null
+/*
+ * 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
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
-# 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.
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 =
*
*/
-#define EXPORT_SYMTAB
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
-# 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.
--- /dev/null
+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
+
--- /dev/null
+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();
use Carp;
use Term::ReadLine;
use IO::Handle;
+use Pack;
# NOTE long long are layed out in ia32 memory as follows:
while ( <STDIN> ) {
print $_;
my $rc = execute_line($_);
- if ($rc != 0) { last; }
+ if ($rc != 0) { last; }
}
exit 0;
} else {
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'});
+ }
}
}
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;
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;
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;
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);
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);
}
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;
}
}
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;
}
}
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;
}
}
# 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;
}
}
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;
# 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;
}
}
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;
}
}
if ( ! -f $file ) {
print "No such file $file\n";
- return -1;
+ return -1;
}
$table = ReadSnapShotTable($file);
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;
}
}
# 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;
}
}
# 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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
$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;
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;
}
}
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;
}
}
$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;
}
}
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;
}
}
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);
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;
}
}
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);
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;
}
}
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);
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;
}
}
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);
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;
}
}
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);
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;
}
}
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) =
"$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;
}
}
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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;
+}
--- /dev/null
+#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_