From 58c14f99437bf9858f817e0a17b5007831987aa8 Mon Sep 17 00:00:00 2001 From: braam Date: Tue, 11 Dec 2001 21:08:42 +0000 Subject: [PATCH] Numerous changes: - new control utility - no Perl - filter obd halfway coded ; requires new patches to kernel - big cleanup in the class driver with better packed ioctls - macros to pack other things, like network packets --- lustre/demos/Makefile.in | 8 +- lustre/include/linux/obd_class.h | 437 ++++++++++++++---- lustre/include/linux/obd_filter.h | 32 ++ lustre/include/linux/obd_support.h | 5 +- lustre/include/linux/obdfs.h | 2 +- lustre/obdclass/Makefile.am | 3 - lustre/obdclass/Makefile.in | 43 +- lustre/obdclass/class_obd.c | 528 ++++++++-------------- lustre/obdclass/genops.c | 1 + lustre/obdfilter/Makefile.am | 14 + lustre/obdfilter/filter.c | 816 ++++++++++++++++++++++++++++++++++ lustre/obdfs/Makefile.am | 1 - lustre/obdfs/Makefile.in | 5 +- lustre/obdfs/super.c | 2 - lustre/scripts/Makefile.in | 4 +- lustre/utils/Makefile.am | 10 + lustre/utils/Pack.pm | 172 +++++++ lustre/{obdclass => utils}/obdcontrol | 423 +++++++++--------- lustre/utils/obdctl.c | 348 +++++++++++++++ lustre/utils/parser.c | 584 ++++++++++++++++++++++++ lustre/utils/parser.h | 55 +++ 21 files changed, 2808 insertions(+), 685 deletions(-) create mode 100644 lustre/include/linux/obd_filter.h create mode 100644 lustre/obdfilter/Makefile.am create mode 100644 lustre/obdfilter/filter.c create mode 100644 lustre/utils/Makefile.am create mode 100644 lustre/utils/Pack.pm rename lustre/{obdclass => utils}/obdcontrol (88%) create mode 100644 lustre/utils/obdctl.c create mode 100644 lustre/utils/parser.c create mode 100644 lustre/utils/parser.h diff --git a/lustre/demos/Makefile.in b/lustre/demos/Makefile.in index ca03afe..4a6aded 100644 --- a/lustre/demos/Makefile.in +++ b/lustre/demos/Makefile.in @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -77,7 +77,9 @@ docdir = @docdir@ moduledir = @moduledir@ modulefsdir = @modulefsdir@ -demo_SCRIPTS = baseclean.sh basesetup.sh obdfsclean.sh obdfssetup.sh obdtest.sh snap3clean.sh snap3set.sh snapclean.sh snapdel.sh snaprest.sh snaprestclean.sh snapsetup.sh snaptest.sh +demo_SCRIPTS = baseclean.sh basesetup.sh obdfsclean.sh obdfssetup.sh \ + obdtest.sh snap3clean.sh snap3set.sh snapclean.sh snapdel.sh \ + snaprest.sh snaprestclean.sh snapsetup.sh snaptest.sh demo_DATA = config.sh EXTRA_DIST = $(demo_SCRIPTS) $(demo_DATA) diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 1cd173e..0314929 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -7,21 +7,101 @@ * See the file COPYING in this distribution */ +#ifndef __KERNEL__ +#include +#define __KERNEL__ +#include +#undef __KERNEL__ +#else +#include +#include +#include #include #include #include #include +#include #include #include /* #include */ #include #include +#endif /* * ======== OBD type Declarations =========== */ +#define MIN(a,b) (((a)<(b)) ? (a): (b)) +#define MAX(a,b) (((a)>(b)) ? (a): (b)) +#define MKSTR(ptr) ((ptr))? (ptr) : "" + +static inline int size_round(int val) +{ + return (val + 3) & (~0x3); +} + +static inline size_t round_strlen(char *str) +{ + return size_round(strlen(str) + 1); +} + +#ifdef __KERNEL__ +static inline char *strdup(char *str) +{ + char *tmp = kmalloc(strlen(str) + 1, GFP_KERNEL); + if (tmp) + memcpy(tmp, str, strlen(str) + 1); + + return NULL; +} +#endif +/* + * copy sizeof(type) bytes from pointer to var and move ptr forward. + * return EFAULT if pointer goes beyond end + */ +#define UNLOGV(var,type,ptr,end) do {var = *(type *)ptr; ptr += sizeof(type); if (ptr > end ) return -EFAULT;} while (0) + + +/* the following two macros convert to little endian */ +/* type must be 32 or 64 */ +#define LUNLOGV(var,type,ptr,end) \ +do { \ + var = le_to_cpu##type(*(type *)ptr); \ + ptr += sizeof(type); \ + if (ptr > end ) \ + return -EFAULT; \ +} while (0) + +/* now log values */ +#define LOGV(var,type,ptr) \ +do { \ + *((type *)ptr) = var; \ + ptr += sizeof(type); \ +} while (0) + +/* and in network order */ +#define LLOGV(var,type,ptr) \ +do { \ + *((type *)ptr) = cpu_to_le##type(var); \ + ptr += sizeof(type); \ +} while (0) + +/* + * set var to point at (type *)ptr, move ptr forward with sizeof(type) + * return from function with EFAULT if ptr goes beyond end + */ +#define UNLOGP(var,type,ptr,end) do {var = (type *)ptr; ptr += sizeof(type); if (ptr > end ) return -EFAULT; } while (0) + +/* + * set var to point at (char *)ptr, move ptr forward by size_round(len); + * return from function with EFAULT if ptr goes beyond end + */ +#define UNLOGL(var,type,len,ptr,end) do {var = (type *)ptr; ptr += size_round(len * sizeof(type)); if (ptr > end ) return -EFAULT; } while (0) + + +#define LOGL(var,len,ptr) do {memcpy((char *)ptr, (const char *)var, len); ptr += size_round(len);} while (0) typedef uint64_t obd_id; typedef uint64_t obd_gr; @@ -37,6 +117,8 @@ typedef uint32_t obd_rdev; typedef uint32_t obd_flag; typedef uint32_t obd_count; + + #define OBD_FL_INLINEDATA (0x00000001UL) #define OBD_FL_OBDMDEXISTS (0x00000002UL) @@ -66,6 +148,33 @@ struct obdo { struct obd_ops *o_op; }; + +struct obd_ioctl_data { + uint32_t ioc_len; + uint32_t ioc_version; + uint32_t ioc_conn1; + uint32_t ioc_conn2; + struct obdo ioc_obdo1; + struct obdo ioc_obdo2; + obd_size ioc_count; + obd_off ioc_offset; + uint32_t ioc_dev; + + /* buffers the kernel will treat as user pointers */ + uint32_t ioc_plen1; + char *ioc_pbuf1; + uint32_t ioc_plen2; + char *ioc_pbuf2; + + /* two inline buffers */ + uint32_t ioc_inllen1; + char *ioc_inlbuf1; + uint32_t ioc_inllen2; + char *ioc_inlbuf2; + + char ioc_bulk[0]; +}; + #define OBD_MD_FLALL (~0UL) #define OBD_MD_FLID (0x00000001UL) #define OBD_MD_FLATIME (0x00000002UL) @@ -113,6 +222,8 @@ typedef struct { __u8 _uuid[16]; /* uuid obd device names */ } obd_devicename; + +#ifdef __KERNEL__ /* corresponds to one of the obdx */ struct obd_device { struct obd_type *obd_type; @@ -120,8 +231,6 @@ struct obd_device { int obd_flags; int obd_refcnt; obd_devicename obd_fsname; - kdev_t obd_rdev; - char * obd_user_name; struct proc_dir_entry *obd_proc_entry; int obd_multi_count; struct obd_conn obd_multi_conn[MAX_MULTI]; @@ -130,6 +239,7 @@ struct obd_device { struct list_head obd_gen_clients; union { struct ext2_obd ext2; + struct filter_obd filter; struct raid1_obd raid1; struct snap_obd snap; struct trace_obd trace; @@ -141,7 +251,6 @@ extern struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device extern void proc_lustre_release_obd_device(struct obd_device *obd); extern void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd); - /* * ======== OBD Operations Declarations =========== */ @@ -158,9 +267,9 @@ struct obd_ops { obd_count *vallen, void **val); int (*o_set_info)(struct obd_conn *, obd_count keylen, void *key, obd_count vallen, void *val); - int (*o_attach)(struct obd_device *dev, obd_count len, void *data); + int (*o_attach)(struct obd_device *dev, struct obd_ioctl_data *data); int (*o_detach)(struct obd_device *dev); - int (*o_setup) (struct obd_device *dev, obd_count len, void *data); + int (*o_setup) (struct obd_device *dev, struct obd_ioctl_data *data); int (*o_cleanup)(struct obd_device *dev); int (*o_connect)(struct obd_conn *conn); int (*o_disconnect)(struct obd_conn *conn); @@ -193,6 +302,8 @@ struct obd_ops { #define OBT(dev) dev->obd_type->typ_ops #define OBP(dev,op) dev->obd_type->typ_ops->o_ ## op +#endif + /* This value is not arbitrarily chosen. KIO_STATIC_PAGES from linux/iobuf.h */ #define MAX_IOVEC (KIO_STATIC_PAGES - 1) @@ -217,6 +328,7 @@ static inline int obdo_has_obdmd(struct obdo *obdo) obdo->o_obdflags & OBD_FL_OBDMDEXISTS); }; +#ifdef __KERNEL__ /* support routines */ extern kmem_cache_t *obdo_cachep; @@ -301,52 +413,44 @@ static inline void obdo_from_iattr(struct obdo *oa, struct iattr *attr) } -static __inline__ void obdo_cpy_md(struct obdo *dst, struct obdo *src) +static inline void iattr_from_obdo(struct iattr *attr, struct obdo *oa) { - CDEBUG(D_INODE, "src obdo %Ld valid 0x%x, dst obdo %Ld\n", - src->o_id, src->o_valid, dst->o_id); - if ( src->o_valid & OBD_MD_FLATIME ) - dst->o_atime = src->o_atime; - if ( src->o_valid & OBD_MD_FLMTIME ) - dst->o_mtime = src->o_mtime; - if ( src->o_valid & OBD_MD_FLCTIME ) - dst->o_ctime = src->o_ctime; - if ( src->o_valid & OBD_MD_FLSIZE ) - dst->o_size = src->o_size; - if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */ - dst->o_blocks = src->o_blocks; - if ( src->o_valid & OBD_MD_FLBLKSZ ) - dst->o_blksize = src->o_blksize; - if ( src->o_valid & OBD_MD_FLMODE ) - dst->o_mode = src->o_mode; - if ( src->o_valid & OBD_MD_FLUID ) - dst->o_uid = src->o_uid; - if ( src->o_valid & OBD_MD_FLGID ) - dst->o_gid = src->o_gid; - if ( src->o_valid & OBD_MD_FLFLAGS ) - dst->o_flags = src->o_flags; - /* - if ( src->o_valid & OBD_MD_FLOBDFLG ) - dst->o_obdflags = src->o_obdflags; - */ - if ( src->o_valid & OBD_MD_FLNLINK ) - dst->o_nlink = src->o_nlink; - if ( src->o_valid & OBD_MD_FLGENER ) - dst->o_generation = src->o_generation; - if ( src->o_valid & OBD_MD_FLINLINE && - src->o_obdflags & OBD_FL_INLINEDATA) { - memcpy(dst->o_inline, src->o_inline, sizeof(src->o_inline)); - dst->o_obdflags |= OBD_FL_INLINEDATA; + unsigned int ia_valid = oa->o_valid; + + if (ia_valid & OBD_MD_FLATIME) { + attr->ia_atime = oa->o_atime; + attr->ia_valid |= ATTR_ATIME; } - if ( src->o_valid & OBD_MD_FLOBDMD && - src->o_obdflags & OBD_FL_OBDMDEXISTS) { - memcpy(dst->o_obdmd, src->o_obdmd, sizeof(src->o_obdmd)); - dst->o_obdflags |= OBD_FL_OBDMDEXISTS; + if (ia_valid & OBD_MD_FLMTIME) { + attr->ia_mtime = oa->o_mtime; + attr->ia_valid |= ATTR_MTIME; + } + if (ia_valid & OBD_MD_FLCTIME) { + attr->ia_ctime = oa->o_ctime; + attr->ia_valid |= ATTR_CTIME; + } + if (ia_valid & OBD_MD_FLSIZE) { + attr->ia_size = oa->o_size; + attr->ia_valid |= ATTR_SIZE; + } + if (ia_valid & OBD_MD_FLMODE) { + attr->ia_mode = oa->o_mode; + attr->ia_valid |= ATTR_MODE; + if (!in_group_p(oa->o_gid) && !capable(CAP_FSETID)) + attr->ia_mode &= ~S_ISGID; + } + if (ia_valid & OBD_MD_FLUID) + { + attr->ia_uid = oa->o_uid; + attr->ia_valid |= ATTR_UID; + } + if (ia_valid & OBD_MD_FLGID) { + attr->ia_gid = oa->o_gid; + attr->ia_valid |= ATTR_GID; } - - dst->o_valid |= src->o_valid; } + /* WARNING: the file systems must take care not to tinker with attributes they don't manage (such as blocks). */ @@ -411,6 +515,57 @@ static __inline__ void obdo_to_inode(struct inode *dst, struct obdo *src) dst->i_generation = src->o_generation; } +#endif + +static __inline__ void obdo_cpy_md(struct obdo *dst, struct obdo *src) +{ +#ifdef __KERNEL__ + CDEBUG(D_INODE, "src obdo %Ld valid 0x%x, dst obdo %Ld\n", + src->o_id, src->o_valid, dst->o_id); +#endif + if ( src->o_valid & OBD_MD_FLATIME ) + dst->o_atime = src->o_atime; + if ( src->o_valid & OBD_MD_FLMTIME ) + dst->o_mtime = src->o_mtime; + if ( src->o_valid & OBD_MD_FLCTIME ) + dst->o_ctime = src->o_ctime; + if ( src->o_valid & OBD_MD_FLSIZE ) + dst->o_size = src->o_size; + if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */ + dst->o_blocks = src->o_blocks; + if ( src->o_valid & OBD_MD_FLBLKSZ ) + dst->o_blksize = src->o_blksize; + if ( src->o_valid & OBD_MD_FLMODE ) + dst->o_mode = src->o_mode; + if ( src->o_valid & OBD_MD_FLUID ) + dst->o_uid = src->o_uid; + if ( src->o_valid & OBD_MD_FLGID ) + dst->o_gid = src->o_gid; + if ( src->o_valid & OBD_MD_FLFLAGS ) + dst->o_flags = src->o_flags; + /* + if ( src->o_valid & OBD_MD_FLOBDFLG ) + dst->o_obdflags = src->o_obdflags; + */ + if ( src->o_valid & OBD_MD_FLNLINK ) + dst->o_nlink = src->o_nlink; + if ( src->o_valid & OBD_MD_FLGENER ) + dst->o_generation = src->o_generation; + if ( src->o_valid & OBD_MD_FLINLINE && + src->o_obdflags & OBD_FL_INLINEDATA) { + memcpy(dst->o_inline, src->o_inline, sizeof(src->o_inline)); + dst->o_obdflags |= OBD_FL_INLINEDATA; + } + if ( src->o_valid & OBD_MD_FLOBDMD && + src->o_obdflags & OBD_FL_OBDMDEXISTS) { + memcpy(dst->o_obdmd, src->o_obdmd, sizeof(src->o_obdmd)); + dst->o_obdflags |= OBD_FL_OBDMDEXISTS; + } + + dst->o_valid |= src->o_valid; +} + + /* returns FALSE if comparison (by flags) is same, TRUE if changed */ static __inline__ int obdo_cmp_md(struct obdo *dst, struct obdo *src, obd_flag compare) @@ -451,7 +606,7 @@ static __inline__ int obdo_cmp_md(struct obdo *dst, struct obdo *src, } - +#ifdef __KERNEL__ int obd_register_type(struct obd_ops *ops, char *nm); int obd_unregister_type(char *nm); @@ -482,60 +637,161 @@ int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst, struct obd_conn *src_conn, struct obdo *src, obd_size count, obd_off offset); - +#endif /* * ======== OBD IOCL Declarations =========== */ -struct oic_generic { - uint32_t att_connid; - int att_typelen; - void *att_type; - int att_datalen; - void *att_data; -}; +#define OBD_IOCTL_VERSION 0x00010001 -/* for preallocation */ -struct oic_prealloc_s { - uint32_t conn_id; - uint32_t alloc; /* user sets it to the number of inodes - * requesting to be preallocated. kernel - * sets it to the actual number of - * succesfully preallocated inodes */ - obd_id ids[32]; /* actual inode numbers */ +struct obd_ioctl_hdr { + uint32_t ioc_len; + uint32_t ioc_version; }; -/* for getattr, setattr, create, destroy */ -struct oic_attr_s { - uint32_t conn_id; - struct obdo obdo; -}; +static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) +{ + int len = sizeof(struct obd_ioctl_data); + len += size_round(data->ioc_inllen1); + len += size_round(data->ioc_inllen2); + return len; +} -/* for copy, migrate */ -struct ioc_mv_s { - uint32_t src_conn_id; - struct obdo src; - uint32_t dst_conn_id; - struct obdo dst; -}; +static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) +{ + if (data->ioc_len > (1<<30)) { + printk("OBD ioctl: ioc_len larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen1 > (1<<30)) { + printk("OBD ioctl: ioc_inllen1 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen2 > (1<<30)) { + printk("OBD ioctl: ioc_inllen2 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inlbuf1 && !data->ioc_inllen1) { + printk("OBD ioctl: inlbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_inlbuf2 && !data->ioc_inllen2) { + printk("OBD ioctl: inlbuf2 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf1 && !data->ioc_plen1) { + printk("OBD ioctl: pbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf2 && !data->ioc_plen2) { + printk("OBD ioctl: pbuf2 pointer but 0 length\n"); + return 1; + } + if (obd_ioctl_packlen(data) != data->ioc_len ) { + printk("OBD ioctl: packlen exceeds ioc_len\n"); + return 1; + } + if (data->ioc_inllen1 && + data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { + printk("OBD ioctl: inlbuf1 not 0 terminated\n"); + return 1; + } + if (data->ioc_inllen2 && + data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2 - 1] != '\0') { + printk("OBD ioctl: inlbuf2 not 0 terminated\n"); + return 1; + } + return 0; +} -/* for read/write */ -struct oic_rw_s { - uint32_t conn_id; - struct obdo obdo; - char *buf; - obd_size count; - obd_off offset; -}; +#ifndef __KERNEL__ +static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, int max) +{ + char *ptr; + struct obd_ioctl_data *overlay; + data->ioc_len = obd_ioctl_packlen(data); + data->ioc_version = OBD_IOCTL_VERSION; + + if (*pbuf && obd_ioctl_packlen(data) > max) + return 1; + if (*pbuf == NULL) { + *pbuf = malloc(data->ioc_len); + } + if (!*pbuf) + return 1; + overlay = (struct obd_ioctl_data *)*pbuf; + memcpy(*pbuf, data, sizeof(*data)); + + ptr = overlay->ioc_bulk; + if (data->ioc_inlbuf1) + LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr); + if (data->ioc_inlbuf2) + LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr); + if (obd_ioctl_is_invalid(overlay)) + return 1; + + return 0; +} +#else -/* for punch, sync */ -struct oic_range_s { - uint32_t conn_id; - struct obdo obdo; - obd_size count; - obd_off offset; -}; + +/* buffer MUST be at least the size of obd_ioctl_hdr */ +static inline int obd_ioctl_getdata(char *buf, char *end, void *arg) +{ + struct obd_ioctl_hdr *hdr; + struct obd_ioctl_data *data; + int err; + ENTRY; + + hdr = (struct obd_ioctl_hdr *)buf; + data = (struct obd_ioctl_data *)buf; + + err = copy_from_user(buf, (void *)arg, sizeof(*hdr)); + if ( err ) { + EXIT; + return err; + } + + if (hdr->ioc_version != OBD_IOCTL_VERSION) { + printk("OBD: version mismatch kernel vs application\n"); + return -EINVAL; + } + + if (hdr->ioc_len + buf >= end) { + printk("OBD: user buffer exceeds kernel buffer\n"); + return -EINVAL; + } + + + if (hdr->ioc_len < sizeof(struct obd_ioctl_data)) { + printk("OBD: user buffer too small for ioctl\n"); + return -EINVAL; + } + + err = copy_from_user(buf, (void *)arg, hdr->ioc_len); + if ( err ) { + EXIT; + return err; + } + + if (obd_ioctl_is_invalid(data)) { + printk("OBD: ioctl not correctly formatted\n"); + return -EINVAL; + } + + if (data->ioc_inllen1) { + data->ioc_inlbuf1 = &data->ioc_bulk[0]; + } + + if (data->ioc_inllen2) { + data->ioc_inlbuf2 = &data->ioc_bulk[0] + size_round(data->ioc_inllen1); + } + + EXIT; + return 0; +} +#endif #define OBD_IOC_CREATE _IOR ('f', 3, long) @@ -560,6 +816,7 @@ struct oic_range_s { #define OBD_IOC_COPY _IOWR('f', 22, long) #define OBD_IOC_MIGR _IOWR('f', 23, long) #define OBD_IOC_PUNCH _IOWR('f', 24, long) +#define OBD_IOC_DEVICE _IOWR('f', 25, long) #define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 32 ) diff --git a/lustre/include/linux/obd_filter.h b/lustre/include/linux/obd_filter.h new file mode 100644 index 0000000..6fb189f --- /dev/null +++ b/lustre/include/linux/obd_filter.h @@ -0,0 +1,32 @@ +#ifndef _OBD_FILTER_H +#define _OBD_FILTER_H +/* + * Copyright (C) 2001 Cluster File Systems, Inc. + * + * This code is issued under the GNU General Public License. + * See the file COPYING in this distribution + */ + + +#ifndef OBD_FILTER_DEVICENAME +#define OBD_FILTER_DEVICENAME "obdfilter" +#endif + +struct run_ctxt { + struct vfsmount *pwdmnt; + struct dentry *pwd; + mm_segment_t fs; +}; + +struct filter_obd { + char *fo_fstype; + struct super_block * fo_sb; + struct vfsmount *fo_vfsmnt; + struct run_ctxt fo_ctxt; + __u64 fo_lastino; +}; + + +extern struct obd_ops filter_obd_ops; + +#endif diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h index 0d37002..c091236 100644 --- a/lustre/include/linux/obd_support.h +++ b/lustre/include/linux/obd_support.h @@ -11,8 +11,7 @@ #include #include -#define MIN(a,b) (((a)<(b)) ? (a): (b)) -#define MAX(a,b) (((a)>(b)) ? (a): (b)) + #define obd_unlock_page(page) do { if (PageLocked(page)) { \ UnlockPage(page);\ @@ -165,7 +164,7 @@ static inline void obd_iput(struct inode *inode) #define OBD_ALLOC(ptr, cast, size) \ do { \ - ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \ + ptr = kmalloc((unsigned long) size, GFP_KERNEL); \ obd_memory += size; \ CDEBUG(D_MALLOC, "kmalloced: %d at %x (tot %ld).\n", \ (int) size, (int) ptr, obd_memory); \ diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index ff959e2..5df8f03 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -10,7 +10,7 @@ #ifndef _OBDFS_H -#define OBDFS_H +#define _OBDFS_H #include #include #include diff --git a/lustre/obdclass/Makefile.am b/lustre/obdclass/Makefile.am index 428942d..f92cd00 100644 --- a/lustre/obdclass/Makefile.am +++ b/lustre/obdclass/Makefile.am @@ -1,6 +1,3 @@ -bin_SCRIPTS = obdcontrol -EXTRA_DIST = $(bin_SCRIPTS) - MODULE = obdclass modulefs_DATA = obdclass.o EXTRA_PROGRAMS = obdclass diff --git a/lustre/obdclass/Makefile.in b/lustre/obdclass/Makefile.in index 16dd2f7..45b7007 100644 --- a/lustre/obdclass/Makefile.in +++ b/lustre/obdclass/Makefile.in @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -85,9 +85,6 @@ docdir = @docdir@ moduledir = @moduledir@ modulefsdir = @modulefsdir@ -bin_SCRIPTS = obdcontrol -EXTRA_DIST = $(bin_SCRIPTS) - MODULE = obdclass modulefs_DATA = obdclass.o EXTRA_PROGRAMS = obdclass @@ -103,8 +100,6 @@ obdclass_OBJECTS = genops.o proc_lustre.o class_obd.o sysctl.o obdclass_LDADD = $(LDADD) obdclass_DEPENDENCIES = obdclass_LDFLAGS = -SCRIPTS = $(bin_SCRIPTS) - CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -154,25 +149,6 @@ obdclass: $(obdclass_OBJECTS) $(obdclass_DEPENDENCIES) @rm -f obdclass $(LINK) $(obdclass_LDFLAGS) $(obdclass_OBJECTS) $(obdclass_LDADD) $(LIBS) -install-binSCRIPTS: $(bin_SCRIPTS) - @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(bindir) - @list='$(bin_SCRIPTS)'; for p in $$list; do \ - if test -f $$p; then \ - echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ - $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ - else if test -f $(srcdir)/$$p; then \ - echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ - $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ - else :; fi; fi; \ - done - -uninstall-binSCRIPTS: - @$(NORMAL_UNINSTALL) - list='$(bin_SCRIPTS)'; for p in $$list; do \ - rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ - done - install-modulefsDATA: $(modulefs_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(modulefsdir) @@ -281,7 +257,7 @@ check-am: all-am check: check-am installcheck-am: installcheck: installcheck-am -install-exec-am: install-binSCRIPTS +install-exec-am: install-exec: install-exec-am install-data-am: install-modulefsDATA @@ -290,14 +266,14 @@ install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-am -uninstall-am: uninstall-binSCRIPTS uninstall-modulefsDATA +uninstall-am: uninstall-modulefsDATA uninstall: uninstall-am -all-am: Makefile $(SCRIPTS) $(DATA) +all-am: Makefile $(DATA) all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: - $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(modulefsdir) + $(mkinstalldirs) $(DESTDIR)$(modulefsdir) mostlyclean-generic: @@ -333,10 +309,9 @@ maintainer-clean-am: maintainer-clean-compile maintainer-clean-tags \ maintainer-clean: maintainer-clean-am .PHONY: mostlyclean-compile distclean-compile clean-compile \ -maintainer-clean-compile uninstall-binSCRIPTS install-binSCRIPTS \ -uninstall-modulefsDATA install-modulefsDATA tags mostlyclean-tags \ -distclean-tags clean-tags maintainer-clean-tags distdir \ -mostlyclean-depend distclean-depend clean-depend \ +maintainer-clean-compile uninstall-modulefsDATA install-modulefsDATA \ +tags mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir mostlyclean-depend distclean-depend clean-depend \ maintainer-clean-depend info-am info dvi-am dvi check check-am \ installcheck-am installcheck install-exec-am install-exec \ install-data-am install-data install-am install uninstall-am uninstall \ diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index bf57215..545f66b 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -6,8 +6,7 @@ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * version 2 as published by the Free Software Foundation. * * Adapted to become the Linux 2.0 Coda pseudo device * Peter Braam @@ -29,7 +28,6 @@ */ #define EXPORT_SYMTAB - #include /* for CONFIG_PROC_FS */ #include #include @@ -50,10 +48,10 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -65,53 +63,26 @@ long obd_memory = 0; struct obd_device obd_dev[MAX_OBD_DEVICES]; struct list_head obd_types; -/* called when opening /dev/obdNNN */ +/* opening /dev/obd */ static int obd_class_open(struct inode * inode, struct file * file) { - int dev; ENTRY; - if (!inode) - return -EINVAL; - dev = MINOR(inode->i_rdev); - if (dev >= MAX_OBD_DEVICES) - return -ENODEV; - obd_dev[dev].obd_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obd_dev[dev].obd_refcnt); - - obd_dev[dev].obd_proc_entry = - proc_lustre_register_obd_device(&obd_dev[dev]); - + file->private_data = NULL; MOD_INC_USE_COUNT; EXIT; return 0; } -/* called when closing /dev/obdNNN */ +/* closing /dev/obd */ static int obd_class_release(struct inode * inode, struct file * file) { - int dev; ENTRY; - if (!inode) - return -EINVAL; - dev = MINOR(inode->i_rdev); - if (dev >= MAX_OBD_DEVICES) - return -ENODEV; - fsync_dev(inode->i_rdev); - if (obd_dev[dev].obd_refcnt <= 0) - printk(KERN_ALERT __FUNCTION__ ": refcount(%d) <= 0\n", - obd_dev[dev].obd_refcnt); - obd_dev[dev].obd_refcnt--; - - if (obd_dev[dev].obd_proc_entry && (obd_dev[dev].obd_refcnt==0)) - proc_lustre_release_obd_device(&obd_dev[dev]); - - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obd_dev[dev].obd_refcnt); - MOD_DEC_USE_COUNT; + if (file->private_data) + file->private_data = NULL; + MOD_DEC_USE_COUNT; EXIT; return 0; } @@ -155,337 +126,251 @@ static struct obd_type *obd_nm_to_type(char *nm) return type; } - -static int getdata(int len, void **data) -{ - void *tmp = NULL; - - if (!len) { - *data = NULL; - return 0; - } - - CDEBUG(D_MALLOC, "len %d, add %p\n", len, *data); - - OBD_ALLOC(tmp, void *, len); - if ( !tmp ) - return -ENOMEM; - - memset(tmp, 0, len); - if ( copy_from_user(tmp, *data, len)) { - OBD_FREE(tmp, len); - return -EFAULT; - } - *data = tmp; - - return 0; -} - -/* to control /dev/obdNNN */ +/* to control /dev/obd */ static int obd_class_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { - struct obd_device *obddev; /* NOTE this must be larger than any of the ioctl data structs */ char buf[1024]; - void *tmp_buf = buf; - struct obd_conn conn; - int err, dev; - long int cli_id; /* connect, disconnect */ - - if (!inode) { - CDEBUG(D_IOCTL, "invalid inode\n"); - return -EINVAL; - } - - dev = MINOR(inode->i_rdev); - if (dev > MAX_OBD_DEVICES) - return -ENODEV; - obddev = &obd_dev[dev]; - conn.oc_dev = obddev; + struct obd_ioctl_data *data; + struct obd_device *obd = filp->private_data; + struct obd_conn conn; + int err = 0; + ENTRY; + + memset(buf, 0, sizeof(buf)); + + if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS) { + printk("OBD ioctl: No device\n"); + return -EINVAL; + } + if (obd_ioctl_getdata(buf, buf + 800, (void *)arg)) { + printk("OBD ioctl: data error\n"); + return -EINVAL; + } + data = (struct obd_ioctl_data *)buf; switch (cmd) { case TCGETS: return -EINVAL; + case OBD_IOC_DEVICE: { + CDEBUG(D_IOCTL, "\n"); + if (data->ioc_dev >= MAX_OBD_DEVICES || + data->ioc_dev < 0) { + printk("OBD ioctl: DEVICE insufficient devices\n"); + return -EINVAL; + } + CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev); + + filp->private_data = &obd_dev[data->ioc_dev]; + EXIT; + return 0; + } + case OBD_IOC_ATTACH: { struct obd_type *type; - struct oic_generic *input = tmp_buf; - char *nm; ENTRY; /* have we attached a type to this device */ - if ( obddev->obd_type || - (obddev->obd_flags & OBD_ATTACHED) ){ - char *name; - if (obddev->obd_type->typ_name) - name = obddev->obd_type->typ_name; - else - name = ""; - CDEBUG(D_IOCTL, - "OBD Device %d already attached to type %s.\n", - dev, name); - EXIT; + if ( obd->obd_type || (obd->obd_flags & OBD_ATTACHED) ){ + printk("OBD: Device %d already typed as %s.\n", + obd->obd_minor, MKSTR(obd->obd_type->typ_name)); return -EBUSY; } - /* get data structures */ - err = copy_from_user(input, (void *)arg, sizeof(*input)); - if ( err ) { - EXIT; - return err; - } - - err = getdata(input->att_typelen + 1, &input->att_type); - if ( err ) { - EXIT; - return err; - } + printk("-----> attach %s %s\n", MKSTR(data->ioc_inlbuf1), + MKSTR(data->ioc_inlbuf2)); /* find the type */ - nm = input->att_type; - type = obd_nm_to_type(nm); - - OBD_FREE(input->att_type, input->att_typelen + 1); + type = obd_nm_to_type(data->ioc_inlbuf1); if ( !type ) { - printk(__FUNCTION__ ": unknown obd type dev %d\n", - dev); - EXIT; + printk("OBD: unknown type dev %d\n", obd->obd_minor); return -EINVAL; } - obddev->obd_type = type; - - /* get the attach data */ - err = getdata(input->att_datalen, &input->att_data); - if ( err ) { - EXIT; - return err; - } - INIT_LIST_HEAD(&obddev->obd_gen_clients); - obddev->obd_multi_count = 0; - - CDEBUG(D_IOCTL, "Attach %d, datalen %d, type %s\n", - dev, input->att_datalen, obddev->obd_type->typ_name); - /* maybe we are done */ - if ( !OBT(obddev) || !OBP(obddev, attach) ) { - obddev->obd_flags |= OBD_ATTACHED; - type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - type->typ_refcnt); - if (input->att_data) - OBD_FREE(input->att_data, input->att_datalen); - MOD_INC_USE_COUNT; - EXIT; - return 0; - } + obd->obd_type = type; + obd->obd_multi_count = 0; + INIT_LIST_HEAD(&obd->obd_gen_clients); /* do the attach */ - err = OBP(obddev, attach)(obddev, input->att_datalen, - input->att_data); - if (input->att_data) - OBD_FREE(input->att_data, input->att_datalen); + if ( OBT(obd) && OBP(obd, attach) ) { + err = OBP(obd, attach)(obd, data); + } if ( err ) { - obddev->obd_flags &= ~OBD_ATTACHED; - obddev->obd_type = NULL; + obd->obd_flags &= ~OBD_ATTACHED; + obd->obd_type = NULL; EXIT; } else { - obddev->obd_flags |= OBD_ATTACHED; + obd->obd_flags |= OBD_ATTACHED; type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - type->typ_refcnt); + printk("OBD: dev %d attached type %s\n", + obd->obd_minor, data->ioc_inlbuf1); + obd->obd_proc_entry = + proc_lustre_register_obd_device(obd); MOD_INC_USE_COUNT; EXIT; } + return err; } case OBD_IOC_DETACH: { - ENTRY; - if (obddev->obd_flags & OBD_SET_UP) { - EXIT; + if (obd->obd_flags & OBD_SET_UP) { + printk("OBD device %d still set up\n", obd->obd_minor); return -EBUSY; } - if (! (obddev->obd_flags & OBD_ATTACHED) ) { - CDEBUG(D_IOCTL, "Device not attached\n"); - EXIT; + if (! (obd->obd_flags & OBD_ATTACHED) ) { + printk("OBD device %d not attached\n", obd->obd_minor); return -ENODEV; } - if ( !list_empty(&obddev->obd_gen_clients) ) { - CDEBUG(D_IOCTL, "Device has connected clients\n"); - EXIT; + if ( !list_empty(&obd->obd_gen_clients) ) { + printk("OBD device %d has connected clients\n", obd->obd_minor); return -EBUSY; } - CDEBUG(D_PSDEV, "Detach %d, type %s\n", dev, - obddev->obd_type->typ_name); - obddev->obd_flags &= ~OBD_ATTACHED; - obddev->obd_type->typ_refcnt--; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obddev->obd_type->typ_refcnt); - obddev->obd_type = NULL; + if (obd->obd_proc_entry) + proc_lustre_release_obd_device(obd); + + obd->obd_flags &= ~OBD_ATTACHED; + obd->obd_type->typ_refcnt--; + obd->obd_type = NULL; MOD_DEC_USE_COUNT; EXIT; return 0; } case OBD_IOC_SETUP: { - struct ioc_setup { - int setup_datalen; - int setup_rdev; - void *setup_data; - } *setup; - - setup = tmp_buf; - - ENTRY; - /* have we attached a type to this device */ - if (!(obddev->obd_flags & OBD_ATTACHED)) { - CDEBUG(D_IOCTL, "Device not attached\n"); - EXIT; + /* have we attached a type to this device? */ + if (!(obd->obd_flags & OBD_ATTACHED)) { + printk("Device %d not attached\n", obd->obd_minor); return -ENODEV; } /* has this been done already? */ - if ( obddev->obd_flags & OBD_SET_UP ) { - CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n", - dev, obddev->obd_type->typ_name); - EXIT; + if ( obd->obd_flags & OBD_SET_UP ) { + printk("Device %d already setup (type %s)\n", + obd->obd_minor, obd->obd_type->typ_name); return -EBUSY; } - /* get main structure */ - err = copy_from_user(setup, (void *) arg, sizeof(*setup)); - if (err) { - EXIT; - return err; - } - - /* get the attach data */ - err = getdata(setup->setup_datalen, &setup->setup_data); - if ( err ) { - EXIT; - return err; - } - obddev->obd_rdev = setup->setup_rdev; - obddev->obd_user_name = (char *)setup->setup_data; - - /* do the setup */ - if ( !OBT(obddev) || !OBP(obddev, setup) ) { - obddev->obd_type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", - dev, obddev->obd_type->typ_refcnt); - if (setup->setup_data) - OBD_FREE(setup->setup_data, - setup->setup_datalen); - obddev->obd_flags |= OBD_SET_UP; - EXIT; - return 0; - } + if ( OBT(obd) && OBP(obd, setup) ) + err = OBP(obd, setup)(obd, data); - CDEBUG(D_PSDEV, "Setup %d, type %s device %x, %s, len %d\n", dev, - obddev->obd_type->typ_name, setup->setup_rdev, - obddev->obd_user_name, setup->setup_datalen); + if (!err) { + obd->obd_type->typ_refcnt++; + obd->obd_flags |= OBD_SET_UP; + EXIT; + } - err = OBP(obddev, setup)(obddev, 0, NULL); - - if ( err ) { - obddev->obd_flags &= ~OBD_SET_UP; - EXIT; - } else { - obddev->obd_type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", - dev, obddev->obd_type->typ_refcnt); - obddev->obd_flags |= OBD_SET_UP; - EXIT; - } - // OBD_FREE(setup->setup_data, setup->setup_datalen); return err; } case OBD_IOC_CLEANUP: { ENTRY; /* has this minor been registered? */ - if (!obddev->obd_type) { - CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev); + if (!obd->obd_type) { + printk("OBD cleanup dev %d has no type.\n", + obd->obd_minor); EXIT; return -ENODEV; } - if ( !obddev->obd_type->typ_refcnt ) { - CDEBUG(D_IOCTL, "dev %d has refcount (%d)!\n", - dev, obddev->obd_type->typ_refcnt); - EXIT; - return -EBUSY; - } - - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { - CDEBUG(D_IOCTL, "device not attached or set up\n"); + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { + printk("OBD cleanup device %d not attached/set up\n", + obd->obd_minor); EXIT; return -ENODEV; } - if ( !OBT(obddev) || !OBP(obddev, cleanup) ) + if ( !OBT(obd) || !OBP(obd, cleanup) ) goto cleanup_out; /* cleanup has no argument */ - err = OBP(obddev, cleanup)(obddev); + err = OBP(obd, cleanup)(obd); if ( err ) { EXIT; return err; } cleanup_out: - obddev->obd_flags &= ~OBD_SET_UP; - obddev->obd_type->typ_refcnt--; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obddev->obd_type->typ_refcnt); + obd->obd_flags &= ~OBD_SET_UP; + obd->obd_type->typ_refcnt--; EXIT; return 0; } + case OBD_IOC_CONNECT: { - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { CDEBUG(D_IOCTL, "Device not attached or set up\n"); return -ENODEV; } - if ( !OBT(obddev) || !OBP(obddev, connect) ) + if ( !OBT(obd) || !OBP(obd, connect) ) return -EOPNOTSUPP; + + conn.oc_id = data->ioc_conn1; + conn.oc_dev = obd; - err = OBP(obddev, connect)(&conn); + err = OBP(obd, connect)(&conn); + CDEBUG(D_IOCTL, "assigned connection %d\n", conn.oc_id); + data->ioc_conn1 = conn.oc_id; if ( err ) return err; - return copy_to_user((int *)arg, &conn.oc_id, - sizeof(uint32_t)); + return copy_to_user((int *)arg, data, sizeof(*data)); } - case OBD_IOC_DISCONNECT: - /* frees data structures */ - /* has this minor been registered? */ - if (!obddev->obd_type) - return -ENODEV; + case OBD_IOC_DISCONNECT: { - get_user(cli_id, (int *) arg); - conn.oc_id = cli_id; + if (!obd->obd_type) + return -ENODEV; - if ( !OBT(obddev) || !OBP(obddev, disconnect)) + if ( !OBT(obd) || !OBP(obd, disconnect)) return -EOPNOTSUPP; - OBP(obddev, disconnect)(&conn); + conn.oc_id = data->ioc_conn1; + conn.oc_dev = obd; + OBP(obd, disconnect)(&conn); return 0; - - case OBD_IOC_DEC_USE_COUNT: + } + + case OBD_IOC_DEC_USE_COUNT: { MOD_DEC_USE_COUNT; return 0; + } + + case OBD_IOC_CREATE: { + /* has this minor been registered? */ + if ( !(obd->obd_flags & OBD_ATTACHED) || + !(obd->obd_flags & OBD_SET_UP)) { + CDEBUG(D_IOCTL, "Device not attached or set up\n"); + return -ENODEV; + } + conn.oc_id = data->ioc_conn1; + conn.oc_dev = obd; + + if ( !OBT(obd) || !OBP(obd, create) ) + return -EOPNOTSUPP; + + err = OBP(obd, create)(&conn, &data->ioc_obdo1); + if (err) { + EXIT; + return err; + } + err = copy_to_user((int *)arg, data, sizeof(*data)); + EXIT; + return err; + } +#if 0 case OBD_IOC_SYNC: { struct oic_range_s *range = tmp_buf; - if (!obddev->obd_type) + if (!obd->obd_type) return -ENODEV; err = copy_from_user(range, (const void *)arg, sizeof(*range)); @@ -495,14 +380,14 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, return err; } - if ( !OBT(obddev) || !OBP(obddev, sync) ) { + if ( !OBT(obd) || !OBP(obd, sync) ) { err = -EOPNOTSUPP; EXIT; return err; } /* XXX sync needs to be tested/verified */ - err = OBP(obddev, sync)(&conn, &range->obdo, range->count, + err = OBP(obd, sync)(&conn, &range->obdo, range->count, range->offset); if ( err ) { @@ -512,42 +397,12 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, return put_user(err, (int *) arg); } - case OBD_IOC_CREATE: { - struct oic_attr_s *attr = tmp_buf; - - err = copy_from_user(attr, (const void *)arg, sizeof(*attr)); - if (err) { - EXIT; - return err; - } - - /* has this minor been registered? */ - if ( !(obddev->obd_flags & OBD_ATTACHED) || - !(obddev->obd_flags & OBD_SET_UP)) { - CDEBUG(D_IOCTL, "Device not attached or set up\n"); - return -ENODEV; - } - conn.oc_id = attr->conn_id; - - if ( !OBT(obddev) || !OBP(obddev, create) ) - return -EOPNOTSUPP; - - err = OBP(obddev, create)(&conn, &attr->obdo); - if (err) { - EXIT; - return err; - } - - err = copy_to_user((int *)arg, attr, sizeof(*attr)); - EXIT; - return err; - } case OBD_IOC_DESTROY: { struct oic_attr_s *attr = tmp_buf; /* has this minor been registered? */ - if (!obddev->obd_type) + if (!obd->obd_type) return -ENODEV; err = copy_from_user(attr, (int *)arg, sizeof(*attr)); @@ -556,11 +411,11 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, return err; } - if ( !OBT(obddev) || !OBP(obddev, destroy) ) + if ( !OBT(obd) || !OBP(obd, destroy) ) return -EOPNOTSUPP; conn.oc_id = attr->conn_id; - err = OBP(obddev, destroy)(&conn, &attr->obdo); + err = OBP(obd, destroy)(&conn, &attr->obdo); EXIT; return err; } @@ -569,18 +424,18 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, struct oic_attr_s *attr = tmp_buf; /* has this minor been registered? */ - if (!obddev->obd_type) + if (!obd->obd_type) return -ENODEV; err = copy_from_user(attr, (int *)arg, sizeof(*attr)); if (err) return err; - if ( !OBT(obddev) || !OBP(obddev, setattr) ) + if ( !OBT(obd) || !OBP(obd, setattr) ) return -EOPNOTSUPP; conn.oc_id = attr->conn_id; - err = OBP(obddev, setattr)(&conn, &attr->obdo); + err = OBP(obd, setattr)(&conn, &attr->obdo); EXIT; return err; } @@ -594,7 +449,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, conn.oc_id = attr->conn_id; ODEBUG(&attr->obdo); - err = OBP(obddev, getattr)(&conn, &attr->obdo); + err = OBP(obd, getattr)(&conn, &attr->obdo); if ( err ) { EXIT; return err; @@ -617,14 +472,14 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, conn.oc_id = rw_s->conn_id; - if ( !OBT(obddev) || !OBP(obddev, read) ) { + if ( !OBT(obd) || !OBP(obd, read) ) { err = -EOPNOTSUPP; EXIT; return err; } - err = OBP(obddev, read)(&conn, &rw_s->obdo, rw_s->buf, + err = OBP(obd, read)(&conn, &rw_s->obdo, rw_s->buf, &rw_s->count, rw_s->offset); ODEBUG(&rw_s->obdo); @@ -651,7 +506,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, conn.oc_id = rw_s->conn_id; - if ( !OBT(obddev) || !OBP(obddev, write) ) { + if ( !OBT(obd) || !OBP(obd, write) ) { err = -EOPNOTSUPP; return err; } @@ -659,7 +514,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, CDEBUG(D_INFO, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n", rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf); - err = OBP(obddev, write)(&conn, &rw_s->obdo, rw_s->buf, + err = OBP(obd, write)(&conn, &rw_s->obdo, rw_s->buf, &rw_s->count, rw_s->offset); ODEBUG(&rw_s->obdo); if ( err ) { @@ -676,24 +531,24 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, struct oic_prealloc_s *prealloc = tmp_buf; /* has this minor been registered? */ - if (!obddev->obd_type) + if (!obd->obd_type) return -ENODEV; err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc)); if (err) return -EFAULT; - if ( !(obddev->obd_flags & OBD_ATTACHED) || - !(obddev->obd_flags & OBD_SET_UP)) { + if ( !(obd->obd_flags & OBD_ATTACHED) || + !(obd->obd_flags & OBD_SET_UP)) { CDEBUG(D_IOCTL, "Device not attached or set up\n"); return -ENODEV; } - if ( !OBT(obddev) || !OBP(obddev, preallocate) ) + if ( !OBT(obd) || !OBP(obd, preallocate) ) return -EOPNOTSUPP; conn.oc_id = prealloc->conn_id; - err = OBP(obddev, preallocate)(&conn, &prealloc->alloc, + err = OBP(obd, preallocate)(&conn, &prealloc->alloc, prealloc->ids); if ( err ) { EXIT; @@ -710,17 +565,17 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, struct statfs buf; /* has this minor been registered? */ - if (!obddev->obd_type) + if (!obd->obd_type) return -ENODEV; tmp = (void *)arg + sizeof(unsigned int); get_user(conn_id, (int *) arg); - if ( !OBT(obddev) || !OBP(obddev, statfs) ) + if ( !OBT(obd) || !OBP(obd, statfs) ) return -EOPNOTSUPP; conn.oc_id = conn_id; - err = OBP(obddev, statfs)(&conn, &buf); + err = OBP(obd, statfs)(&conn, &buf); if ( err ) { EXIT; return err; @@ -733,8 +588,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, case OBD_IOC_COPY: { struct ioc_mv_s *mvdata = tmp_buf; - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { CDEBUG(D_IOCTL, "Device not attached or set up\n"); return -ENODEV; } @@ -746,17 +601,17 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, return err; } - if ( !OBT(obddev) || !OBP(obddev, copy) ) + if ( !OBT(obd) || !OBP(obd, copy) ) return -EOPNOTSUPP; /* do the partition */ CDEBUG(D_INFO, "Copy %d, type %s dst %Ld src %Ld\n", dev, - obddev->obd_type->typ_name, mvdata->dst.o_id, + obd->obd_type->typ_name, mvdata->dst.o_id, mvdata->src.o_id); conn.oc_id = mvdata->src_conn_id; - err = OBP(obddev, copy)(&conn, &mvdata->dst, + err = OBP(obd, copy)(&conn, &mvdata->dst, &conn, &mvdata->src, mvdata->src.o_size, 0); return err; @@ -765,8 +620,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, case OBD_IOC_MIGR: { struct ioc_mv_s *mvdata = tmp_buf; - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { CDEBUG(D_IOCTL, "Device not attached or set up\n"); return -ENODEV; } @@ -779,16 +634,16 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, CDEBUG(D_INFO, "Migrate copying %d bytes\n", sizeof(*mvdata)); - if ( !OBT(obddev) || !OBP(obddev, migrate) ) + if ( !OBT(obd) || !OBP(obd, migrate) ) return -EOPNOTSUPP; /* do the partition */ CDEBUG(D_INFO, "Migrate %d, type %s conn %d src %Ld dst %Ld\n", - dev, obddev->obd_type->typ_name, mvdata->src_conn_id, + dev, obd->obd_type->typ_name, mvdata->src_conn_id, mvdata->src.o_id, mvdata->dst.o_id); conn.oc_id = mvdata->src_conn_id; - err = OBP(obddev, migrate)(&conn, &mvdata->dst, &mvdata->src, + err = OBP(obd, migrate)(&conn, &mvdata->dst, &mvdata->src, mvdata->src.o_size, 0); return err; @@ -804,14 +659,14 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, conn.oc_id = rw_s->conn_id; - if ( !OBT(obddev) || !OBP(obddev, punch) ) { + if ( !OBT(obd) || !OBP(obd, punch) ) { err = -EOPNOTSUPP; return err; } CDEBUG(D_INFO, "PUNCH: conn %d, count %Ld, offset %Ld\n", rw_s->conn_id, rw_s->count, rw_s->offset); - err = OBP(obddev, punch)(&conn, &rw_s->obdo, rw_s->count, + err = OBP(obd, punch)(&conn, &rw_s->obdo, rw_s->count, rw_s->offset); ODEBUG(&rw_s->obdo); if ( err ) { @@ -885,6 +740,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, EXIT; return err; } +#endif + default: + return -EINVAL; + } } /* obd_class_ioctl */ @@ -956,6 +815,12 @@ static struct file_operations obd_psdev_fops = { /* modules setup */ +#define OBD_MINOR 241 +static struct miscdevice obd_psdev = { + OBD_MINOR, + "obd_psdev", + &obd_psdev_fops +}; int init_obd(void) { @@ -966,10 +831,9 @@ int init_obd(void) INIT_LIST_HEAD(&obd_types); - if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev", - &obd_psdev_fops)) { - printk(KERN_ERR __FUNCTION__ ": unable to get major %d\n", - OBD_PSDEV_MAJOR); + if ( (err = misc_register(&obd_psdev)) ) { + printk(KERN_ERR __FUNCTION__ ": cannot register %d err %d\n", + OBD_MINOR, err); return -EIO; } @@ -1017,14 +881,14 @@ void cleanup_module(void) int i; ENTRY; - unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev"); + misc_deregister(&obd_psdev); for (i = 0; i < MAX_OBD_DEVICES; i++) { - struct obd_device *obddev = &obd_dev[i]; - if ( obddev->obd_type && - (obddev->obd_flags & OBD_SET_UP) && - OBT(obddev) && OBP(obddev, detach) ) { + struct obd_device *obd = &obd_dev[i]; + if ( obd->obd_type && + (obd->obd_flags & OBD_SET_UP) && + OBT(obd) && OBP(obd, detach) ) { /* XXX should this call generic detach otherwise? */ - OBP(obddev, detach)(obddev); + OBP(obd, detach)(obd); } } diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index 545b0c7..fc8770e 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -12,6 +12,7 @@ #include +#include #include #include #include diff --git a/lustre/obdfilter/Makefile.am b/lustre/obdfilter/Makefile.am new file mode 100644 index 0000000..fc10f59 --- /dev/null +++ b/lustre/obdfilter/Makefile.am @@ -0,0 +1,14 @@ +# Copyright (C) 2001 Cluster File Systems, Inc. +# +# This code is issued under the GNU General Public License. +# See the file COPYING in this distribution + +MODULE = obdfilter +modulefs_DATA = obdfilter.o +EXTRA_PROGRAMS = obdfilter + +EXT2C = filter.c +obdfilter_SOURCES = filter.c + +include $(top_srcdir)/Rules + diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c new file mode 100644 index 0000000..ca9ee52 --- /dev/null +++ b/lustre/obdfilter/filter.c @@ -0,0 +1,816 @@ +/* + * linux/fs/ext2_obd/ext2_obd.c + * + * Copyright (C) 1999 Stelias Computing, Inc. + * Copyright (C) 1999 Seagate Technology, Inc. + * Copyright (C) 2001 Cluster File Systems, Inc. + * + * This code is issued under the GNU General Public License. + * See the file COPYING in this distribution + * + * This is the object based disk driver based on ext2 + * written by Peter Braam , Phil Schwan + * Andreas Dilger + * + */ + +#define EXPORT_SYMTAB + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +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 diff --git a/lustre/obdfs/Makefile.am b/lustre/obdfs/Makefile.am index 2664496..b154c51 100644 --- a/lustre/obdfs/Makefile.am +++ b/lustre/obdfs/Makefile.am @@ -6,7 +6,6 @@ MODULE = obdfs modulefs_DATA = obdfs.o EXTRA_PROGRAMS = obdfs -# obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c obdfs_SOURCES = rw.c file.c dir.c sysctl.c super.c namei.c symlink.c include $(top_srcdir)/Rules diff --git a/lustre/obdfs/Makefile.in b/lustre/obdfs/Makefile.in index 81f1805..84ba0b5 100644 --- a/lustre/obdfs/Makefile.in +++ b/lustre/obdfs/Makefile.in @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -93,7 +93,6 @@ modulefsdir = @modulefsdir@ MODULE = obdfs modulefs_DATA = obdfs.o EXTRA_PROGRAMS = obdfs -# obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c obdfs_SOURCES = rw.c file.c dir.c sysctl.c super.c namei.c symlink.c mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index f569f30..031b8f3 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -11,8 +11,6 @@ * */ -#define EXPORT_SYMTAB - #include #include #include diff --git a/lustre/scripts/Makefile.in b/lustre/scripts/Makefile.in index 040cbb0..4e5fad9 100644 --- a/lustre/scripts/Makefile.in +++ b/lustre/scripts/Makefile.in @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am new file mode 100644 index 0000000..90007fc --- /dev/null +++ b/lustre/utils/Makefile.am @@ -0,0 +1,10 @@ +bin_SCRIPTS = obdcontrol +EXTRA_DIST = $(bin_SCRIPTS) + +CFLAGS:=-g -I. -I../include -Wall +KFLAGS:= +CPPFLAGS := +LDADD := -lreadline -ltermcap -lefence +bin_PROGRAMS = obdctl +obdctl_SOURCES = parser.c obdctl.c + diff --git a/lustre/utils/Pack.pm b/lustre/utils/Pack.pm new file mode 100644 index 0000000..ad9f688 --- /dev/null +++ b/lustre/utils/Pack.pm @@ -0,0 +1,172 @@ +package Pack; +use Carp; +use Exporter; +@EXPORT = qw(LOGL, UNLOGL, LOGU32, UNLOGU32, LLOGU32, LUNLOGU32, LOGU64, UNLOGU64, LLOGU64, LUNLOGU64); + +sub round_len { + return ($_[0] + 3) & ~0x3; +} + +sub roundq_len { + return ($_[0] + 3) & ~0x7; +} + +# pack a string $_[2] +# at $offset ($_[1]) +# in $buf ($_[0]) +# padd to 32bit alignment move $_[1] forward + +sub LOGL{ + my $len = length($_[2]); + my $rlen = round_len($len); + my $padd = $rlen + $off - length($_[0]); + + if ($padd > 0) { + $_[0] .= pack "x$padd"; + } + substr $_[0], $_[1], $len, $_[2]; + $_[1] += $rlen; +} + +# pack $_[2], a u32, into $_[0] at offset $_[1] +sub LOGU32 { + if ($_[1] != round_len($_[1])) { + confess "packing I on non-word boundary"; + } + my $padd = 4 + $off - length($_[0]); + + if ($padd > 0) { + $_[0] .= pack "L", $_[2]; + } else { + substr $_[0], $_[1], $len, pack "L", $_[2]; + } + $_[1] += 4; +} + +# pack $_[2], a u32, into $_[0] at offset $_[1] +# use little endian +sub LLOGU32 { + if ($_[1] != round_len($_[1])) { + confess "packing V on non-word boundary"; + } + my $padd = 4 + $off - length($_[0]); + + if ($padd > 0) { + $_[0] .= pack "V", $_[2]; + } else { + substr $_[0], $_[1], $len, pack "V", $_[2]; + } + $_[1] += 4; +} + +sub LLOGU64 { + if ($_[1] != roundq_len($_[1])) { + confess "packing Q on non-word boundary"; + } + my $padd = 8 + $off - length($_[0]); + + if ($padd > 0) { + $_[0] .= pack "VV", $_[3], $_[2]; + } else { + substr $_[0], $_[1], $len, pack "VV", $_[3], $_[2]; + } + $_[1] += 8; +} + +sub LLOGU64 { + if ($_[1] != roundq_len($_[1])) { + confess "packing Q on non-word boundary"; + } + my $padd = 8 + $off - length($_[0]); + + if ($padd > 0) { + $_[0] .= pack "LL", $_[3], $_[2]; + } else { + substr $_[0], $_[1], $len, pack "LL", $_[3], $_[2]; + } + $_[1] += 8; +} + +sub UNLOGL { + if (length($_[0]) < $_[1] + round_len($_[2]) ) { + confess "unpacking buf beyond string length"; + } + + $_[3] = unpack "x$_[1]a$_[2]", $_[0]; + $_[1] += round_len($_[2]); + return $_[3]; +} + +sub UNLOGU32 { + if (length($_[0]) < $_[1] + 4) { + confess "unpacking u32 beyond string length"; + } + + $_[2] = unpack "x$_[1]L", $_[0]; + $_[1] += 4; + return $_[2]; +} + +sub LUNLOGU32 { + if (length($_[0]) < $_[1] + 4) { + confess "lunpacking u32 beyond string length"; + } + $_[2] = unpack "x$_[1]V", $_[0]; + $_[1] += 4; + return $_[2]; +} + +sub UNLOGU64 { + if (length($_[0]) < $_[1] + 8) { + confess "unpacking u64 beyond string length"; + } + + ($_[3], $_[2]) = unpack "x$_[1]LL", $_[0]; + $_[1] += 8; + return ($_[2], $_[3]); +} + +sub LUNLOGU64 { + if (length($_[0]) < $_[1] + 8) { + confess "lunpacking u64 beyond string length"; + } + + ($_[3], $_[2]) = unpack "x$_[1]VV", $_[0]; + $_[1] += 8; + return ($_[2], $_[3]); +} + +sub test { + $buf = ""; + $off = 0; + + LOGL($buf, $off, "moose"); + print "off $off\n"; + printf "len %d\n", length($buf); + LLOGU64($buf, $off, 0x01020304, 0x05060708); + print "off $off\n"; + printf "len %d\n", length($buf); + LLOGU32($buf, $off, 0x01020304); + print "off $off\n"; + printf "len %d\n", length($buf); + $off = 0; + UNLOGL($buf, $off, length("moose"), $str); + print "off $off $str\n"; + LUNLOGU64($buf, $off, $high, $low); + printf "off $off high %x low %x\n", $high, $low; + LUNLOGU32($buf, $off, $low); + printf "off $off long %x\n", $low; + + $off = 0; + $str = UNLOGL($buf, $off, length("moose")); + print "assigned off $off $str\n"; + ($high, $low) = LUNLOGU64($buf, $off); + printf "assigned off $off high %x low %x\n", $high, $low; + $low = LUNLOGU32($buf, $off, $low); + printf "assigned off $off long %x\n", $low; + + sysopen F, "/tmp/out", 2; + syswrite F, $buf, length($buf); +} + +# test(); diff --git a/lustre/obdclass/obdcontrol b/lustre/utils/obdcontrol similarity index 88% rename from lustre/obdclass/obdcontrol rename to lustre/utils/obdcontrol index f12a212..7a0d108 100755 --- a/lustre/obdclass/obdcontrol +++ b/lustre/utils/obdcontrol @@ -94,6 +94,7 @@ use Storable; use Carp; use Term::ReadLine; use IO::Handle; +use Pack; # NOTE long long are layed out in ia32 memory as follows: @@ -290,7 +291,7 @@ if ( $file ) { while ( ) { print $_; my $rc = execute_line($_); - if ($rc != 0) { last; } + if ($rc != 0) { last; } } exit 0; } else { @@ -311,17 +312,17 @@ if ( $file ) { sub completeme { my ($text, $line, $start, $end) = @_; if (substr($line, 0, $start) =~ /^\s*$/) { - if ($] < 5.6) { # PErl version is less than 5.6.0 - return (exists $commands{$text}) ? $text : 0; + if ($] < 5.6) { # PErl version is less than 5.6.0 + return (exists $commands{$text}) ? $text : 0; #Above line doesn't perform command completion, but #perl5.005 Term-ReadLine lacks support for completion matching #and perl5.6.0 requires glibc2.2.2 that won't run under Redhat6.2......sigh. - } - else { - $attribs->{completion_word} = \@jcm_cmd_list; - return $term->completion_matches($text, - $attribs->{'list_completion_function'}); - } + } + else { + $attribs->{completion_word} = \@jcm_cmd_list; + return $term->completion_matches($text, + $attribs->{'list_completion_function'}); + } } } @@ -374,32 +375,32 @@ sub Device { my $device = shift; if ( ! $device && ! $::device ) { # first time ever - $device = '/dev/obd0'; + $device = '/dev/obd0'; } if (($device) && ($::device ne $device)) { - local *NEW_OBD; - my $newfd; + local *NEW_OBD; + my $newfd; - if ($::client_id) { - print "Disconnecting active session ($::client_id)..."; - Disconnect($::client_id); - } + if ($::client_id) { + print "Disconnecting active session ($::client_id)..."; + Disconnect($::client_id); + } - if ($opendevfds{$device}) { - $::dev_obd = $opendevfds{$device}; + if ($opendevfds{$device}) { + $::dev_obd = $opendevfds{$device}; + } + else { + # Open the device, as we need an FD for the ioctl + if (!sysopen(NEW_OBD, $device, 0)) { + print "Cannot open $device. Did you insert the obdclass module ?\n"; + return -1; + } + print "Opened device $device\n"; + $opendevfds{$device} = *NEW_OBD; + $::dev_obd = *NEW_OBD; } - else { - # Open the device, as we need an FD for the ioctl - if (!sysopen(NEW_OBD, $device, 0)) { - print "Cannot open $device. Did you insert the obdclass module ?\n"; - return -1; - } - print "Opened device $device\n"; - $opendevfds{$device} = *NEW_OBD; - $::dev_obd = *NEW_OBD; - } - $::device = $device; + $::device = $device; } print "Current device is $::device\n"; return 0; @@ -410,35 +411,35 @@ sub Close { my $fd2close; if ( ! $device && ! $::device ) { # first time ever - print "Nothing to close\n"; - return -1; + print "Nothing to close\n"; + return -1; } if ( ! $device ) { - $device = $::device; + $device = $::device; } if ($::device eq $device) { - if ($::client_id) { - print "Disconnecting active session ($::client_id)..."; - Disconnect($::client_id); - } + if ($::client_id) { + print "Disconnecting active session ($::client_id)..."; + Disconnect($::client_id); + } } $fd2close = $opendevfds{$device}; if ($fd2close) { # XXXX something wrong in this if statement - close ($fd2close); - $opendevfds{$device} = undef; - print "Closed device $device\n"; + close ($fd2close); + $opendevfds{$device} = undef; + print "Closed device $device\n"; } else { - print "Device $device was not open\n"; - return -1; + print "Device $device was not open\n"; + return -1; } if ($::device eq $device) { - $::dev_obd = undef; - $::device = undef; + $::dev_obd = undef; + $::device = undef; } print "No current device. You just closed the current device ($device).\n"; return 0; @@ -448,23 +449,23 @@ sub Script { my $cmdfilename = shift; my $rc = 0; if ( ! $cmdfilename ) { - print "please specify a command file name\n"; - return -1; + print "please specify a command file name\n"; + return -1; } if (! open(CMDF, $cmdfilename)) { - print "Cannot open $cmdfilename: $!\n"; - return -1; + print "Cannot open $cmdfilename: $!\n"; + return -1; } while () { - if (/^#/) { - next; - } + if (/^#/) { + next; + } print "execute> $_"; - $rc = execute_line($_); - if ($rc != 0) { - print "Something went wrong .......command exit status: $rc\n"; - last; - } + $rc = execute_line($_); + if ($rc != 0) { + print "Something went wrong .......command exit status: $rc\n"; + last; + } } close(CMDF); return $rc; @@ -474,8 +475,8 @@ sub Shell { my $user_shell=$ENV{'SHELL'}; print "% $user_shell -c '@_'\n"; if ( ! @_ ) { - print "please specify a shell command\n"; - return; + print "please specify a shell command\n"; + return; } system("$user_shell -c '@_'"); return ($? >> 8); @@ -499,20 +500,20 @@ sub Procsys { my $value = shift; foreach $i (0 .. $#procsysobd_objects) { - my $sysobd = $procsysobd_objects[$i]; + my $sysobd = $procsysobd_objects[$i]; - if (defined $set_sysobd) { - if ($sysobd ne $set_sysobd) { next; } + if (defined $set_sysobd) { + if ($sysobd ne $set_sysobd) { next; } - if (defined $value) { # set this one - system("echo \"$value\" > /proc/sys/obd/$sysobd"); - } - system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd"); - last; - } - else { - system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd"); - } + if (defined $value) { # set this one + system("echo \"$value\" > /proc/sys/obd/$sysobd"); + } + system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd"); + last; + } + else { + system("echo \"/proc/sys/obd/$sysobd:\"; cat /proc/sys/obd/$sysobd"); + } } return ($? >> 8); } @@ -581,20 +582,20 @@ usage: my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_ATTACH, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -604,21 +605,21 @@ sub Detach { my $data = ""; if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_DETACH, $data); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -640,21 +641,21 @@ sub TestExt2Iterator { print "type $type (len $len), datalen $datalen ($cl)\n"; my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_EXT2_RUNIT, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -680,21 +681,21 @@ sub SnapDelete { # are deleted, the snapshot itself is also removed from the table. if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_SNAP_DELETE, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -758,15 +759,15 @@ sub SnapRestore { my $cl = length($data); my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_SNAP_RESTORE, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Snaprestore finished (success)\n"; delete $table->{$restoretime} if defined $restoretime; @@ -776,10 +777,10 @@ sub SnapRestore { # set it in the kernel SnapSetTable($tableno, $snaptable); # PrintSnapShotTable($table); - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -810,21 +811,21 @@ sub SnapPrint { print "type $type (len $len), datalen $datalen ($cl)\n"; my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_SNAP_PRINTTABLE, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -840,7 +841,7 @@ sub SnapSetTable { if ( ! -f $file ) { print "No such file $file\n"; - return -1; + return -1; } $table = ReadSnapShotTable($file); @@ -865,21 +866,21 @@ sub SnapSetTable { print "type $type (len $len), datalen $datalen ($cl)\n"; my $packed = pack("Lipip", $::client_id, length($type), $type, $datalen, $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_SNAP_SETTABLE, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -998,21 +999,21 @@ sub Copy { # XXX need to fix copy so we can have 2 client IDs here my $packed = pack("L", $::client_id) . obdo_pack($dst_obdo) . pack("L", $::client_id) . obdo_pack($src_obdo); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_COPY, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1028,21 +1029,21 @@ sub Migrate { # We pack a dummy connection ID here my $packed = pack("L", $::client_id) . obdo_pack($dst_obdo) . pack("L", $::client_id) . obdo_pack($src_obdo); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_MIGR, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1055,20 +1056,20 @@ sub Format { my $packed = pack("ip", $datalen, $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_FORMATOBD, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1081,20 +1082,20 @@ sub Partition { my $packed = pack("ip", $datalen, $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_PARTITION, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1120,41 +1121,41 @@ sub Setup { my $packed = pack("iip", $datalen, $::st->rdev(), $data); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_SETUP, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } sub Cleanup { my $err = "0"; if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_CLEANUP, $err); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; $::client_id = 0; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1164,23 +1165,23 @@ sub Connect { my $packed = ""; if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } $rc = ioctl($::dev_obd, &OBD_IOC_CONNECT, $packed); $id = unpack("I", $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { $::client_id = $id; print "Client ID : $id\n"; print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1200,21 +1201,21 @@ sub Disconnect { my $packed = pack("L", $id); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_DISCONNECT, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { $::client_id = undef; print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1259,10 +1260,10 @@ sub Create { $obdo->{valid} = &OBD_MD_FLMODE; my $packed = pack("I", $::client_id) . obdo_pack($obdo); - if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; - } + if (! defined $::dev_obd) { + print "No current device.\n"; + return -1; + } $rc = ioctl($::dev_obd, &OBD_IOC_CREATE, $packed); if ($rc ne "0 but true") { last; @@ -1274,33 +1275,33 @@ sub Create { if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } sub Sync { my $err = "0"; if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_SYNC, $err); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1320,20 +1321,20 @@ sub Destroy { print "Destroying object $id...\n"; my $packed = pack("IL", $::client_id, $id); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_DESTROY, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1356,21 +1357,21 @@ sub Getattr { $obdo->{valid} = &OBD_MD_FLALL; my $packed = pack("L", $::client_id) . obdo_pack($obdo); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_GETATTR, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { $obdo = obdo_unpack($packed, 4); obdo_print($obdo); - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1424,20 +1425,20 @@ sub Setattr { printf "valid is %x, mode is %o\n", $obdo->{valid}, $obdo->{mode}; my $packed = pack("L", $::client_id) . obdo_pack($obdo); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_SETATTR, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1476,8 +1477,8 @@ sub Read { pack("p LL LL", $buf, $count, $offset); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_READ, $packed); @@ -1485,20 +1486,20 @@ sub Read { if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { if ($retval >= 0) { print substr($buf, 0, $retval); print "\nRead $retval of an attempted $count bytes.\n"; print "Finished (success)\n"; - return 0; + return 0; } else { print "Finished (error $retval)\n"; - return $retval; + return $retval; } } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1537,8 +1538,8 @@ sub Read2 { pack("p LL LL", $buf, $count, $offset); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_READ2, $packed); @@ -1546,20 +1547,20 @@ sub Read2 { if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { if ($retval >= 0) { print substr($buf, 0, $retval); print "\nRead $retval of an attempted $count bytes.\n"; print "Finished (success)\n"; - return 0; - } else { + return 0; + } else { print "Finished (error $retval)\n"; - return $retval; + return $retval; } } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1595,8 +1596,8 @@ sub Write { pack("p LL LL", $text, $count, $offset); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_WRITE, $packed); @@ -1604,19 +1605,19 @@ sub Write { if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { if ($retval >= 0) { print "\nWrote $retval of an attempted $count bytes.\n"; print "Finished (success)\n"; - return 0; + return 0; } else { print "Finished (error $retval)\n"; - return $retval; + return $retval; } } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1646,8 +1647,8 @@ sub Punch { pack("p LL LL", $buf, $start, $count); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_PUNCH, $packed); @@ -1659,14 +1660,14 @@ sub Punch { if ($retval >= 0) { print "\nPunched $retval of an attempted $count bytes.\n"; print "Finished (success)\n"; - return 0; + return 0; } else { print "Finished (error $retval)\n"; - return $retval; + return $retval; } } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1687,14 +1688,14 @@ sub Preallocate { my $packed = pack("LLx128", $::client_id, $num); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_PREALLOCATE, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { my $alloc = unpack("x4L", $packed); my @ids = unpack("x8L32", $packed); @@ -1705,29 +1706,29 @@ sub Preallocate { print $i . " "; } print "\nFinished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } sub Decusecount { if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_DEC_USE_COUNT, 0); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } @@ -1754,14 +1755,14 @@ sub Statfs { 0, 0, 0, 0, 0, 0); if (! defined $::dev_obd) { - print "No current device.\n"; - return -1; + print "No current device.\n"; + return -1; } my $rc = ioctl($::dev_obd, &OBD_IOC_STATFS, $packed); if (!defined $rc) { print STDERR "ioctl failed: $!\n"; - return -1; + return -1; } elsif ($rc eq "0 but true") { # skip both the conn_id and the fs_type in the buffer my ($bsize, $blocks, $bfree, $bavail, $files, $ffree) = @@ -1770,10 +1771,10 @@ sub Statfs { "$bfree free ($bavail available).\n"); print "$files files, " . ($files - $ffree) . " used, $ffree free.\n"; print "Finished (success)\n"; - return 0; + return 0; } else { print "ioctl returned error code $rc.\n"; - return -1; + return -1; } } diff --git a/lustre/utils/obdctl.c b/lustre/utils/obdctl.c new file mode 100644 index 0000000..eebb238 --- /dev/null +++ b/lustre/utils/obdctl.c @@ -0,0 +1,348 @@ +#include +#include +#include +#include +#include +#include +#include +#define printk printf +#include +#include +#include +#include +#include +#include +#include + +#define __KERNEL__ +#include +#undef __KERNEL__ + +#include "parser.h" +#include + +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 1) { + return Parser_execarg(argc - 1, &argv[1], list); + } + + Parser_init("obdctl > ", list); + Parser_commands(); + + return 0; +} + diff --git a/lustre/utils/parser.c b/lustre/utils/parser.c new file mode 100644 index 0000000..63eb906 --- /dev/null +++ b/lustre/utils/parser.c @@ -0,0 +1,584 @@ +#include +#include +#include +#include +#include +#include +#include + +#define READLINE_LIBRARY +#include + +extern void using_history(void); +extern void stifle_history(int); +extern void add_history(char *); + +#include "parser.h" +#define CMD_COMPLETE 0 +#define CMD_INCOMPLETE 1 +#define CMD_NONE 2 +#define CMD_AMBIG 3 + +static command_t * top_level; /* Top level of commands, initialized by + * InitParser */ +static command_t * match_tbl; /* Command completion against this table */ +static char * parser_prompt = NULL;/* Parser prompt, set by InitParser */ +static int done; /* Set to 1 if user types exit or quit */ + + +/* static functions */ +static char *skipwhitespace(char *s); +static char *skiptowhitespace(char *s); +static command_t *find_cmd(char *name, command_t cmds[], char **next); +static int process(char *s, char **next, command_t *lookup, command_t **result, char **prev); +static char *command_generator(const char *text, int state); +static char **command_completion(char *text, int start, int end); +static void print_commands(char *str, command_t *table); + +static char * skipwhitespace(char * s) +{ + char * t; + int len; + + len = (int)strlen(s); + for (t = s; t <= s + len && isspace(*t); t++); + return(t); +} + + +static char * skiptowhitespace(char * s) +{ + char * t; + + for (t = s; *t && !isspace(*t); t++); + return(t); +} + +static int line2args(char *line, char **argv, int maxargs) +{ + char *arg; + int i = 0; + + arg = strtok(line, " \t"); + if ( arg ) { + argv[i] = arg; + i++; + } else + return 0; + + while( (arg = strtok(NULL, " \t")) && (i <= maxargs)) { + argv[i] = arg; + i++; + } + return i; +} + +/* find a command -- return it if unique otherwise print alternatives */ + +static command_t *Parser_findargcmd(char *name, command_t cmds[]) +{ + command_t *cmd; + int i; + + for (i = 0; cmds[i].pc_name; i++) { + cmd = &cmds[i]; + + if (strlen(name) != strlen(cmd->pc_name)) + continue; + + if (strlen(name) == strlen(cmd->pc_name)) { + if (strcmp(name, cmd->pc_name) == 0) + return cmd; + else + continue; + } + + } + return NULL; +} + +int Parser_execarg(int argc, char **argv, command_t cmds[]) +{ + command_t *cmd; + int i; + + cmd = Parser_findargcmd(argv[0], cmds); + if ( cmd ) { + return (cmd->pc_func)(argc, argv); + } else { + printf("Try interactive use without arguments or use one of: "); + for (i=0 ; cmds[i].pc_name ; i++) { + cmd = &cmds[i]; + printf("\"%s\" ", cmd->pc_name); + } + printf("as argument.\n"); + } + return -1; +} + +/* returns the command_t * (NULL if not found) corresponding to a + _partial_ match with the first token in name. It sets *next to + point to the following token. Does not modify *name. */ +static command_t * find_cmd(char * name, command_t cmds[], char ** next) +{ + int i, len; + + if (!cmds || !name ) + return NULL; + + /* This sets name to point to the first non-white space character, + and next to the first whitespace after name, len to the length: do + this with strtok*/ + name = skipwhitespace(name); + *next = skiptowhitespace(name); + len = *next - name; + if (len == 0) + return NULL; + + for (i = 0; cmds[i].pc_name; i++) { + if (strncasecmp(name, cmds[i].pc_name, len) == 0) { + *next = skipwhitespace(*next); + return(&cmds[i]); + } + } + return NULL; +} + +/* Recursively process a command line string s and find the command + corresponding to it. This can be ambiguous, full, incomplete, + non-existent. */ +static int process(char *s, char ** next, command_t *lookup, + command_t **result, char **prev) +{ + *result = find_cmd(s, lookup, next); + *prev = s; + + /* non existent */ + if ( ! *result ) + return CMD_NONE; + + /* found entry: is it ambigous, i.e. not exact command name and + more than one command in the list matches. Note that find_cmd + points to the first ambiguous entry */ + if ( strncasecmp(s, (*result)->pc_name, strlen((*result)->pc_name)) && + find_cmd(s, (*result) + 1, next)) + return CMD_AMBIG; + + /* found a unique command: component or full? */ + if ( (*result)->pc_func ) { + return CMD_COMPLETE; + } else { + if ( *next == '\0' ) { + return CMD_INCOMPLETE; + } else { + return process(*next, next, (*result)->pc_sub_cmd, result, prev); + } + } +} + +static char * command_generator(const char * text, int state) +{ + static int index, + len; + char *name; + + /* Do we have a match table? */ + if (!match_tbl) + return NULL; + + /* If this is the first time called on this word, state is 0 */ + if (!state) { + index = 0; + len = (int)strlen(text); + } + + /* Return the next name in the command list that paritally matches test */ + while ( (name = (match_tbl + index)->pc_name) ) { + index++; + + if (strncasecmp(name, text, len) == 0) { + return(strdup(name)); + } + } + + /* No more matches */ + return NULL; +} + +/* probably called by readline */ +static char **command_completion(char * text, int start, int end) +{ + command_t * table; + char * pos; + + match_tbl = top_level; + for (table = find_cmd(rl_line_buffer, match_tbl, &pos); + table; + table = find_cmd(pos, match_tbl, &pos)) { + + if (*(pos - 1) == ' ') match_tbl = table->pc_sub_cmd; + } + + return(rl_completion_matches(text, command_generator)); +} + +/* take a string and execute the function or print help */ +void execute_line(char * line) +{ + command_t *cmd, *ambig; + char *prev; + char *next, *tmp; + char *argv[MAXARGS]; + int i; + + switch( process(line, &next, top_level, &cmd, &prev) ) { + case CMD_AMBIG: + fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line); + while( (ambig = find_cmd(prev, cmd, &tmp)) ) { + fprintf(stderr, "%s ", ambig->pc_name); + cmd = ambig + 1; + } + fprintf(stderr, "\n"); + break; + case CMD_NONE: + fprintf(stderr, "No such command, type help\n"); + break; + case CMD_INCOMPLETE: + fprintf(stderr, + "'%s' incomplete command. Use '%s x' where x is one of:\n", + line, line); + fprintf(stderr, "\t"); + for (i = 0; cmd->pc_sub_cmd[i].pc_name; i++) { + fprintf(stderr, "%s ", cmd->pc_sub_cmd[i].pc_name); + } + fprintf(stderr, "\n"); + break; + case CMD_COMPLETE: + i = line2args(line, argv, MAXARGS); + (cmd->pc_func)(i, argv); + break; + } + + return; +} + +/* this is the command execution machine */ +void Parser_commands(void) +{ + char *line, + *s; + + using_history(); + stifle_history(HISTORY); + + rl_attempted_completion_function = + (rl_completion_func_t *)command_completion; + rl_completion_entry_function = (rl_compentry_func_t *)command_generator; + + while(!done) { + line = readline(parser_prompt); + + if (!line) break; + + s = skipwhitespace(line); + + if (*s) { + add_history(s); + execute_line(s); + } + + free(line); + } +} + + +/* sets the parser prompt */ +void Parser_init(char * prompt, command_t * cmds) +{ + done = 0; + top_level = cmds; + if (parser_prompt) free(parser_prompt); + parser_prompt = strdup(prompt); +} + +/* frees the parser prompt */ +void Parser_exit(int argc, char *argv[]) +{ + done = 1; + free(parser_prompt); + parser_prompt = NULL; +} + +/* convert a string to an integer */ +int Parser_int(char *s, int *val) +{ + int ret; + + if (*s != '0') + ret = sscanf(s, "%d", val); + else if (*(s+1) != 'x') + ret = sscanf(s, "%o", val); + else { + s++; + ret = sscanf(++s, "%x", val); + } + + return(ret); +} + + + +void Parser_qhelp(int argc, char *argv[]) { + + printf("Available commands are:\n"); + + print_commands(NULL, top_level); + printf("For more help type: help command-name\n"); +} + +int Parser_help(int argc, char **argv) +{ + char line[1024]; + char *next, *prev, *tmp; + command_t *result, *ambig; + int i; + + if ( argc == 1 ) { + Parser_qhelp(argc, argv); + return 0; + } + + line[0]='\0'; + for ( i = 1 ; i < argc ; i++ ) { + strcat(line, argv[i]); + } + + switch ( process(line, &next, top_level, &result, &prev) ) { + case CMD_COMPLETE: + fprintf(stderr, "%s: %s\n",line, result->pc_help); + break; + case CMD_NONE: + fprintf(stderr, "%s: Unknown command.\n", line); + break; + case CMD_INCOMPLETE: + fprintf(stderr, + "'%s' incomplete command. Use '%s x' where x is one of:\n", + line, line); + fprintf(stderr, "\t"); + for (i = 0; result->pc_sub_cmd[i].pc_name; i++) { + fprintf(stderr, "%s ", result->pc_sub_cmd[i].pc_name); + } + fprintf(stderr, "\n"); + break; + case CMD_AMBIG: + fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line); + while( (ambig = find_cmd(prev, result, &tmp)) ) { + fprintf(stderr, "%s ", ambig->pc_name); + result = ambig + 1; + } + fprintf(stderr, "\n"); + break; + } + return 0; +} + +/************************************************************************* + * COMMANDS * + *************************************************************************/ + + +static void print_commands(char * str, command_t * table) { + command_t * cmds; + char buf[80]; + + for (cmds = table; cmds->pc_name; cmds++) { + if (cmds->pc_func) { + if (str) printf("\t%s %s\n", str, cmds->pc_name); + else printf("\t%s\n", cmds->pc_name); + } + if (cmds->pc_sub_cmd) { + if (str) { + sprintf(buf, "%s %s", str, cmds->pc_name); + print_commands(buf, cmds->pc_sub_cmd); + } else { + print_commands(cmds->pc_name, cmds->pc_sub_cmd); + } + } + } +} + +char *Parser_getstr(const char *prompt, const char *deft, char *res, + size_t len) +{ + char *line = NULL; + int size = strlen(prompt) + strlen(deft) + 8; + char *theprompt; + theprompt = malloc(size); + assert(theprompt); + + sprintf(theprompt, "%s [%s]: ", prompt, deft); + + line = readline(theprompt); + free(theprompt); + + if ( line == NULL || *line == '\0' ) { + strncpy(res, deft, len); + } else { + strncpy(res, line, len); + } + + if ( line ) { + free(line); + return res; + } else { + return NULL; + } +} + +/* get integer from prompt, loop forever to get it */ +int Parser_getint(const char *prompt, long min, long max, long deft, int base) +{ + int rc; + long result; + char *line; + int size = strlen(prompt) + 40; + char *theprompt = malloc(size); + assert(theprompt); + sprintf(theprompt,"%s [%ld, (0x%lx)]: ", prompt, deft, deft); + + fflush(stdout); + + do { + line = NULL; + line = readline(theprompt); + if ( !line ) { + fprintf(stdout, "Please enter an integer.\n"); + fflush(stdout); + continue; + } + if ( *line == '\0' ) { + free(line); + result = deft; + break; + } + rc = Parser_arg2int(line, &result, base); + free(line); + if ( rc != 0 ) { + fprintf(stdout, "Invalid string.\n"); + fflush(stdout); + } else if ( result > max || result < min ) { + fprintf(stdout, "Error: response must lie between %ld and %ld.\n", + min, max); + fflush(stdout); + } else { + break; + } + } while ( 1 ) ; + + if (theprompt) + free(theprompt); + return result; + +} + +/* get boolean (starting with YyNn; loop forever */ +int Parser_getbool(const char *prompt, int deft) +{ + int result = 0; + char *line; + int size = strlen(prompt) + 8; + char *theprompt = malloc(size); + assert(theprompt); + + fflush(stdout); + + if ( deft != 0 && deft != 1 ) { + fprintf(stderr, "Error: Parser_getbool given bad default (%d).\n", + deft); + assert ( 0 ); + } + sprintf(theprompt, "%s [%s]: ", prompt, (deft==0)? "N" : "Y"); + + do { + line = NULL; + line = readline(theprompt); + if ( line == NULL ) { + result = deft; + break; + } + if ( *line == '\0' ) { + result = deft; + break; + } + if ( *line == 'y' || *line == 'Y' ) { + result = 1; + break; + } + if ( *line == 'n' || *line == 'N' ) { + result = 0; + break; + } + if ( line ) + free(line); + fprintf(stdout, "Invalid string. Must start with yY or nN\n"); + fflush(stdout); + } while ( 1 ); + + if ( line ) + free(line); + if ( theprompt ) + free(theprompt); + return result; +} + +/* parse int out of a string or prompt for it */ +long Parser_intarg(const char *inp, const char *prompt, int deft, + int min, int max, int base) +{ + long result; + int rc; + + rc = Parser_arg2int(inp, &result, base); + + if ( rc == 0 ) { + return result; + } else { + return Parser_getint(prompt, deft, min, max, base); + } +} + +/* parse int out of a string or prompt for it */ +char *Parser_strarg(char *inp, const char *prompt, const char *deft, + char *answer, int len) +{ + + if ( inp == NULL || *inp == '\0' ) { + return Parser_getstr(prompt, deft, answer, len); + } else + return inp; +} + +/* change a string into a number: return 0 on success. No invalid characters + allowed. The processing of base and validity follows strtol(3)*/ +int Parser_arg2int(const char *inp, long *result, int base) +{ + char *endptr; + + if ( (base !=0) && (base < 2 || base > 36) ) + return 1; + + *result = strtol(inp, &endptr, base); + + if ( *inp != '\0' && *endptr == '\0' ) + return 0; + else + return 1; +} + +int Parser_quit(int argc, char **argv) +{ + argc = argc; + argv = argv; + exit(0); + return 0; +} diff --git a/lustre/utils/parser.h b/lustre/utils/parser.h new file mode 100644 index 0000000..a35ab75 --- /dev/null +++ b/lustre/utils/parser.h @@ -0,0 +1,55 @@ +#ifndef _PARSER_H_ +#define _PARSER_H_ + +#define HISTORY 100 /* Don't let history grow unbounded */ +#define MAXARGS 100 + +typedef struct parser_cmd { + char *pc_name; + int (* pc_func)(int, char **); + struct parser_cmd * pc_sub_cmd; + char *pc_help; +} command_t; + +typedef struct argcmd { + char *ac_name; + int (*ac_func)(int, char **); + char *ac_help; +} argcmd_t; + +int Parser_quit(int argc, char **argv); +void Parser_init(char *, command_t *); /* Set prompt and load command list */ +void Parser_commands(void); /* Start the command parser */ +void Parser_qhelp(int, char **); /* Quick help routine */ +int Parser_help(int, char **); /* Detailed help routine */ +void Parser_exit(int, char **); /* Shuts down command parser */ +int Parser_execarg(int argc, char **argv, command_t cmds[]); +void execute_line(char * line); + +/* Converts a string to an integer */ +int Parser_int(char *, int *); + +/* Prompts for a string, with default values and a maximum length */ +char *Parser_getstr(const char *prompt, const char *deft, char *res, + size_t len); + +/* Prompts for an integer, with minimum, maximum and default values and base */ +int Parser_getint(const char *prompt, long min, long max, long deft, + int base); + +/* Prompts for a yes/no, with default */ +int Parser_getbool(const char *prompt, int deft); + +/* Extracts an integer from a string, or prompts if it cannot get one */ +long Parser_intarg(const char *inp, const char *prompt, int deft, + int min, int max, int base); + +/* Extracts a word from the input, or propmts if it cannot get one */ +char *Parser_strarg(char *inp, const char *prompt, const char *deft, + char *answer, int len); + +/* Extracts an integer from a string with a base */ +int Parser_arg2int(const char *inp, long *result, int base); + + +#endif _PARSER_H_ -- 1.8.3.1